aboutsummaryrefslogtreecommitdiff
path: root/mubios/services
diff options
context:
space:
mode:
Diffstat (limited to 'mubios/services')
-rw-r--r--mubios/services/int15.c46
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;