diff options
-rw-r--r-- | include/bios.h | 1 | ||||
-rw-r--r-- | linuxboot.c | 2 | ||||
-rw-r--r-- | main.c | 13 |
3 files changed, 14 insertions, 2 deletions
diff --git a/include/bios.h b/include/bios.h index a187a46..4ed3a1a 100644 --- a/include/bios.h +++ b/include/bios.h @@ -42,6 +42,7 @@ extern void boot_from_fwcfg(void); extern bool boot_from_cbfs(void *base, size_t sz); extern uint16_t e820_seg; +extern uint32_t lowmem; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) diff --git a/linuxboot.c b/linuxboot.c index fc8b7fa..7ce07bc 100644 --- a/linuxboot.c +++ b/linuxboot.c @@ -64,6 +64,8 @@ bool parse_bzimage(struct linuxboot_args *args) initrd_max = ldl_p(header+0x22c); else initrd_max = 0x37ffffff; + if (initrd_max > lowmem - 1) + initrd_max = lowmem - 1; if (protocol >= 0x202) stl_p(header+0x228, cmdline_addr); @@ -89,12 +89,16 @@ static void setup_idt(void) set_realmode_int(0x15, bios_int15); } +/* Top of memory below 4GB. */ +uint32_t lowmem; + static void extract_e820(void) { int id = fw_cfg_file_id("etc/e820"); uint32_t size; int nr_map; struct e820map *e820; + int i; if (id == -1) panic(); @@ -114,8 +118,13 @@ static void extract_e820(void) e820->map[3] = (struct e820entry) { .addr = 0xf0000, .size = 64 * 1024, .type = E820_RESERVED }; /* firmware */ fw_cfg_read(&e820->map[4], size); - e820->map[4].addr = 1024 * 1024; - e820->map[4].size -= 1024 * 1024; + for (i = 4; i < e820->nr_map; i++) + if (e820->map[i].addr == 0) { + lowmem = e820->map[i].size; + e820->map[i].addr = 1024 * 1024; + e820->map[i].size -= 1024 * 1024; + break; + } e820_seg = ((uintptr_t) e820) >> 4; } |