From 7f6ac2d13596fb30f1f0e289d4189d0d9dc374c1 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Sat, 18 Jun 2022 23:40:34 +0200 Subject: [PATCH] multiboot2: Add mb2_alloc() for quirky allocation locations --- common/lib/elf.c | 34 +--------------- common/lib/elf.h | 2 +- common/protos/multiboot2.c | 83 +++++++++++++++++++++++--------------- 3 files changed, 54 insertions(+), 65 deletions(-) diff --git a/common/lib/elf.c b/common/lib/elf.c index e5e6d8da..89f78067 100644 --- a/common/lib/elf.c +++ b/common/lib/elf.c @@ -313,22 +313,7 @@ struct elf_section_hdr_info* elf64_section_hdr_info(uint8_t *elf) { info->section_entry_size = hdr.shdr_size; info->section_hdr_size = info->num * info->section_entry_size; info->str_section_idx = hdr.shstrndx; - info->section_hdrs = ext_mem_alloc(info->section_hdr_size); - - memcpy(info->section_hdrs, elf + (hdr.shoff), info->section_hdr_size); - - for (size_t i = 0; i < info->num; i++) { - struct elf64_shdr *shdr = info->section_hdrs + i * hdr.shdr_size; - - if (shdr->sh_addr != 0 || shdr->sh_size == 0) { - continue; - } - - void *section = conv_mem_alloc(shdr->sh_size); - memcpy(section, elf + shdr->sh_offset, shdr->sh_size); - - shdr->sh_addr = (uintptr_t)section; - } + info->section_offset = hdr.shoff; return info; } @@ -345,22 +330,7 @@ struct elf_section_hdr_info* elf32_section_hdr_info(uint8_t *elf) { info->section_entry_size = hdr.shdr_size; info->section_hdr_size = info->num * info->section_entry_size; info->str_section_idx = hdr.shstrndx; - info->section_hdrs = ext_mem_alloc(info->section_hdr_size); - - memcpy(info->section_hdrs, elf + (hdr.shoff), info->section_hdr_size); - - for (size_t i = 0; i < info->num; i++) { - struct elf32_shdr *shdr = info->section_hdrs + i * hdr.shdr_size; - - if (shdr->sh_addr != 0 || shdr->sh_size == 0) { - continue; - } - - void *section = conv_mem_alloc(shdr->sh_size); - memcpy(section, elf + shdr->sh_offset, shdr->sh_size); - - shdr->sh_addr = (uintptr_t)section; - } + info->section_offset = hdr.shoff; return info; } diff --git a/common/lib/elf.h b/common/lib/elf.h index afd31a0c..fc099bdd 100644 --- a/common/lib/elf.h +++ b/common/lib/elf.h @@ -22,7 +22,7 @@ struct elf_section_hdr_info { uint32_t section_entry_size; uint32_t str_section_idx; uint32_t num; - void* section_hdrs; + uint32_t section_offset; }; int elf_bits(uint8_t *elf); diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c index c9d4fcbf..d4e7d3ea 100644 --- a/common/protos/multiboot2.c +++ b/common/protos/multiboot2.c @@ -55,6 +55,20 @@ static size_t get_multiboot2_info_size( #define append_tag(P, TAG) ({ (P) += ALIGN_UP((TAG)->size, MULTIBOOT_TAG_ALIGN); }) +static uint32_t kernel_top; + +static void *mb2_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 multiboot2_load(char *config, char* cmdline) { struct file_handle *kernel_file; @@ -175,8 +189,6 @@ bool multiboot2_load(char *config, char* cmdline) { } } - uint32_t kernel_top; - if (addresstag != NULL) { if (addresstag->load_addr > addresstag->header_addr) panic(true, "multiboot2: Illegal load address"); @@ -284,6 +296,42 @@ bool multiboot2_load(char *config, char* cmdline) { struct multiboot2_start_tag *mbi_start = (struct multiboot2_start_tag *)mb2_info; info_idx += sizeof(struct multiboot2_start_tag); + ////////////////////////////////////////////// + // Create ELF info tag + ////////////////////////////////////////////// + if (section_hdr_info == NULL) { + if (is_elf_info_requested) { + panic(true, "multiboot2: Cannot return ELF file information"); + } + } else { + uint32_t size = sizeof(struct multiboot_tag_elf_sections) + section_hdr_info->section_hdr_size; + struct multiboot_tag_elf_sections *tag = (struct multiboot_tag_elf_sections*)(mb2_info + info_idx); + + tag->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS; + tag->size = size; + + tag->num = section_hdr_info->num; + tag->entsize = section_hdr_info->section_entry_size; + tag->shndx = section_hdr_info->str_section_idx; + + memcpy(tag->sections, kernel + section_hdr_info->section_offset, section_hdr_info->section_hdr_size); + + for (size_t i = 0; i < section_hdr_info->num; i++) { + struct elf64_shdr *shdr = (void *)kernel + section_hdr_info->section_offset + i * section_hdr_info->section_entry_size; + + if (shdr->sh_addr != 0 || shdr->sh_size == 0) { + continue; + } + + void *section = mb2_alloc(shdr->sh_size); + memcpy(section, kernel + shdr->sh_offset, shdr->sh_size); + + shdr->sh_addr = (uintptr_t)section; + } + + append_tag(info_idx, tag); + } + ////////////////////////////////////////////// // Create modules tag ////////////////////////////////////////////// @@ -298,19 +346,14 @@ bool multiboot2_load(char *config, char* cmdline) { if ((f = uri_open(module_path)) == NULL) panic(true, "multiboot2: Failed to open module with path `%s`. Is the path correct?", module_path); - void *module_addr = (void *)(uintptr_t)ALIGN_UP(kernel_top, 4096); // Module commandline can be null, so we guard against that and make the // string "". char *module_cmdline = conf_tuple.value2; if (!module_cmdline) module_cmdline = ""; - while (!memmap_alloc_range((uintptr_t)module_addr, f->size, MEMMAP_KERNEL_AND_MODULES, - true, false, false, false)) { - module_addr += 0x200000; - } + void *module_addr = mb2_alloc(f->size); - kernel_top = (uintptr_t)module_addr + f->size; fread(f, module_addr, 0, f->size); struct multiboot_tag_module *module_tag = (struct multiboot_tag_module *)(mb2_info + info_idx); @@ -548,30 +591,6 @@ bool multiboot2_load(char *config, char* cmdline) { } #endif - ////////////////////////////////////////////// - // Create ELF info tag - ////////////////////////////////////////////// - { - if (section_hdr_info == NULL) { - if (is_elf_info_requested) { - panic(true, "multiboot2: Cannot return ELF file information"); - } - } else { - uint32_t size = sizeof(struct multiboot_tag_elf_sections) + section_hdr_info->section_hdr_size; - struct multiboot_tag_elf_sections *tag = (struct multiboot_tag_elf_sections*)(mb2_info + info_idx); - - tag->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS; - tag->size = size; - - tag->num = section_hdr_info->num; - tag->entsize = section_hdr_info->section_entry_size; - tag->shndx = section_hdr_info->str_section_idx; - - memcpy(tag->sections, section_hdr_info->section_hdrs, section_hdr_info->section_hdr_size); - append_tag(info_idx, tag); - } - } - #if uefi == 1 efi_exit_boot_services(); #endif