misc: Bring mb2 up to par to mb1 wrt everywhere ranges and bug fixes
This commit is contained in:
parent
19287d5ca1
commit
215bf87993
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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 */
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue