diff options
| -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; |
