multiboot1: Properly support relocation for a.out kludge kernels and bug fixes
This commit is contained in:
parent
fba565b34e
commit
d7d0a84462
|
@ -86,39 +86,63 @@ bool multiboot1_load(char *config, char *cmdline) {
|
||||||
struct elf_section_hdr_info *section_hdr_info = NULL;
|
struct elf_section_hdr_info *section_hdr_info = NULL;
|
||||||
|
|
||||||
struct elf_range *elf_ranges;
|
struct elf_range *elf_ranges;
|
||||||
uint64_t elf_ranges_count, slide;
|
uint64_t elf_ranges_count, slide = 0;
|
||||||
|
|
||||||
if (header.flags & (1 << 16)) {
|
if (header.flags & (1 << 16)) {
|
||||||
if (header.load_addr > header.header_addr)
|
if (header.load_addr > header.header_addr)
|
||||||
panic(true, "multiboot1: Illegal load address");
|
panic(true, "multiboot1: Illegal load address");
|
||||||
|
|
||||||
size_t load_size = 0;
|
size_t load_size;
|
||||||
|
|
||||||
if (header.load_end_addr)
|
if (header.load_end_addr)
|
||||||
load_size = header.load_end_addr - header.load_addr;
|
load_size = header.load_end_addr - header.load_addr;
|
||||||
else
|
else
|
||||||
load_size = kernel_file_size;
|
load_size = kernel_file_size;
|
||||||
|
|
||||||
memmap_alloc_range(header.load_addr, load_size, MEMMAP_KERNEL_AND_MODULES, true, true, false, false);
|
uint32_t bss_size = 0;
|
||||||
memcpy((void *)(uintptr_t)header.load_addr, kernel + (header_offset
|
|
||||||
- (header.header_addr - header.load_addr)), load_size);
|
|
||||||
|
|
||||||
kernel_top = header.load_addr + load_size;
|
|
||||||
|
|
||||||
if (header.bss_end_addr) {
|
if (header.bss_end_addr) {
|
||||||
uintptr_t bss_addr = header.load_addr + load_size;
|
uintptr_t bss_addr = header.load_addr + load_size;
|
||||||
if (header.bss_end_addr < bss_addr)
|
if (header.bss_end_addr < bss_addr)
|
||||||
panic(true, "multiboot1: Illegal bss end address");
|
panic(true, "multiboot1: Illegal bss end address");
|
||||||
|
|
||||||
uint32_t bss_size = header.bss_end_addr - bss_addr;
|
bss_size = header.bss_end_addr - bss_addr;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry_point = header.entry_addr;
|
size_t full_size = load_size + bss_size;
|
||||||
|
|
||||||
|
bool simulation = true;
|
||||||
|
size_t try_count = 0;
|
||||||
|
size_t max_simulated_tries = 0x100000;
|
||||||
|
|
||||||
|
retry_raw_load:;
|
||||||
|
uint64_t load_addr = header.load_addr + slide;
|
||||||
|
|
||||||
|
if (!memmap_alloc_range(load_addr, full_size, MEMMAP_BOOTLOADER_RECLAIMABLE, true, false, simulation, false)) {
|
||||||
|
if (simulation == false || ++try_count == max_simulated_tries) {
|
||||||
|
panic(true, "multiboot1: Failed to allocate necessary memory range (%X-%X)", load_addr, load_addr + full_size);
|
||||||
|
}
|
||||||
|
slide += 0x1000;
|
||||||
|
goto retry_raw_load;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simulation) {
|
||||||
|
simulation = false;
|
||||||
|
goto retry_raw_load;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((void *)(uintptr_t)load_addr, 0, full_size);
|
||||||
|
|
||||||
|
memcpy((void *)(uintptr_t)load_addr, kernel + (header_offset
|
||||||
|
- (header.header_addr - header.load_addr)), load_size);
|
||||||
|
|
||||||
|
kernel_top = load_addr + full_size;
|
||||||
|
|
||||||
|
entry_point = header.entry_addr + slide;
|
||||||
|
|
||||||
|
elf_ranges_count = 1;
|
||||||
|
elf_ranges = ext_mem_alloc(sizeof(struct elf_range));
|
||||||
|
|
||||||
|
elf_ranges->base = load_addr;
|
||||||
|
elf_ranges->length = full_size;
|
||||||
} else {
|
} else {
|
||||||
int bits = elf_bits(kernel);
|
int bits = elf_bits(kernel);
|
||||||
|
|
||||||
|
@ -136,19 +160,14 @@ bool multiboot1_load(char *config, char *cmdline) {
|
||||||
case 32:
|
case 32:
|
||||||
if (elf32_load(kernel, &entry_point, &kernel_top, MEMMAP_BOOTLOADER_RECLAIMABLE, &slide, &elf_ranges, &elf_ranges_count))
|
if (elf32_load(kernel, &entry_point, &kernel_top, MEMMAP_BOOTLOADER_RECLAIMABLE, &slide, &elf_ranges, &elf_ranges_count))
|
||||||
panic(true, "multiboot1: ELF32 load failure");
|
panic(true, "multiboot1: ELF32 load failure");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 64: {
|
case 64: {
|
||||||
uint64_t e, t;
|
uint64_t e, t;
|
||||||
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(kernel, &e, &t, &slide, MEMMAP_BOOTLOADER_RECLAIMABLE, false, true, &elf_ranges, &elf_ranges_count, false, NULL, NULL, NULL, NULL))
|
||||||
panic(true, "multiboot1: ELF64 load failure");
|
panic(true, "multiboot1: ELF64 load failure");
|
||||||
entry_point = e - slide;
|
entry_point = e;
|
||||||
|
kernel_top = t;
|
||||||
t -= slide;
|
|
||||||
if (t < 0x100000) {
|
|
||||||
kernel_top = 0x100000;
|
|
||||||
} else {
|
|
||||||
kernel_top = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -157,6 +176,13 @@ bool multiboot1_load(char *config, char *cmdline) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entry_point -= slide;
|
||||||
|
|
||||||
|
kernel_top -= slide;
|
||||||
|
if (kernel_top < 0x100000) {
|
||||||
|
kernel_top = 0x100000;
|
||||||
|
}
|
||||||
|
|
||||||
// GRUB allocates boot info at 0x10000, *except* if the kernel happens
|
// GRUB allocates boot info at 0x10000, *except* if the kernel happens
|
||||||
// to overlap this region, then it gets moved to right after the
|
// to overlap this region, then it gets moved to right after the
|
||||||
// kernel, or whichever PHDR happens to sit at 0x10000.
|
// kernel, or whichever PHDR happens to sit at 0x10000.
|
||||||
|
|
Loading…
Reference in New Issue