Skip to content

Commit 8c7738e

Browse files
committed
[FREELDR] Add/change necessary code for the relocation code (reactos#7530)
CORE-19882 1
1 parent 22d077f commit 8c7738e

File tree

6 files changed

+156
-8
lines changed

6 files changed

+156
-8
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ SwitchToRealCompSegment:
214214
.byte HEX(0EA) // 32bit long jmp
215215
AddressOfRealModeEntryPoint:
216216
.long 0 // receives address of RealModeEntryPoint
217-
.word HEX(20)//RMODE_CS
217+
.word L_RMODE_CS
218218
nop
219219

220220
CallRealMode_return:

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: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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+
#define RELOCATOR_BLOCK_SIZE HEX(200)
9+
#define RELOCATOR_BLOCK_SIZE_SEGMENT (RELOCATOR_BLOCK_SIZE / 16)
10+
11+
Relocator16SS:
12+
.word 0
13+
Relocator16EAX:
14+
.long 0
15+
Relocator16ESP:
16+
.long 0
17+
18+
/* This function will Update BSS_CurrentBaseAddress, instruction pointer, code segment and relocate if necessary */
19+
RelocateFreeLdr:
20+
/* Clear direction flag */
21+
cld
22+
23+
/* Clear necessary registers */
24+
xor eax, eax
25+
xor ebx, ebx
26+
xor ecx, ecx
27+
28+
/* Call the sub function to get the base address */
29+
call .SubCall
30+
.SubCall:
31+
/* Pop the return address into bx. Since the return address is consumed,
32+
* this function does not return to UpdateCurrentCodeSegment */
33+
pop bx
34+
35+
/* Calculate the base address by adjusting the offset */
36+
sub bx, offset .SubCall - FREELDR_BASE
37+
38+
/* Load the current code segment into eax */
39+
mov ax, cs
40+
41+
/* Shift the segment address to get its physical address (real mode calculation) */
42+
shl eax, 4
43+
44+
/* Add the physical segment base to the relative base address */
45+
add eax, ebx
46+
47+
/* Store the calculated base address (low 32 bits) */
48+
mov dword ptr ds:[BSS_CurrentBaseAddress], eax
49+
50+
.FixBaseAddress:
51+
/* Don't relocate if it's not necessary */
52+
cmp eax, FREELDR_BASE
53+
jz .NotNecessaryRelocation
54+
55+
/* Setup source segment */
56+
shr eax, 4
57+
mov ds, ax
58+
59+
/* Move the realmode FREELDR code to TEMPCODE16_BASE */
60+
mov di, TEMPCODE16_BASE
61+
xor si, si
62+
mov cx, FREELDR_PE_BASE - FREELDR_BASE
63+
rep movsb
64+
65+
ljmp16 TEMPCODE16_BASE / 16, (.FixBaseAddress2 - FREELDR_BASE)
66+
.FixBaseAddress2:
67+
/* Save DX */
68+
push dx
69+
70+
/* Prepare the registers for relocation */
71+
mov dx, (MEMORY_MARGIN - FREELDR_BASE) / 16
72+
mov eax, dword ptr es:[BSS_CurrentBaseAddress]
73+
shr eax, 4
74+
mov ds, ax
75+
mov ax, FREELDR_BASE / 16
76+
mov es, ax
77+
78+
/* If current base address is lower than the final one then just copy it backwards */
79+
cmp dword ptr fs:[BSS_CurrentBaseAddress], FREELDR_BASE
80+
jb .PreFixLoopInverted
81+
.FixLoop:
82+
/* Copy `RELOCATOR_BLOCK_SIZE` bytes from source to destination */
83+
xor di, di
84+
xor si, si
85+
mov cx, RELOCATOR_BLOCK_SIZE
86+
rep movsb
87+
88+
/* Increment DS */
89+
mov ax, ds
90+
add ax, RELOCATOR_BLOCK_SIZE_SEGMENT
91+
mov ds, ax
92+
93+
/* Increment ES */
94+
mov ax, es
95+
add ax, RELOCATOR_BLOCK_SIZE_SEGMENT
96+
mov es, ax
97+
98+
/* Repeat the loop */
99+
sub dx, RELOCATOR_BLOCK_SIZE_SEGMENT
100+
jnz .FixLoop
101+
jmp .FinishedRelocation
102+
.PreFixLoopInverted:
103+
/* Move DS to the end */
104+
mov ax, ds
105+
add ax, dx
106+
mov ds, ax
107+
108+
/* Move ES to the end */
109+
mov ax, es
110+
add ax, dx
111+
mov es, ax
112+
.FixLoopInverted:
113+
/* Decrement DS */
114+
mov ax, ds
115+
sub ax, RELOCATOR_BLOCK_SIZE_SEGMENT
116+
mov ds, ax
117+
118+
/* Decrement ES */
119+
mov ax, es
120+
sub ax, RELOCATOR_BLOCK_SIZE_SEGMENT
121+
mov es, ax
122+
123+
/* Copy `RELOCATOR_BLOCK_SIZE` bytes from source to destination */
124+
std
125+
mov di, RELOCATOR_BLOCK_SIZE
126+
mov si, di
127+
mov cx, di
128+
rep movsb
129+
130+
/* Repeat the loop */
131+
sub dx, RELOCATOR_BLOCK_SIZE_SEGMENT
132+
jnz .FixLoopInverted
133+
134+
.FinishedRelocation:
135+
/* Restore dx and restart freeldr with new base address */
136+
pop dx
137+
ljmp16 FREELDR_BASE / 16, 0
138+
139+
.NotNecessaryRelocation:
140+
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: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
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 */
17-
#define FREELDR_BASE HEX(F800)
17+
#define FREELDR_BASE HEX(F600)
1818
#define FREELDR_PE_BASE HEX(10000)
19+
#define TEMPDATA16_BASE HEX(7000)
20+
#define TEMPCODE16_BASE HEX(7400)
21+
#define TEMPCODE_BASE HEX(200000)
1922
#define MEMORY_MARGIN HEX(88000) /* We need this much memory */
2023

2124
#define BIOSCALLBUFSEGMENT (BIOSCALLBUFFER/16) /* Buffer to store temporary data for any Int386() call */
@@ -49,6 +52,7 @@
4952
#define BSS_PnpResult (BSS_START + 104)
5053
#define BSS_BootDrive (BSS_START + 108) // 1 byte
5154
#define BSS_BootPartition (BSS_START + 109) // 1 byte
55+
#define BSS_CurrentBaseAddress (BSS_START + 110) // 4 bytes
5256

5357

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

boot/freeldr/freeldr/pcat.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ if(ARCH STREQUAL "i386")
1313
CreateBootSectorTarget(frldr16
1414
${CMAKE_CURRENT_SOURCE_DIR}/arch/realmode/i386.S
1515
${CMAKE_CURRENT_BINARY_DIR}/frldr16.bin
16-
F800)
16+
F600)
1717
elseif(ARCH STREQUAL "amd64")
1818
CreateBootSectorTarget(frldr16
1919
${CMAKE_CURRENT_SOURCE_DIR}/arch/realmode/amd64.S
2020
${CMAKE_CURRENT_BINARY_DIR}/frldr16.bin
21-
F800)
21+
F600)
2222
endif()
2323

2424

0 commit comments

Comments
 (0)