diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-11-09 23:49:35 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-11-09 23:49:35 +0800 |
| commit | 9f45c30789b6133d4b5fb4ef07f0818a3ea4de48 (patch) | |
| tree | f51bffeff6206ff37bb1589c58e1a9a282b44685 | |
| parent | 2bc8a824fd424aa3e21bc394fd0be3191b830888 (diff) | |
| download | rcc-project-9f45c30789b6133d4b5fb4ef07f0818a3ea4de48.tar.gz rcc-project-9f45c30789b6133d4b5fb4ef07f0818a3ea4de48.tar.xz | |
[mubios] Derive the E820 map from the CMOS memory size
The E820 map ended the usable region at a hardcoded 0x08000000, so a guest
with more RAM had the extra memory reported as reserved and ran out of memory
during initramfs unpacking.
Add cmos_read8() and size the extended memory entry from CMOS registers 0x34
and 0x35, falling back to the 16 MiB units in 0x30 and 0x31 and then to the
previous 128 MiB end when neither is programmed.
| -rw-r--r-- | mubios/drivers/cmos.c | 20 | ||||
| -rw-r--r-- | mubios/include/bios.h | 2 | ||||
| -rw-r--r-- | mubios/services/int15.c | 46 |
3 files changed, 66 insertions, 2 deletions
diff --git a/mubios/drivers/cmos.c b/mubios/drivers/cmos.c new file mode 100644 index 0000000..35148d8 --- /dev/null +++ b/mubios/drivers/cmos.c @@ -0,0 +1,20 @@ +/* + RCC-Project + + Copyright (C) 2026 Richard Qin + + This file is part of RCC-Project. + */ + +#include "bios.h" +#include "io.h" + +#define CMOS_INDEX_PORT 0x0070u +#define CMOS_DATA_PORT 0x0071u + +u8 +cmos_read8 (u8 index) +{ + io_out8 (CMOS_INDEX_PORT, index); + return io_in8 (CMOS_DATA_PORT); +} diff --git a/mubios/include/bios.h b/mubios/include/bios.h index c1c70d8..3c8b0dc 100644 --- a/mubios/include/bios.h +++ b/mubios/include/bios.h @@ -44,6 +44,8 @@ void serial_init (void); void serial_putc (u8 value); void serial_write (const char *text); +u8 cmos_read8 (u8 index); + void kbd_init (void); void pic_init (void); void pit_init (void); 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; |
