From 6117e0c29c7fef6dbcf648536af65258f25a52f5 Mon Sep 17 00:00:00 2001 From: David Karoly Date: Sun, 19 Dec 2021 12:17:58 +0100 Subject: [PATCH] boot/loader: relocate kernel to virtual address space on 32-bit architectures Change-Id: Ic86ca6874f358df8755a0c691cccb155d145e06c Reviewed-on: https://review.haiku-os.org/c/haiku/+/4675 Tested-by: Commit checker robot Reviewed-by: Fredrik Holmqvist --- headers/private/kernel/boot/elf.h | 3 +++ src/system/boot/loader/elf.cpp | 27 ++++++++++++++++++++++++- src/system/kernel/arch/arm/arch_elf.cpp | 8 +++++++- src/system/kernel/arch/x86/arch_elf.cpp | 8 +++++++- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index 97d15d59c4..ff87f5c1f1 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -90,6 +90,9 @@ extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image, Elf32_Sym* symbol, Elf32_Addr* symbolAddress); extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image, Elf64_Sym* symbol, Elf64_Addr* symbolAddress); +extern Elf32_Addr boot_elf32_get_relocation(Elf32_Addr resolveAddress); +extern void boot_elf32_set_relocation(Elf32_Addr resolveAddress, + Elf32_Addr finalAddress); extern void boot_elf64_set_relocation(Elf64_Addr resolveAddress, Elf64_Addr finalAddress); #endif diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 3117723513..3b5b8dac9a 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -86,13 +86,24 @@ struct ELF32Class { return status; *_mappedAddress = (void*)*_address; + + addr_t res; + platform_bootloader_address_to_kernel_address((void*)*_address, &res); + + *_address = res; + return B_OK; } static inline void* Map(AddrType address) { - return (void*)address; + void *result = NULL; + if (platform_kernel_address_to_bootloader_address(address, &result) != B_OK) { + panic("Couldn't convert address 0x%08x", (uint32_t)address); + } + + return result; } }; @@ -742,6 +753,20 @@ boot_elf_resolve_symbol(preloaded_elf32_image* image, Elf32_Sym* symbol, { return ELF32Loader::Resolve(image, symbol, symbolAddress); } + +Elf32_Addr +boot_elf32_get_relocation(Elf32_Addr resolveAddress) +{ + Elf32_Addr* src = (Elf32_Addr*)ELF32Class::Map(resolveAddress); + return *src; +} + +void +boot_elf32_set_relocation(Elf32_Addr resolveAddress, Elf32_Addr finalAddress) +{ + Elf32_Addr* dest = (Elf32_Addr*)ELF32Class::Map(resolveAddress); + *dest = finalAddress; +} #endif diff --git a/src/system/kernel/arch/arm/arch_elf.cpp b/src/system/kernel/arch/arm/arch_elf.cpp index e8d46b9494..7508a71b43 100644 --- a/src/system/kernel/arch/arm/arch_elf.cpp +++ b/src/system/kernel/arch/arm/arch_elf.cpp @@ -220,7 +220,11 @@ arch_elf_relocate_rel(struct elf_image_info *image, switch (ELF32_R_TYPE(rel[i].r_info)) { case R_ARM_ABS32: case R_ARM_RELATIVE: +#ifndef _BOOT_MODE A = *(addr_t *)(image->text_region.delta + rel[i].r_offset); +#else + A = boot_elf32_get_relocation(image->text_region.delta + rel[i].r_offset); +#endif TRACE(("A %p\n", (void *)A)); break; } @@ -252,8 +256,10 @@ arch_elf_relocate_rel(struct elf_image_info *image, rel[i].r_offset); return B_BAD_ADDRESS; } -#endif *resolveAddress = finalAddress; +#else + boot_elf32_set_relocation((Elf32_Addr)resolveAddress, finalAddress); +#endif TRACE(("-> offset %#lx = %#lx\n", (image->text_region.delta + rel[i].r_offset), finalAddress)); } diff --git a/src/system/kernel/arch/x86/arch_elf.cpp b/src/system/kernel/arch/x86/arch_elf.cpp index 7e991137d3..3e20a4aa21 100644 --- a/src/system/kernel/arch/x86/arch_elf.cpp +++ b/src/system/kernel/arch/x86/arch_elf.cpp @@ -113,7 +113,11 @@ arch_elf_relocate_rel(struct elf_image_info *image, case R_386_RELATIVE: case R_386_GOTOFF: case R_386_GOTPC: +#ifndef _BOOT_MODE A = *(uint32 *)(image->text_region.delta + rel[i].r_offset); +#else + A = boot_elf32_get_relocation(image->text_region.delta + rel[i].r_offset); +#endif TRACE(("A %p\n", (void *)A)); break; } @@ -159,8 +163,10 @@ arch_elf_relocate_rel(struct elf_image_info *image, rel[i].r_offset); return B_BAD_ADDRESS; } -#endif *resolveAddress = finalAddress; +#else + boot_elf32_set_relocation((Elf32_Addr)resolveAddress, finalAddress); +#endif TRACE(("-> offset %#lx (%#lx) = %#lx\n", (image->text_region.delta + rel[i].r_offset), rel[i].r_offset, finalAddress)); }