misc: Bring mb2 up to par to mb1 wrt everywhere ranges and bug fixes
diff --git a/common/lib/elf.c b/common/lib/elf.c
index 6a76ddef..03948527 100644
--- a/common/lib/elf.c
+++ b/common/lib/elf.c
@@ -514,7 +514,6 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl
size_t max_simulated_tries = 0x100000;
uint64_t entry = hdr.entry;
- bool entry_adjusted = false;
uint64_t max_align = elf64_max_align(elf);
@@ -768,7 +767,7 @@ int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t *top, uint32_t allo
bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
struct elsewhere_range **ranges,
- size_t *ranges_count) {
+ uint64_t *ranges_count) {
struct elf32_hdr *hdr = (void *)elf;
if (strncmp((char *)hdr->ident, "\177ELF", 4)) {
@@ -786,7 +785,7 @@ bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
return false;
}
- *entry_point = hdr.entry;
+ *entry_point = hdr->entry;
bool entry_adjusted = false;
if (hdr->phdr_size < sizeof(struct elf32_phdr)) {
@@ -795,7 +794,7 @@ bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
*ranges_count = 0;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
- struct elf32_phdr *phdr = (void *)elf + (hdr.phoff + i * hdr.phdr_size);
+ struct elf32_phdr *phdr = (void *)elf + (hdr->phoff + i * hdr->phdr_size);
if (phdr->p_type != PT_LOAD)
continue;
@@ -808,31 +807,31 @@ bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
size_t cur_entry = 0;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
- struct elf32_phdr *phdr = (void *)elf + (hdr.phoff + i * hdr.phdr_size);
+ struct elf32_phdr *phdr = (void *)elf + (hdr->phoff + i * hdr->phdr_size);
if (phdr->p_type != PT_LOAD)
continue;
// Sanity checks
- if (phdr->p_filesz > phdr.p_memsz) {
+ if (phdr->p_filesz > phdr->p_memsz) {
panic(true, "elf: p_filesz > p_memsz");
}
- void *elsewhere = ext_mem_alloc(phdr.p_memsz);
+ void *elsewhere = ext_mem_alloc(phdr->p_memsz);
- memcpy(elsewhere, elf + phdr.p_offset, phdr.p_filesz);
+ memcpy(elsewhere, elf + phdr->p_offset, phdr->p_filesz);
if (!entry_adjusted
- && *entry_point >= phdr.p_vaddr
- && *entry_point < (phdr.p_vaddr + phdr.p_memsz)) {
- *entry_point -= phdr.p_vaddr;
- *entry_point += phdr.p_paddr;
+ && *entry_point >= phdr->p_vaddr
+ && *entry_point < (phdr->p_vaddr + phdr->p_memsz)) {
+ *entry_point -= phdr->p_vaddr;
+ *entry_point += phdr->p_paddr;
entry_adjusted = true;
}
- *entry[cur_entry].elsewhere = elsewhere;
- *entry[cur_entry].target = phdr.p_paddr;
- *entry[cur_entry].length = phdr.p_memsz;
+ (*ranges[cur_entry]).elsewhere = (uintptr_t)elsewhere;
+ (*ranges[cur_entry]).target = phdr->p_paddr;
+ (*ranges[cur_entry]).length = phdr->p_memsz;
cur_entry++;
}
@@ -842,7 +841,7 @@ bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
bool elf64_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
struct elsewhere_range **ranges,
- size_t *ranges_count) {
+ uint64_t *ranges_count) {
struct elf64_hdr *hdr = (void *)elf;
if (strncmp((char *)hdr->ident, "\177ELF", 4)) {
@@ -860,7 +859,7 @@ bool elf64_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
return false;
}
- *entry_point = hdr.entry;
+ *entry_point = hdr->entry;
bool entry_adjusted = false;
if (hdr->phdr_size < sizeof(struct elf64_phdr)) {
@@ -869,7 +868,7 @@ bool elf64_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
*ranges_count = 0;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
- struct elf64_phdr *phdr = (void *)elf + (hdr.phoff + i * hdr.phdr_size);
+ struct elf64_phdr *phdr = (void *)elf + (hdr->phoff + i * hdr->phdr_size);
if (phdr->p_type != PT_LOAD)
continue;
@@ -882,31 +881,31 @@ bool elf64_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
size_t cur_entry = 0;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
- struct elf64_phdr *phdr = (void *)elf + (hdr.phoff + i * hdr.phdr_size);
+ struct elf64_phdr *phdr = (void *)elf + (hdr->phoff + i * hdr->phdr_size);
if (phdr->p_type != PT_LOAD)
continue;
// Sanity checks
- if (phdr->p_filesz > phdr.p_memsz) {
+ if (phdr->p_filesz > phdr->p_memsz) {
panic(true, "elf: p_filesz > p_memsz");
}
- void *elsewhere = ext_mem_alloc(phdr.p_memsz);
+ void *elsewhere = ext_mem_alloc(phdr->p_memsz);
- memcpy(elsewhere, elf + phdr.p_offset, phdr.p_filesz);
+ memcpy(elsewhere, elf + phdr->p_offset, phdr->p_filesz);
if (!entry_adjusted
- && *entry_point >= phdr.p_vaddr
- && *entry_point < (phdr.p_vaddr + phdr.p_memsz)) {
- *entry_point -= phdr.p_vaddr;
- *entry_point += phdr.p_paddr;
+ && *entry_point >= phdr->p_vaddr
+ && *entry_point < (phdr->p_vaddr + phdr->p_memsz)) {
+ *entry_point -= phdr->p_vaddr;
+ *entry_point += phdr->p_paddr;
entry_adjusted = true;
}
- *entry[cur_entry].elsewhere = elsewhere;
- *entry[cur_entry].target = phdr.p_paddr;
- *entry[cur_entry].length = phdr.p_memsz;
+ (*ranges[cur_entry]).elsewhere = (uintptr_t)elsewhere;
+ (*ranges[cur_entry]).target = phdr->p_paddr;
+ (*ranges[cur_entry]).length = phdr->p_memsz;
cur_entry++;
}
diff --git a/common/lib/elf.h b/common/lib/elf.h
index 93855568..d611de20 100644
--- a/common/lib/elf.h
+++ b/common/lib/elf.h
@@ -36,10 +36,10 @@ struct elf_section_hdr_info* elf32_section_hdr_info(uint8_t *elf);
bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
struct elsewhere_range **ranges,
- size_t *ranges_count);
+ uint64_t *ranges_count);
bool elf64_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
struct elsewhere_range **ranges,
- size_t *ranges_count);
+ uint64_t *ranges_count);
struct elf64_hdr {
uint8_t ident[16];
diff --git a/common/lib/elsewhere.c b/common/lib/elsewhere.c
index 50babe05..8b2509ab 100644
--- a/common/lib/elsewhere.c
+++ b/common/lib/elsewhere.c
@@ -3,6 +3,7 @@
#include <stdbool.h>
#include <lib/elsewhere.h>
#include <lib/blib.h>
+#include <mm/pmm.h>
static bool elsewhere_overlap_check(uint64_t base1, uint64_t top1,
uint64_t base2, uint64_t top2) {
@@ -12,7 +13,7 @@ static bool elsewhere_overlap_check(uint64_t base1, uint64_t top1,
bool elsewhere_append(
bool flexible_target,
- struct elsewhere_range *ranges, size_t *ranges_count,
+ struct elsewhere_range *ranges, uint64_t *ranges_count,
void *elsewhere, uint64_t *target, size_t t_length) {
// original target of -1 means "allocate after top of all ranges"
// flexible target is ignored
@@ -80,7 +81,7 @@ retry:
}
// Add the elsewhere range
- ranges[*ranges_count].elsewhere = elsewhere;
+ ranges[*ranges_count].elsewhere = (uintptr_t)elsewhere;
ranges[*ranges_count].target = *target;
ranges[*ranges_count].length = t_length;
*ranges_count += 1;
diff --git a/common/lib/elsewhere.h b/common/lib/elsewhere.h
index 575d8e1e..c61f1bfb 100644
--- a/common/lib/elsewhere.h
+++ b/common/lib/elsewhere.h
@@ -13,7 +13,7 @@ struct elsewhere_range {
bool elsewhere_append(
bool flexible_target,
- struct elsewhere_range *ranges, size_t *ranges_count,
+ struct elsewhere_range *ranges, uint64_t *ranges_count,
void *elsewhere, uint64_t *target, size_t t_length);
#endif
diff --git a/common/protos/limine.c b/common/protos/limine.c
index b66d614c..8f1f9e14 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -162,7 +162,7 @@ bool limine_load(char *config, char *cmdline) {
bool is_reloc;
if (elf64_load(kernel, &entry_point, NULL, &slide,
- MEMMAP_KERNEL_AND_MODULES, kaslr, false,
+ MEMMAP_KERNEL_AND_MODULES, kaslr,
&ranges, &ranges_count,
true, &physical_base, &virtual_base, &image_size,
&is_reloc)) {
diff --git a/common/protos/multiboot.32.c b/common/protos/multiboot.32.c
new file mode 100644
index 00000000..c5f8b9f1
--- /dev/null
+++ b/common/protos/multiboot.32.c
@@ -0,0 +1,36 @@
+#include <stdint.h>
+#include <stdnoreturn.h>
+#if bios == 1
+# include <sys/idt.h>
+#endif
+
+noreturn void multiboot_spinup_32(
+ uint32_t reloc_stub,
+ uint32_t magic, uint32_t protocol_info,
+ uint32_t entry_point,
+ uint32_t elf_ranges, uint32_t elf_ranges_count) {
+#if bios == 1
+ struct idtr idtr;
+
+ idtr.limit = 0x3ff;
+ idtr.ptr = 0;
+
+ asm volatile (
+ "lidt %0"
+ :
+ : "m" (idtr)
+ : "memory"
+ );
+#endif
+
+ asm volatile (
+ "jmp *%%ebx"
+ :
+ : "b"(reloc_stub), "S"(magic),
+ "a"(elf_ranges), "d"(elf_ranges_count),
+ "D"(protocol_info), "c"(entry_point)
+ : "memory"
+ );
+
+ __builtin_unreachable();
+}
diff --git a/common/protos/multiboot.h b/common/protos/multiboot.h
index d1aaeff6..b2683c83 100644
--- a/common/protos/multiboot.h
+++ b/common/protos/multiboot.h
@@ -2,6 +2,7 @@
#define __PROTOS__MULTIBOOT_H__
#include <stdint.h>
+#include <lib/blib.h>
struct mb_reloc_stub {
char jmp[4];
@@ -10,4 +11,7 @@ struct mb_reloc_stub {
uint32_t mb_info_target;
};
+extern symbol multiboot_spinup_32;
+extern symbol multiboot_reloc_stub, multiboot_reloc_stub_end;
+
#endif
diff --git a/common/protos/multiboot1.32.c b/common/protos/multiboot1.32.c
deleted file mode 100644
index b67eb3b0..00000000
--- a/common/protos/multiboot1.32.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <stdnoreturn.h>
-#include <mm/vmm.h>
-#if bios == 1
-# include <sys/idt.h>
-#endif
-#include <protos/multiboot.h>
-
-noreturn void multiboot1_spinup_32(uint32_t entry_point,
- uint32_t multiboot1_info, uint32_t mb_info_target,
- uint32_t mb_info_size,
- uint32_t elf_ranges, uint32_t elf_ranges_count,
- uint32_t slide,
- struct mb_reloc_stub *reloc_stub) {
-#if bios == 1
- struct idtr idtr;
-
- idtr.limit = 0x3ff;
- idtr.ptr = 0;
-
- asm volatile (
- "lidt %0"
- :
- : "m" (idtr)
- : "memory"
- );
-#endif
-
- reloc_stub->magic = 0x2badb002;
- reloc_stub->entry_point = entry_point;
- reloc_stub->mb_info_target = mb_info_target;
-
- asm volatile (
- "jmp *%%ebx"
- :
- : "b"(reloc_stub), "S"(multiboot1_info),
- "c"(mb_info_size), "a"(elf_ranges), "d"(elf_ranges_count),
- "D"(slide)
- : "memory"
- );
-
- __builtin_unreachable();
-}
diff --git a/common/protos/multiboot1.c b/common/protos/multiboot1.c
index b8c2a737..853e375d 100644
--- a/common/protos/multiboot1.c
+++ b/common/protos/multiboot1.c
@@ -1,8 +1,8 @@
#include <stdint.h>
#include <stddef.h>
-#include <stdnoreturn.h>
-#include <config.h>
#include <protos/multiboot1.h>
+#include <protos/multiboot.h>
+#include <config.h>
#include <lib/libc.h>
#include <lib/elf.h>
#include <lib/blib.h>
@@ -20,10 +20,6 @@
#include <mm/pmm.h>
#include <drivers/vga_textmode.h>
-extern symbol multiboot_reloc_stub, multiboot_reloc_stub_end;
-
-noreturn void multiboot1_spinup_32(uint32_t entry_point, uint32_t multiboot1_info);
-
#define LIMINE_BRAND "Limine " LIMINE_VERSION
// Returns the size required to store the multiboot info.
@@ -122,7 +118,7 @@ bool multiboot1_load(char *config, char *cmdline) {
ranges_count = 1;
ranges = ext_mem_alloc(sizeof(struct elsewhere_range));
- ranges->elsewhere = elsewhere;
+ ranges->elsewhere = (uintptr_t)elsewhere;
ranges->target = header.load_addr;
ranges->length = full_size;
} else {
@@ -171,8 +167,8 @@ bool multiboot1_load(char *config, char *cmdline) {
struct elsewhere_range *new_ranges = ext_mem_alloc(sizeof(struct elsewhere_range) *
(ranges_count
+ 1 /* mb1 info range */
- + n_modules,
- + section_hdr_info ? section_hdr_info->num : 0));
+ + n_modules
+ + (section_hdr_info ? section_hdr_info->num : 0)));
memcpy(new_ranges, ranges, sizeof(struct elsewhere_range) * ranges_count);
pmm_free(ranges, sizeof(struct elsewhere_range) * ranges_count);
@@ -256,7 +252,7 @@ bool multiboot1_load(char *config, char *cmdline) {
char *lowmem_modstr = mb1_info_alloc(&mb1_info_raw, strlen(module_cmdline) + 1);
strcpy(lowmem_modstr, module_cmdline);
- void *module_addr = freadall(f);
+ void *module_addr = freadall(f, MEMMAP_BOOTLOADER_RECLAIMABLE);
uint64_t module_target = (uint64_t)-1; /* no target preference, use top */
elsewhere_append(true /* flexible target */,
@@ -390,7 +386,8 @@ nofb:;
irq_flush_type = IRQ_PIC_ONLY_FLUSH;
- common_spinup(multiboot_spinup_32, 4,
- 0x2badb002, entry_point,
+ common_spinup(multiboot_spinup_32, 6,
+ (uint32_t)(uintptr_t)reloc_stub, (uint32_t)0x2badb002,
+ (uint32_t)mb1_info_final_loc, (uint32_t)entry_point,
(uint32_t)(uintptr_t)ranges, (uint32_t)ranges_count);
}
diff --git a/common/protos/multiboot2.32.c b/common/protos/multiboot2.32.c
deleted file mode 100644
index c73ee8b4..00000000
--- a/common/protos/multiboot2.32.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <stdnoreturn.h>
-#include <mm/vmm.h>
-#if bios == 1
-# include <sys/idt.h>
-#endif
-#include <protos/multiboot.h>
-
-noreturn void multiboot2_spinup_32(uint32_t entry_point,
- uint32_t multiboot2_info, uint32_t mb_info_target,
- uint32_t mb_info_size,
- uint32_t elf_ranges, uint32_t elf_ranges_count,
- uint32_t slide,
- struct mb_reloc_stub *reloc_stub) {
-#if bios == 1
- struct idtr idtr;
-
- idtr.limit = 0x3ff;
- idtr.ptr = 0;
-
- asm volatile (
- "lidt %0"
- :
- : "m" (idtr)
- : "memory"
- );
-#endif
-
- reloc_stub->magic = 0x36d76289;
- reloc_stub->entry_point = entry_point;
- reloc_stub->mb_info_target = mb_info_target;
-
- asm volatile (
- "jmp *%%ebx"
- :
- : "b"(reloc_stub), "S"(multiboot2_info),
- "c"(mb_info_size), "a"(elf_ranges), "d"(elf_ranges_count),
- "D"(slide)
- : "memory"
- );
-
- __builtin_unreachable();
-}
diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c
index 9d8e232e..d82aa009 100644
--- a/common/protos/multiboot2.c
+++ b/common/protos/multiboot2.c
@@ -1,6 +1,7 @@
-#include <protos/multiboot2.h>
#include <stdint.h>
#include <stddef.h>
+#include <protos/multiboot2.h>
+#include <protos/multiboot.h>
#include <config.h>
#include <lib/libc.h>
#include <lib/elf.h>
@@ -10,6 +11,7 @@
#include <lib/uri.h>
#include <lib/fb.h>
#include <lib/term.h>
+#include <lib/elsewhere.h>
#include <sys/pic.h>
#include <sys/cpu.h>
#include <sys/idt.h>
@@ -20,8 +22,6 @@
#include <lib/blib.h>
#include <drivers/vga_textmode.h>
-extern symbol multiboot_reloc_stub, multiboot_reloc_stub_end;
-
#define LIMINE_BRAND "Limine " LIMINE_VERSION
/// Returns the size required to store the multiboot2 info.
@@ -57,26 +57,6 @@ 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 bool mb2_overlap_check(uint64_t base1, uint64_t top1,
- uint64_t base2, uint64_t top2) {
- return ((base1 >= base2 && base1 < top2)
- || (top1 > base2 && top1 <= top2));
-}
-
-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;
@@ -122,7 +102,7 @@ bool multiboot2_load(char *config, char* cmdline) {
bool is_elf_info_requested = false;
- uint32_t entry_point = 0xffffffff;
+ uint64_t entry_point = 0xffffffff;
// Iterate through the entries...
for (struct multiboot_header_tag *tag = (struct multiboot_header_tag*)(header + 1); // header + 1 to skip the header struct.
@@ -197,8 +177,8 @@ bool multiboot2_load(char *config, char* cmdline) {
}
}
- struct elf_range *elf_ranges;
- uint64_t elf_ranges_count, slide;
+ struct elsewhere_range *ranges;
+ uint64_t ranges_count;
if (addresstag != NULL) {
if (addresstag->load_addr > addresstag->header_addr)
@@ -217,7 +197,7 @@ bool multiboot2_load(char *config, char* cmdline) {
memcpy((void *)(uintptr_t)addresstag->load_addr, kernel + (header_offset
- (addresstag->header_addr - addresstag->load_addr)), load_size);
- kernel_top = addresstag->load_addr + load_size;
+ //kernel_top = addresstag->load_addr + load_size;
if (addresstag->bss_end_addr) {
uintptr_t bss_addr = addresstag->load_addr + load_size;
@@ -229,20 +209,20 @@ bool multiboot2_load(char *config, char* cmdline) {
memmap_alloc_range(bss_addr, bss_size, MEMMAP_KERNEL_AND_MODULES, true, true, false, false);
memset((void *)bss_addr, 0, bss_size);
- kernel_top = bss_addr + bss_size;
+ //kernel_top = bss_addr + bss_size;
}
} else {
+ uint64_t e;
int bits = elf_bits(kernel);
- uint64_t e = 0, t = 0;
switch (bits) {
case 32:
- if (elf32_load(kernel, (uint32_t *)&e, (uint32_t *)&t, MEMMAP_BOOTLOADER_RECLAIMABLE, &slide, &elf_ranges, &elf_ranges_count))
+ if (elf32_load_elsewhere(kernel, &e, &ranges, &ranges_count))
panic(true, "multiboot2: ELF32 load failure");
break;
case 64: {
- if (elf64_load(kernel, &e, &t, &slide, MEMMAP_BOOTLOADER_RECLAIMABLE, false, true, &elf_ranges, &elf_ranges_count, false, NULL, NULL, NULL, NULL))
+ if (elf64_load_elsewhere(kernel, &e, &ranges, &ranges_count))
panic(true, "multiboot2: ELF64 load failure");
break;
@@ -251,17 +231,9 @@ bool multiboot2_load(char *config, char* cmdline) {
panic(true, "multiboot2: Invalid ELF file bitness");
}
- e -= slide;
if (entry_point == 0xffffffff) {
entry_point = e;
}
-
- t -= slide;
- if (t < 0x100000) {
- kernel_top = 0x100000;
- } else {
- kernel_top = t;
- }
}
struct elf_section_hdr_info *section_hdr_info = NULL;
@@ -311,41 +283,30 @@ bool multiboot2_load(char *config, char* cmdline) {
size_t info_idx = 0;
+ // Realloc elsewhere ranges to include mb2 info, modules, and elf sections
+ struct elsewhere_range *new_ranges = ext_mem_alloc(sizeof(struct elsewhere_range) *
+ (ranges_count
+ + 1 /* mb2 info range */
+ + n_modules
+ + (section_hdr_info ? section_hdr_info->num : 0)));
+
+ memcpy(new_ranges, ranges, sizeof(struct elsewhere_range) * ranges_count);
+ pmm_free(ranges, sizeof(struct elsewhere_range) * ranges_count);
+ ranges = new_ranges;
+
// GRUB allocates boot info at 0x10000, *except* if the kernel happens
// to overlap this region, then it gets moved to right after the
// kernel, or whichever PHDR happens to sit at 0x10000.
// Allocate it wherever, then move it to where GRUB puts it
// afterwards.
+
+ // Elsewhere append mb2 info *after* kernel but *before* modules.
uint8_t *mb2_info = ext_mem_alloc(mb2_info_size);
uint64_t mb2_info_final_loc = 0x10000;
-retry_mb2_info_reloc:
- for (size_t i = 0; i < elf_ranges_count; i++) {
- uint64_t mb2_info_top = mb2_info_final_loc + mb2_info_size;
-
- uint64_t base = elf_ranges[i].base - slide;
- uint64_t length = elf_ranges[i].length - slide;
- uint64_t top = base + length;
-
- // Do they overlap?
- if (mb2_overlap_check(base, top, mb2_info_final_loc, mb2_info_top)) {
- mb2_info_final_loc = top;
- goto retry_mb2_info_reloc;
- }
- // Make sure it is memory that actually exists.
- if (!memmap_alloc_range(mb2_info_final_loc, mb2_info_size, MEMMAP_BOOTLOADER_RECLAIMABLE,
- MEMMAP_USABLE, false, true, false)) {
- if (!memmap_alloc_range(mb2_info_final_loc, mb2_info_size, MEMMAP_BOOTLOADER_RECLAIMABLE,
- MEMMAP_BOOTLOADER_RECLAIMABLE, false, true, false)) {
- mb2_info_final_loc += 0x1000;
- goto retry_mb2_info_reloc;
- }
- }
- }
-
- if (mb2_info_final_loc + mb2_info_size > kernel_top) {
- kernel_top = mb2_info_final_loc + mb2_info_size;
- }
+ elsewhere_append(true /* flexible target */,
+ ranges, &ranges_count,
+ mb2_info, &mb2_info_final_loc, mb2_info_size);
struct multiboot2_start_tag *mbi_start = (struct multiboot2_start_tag *)mb2_info;
info_idx += sizeof(struct multiboot2_start_tag);
@@ -377,10 +338,13 @@ retry_mb2_info_reloc:
continue;
}
- void *section = mb2_alloc(shdr->sh_size);
- memcpy(section, kernel + shdr->sh_offset, shdr->sh_size);
+ uint64_t section = (uint64_t)-1; /* no target preference, use top */
+
+ elsewhere_append(true /* flexible target */,
+ ranges, &ranges_count,
+ kernel + shdr->sh_offset, §ion, shdr->sh_size);
- shdr->sh_addr = (uintptr_t)section;
+ shdr->sh_addr = section;
}
append_tag(info_idx, tag);
@@ -406,15 +370,18 @@ retry_mb2_info_reloc:
char *module_cmdline = conf_tuple.value2;
if (!module_cmdline) module_cmdline = "";
- void *module_addr = mb2_alloc(f->size);
+ void *module_addr = freadall(f, MEMMAP_BOOTLOADER_RECLAIMABLE);
+ uint64_t module_target = (uint64_t)-1;
- fread(f, module_addr, 0, f->size);
+ elsewhere_append(true /* flexible target */,
+ ranges, &ranges_count,
+ module_addr, &module_target, f->size);
struct multiboot_tag_module *module_tag = (struct multiboot_tag_module *)(mb2_info + info_idx);
module_tag->type = MULTIBOOT_TAG_TYPE_MODULE;
module_tag->size = sizeof(struct multiboot_tag_module) + strlen(module_cmdline) + 1;
- module_tag->mod_start = (uint32_t)(size_t)module_addr;
+ module_tag->mod_start = module_target;
module_tag->mod_end = module_tag->mod_start + f->size;
strcpy(module_tag->cmdline, module_cmdline); // Copy over the command line
@@ -645,9 +612,9 @@ retry_mb2_info_reloc:
}
#endif
- // Load relocation stub where it won't get overwritten
+ // Load relocation stub where it won't get overwritten (hopefully)
size_t reloc_stub_size = (size_t)multiboot_reloc_stub_end - (size_t)multiboot_reloc_stub;
- void *reloc_stub = mb2_alloc(reloc_stub_size);
+ void *reloc_stub = ext_mem_alloc(reloc_stub_size);
memcpy(reloc_stub, multiboot_reloc_stub, reloc_stub_size);
#if uefi == 1
@@ -743,11 +710,8 @@ retry_mb2_info_reloc:
irq_flush_type = IRQ_PIC_ONLY_FLUSH;
- common_spinup(multiboot2_spinup_32, 8,
- entry_point,
- (uint32_t)(uintptr_t)mb2_info, (uint32_t)mb2_info_final_loc,
- (uint32_t)mb2_info_size,
- (uint32_t)(uintptr_t)elf_ranges, (uint32_t)elf_ranges_count,
- (uint32_t)slide,
- (uint32_t)(uintptr_t)reloc_stub);
+ common_spinup(multiboot_spinup_32, 6,
+ (uint32_t)(uintptr_t)reloc_stub, (uint32_t)0x36d76289,
+ (uint32_t)mb2_info_final_loc, (uint32_t)entry_point,
+ (uint32_t)(uintptr_t)ranges, (uint32_t)ranges_count);
}
diff --git a/common/protos/multiboot2.h b/common/protos/multiboot2.h
index 5be4108d..a0be2015 100644
--- a/common/protos/multiboot2.h
+++ b/common/protos/multiboot2.h
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <stdbool.h>
-#include <stdnoreturn.h>
bool multiboot2_load(char *config, char *cmdline);
@@ -416,6 +415,4 @@ struct multiboot_tag_load_base_addr
uint32_t load_base_addr;
};
-noreturn void multiboot2_spinup_32(uint32_t entry_point, uint32_t multiboot1_info);
-
#endif
diff --git a/common/protos/multiboot_reloc.asm_x86 b/common/protos/multiboot_reloc.asm_x86
index 821b9d83..6bb63107 100644
--- a/common/protos/multiboot_reloc.asm_x86
+++ b/common/protos/multiboot_reloc.asm_x86
@@ -8,44 +8,43 @@ multiboot_reloc_stub:
times 4-($-multiboot_reloc_stub) db 0
- .magic_value: dd 0
- .entry_point: dd 0
- .mb_info_target: dd 0
-
; EBX = self
- ; ESI = multiboot info (original)
- ; ECX = multiboot info (size)
-
- ; EAX = elf ranges
- ; EDX = elf ranges count
- ; EDI = slide
+ ; ESI = magic value
+ ; EDI = protocol info
+ ; ECX = entry point
+ ; EAX = ranges
+ ; EDX = ranges count
.code:
- mov ebp, edi
- mov edi, [ebx + (.mb_info_target - multiboot_reloc_stub)]
+ push edi
+ push esi
+ push ecx
- ; Copy multiboot info; frees ESI, EDI, and ECX
- rep movsb
+ .ranges_loop:
+ test edx, edx ; Loop until we're done
+ jz .ranges_loop_out
- .elf_ranges_loop:
- mov esi, [eax] ; ESI = elf_range.base
- mov edi, esi ; EDI = elf_range.base - slide
- sub edi, ebp
- mov ecx, [eax+8] ; ECX = elf_range.length
- rep movsb ; Copy range to target location
+ mov esi, [eax] ; ESI = range.elsewhere
+ mov edi, [eax+8] ; EDI = range.target
+ mov ecx, [eax+16] ; ECX = range.length
+ rep movsb ; Copy range to target location
- add eax, 24 ; Move to the next elf_range
+ add eax, 24 ; Move to the next range
- dec edx ; Loop until we're done
- jnz .elf_ranges_loop
+ dec edx
+ jmp .ranges_loop
+ .ranges_loop_out:
; We're done relocating!
+ pop ecx
+ pop esi
+ pop edi
- push dword [ebx + (.entry_point - multiboot_reloc_stub)]
+ push ecx
- mov eax, [ebx + (.magic_value - multiboot_reloc_stub)]
- mov ebx, [ebx + (.mb_info_target - multiboot_reloc_stub)]
+ mov eax, esi ; EAX = magic value
+ mov ebx, edi ; EBX = protocol info
xor ecx, ecx
xor edx, edx
xor esi, esi
