Skip to content

Commit b0ee40f

Browse files
committed
[FREELDR] Change base address and add/change some things (reactos#7530)
CORE-19882
1 parent afb96ac commit b0ee40f

File tree

8 files changed

+214
-11
lines changed

8 files changed

+214
-11
lines changed

boot/freeldr/freeldr/arch/amd64/entry.S

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <arch/pc/x86common.h>
55
#include <arch/pc/pcbios.h>
66

7+
EXTERN RelocateFreeldr:PROC
78
EXTERN BootMain:PROC
89
EXTERN cmdline:DWORD
910

@@ -28,6 +29,12 @@ RealEntryPoint:
2829

2930
//mov word ptr [HEX(b8000)], HEX(0e00) + '1'
3031

32+
/* Keep only the low 16 bits part of stack */
33+
and rsp, HEX(FFFF)
34+
35+
/* Relocate Freeldr if needed */
36+
call RelocateFreeldr
37+
3138
/* Setup long mode stack */
3239
mov rsp, qword ptr [stack64]
3340

@@ -214,7 +221,7 @@ SwitchToRealCompSegment:
214221
.byte HEX(0EA) // 32bit long jmp
215222
AddressOfRealModeEntryPoint:
216223
.long 0 // receives address of RealModeEntryPoint
217-
.word HEX(20)//RMODE_CS
224+
.word L_RMODE_CS
218225
nop
219226

220227
CallRealMode_return:

boot/freeldr/freeldr/arch/i386/entry.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <arch/pc/x86common.h>
2222
#include <arch/pc/pcbios.h>
2323

24+
EXTERN RelocateFreeldr:PROC
2425
EXTERN _BootMain:PROC
2526
EXTERN _InitIdt:PROC
2627
EXTERN _i386Idt:DWORD
@@ -47,6 +48,12 @@ _RealEntryPoint:
4748
mov gs, ax
4849
mov ss, ax
4950

51+
/* Keep only the low 16 bits part of stack */
52+
and esp, HEX(FFFF)
53+
54+
/* Relocate Freeldr if needed */
55+
call RelocateFreeldr
56+
5057
/* Setup protected mode stack */
5158
mov esp, dword ptr ds:[stack32]
5259

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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

boot/freeldr/freeldr/arch/realmode/amd64.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ stack16:
367367

368368

369369
#include "int386.inc"
370+
#include "helpers_all.inc"
370371
#include "helpers.inc"
371372
#include "pxe.inc"
372373
#include "pnp.inc"
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* PROJECT: FreeLoader
3+
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4+
* PURPOSE: Real mode helper code for all architectures
5+
* COPYRIGHT: Copyright 2024-2025 Daniel Victor <[email protected]>
6+
*/
7+
8+
Relocator16SS:
9+
.word 0
10+
Relocator16EAX:
11+
.long 0
12+
Relocator16ESP:
13+
.long 0
14+
15+
cs_writestr:
16+
/* Save necessary registers */
17+
push ax
18+
push ds
19+
20+
/* Prepare ds before writestr call */
21+
mov ax, cs
22+
mov ds, ax
23+
24+
/* Display the message */
25+
call writestr
26+
27+
/* Restore necessary registers and return */
28+
pop ds
29+
pop ax
30+
ret
31+
32+
/* This function will Update BSS_CurrentBaseAddress, instruction pointer and code segment */
33+
UpdateCurrentCodeSegment:
34+
/* Clear necessary registers */
35+
xor eax, eax
36+
xor ebx, ebx
37+
xor ecx, ecx
38+
39+
/* Call the sub function to get the base address */
40+
call .SubCall
41+
.SubCall:
42+
/* Pop the return address into bx. Since the return address is consumed,
43+
* this function does not return to UpdateCurrentCodeSegment */
44+
pop bx
45+
46+
/* Calculate the base address by adjusting the offset */
47+
sub bx, offset .SubCall
48+
49+
/* Load the current code segment into eax */
50+
mov ax, cs
51+
52+
/* Shift the segment address to get its physical address (real mode calculation) */
53+
shl eax, 4
54+
55+
/* Add the physical segment base to the relative base address */
56+
add eax, ebx
57+
58+
/* Store the calculated base address (low 32 bits) */
59+
mov dword ptr ds:[BSS_CurrentBaseAddress], eax
60+
61+
/* Clear the high 32 bits (not used in 32-bit environments) */
62+
mov dword ptr ds:[BSS_CurrentBaseAddress + 4], ecx
63+
64+
/* Save the return address offset */
65+
mov ecx, ebx
66+
67+
/* Convert the base address to segment and set the offset */
68+
mov ebx, eax
69+
shr ebx, 4
70+
mov ax, offset .Return
71+
72+
/* Change the CS and IP using retf method */
73+
push bx
74+
push ax
75+
retf
76+
.Return:
77+
/* Relocate the return value to get offset */
78+
pop ax
79+
sub ax, cx
80+
push ax
81+
82+
/* Return to the caller */
83+
ret

boot/freeldr/freeldr/arch/realmode/i386.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ rmode_idtptr:
199199
.long 0 /* Base Address */
200200

201201
#include "int386.inc"
202+
#include "helpers_all.inc"
202203
#if defined(SARCH_PC98)
203204
#include "helpers_pc98.inc"
204205
#else

boot/freeldr/freeldr/include/arch/pc/x86common.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
1212
#define BIOSCALLBUFFER HEX(4000) /* Buffer to store temporary data for any Int386() call */
1313
#define STACK16ADDR HEX(6F00) /* The 16-bit stack top will be at 0000:6F00 */
1414
#define BSS_START HEX(6F00)
15-
#define STACKLOW HEX(7000)
15+
#define STACKLOW HEX(8000)
1616
#define STACKADDR HEX(F000) /* The 32/64-bit stack top will be at 0000:F000, or 0xF000 */
1717
#define FREELDR_BASE HEX(F800)
18-
#define FREELDR_PE_BASE HEX(10000)
19-
#define MEMORY_MARGIN HEX(88000) /* We need this much memory */
18+
#define FREELDR_PE_BASE HEX(10000)
19+
#define GDTDATA_BASE HEX(7000)
20+
#define TEMPDATA16_BASE HEX(7100)
21+
#define TEMPCODE16_BASE HEX(7300)
22+
#define TEMPCODE_BASE HEX(200000)
23+
#define MEMORY_MARGIN HEX(88000) /* We need this much memory */
2024

2125
#define BIOSCALLBUFSEGMENT (BIOSCALLBUFFER/16) /* Buffer to store temporary data for any Int386() call */
2226
#define BIOSCALLBUFOFFSET HEX(0000) /* Buffer to store temporary data for any Int386() call */
@@ -49,6 +53,7 @@
4953
#define BSS_PnpResult (BSS_START + 104)
5054
#define BSS_BootDrive (BSS_START + 108) // 1 byte
5155
#define BSS_BootPartition (BSS_START + 109) // 1 byte
56+
#define BSS_CurrentBaseAddress (BSS_START + 110) // 8 bytes
5257

5358

5459
/* Realmode function IDs */
@@ -73,7 +78,9 @@
7378
#define RMODE_DS HEX(20) /* RMode data selector, base 0 limit 64k */
7479
//#else
7580
/* Long mode selectors */
76-
#define LMODE_CS HEX(10)
77-
#define LMODE_DS HEX(18)
78-
#define CMODE_CS HEX(30)
81+
#define LMODE_CS HEX(10)
82+
#define LMODE_DS HEX(18)
83+
#define L_RMODE_CS HEX(20)
84+
#define L_RMODE_DS HEX(28)
85+
#define CMODE_CS HEX(30)
7986
//#endif

boot/freeldr/freeldr/pcat.cmake

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@
99
## Copyright 2023 Hermès Bélusca-Maïto <[email protected]>
1010
##
1111

12+
set(FREELDR_BASE 0000)
13+
1214
if(ARCH STREQUAL "i386")
1315
CreateBootSectorTarget(frldr16
1416
${CMAKE_CURRENT_SOURCE_DIR}/arch/realmode/i386.S
1517
${CMAKE_CURRENT_BINARY_DIR}/frldr16.bin
16-
F800)
18+
${FREELDR_BASE})
1719
elseif(ARCH STREQUAL "amd64")
1820
CreateBootSectorTarget(frldr16
1921
${CMAKE_CURRENT_SOURCE_DIR}/arch/realmode/amd64.S
2022
${CMAKE_CURRENT_BINARY_DIR}/frldr16.bin
21-
F800)
23+
${FREELDR_BASE})
2224
endif()
2325

2426

@@ -36,7 +38,8 @@ list(APPEND PCATLDR_BASE_ASM_SOURCE)
3638

3739
if(ARCH STREQUAL "i386")
3840
list(APPEND PCATLDR_BASE_ASM_SOURCE
39-
arch/i386/multiboot.S)
41+
arch/i386/multiboot.S
42+
arch/i386/relocldr.S)
4043

4144
list(APPEND PCATLDR_COMMON_ASM_SOURCE
4245
arch/i386/drvmap.S
@@ -111,7 +114,8 @@ if(ARCH STREQUAL "i386")
111114

112115
elseif(ARCH STREQUAL "amd64")
113116
list(APPEND PCATLDR_BASE_ASM_SOURCE
114-
arch/i386/multiboot.S)
117+
arch/i386/multiboot.S
118+
arch/i386/relocldr.S)
115119

116120
list(APPEND PCATLDR_COMMON_ASM_SOURCE
117121
arch/amd64/entry.S

0 commit comments

Comments
 (0)