multiboot1: Add ELF sections load support

This commit is contained in:
mintsuki 2022-06-19 01:46:38 +02:00
parent 77fa71ae92
commit 3ef8a29933

View File

@ -21,6 +21,20 @@
noreturn void multiboot1_spinup_32(uint32_t entry_point, uint32_t multiboot1_info);
static uint32_t kernel_top;
static void *mb1_alloc(size_t size) {
void *ret = (void *)(uintptr_t)ALIGN_UP(kernel_top, 4096);
while (!memmap_alloc_range((uintptr_t)ret, size, MEMMAP_KERNEL_AND_MODULES,
true, false, false, false)) {
ret += 0x200000;
}
kernel_top = (uintptr_t)ret + size;
return ret;
}
bool multiboot1_load(char *config, char *cmdline) {
struct file_handle *kernel_file;
@ -63,7 +77,8 @@ bool multiboot1_load(char *config, char *cmdline) {
panic(true, "multiboot1: Header checksum is invalid");
uint32_t entry_point;
uint32_t kernel_top;
struct elf_section_hdr_info *section_hdr_info = NULL;
if (header.flags & (1 << 16)) {
if (header.load_addr > header.header_addr)
@ -99,6 +114,16 @@ bool multiboot1_load(char *config, char *cmdline) {
} else {
int bits = elf_bits(kernel);
switch (bits) {
case 32:
section_hdr_info = elf32_section_hdr_info(kernel);
break;
case 64: {
section_hdr_info = elf64_section_hdr_info(kernel);
break;
}
}
switch (bits) {
case 32:
if (elf32_load(kernel, &entry_point, &kernel_top, MEMMAP_KERNEL_AND_MODULES))
@ -118,6 +143,33 @@ bool multiboot1_load(char *config, char *cmdline) {
}
}
if (section_hdr_info != NULL) {
multiboot1_info->elf_sect.num = section_hdr_info->num;
multiboot1_info->elf_sect.size = section_hdr_info->section_entry_size;
multiboot1_info->elf_sect.shndx = section_hdr_info->str_section_idx;
void *sections = conv_mem_alloc(section_hdr_info->section_entry_size * section_hdr_info->num);
multiboot1_info->elf_sect.addr = (uintptr_t)sections;
memcpy(sections, kernel + section_hdr_info->section_offset, section_hdr_info->section_entry_size * section_hdr_info->num);
for (size_t i = 0; i < section_hdr_info->num; i++) {
struct elf64_shdr *shdr = (void *)sections + section_hdr_info->section_offset + i * section_hdr_info->section_entry_size;
if (shdr->sh_addr != 0 || shdr->sh_size == 0) {
continue;
}
void *section = mb1_alloc(shdr->sh_size);
memcpy(section, kernel + shdr->sh_offset, shdr->sh_size);
shdr->sh_addr = (uintptr_t)section;
}
multiboot1_info->flags |= (1 << 5);
}
uint32_t n_modules;
for (n_modules = 0; ; n_modules++) {
@ -152,12 +204,8 @@ bool multiboot1_load(char *config, char *cmdline) {
char *lowmem_modstr = conv_mem_alloc(strlen(module_cmdline) + 1);
strcpy(lowmem_modstr, module_cmdline);
void *module_addr = (void *)(uintptr_t)ALIGN_UP(kernel_top, 4096);
while (!memmap_alloc_range((uintptr_t)module_addr, f->size, MEMMAP_KERNEL_AND_MODULES,
true, false, false, false)) {
module_addr += 0x200000;
}
kernel_top = (uintptr_t)module_addr + f->size;
void *module_addr = mb1_alloc(f->size);
fread(f, module_addr, 0, f->size);
m->begin = (uint32_t)(size_t)module_addr;