Skip to content

Commit 16f9ad2

Browse files
iLauncherDevHBelusca
authored andcommitted
[FREELDR] Add/change necessary code for the relocation code (reactos#8439)
CORE-19882
1 parent 7011978 commit 16f9ad2

File tree

4 files changed

+183
-28
lines changed

4 files changed

+183
-28
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/i386/entry.S

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,6 @@ SwitchToReal16Address:
233233
nop
234234

235235

236-
/* 16-bit stack pointer */
237-
stack16:
238-
.word STACK16ADDR
239-
240236
/* 32-bit stack pointer */
241237
stack32:
242238
.long STACKADDR
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* PROJECT: FreeLoader
3+
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4+
* PURPOSE: Real-mode FreeLoader relocator
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+
#define RELOCATOR_FUNCTION_BASE FREELDR_BASE
12+
13+
#define RELOCATOR_PROGRAM_SIZE (MEMORY_MARGIN - FREELDR_BASE)
14+
#define RELOCATOR_PROGRAM_SIZE_BLOCKS ((RELOCATOR_PROGRAM_SIZE + (RELOCATOR_BLOCK_SIZE - 1)) / RELOCATOR_BLOCK_SIZE)
15+
#define RELOCATOR_PROGRAM_SIZE_ALIGNED (RELOCATOR_PROGRAM_SIZE_BLOCKS * RELOCATOR_BLOCK_SIZE)
16+
17+
/* WARNING: This function must be called at the real-mode entry point since it restarts FreeLoader
18+
* This function will update BSS_CurrentSegmentBaseAddress and relocate if necessary */
19+
RelocateFreeLdr:
20+
/* Clear direction flag */
21+
cld
22+
23+
/* Call the sub-function to retrieve the base address */
24+
call .SubCall
25+
.SubCall:
26+
/* Pop the return address into BX. Since the return address is consumed,
27+
* this function does not return to RelocateFreeLdr */
28+
pop bx
29+
30+
/* Calculate IP base address and convert to segment value */
31+
sub bx, offset .SubCall - RELOCATOR_FUNCTION_BASE
32+
shr bx, 4
33+
34+
/* Load CS base address into AX and add it with IP base address */
35+
mov ax, cs
36+
add ax, bx
37+
38+
/* Store the calculated base address (low 16 bits) */
39+
mov word ptr fs:[BSS_CurrentSegmentBaseAddress], ax
40+
41+
.RelocateFrLdr16:
42+
/* If the current base address is the same as FREELDR_BASE then it's not necessary to relocate */
43+
cmp ax, FREELDR_BASE / 16
44+
jz .NotNecessaryRelocation
45+
46+
/* Setup source segment */
47+
mov ds, ax
48+
49+
/* Setup destination segment */
50+
xor ax, ax
51+
mov es, ax
52+
53+
/* Copy the realmode part of FRLDR16 code to TEMPCODE16_BASE */
54+
mov di, TEMPCODE16_BASE
55+
mov si, offset RELOCATOR_FUNCTION_START - RELOCATOR_FUNCTION_BASE
56+
mov cx, offset RELOCATOR_FUNCTION_END - RELOCATOR_FUNCTION_START
57+
rep movsb
58+
59+
/* Jump to relocated realmode part */
60+
ljmp16 TEMPCODE16_BASE / 16, 0
61+
62+
RELOCATOR_FUNCTION_START:
63+
64+
.SetupRelocation:
65+
/* Save DX (contains the boot drive and partition numbers) */
66+
push dx
67+
68+
/* Prepare the copy size in 16-byte blocks */
69+
mov dx, RELOCATOR_PROGRAM_SIZE_ALIGNED / 16
70+
71+
/* Prepare the destination register */
72+
mov ax, FREELDR_BASE / 16
73+
mov es, ax
74+
75+
/* Prepare the source register */
76+
mov ax, word ptr fs:[BSS_CurrentSegmentBaseAddress]
77+
mov ds, ax
78+
79+
/* If current base address is lower than the final one then just copy it backwards */
80+
cmp ax, FREELDR_BASE / 16
81+
jb .SetupRelocateLoopBackward
82+
.RelocateLoopForward:
83+
/* Abort the loop if DX is below `RELOCATOR_BLOCK_SIZE_SEGMENT` */
84+
cmp dx, RELOCATOR_BLOCK_SIZE_SEGMENT
85+
jb .FinishedRelocation
86+
87+
/* Copy `RELOCATOR_BLOCK_SIZE` bytes from source to destination */
88+
xor di, di
89+
xor si, si
90+
mov cx, RELOCATOR_BLOCK_SIZE
91+
rep movsb
92+
93+
/* Increment ES */
94+
mov ax, es
95+
add ax, RELOCATOR_BLOCK_SIZE_SEGMENT
96+
mov es, ax
97+
98+
/* Increment DS */
99+
mov ax, ds
100+
add ax, RELOCATOR_BLOCK_SIZE_SEGMENT
101+
mov ds, ax
102+
103+
/* Repeat the loop */
104+
sub dx, RELOCATOR_BLOCK_SIZE_SEGMENT
105+
jmp .RelocateLoopForward
106+
107+
.SetupRelocateLoopBackward:
108+
/* Set direction flag for inverted copy */
109+
std
110+
111+
/* Move destination register to the end */
112+
mov ax, es
113+
add ax, dx
114+
mov es, ax
115+
116+
/* Move source register to the end */
117+
mov ax, ds
118+
add ax, dx
119+
mov ds, ax
120+
.RelocateLoopBackward:
121+
/* Abort the loop if DX is below `RELOCATOR_BLOCK_SIZE_SEGMENT` */
122+
cmp dx, RELOCATOR_BLOCK_SIZE_SEGMENT
123+
jb .FinishedRelocation
124+
125+
/* Decrement ES */
126+
mov ax, es
127+
sub ax, RELOCATOR_BLOCK_SIZE_SEGMENT
128+
mov es, ax
129+
130+
/* Decrement DS */
131+
mov ax, ds
132+
sub ax, RELOCATOR_BLOCK_SIZE_SEGMENT
133+
mov ds, ax
134+
135+
/* Copy `RELOCATOR_BLOCK_SIZE` bytes from source to destination */
136+
mov di, RELOCATOR_BLOCK_SIZE - 1
137+
mov si, di
138+
mov cx, RELOCATOR_BLOCK_SIZE
139+
rep movsb
140+
141+
/* Repeat the loop */
142+
sub dx, RELOCATOR_BLOCK_SIZE_SEGMENT
143+
jmp .RelocateLoopBackward
144+
145+
.FinishedRelocation:
146+
/* Restore DX and restart FreeLoader with new base address */
147+
pop dx
148+
ljmp16 FREELDR_BASE / 16, 0
149+
150+
RELOCATOR_FUNCTION_END:
151+
152+
.NotNecessaryRelocation:
153+
ret

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

Lines changed: 29 additions & 23 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 */
1717
#define FREELDR_BASE HEX(F800)
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 */
@@ -30,25 +33,26 @@
3033
#define MAX_DISKREADBUFFER_SIZE HEX(FE00)
3134

3235
/* These addresses specify the realmode "BSS section" layout */
33-
#define BSS_RealModeEntry (BSS_START + 0)
34-
#define BSS_CallbackReturn (BSS_START + 4)
35-
#define BSS_RegisterSet (BSS_START + 8) /* size = 40 */
36-
#define BSS_IntVector (BSS_START + 52)
37-
#define BSS_PxeEntryPoint (BSS_START + 56)
38-
#define BSS_PxeBufferSegment (BSS_START + 60)
39-
#define BSS_PxeBufferOffset (BSS_START + 64)
40-
#define BSS_PxeFunction (BSS_START + 68)
41-
#define BSS_PxeResult (BSS_START + 72)
42-
#define BSS_PnpBiosEntryPoint (BSS_START + 76)
43-
#define BSS_PnpBiosDataSegment (BSS_START + 80)
44-
#define BSS_PnpBiosBufferSegment (BSS_START + 84)
45-
#define BSS_PnpBiosBufferOffset (BSS_START + 88)
46-
#define BSS_PnpNodeSize (BSS_START + 92)
47-
#define BSS_PnpNodeCount (BSS_START + 96)
48-
#define BSS_PnpNodeNumber (BSS_START + 100)
49-
#define BSS_PnpResult (BSS_START + 104)
50-
#define BSS_BootDrive (BSS_START + 108) // 1 byte
51-
#define BSS_BootPartition (BSS_START + 109) // 1 byte
36+
#define BSS_RealModeEntry (BSS_START + 0)
37+
#define BSS_CallbackReturn (BSS_START + 4)
38+
#define BSS_RegisterSet (BSS_START + 8) /* size = 40 */
39+
#define BSS_IntVector (BSS_START + 52)
40+
#define BSS_PxeEntryPoint (BSS_START + 56)
41+
#define BSS_PxeBufferSegment (BSS_START + 60)
42+
#define BSS_PxeBufferOffset (BSS_START + 64)
43+
#define BSS_PxeFunction (BSS_START + 68)
44+
#define BSS_PxeResult (BSS_START + 72)
45+
#define BSS_PnpBiosEntryPoint (BSS_START + 76)
46+
#define BSS_PnpBiosDataSegment (BSS_START + 80)
47+
#define BSS_PnpBiosBufferSegment (BSS_START + 84)
48+
#define BSS_PnpBiosBufferOffset (BSS_START + 88)
49+
#define BSS_PnpNodeSize (BSS_START + 92)
50+
#define BSS_PnpNodeCount (BSS_START + 96)
51+
#define BSS_PnpNodeNumber (BSS_START + 100)
52+
#define BSS_PnpResult (BSS_START + 104)
53+
#define BSS_BootDrive (BSS_START + 108) // 1 byte
54+
#define BSS_BootPartition (BSS_START + 109) // 1 byte
55+
#define BSS_CurrentSegmentBaseAddress (BSS_START + 110) // 2 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

0 commit comments

Comments
 (0)