mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:27:35 +00:00
Prekernel: Support kernel preloaded at high address
Loaders try to put modules as low as reasonable but on EFI often "reasonable" is much higher than on BIOS. As a result target can be easily higher than source. Then we have 2 problems: * memmove compares virtual address and since target is mapped higher it ends up going backwards which is wrong if target is physically below source * order of copying of sections must be inverted if target is below source
This commit is contained in:
parent
982ce17927
commit
d13609a607
1 changed files with 23 additions and 3 deletions
|
@ -74,6 +74,22 @@ extern "C" [[noreturn]] void init();
|
||||||
|
|
||||||
u64 generate_secure_seed();
|
u64 generate_secure_seed();
|
||||||
|
|
||||||
|
static void memmove_virt(void* dest_virt, FlatPtr dest_phys, void* src, size_t n)
|
||||||
|
{
|
||||||
|
if (dest_phys < (FlatPtr)src) {
|
||||||
|
u8* pd = (u8*)dest_virt;
|
||||||
|
u8 const* ps = (u8 const*)src;
|
||||||
|
for (; n--;)
|
||||||
|
*pd++ = *ps++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* pd = (u8*)dest_virt;
|
||||||
|
u8 const* ps = (u8 const*)src;
|
||||||
|
for (pd += n, ps += n; n--;)
|
||||||
|
*--pd = *--ps;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" [[noreturn]] void init()
|
extern "C" [[noreturn]] void init()
|
||||||
{
|
{
|
||||||
if (multiboot_info_ptr->mods_count < 1)
|
if (multiboot_info_ptr->mods_count < 1)
|
||||||
|
@ -154,11 +170,15 @@ extern "C" [[noreturn]] void init()
|
||||||
|
|
||||||
reload_cr3();
|
reload_cr3();
|
||||||
|
|
||||||
for (ssize_t i = kernel_elf_header.e_phnum - 1; i >= 0; i--) {
|
int backwards = kernel_physical_base >= (FlatPtr)kernel_image;
|
||||||
auto& kernel_program_header = kernel_program_headers[i];
|
|
||||||
|
for (ssize_t i = 0; i < kernel_elf_header.e_phnum; i++) {
|
||||||
|
auto& kernel_program_header = kernel_program_headers[backwards ? kernel_elf_header.e_phnum - 1 - i : i];
|
||||||
if (kernel_program_header.p_type != PT_LOAD)
|
if (kernel_program_header.p_type != PT_LOAD)
|
||||||
continue;
|
continue;
|
||||||
__builtin_memmove((u8*)kernel_load_base + kernel_program_header.p_vaddr, kernel_image + kernel_program_header.p_offset, kernel_program_header.p_filesz);
|
memmove_virt((u8*)kernel_load_base + kernel_program_header.p_vaddr,
|
||||||
|
kernel_physical_base + kernel_program_header.p_vaddr,
|
||||||
|
kernel_image + kernel_program_header.p_offset, kernel_program_header.p_filesz);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ssize_t i = kernel_elf_header.e_phnum - 1; i >= 0; i--) {
|
for (ssize_t i = kernel_elf_header.e_phnum - 1; i >= 0; i--) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue