|
| 1 | +/* |
| 2 | + * PROJECT: FreeLoader |
| 3 | + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) |
| 4 | + * PURPOSE: Relocate freeldr to the expected address. |
| 5 | + * COPYRIGHT: Copyright 2024-2025 Daniel Victor <[email protected]> |
| 6 | + */ |
| 7 | + |
| 8 | +#include <asm.inc> |
| 9 | +#include <arch/pc/x86common.h> |
| 10 | + |
| 11 | +#ifdef _M_IX86 |
| 12 | +#define rax eax |
| 13 | +#define rsi esi |
| 14 | +#define rsp esp |
| 15 | +#define rdi edi |
| 16 | +#define rcx ecx |
| 17 | +#define qword dword |
| 18 | +#endif |
| 19 | + |
| 20 | +#ifdef _USE_ML |
| 21 | +EXTERN __bss_start__:DWORD |
| 22 | +EXTERN __bss_end__:DWORD |
| 23 | +#endif |
| 24 | + |
| 25 | +#ifdef _M_IX86 |
| 26 | +.code32 |
| 27 | +ASSUME ES:NOTHING, FS:NOTHING, GS:NOTHING |
| 28 | +#define PointerSize 4 |
| 29 | +#else |
| 30 | +.code64 |
| 31 | +#define PointerSize 8 |
| 32 | +#endif |
| 33 | + |
| 34 | +PUBLIC RelocateFreeldr |
| 35 | +RelocateFreeldr: |
| 36 | + /* Skip the entire relocation code if BSS_CurrentBaseAddress is same as FREELDR_BASE */ |
| 37 | + cmp qword ptr [BSS_CurrentBaseAddress], FREELDR_BASE |
| 38 | + jz .IsNotNtldr |
| 39 | + |
| 40 | +.FirstStep: |
| 41 | + /* Save the registers */ |
| 42 | + push rsi |
| 43 | + push rdi |
| 44 | + push rcx |
| 45 | + |
| 46 | + /* Relocate Freeldr to TEMPCODE_BASE */ |
| 47 | + mov rsi, qword ptr [BSS_CurrentBaseAddress] |
| 48 | + mov rdi, TEMPCODE_BASE |
| 49 | + mov rcx, offset __bss_start__ - FREELDR_BASE |
| 50 | + rep movsb |
| 51 | + |
| 52 | + /* Jump to the final step relocation */ |
| 53 | + mov rdi, offset .FinalStep + TEMPCODE_BASE - FREELDR_BASE |
| 54 | + push rdi |
| 55 | + ret |
| 56 | + |
| 57 | +.FinalStep: |
| 58 | + /* Relocate Freeldr back to FREELDR_BASE */ |
| 59 | + mov rsi, TEMPCODE_BASE |
| 60 | + mov rdi, FREELDR_BASE |
| 61 | + mov rcx, offset __bss_start__ - FREELDR_BASE |
| 62 | + |
| 63 | + /* Start the relocation */ |
| 64 | + rep movsb |
| 65 | + |
| 66 | + /* Restore the registers */ |
| 67 | + pop rcx |
| 68 | + pop rdi |
| 69 | + pop rsi |
| 70 | + |
| 71 | + /* Save source register */ |
| 72 | + push rsi |
| 73 | + |
| 74 | + /* Store the base address in the source register */ |
| 75 | + mov rsi, qword ptr [BSS_CurrentBaseAddress] |
| 76 | + |
| 77 | + /* Set the base address with FREELDR base address */ |
| 78 | + mov qword ptr [BSS_CurrentBaseAddress], FREELDR_BASE |
| 79 | + |
| 80 | + /* Subtract the return address from source register to get offset */ |
| 81 | + sub qword ptr [rsp + PointerSize], rsi |
| 82 | + |
| 83 | + /* Sum the return address with FREELDR base address */ |
| 84 | + add qword ptr [rsp + PointerSize], FREELDR_BASE |
| 85 | + |
| 86 | + /* Restore source register */ |
| 87 | + pop rsi |
| 88 | + |
| 89 | +.IsNotNtldr: |
| 90 | + /* Return to the relocated address */ |
| 91 | + ret |
| 92 | + |
| 93 | +END |
0 commit comments