diff --git a/qloader2.bin b/qloader2.bin index dd49ad0f..873de69d 100644 Binary files a/qloader2.bin and b/qloader2.bin differ diff --git a/src/lib/blib.c b/src/lib/blib.c index 4337ae33..742eecf5 100644 --- a/src/lib/blib.c +++ b/src/lib/blib.c @@ -7,6 +7,25 @@ #include #include #include +#include + +// Checks if a given memory range is entirely within a usable e820 entry. +// TODO: Consider the possibility of adjacent usable entries. +// TODO: Consider the possibility of usable entry being overlapped by non-usable +// ones. +void is_valid_memory_range(size_t base, size_t size) { + for (size_t i = 0; i < e820_entries; i++) { + if (e820_map[i].type != 1) + continue; + size_t entry_base = e820_map[i].base; + size_t entry_top = e820_map[i].base + e820_map[i].length; + size_t limit = base + size; + if (base >= entry_base && base < entry_top && + limit >= entry_base && limit < entry_top) + return; + } + panic("Out of memory"); +} uint8_t bcd_to_int(uint8_t val) { return (val & 0x0f) + ((val & 0xf0) >> 4) * 10; diff --git a/src/lib/blib.h b/src/lib/blib.h index 250979dd..4fbcbb02 100644 --- a/src/lib/blib.h +++ b/src/lib/blib.h @@ -4,6 +4,8 @@ #include #include +void is_valid_memory_range(size_t base, size_t size); + uint8_t bcd_to_int(uint8_t val); int cpuid(uint32_t leaf, uint32_t subleaf, diff --git a/src/lib/e820.c b/src/lib/e820.c index f0e2e1a3..aaea8570 100644 --- a/src/lib/e820.c +++ b/src/lib/e820.c @@ -1,8 +1,11 @@ +#include +#include #include #include #include struct e820_entry_t *e820_map; +size_t e820_entries; static const char *e820_type(uint32_t type) { switch (type) { @@ -21,13 +24,11 @@ static const char *e820_type(uint32_t type) { } } -int init_e820(void) { +void init_e820(void) { struct rm_regs r = {0}; - int entry_count; - e820_map = balloc(sizeof(struct e820_entry_t)); - for (int i = 0; ; i++) { + for (size_t i = 0; ; i++) { struct e820_entry_t entry; r.eax = 0xe820; @@ -39,25 +40,23 @@ int init_e820(void) { e820_map[i] = entry; if (r.eflags & EFLAGS_CF) { - entry_count = i; + e820_entries = i; break; } if (!r.ebx) { - entry_count = ++i; + e820_entries = ++i; break; } balloc(sizeof(struct e820_entry_t)); } - for (int i = 0; i < entry_count; i++) { + for (size_t i = 0; i < e820_entries; i++) { print("e820: [%X -> %X] : %X <%s>\n", e820_map[i].base, e820_map[i].base + e820_map[i].length, e820_map[i].length, e820_type(e820_map[i].type)); } - - return entry_count; } diff --git a/src/lib/e820.h b/src/lib/e820.h index 95e7ab2b..7ee07683 100644 --- a/src/lib/e820.h +++ b/src/lib/e820.h @@ -2,8 +2,7 @@ #define __LIB__E820_H__ #include - -#define E820_MAX_ENTRIES 256 +#include struct e820_entry_t { uint64_t base; @@ -13,7 +12,8 @@ struct e820_entry_t { } __attribute__((packed)); extern struct e820_entry_t *e820_map; +extern size_t e820_entries; -int init_e820(void); +void init_e820(void); #endif diff --git a/src/lib/elf.c b/src/lib/elf.c index f0ff11db..71742545 100644 --- a/src/lib/elf.c +++ b/src/lib/elf.c @@ -243,8 +243,9 @@ int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *top) { if (this_top > *top) *top = this_top; - fread(fd, (void *)(uint32_t)phdr.p_vaddr, - phdr.p_offset, phdr.p_filesz); + is_valid_memory_range((size_t)phdr.p_vaddr, (size_t)phdr.p_memsz); + + fread(fd, (void *)(uint32_t)phdr.p_vaddr, phdr.p_offset, phdr.p_filesz); size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz); @@ -292,6 +293,8 @@ int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t *top) { if (this_top > *top) *top = this_top; + is_valid_memory_range((size_t)phdr.p_paddr, (size_t)phdr.p_memsz); + fread(fd, (void *)phdr.p_paddr, phdr.p_offset, phdr.p_filesz); size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz); diff --git a/src/main.c b/src/main.c index 8f44f728..3a0ff8ed 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ asm ( #include #include #include +#include #include #include #include @@ -149,6 +150,8 @@ void main(int boot_drive) { } got_entry: + init_e820(); + if (!config_get_value(buf, 0, 32, "KERNEL_DRIVE")) { drive = boot_drive; } else { diff --git a/src/protos/linux.c b/src/protos/linux.c index 21e88ce7..61443f08 100644 --- a/src/protos/linux.c +++ b/src/protos/linux.c @@ -7,6 +7,9 @@ #include #include +#define KERNEL_LOAD_ADDR ((size_t)0x100000) +#define INITRD_LOAD_ADDR ((size_t)0x1000000) + void linux_load(struct file_handle *fd, char *cmdline) { uint32_t signature; fread(fd, &signature, 0x202, sizeof(uint32_t)); @@ -70,7 +73,8 @@ void linux_load(struct file_handle *fd, char *cmdline) { // load kernel print("Loading kernel...\n"); - fread(fd, (void *)0x100000, real_mode_code_size, fd->size - real_mode_code_size); + is_valid_memory_range(KERNEL_LOAD_ADDR, fd->size - real_mode_code_size); + fread(fd, (void *)KERNEL_LOAD_ADDR, real_mode_code_size, fd->size - real_mode_code_size); char initrd_path[64]; if (!config_get_value(initrd_path, 0, 64, "INITRD_PATH")) @@ -88,10 +92,10 @@ void linux_load(struct file_handle *fd, char *cmdline) { } print("Loading initrd...\n"); - size_t initrd_addr = 0x1000000; - fread(&initrd, (void *)initrd_addr, 0, initrd.size); + is_valid_memory_range(INITRD_LOAD_ADDR, initrd.size); + fread(&initrd, (void *)INITRD_LOAD_ADDR, 0, initrd.size); - *((uint32_t *)(real_mode_code + 0x218)) = (uint32_t)initrd_addr; + *((uint32_t *)(real_mode_code + 0x218)) = (uint32_t)INITRD_LOAD_ADDR; *((uint32_t *)(real_mode_code + 0x21c)) = (uint32_t)initrd.size; uint16_t real_mode_code_seg = rm_seg(real_mode_code); diff --git a/src/protos/stivale.c b/src/protos/stivale.c index 148f69eb..4464e832 100644 --- a/src/protos/stivale.c +++ b/src/protos/stivale.c @@ -97,7 +97,7 @@ void stivale_load(struct file_handle *fd, char *cmdline) { print("stivale: Top used address in ELF: %X\n", top_used_addr); - stivale_struct.memory_map_entries = (uint64_t)init_e820(); + stivale_struct.memory_map_entries = (uint64_t)e820_entries; stivale_struct.memory_map_addr = (uint64_t)(size_t)e820_map; stivale_struct.module_count = 0; @@ -126,6 +126,7 @@ void stivale_load(struct file_handle *fd, char *cmdline) { ((uint32_t)top_used_addr & ~((uint32_t)0xfff)) + 0x1000 : (uint32_t)top_used_addr); + is_valid_memory_range((size_t)module_addr, f.size); fread(&f, module_addr, 0, f.size); m->begin = (uint64_t)(size_t)module_addr;