diff options
Diffstat (limited to 'mubios/services/int15.c')
| -rw-r--r-- | mubios/services/int15.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/mubios/services/int15.c b/mubios/services/int15.c index eb66f5c..b9edb76 100644 --- a/mubios/services/int15.c +++ b/mubios/services/int15.c @@ -37,9 +37,42 @@ static const struct e820_entry e820_map[] = { { 0x00000000u, 0x00000000u, 0x0009C000u, 0x00000000u, 1u }, { 0x0009C000u, 0x00000000u, 0x00004000u, 0x00000000u, 2u }, { 0x000A0000u, 0x00000000u, 0x00060000u, 0x00000000u, 2u }, - { 0x00100000u, 0x00000000u, 0x07F00000u, 0x00000000u, 1u } }; + { 0x00100000u, 0x00000000u, 0x00000000u, 0x00000000u, 1u } }; #define E820_ENTRY_COUNT ((u32)(sizeof (e820_map) / sizeof (e820_map[0]))) +#define E820_MEMORY_BASE 0x00100000u +#define E820_FALLBACK_END 0x08000000u +#define CMOS_EXTENDED_MEMORY_LOW_16M 0x30u +#define CMOS_EXTENDED_MEMORY_HIGH_16M 0x31u +#define CMOS_EXTENDED_MEMORY_LOW 0x34u +#define CMOS_EXTENDED_MEMORY_HIGH 0x35u + +static u32 +get_memory_end (void) +{ + u16 units; + u16 extended_kib; + u32 memory_end; + + units = (u16)cmos_read8 (CMOS_EXTENDED_MEMORY_LOW) + | (u16)((u16)cmos_read8 (CMOS_EXTENDED_MEMORY_HIGH) << 8); + if (units != 0u) + { + memory_end = 0x01000000u + ((u32)units << 16); + } + else + { + extended_kib = (u16)cmos_read8 (CMOS_EXTENDED_MEMORY_LOW_16M) + | (u16)((u16)cmos_read8 (CMOS_EXTENDED_MEMORY_HIGH_16M) + << 8); + if (extended_kib != 0u) + memory_end = E820_MEMORY_BASE + ((u32)extended_kib << 10); + else + memory_end = E820_FALLBACK_END; + } + + return memory_end; +} static void int15_fail (struct bios_regs *regs) @@ -51,9 +84,11 @@ int15_fail (struct bios_regs *regs) void int15_service (struct bios_regs *regs) { + struct e820_entry entry; struct e820_entry *output; u32 index; u32 address; + u32 memory_end; if (regs->eax != E820_FUNCTION || regs->edx != E820_SIGNATURE || regs->ecx < E820_ENTRY_SIZE) @@ -73,7 +108,14 @@ int15_service (struct bios_regs *regs) address = ((u32)regs->es << 4) + (u16)regs->edi; output = (struct e820_entry *)address; - *output = e820_map[index]; + entry = e820_map[index]; + if (index == 3u) + { + memory_end = get_memory_end (); + entry.length_low = memory_end - E820_MEMORY_BASE; + } + + *output = entry; regs->eax = E820_SIGNATURE; regs->ecx = E820_ENTRY_SIZE; |
