multiboot2: Add mb2_alloc() for quirky allocation locations
diff --git a/common/lib/elf.c b/common/lib/elf.c
index f6f41919..ee487eb7 100644
--- a/common/lib/elf.c
+++ b/common/lib/elf.c
@@ -308,22 +308,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;
}
@@ -340,22 +325,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 98af704c..4c819770 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 744536e7..928e4775 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
