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