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 #include #include +#include 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 f6c2f3e7..bd75a9c4 100644 --- a/common/protos/limine.c +++ b/common/protos/limine.c @@ -286,7 +286,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 +#include +#if bios == 1 +# include +#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 +#include 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 -#include -#include -#include -#include -#if bios == 1 -# include -#endif -#include - -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 #include -#include -#include #include +#include +#include #include #include #include @@ -20,10 +20,6 @@ #include #include -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 -#include -#include -#include -#include -#if bios == 1 -# include -#endif -#include - -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 #include #include +#include +#include #include #include #include @@ -10,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -20,8 +22,6 @@ #include #include -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 */ - shdr->sh_addr = (uintptr_t)section; + elsewhere_append(true /* flexible target */, + ranges, &ranges_count, + kernel + shdr->sh_offset, §ion, shdr->sh_size); + + 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 #include -#include 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