Skip to content

Commit 28e6b30

Browse files
HBeluscabinarymaster
authored andcommitted
** WIP ** [FREELDR] Don't load a full FAT12/16 table when loading FREELDR.SYS.
CORE-15427, CORE-14558, CORE-16195, CORE-13740 Supersedes PR reactos#2182 At least the way we currently do it and have our data layed out in memory. Otherwise we risk corrupting either the FAT-loading code, or the contents of FREELDR.SYS being loaded, when said FAT table is quite large.
1 parent 6c3fe69 commit 28e6b30

File tree

1 file changed

+110
-34
lines changed

1 file changed

+110
-34
lines changed

boot/freeldr/freeldr/arch/realmode/fathelp.inc

Lines changed: 110 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
// fathelp.S
2-
// FAT12/16 Boot Sector Helper Code
3-
// Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
1+
/*
2+
* PROJECT: FreeLoader
3+
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4+
* PURPOSE: FAT12/16 Boot Sector Helper Code
5+
* COPYRIGHT: Copyright 1998-2003 Brian Palmer ([email protected])
6+
* Copyright 2019 Dmitry Borisov (di[email protected])
7+
* Copyright 2022 Hermès Bélusca-Maïto
8+
*/
49

510
//#include <asm.inc>
611

@@ -67,12 +72,10 @@ FatHelperEntryPoint:
6772
mov si, offset msgLoading
6873
call word ptr [bp-PutCharsOffset]
6974

70-
call ReadFatIntoMemory
71-
7275
/* Restore AX (start cluster) */
7376
pop ax
77+
xor dx, dx
7478

75-
// AX has start cluster of freeldr.sys
7679
mov bx, FREELDR_BASE / 16
7780
mov es, bx
7881

@@ -95,7 +98,7 @@ LoadFile3:
9598
pop es
9699

97100
xor bx, bx
98-
mov bl, [bp+SectsPerCluster]
101+
mov bl, byte ptr [bp+SectsPerCluster]
99102
shl bx, 5 // BX = BX * 512 / 16
100103
mov ax, es // Increment the load address by
101104
add ax, bx // The size of a cluster
@@ -122,33 +125,43 @@ LoadFile_Done:
122125
jmp start
123126

124127

125-
// Reads the entire FAT into memory at 7000:0000
126-
ReadFatIntoMemory:
127-
mov ax, [bp+HiddenSectors]
128-
mov dx, [bp+HiddenSectors+2]
129-
add ax, [bp+ReservedSectors]
130-
adc dx, 0
131-
mov cx, [bp+SectorsPerFat]
132-
mov bx, HEX(7000)
133-
mov es,bx
134-
xor bx,bx
135-
call word ptr [bp-ReadSectorsOffset]
136-
ret
137-
138-
139128
// Returns the FAT entry for a given cluster number for 16-bit FAT
140-
// On entry AX has cluster number
129+
// On entry DX:AX has cluster number
141130
// On return AX has FAT entry for that cluster
142131
GetFatEntry16:
143-
mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)
144-
mul cx
145-
shl dx,12
132+
// NOTE: Do the DX:AX arithmetics via EAX instead.
133+
xchg ax, dx
134+
shl eax, 16 // HIWORD(EAX) = old DX
135+
mov ax, dx // LOWORD(EAX) = DX == old AX.
136+
137+
shl ax, 1 // AX = AX * 2 (since FAT16 entries are 2 bytes)
146138

147-
mov bx, HEX(7000)
148-
add bx,dx
149-
mov es,bx
150-
mov bx,ax // Restore FAT entry offset
151-
mov ax, es:[bx] // Get FAT entry
139+
mov cx, ax // Save this for later in CX
140+
141+
// mov bx, HEX(9000)
142+
// add bx, dx
143+
// mov es, bx
144+
145+
xor edx, edx // Dividend
146+
movzx ebx, word ptr [bp+BytesPerSector] // FAT Sector Number = original AX / BytesPerSector
147+
div ebx
148+
149+
// Now reconstruct DX:AX from EAX
150+
mov dx, ax
151+
shr eax, 16
152+
xchg dx, ax
153+
154+
add ax, word ptr [bp+HiddenSectors] // FAT Sector Number += HiddenSectors
155+
adc dx, word ptr [bp+HiddenSectors+2]
156+
add ax, word ptr [bp+ReservedSectors] // FAT Sector Number += ReservedSectors
157+
adc dx, 0
158+
159+
dec bx
160+
and cx, bx // FAT Offset Within Sector = CX % BytesPerSector
161+
// DX:AX holds logical FAT sector number
162+
// CX holds FAT entry offset
163+
164+
call LoadFatSector // Get FAT entry in AX
152165

153166
ret
154167

@@ -162,10 +175,25 @@ GetFatEntry12:
162175
shr ax, 1
163176
add ax, cx // AX = AX * 1.5 (AX = AX + (AX / 2)) , since FAT12 entries are 12 bits
164177

165-
mov bx, HEX(7000)
166-
mov es,bx
167-
mov bx,ax // Put FAT entry offset into BX
168-
mov ax, es:[bx] // Get FAT entry
178+
mov cx, ax // Save this for later in CX
179+
180+
xor dx, dx // Dividend
181+
mov bx, word ptr [bp+BytesPerSector] // FAT Sector Number = original AX / BytesPerSector
182+
div bx
183+
184+
xor dx, dx
185+
add ax, word ptr [bp+HiddenSectors] // FAT Sector Number += HiddenSectors
186+
adc dx, word ptr [bp+HiddenSectors+2]
187+
add ax, word ptr [bp+ReservedSectors] // FAT Sector Number += ReservedSectors
188+
adc dx, 0
189+
190+
dec bx
191+
and cx, bx // FAT Offset Within Sector = CX % BytesPerSector
192+
// DX:AX holds logical FAT sector number
193+
// CX holds FAT entry offset
194+
195+
call LoadFatSector // Get FAT entry in AX
196+
169197
pop cx // Get cluster number from stack
170198
and cx, 1
171199
jz UseLow12Bits
@@ -177,9 +205,57 @@ UseLow12Bits:
177205
and ax, HEX(0fff)
178206

179207
GetFatEntry12_Done:
208+
ret
209+
210+
211+
/*
212+
* This code is directly adapted from fat32.S
213+
* BUT: Use DX:AX instead of EAX for the FAT logical sector number.
214+
* CX: FAT entry offset.
215+
*/
216+
LoadFatSector:
217+
push cx // Save FAT entry offset
180218

219+
//
220+
// FIXME: Why loading the sectors at 7000h do fail?
221+
// In the meantime, do as with FAT32 and load the sectors
222+
// at 9000h instead; this seems to work fine...
223+
//
224+
mov bx, HEX(9000) // We will load it to [9000:0000h]
225+
mov es, bx
226+
227+
// DX:AX holds logical FAT sector number
228+
// Check if we have already loaded it
229+
//
230+
// FIXME: Why using cs:[...] does not work?
231+
//
232+
cmp ax, word ptr [bp+FatSectorInCache]
233+
jne DoLoad
234+
cmp dx, word ptr [bp+FatSectorInCache+2]
235+
je LoadFatSectorAlreadyLoaded
236+
237+
DoLoad:
238+
mov word ptr [bp+FatSectorInCache], ax
239+
mov word ptr [bp+FatSectorInCache+2], dx
240+
xor bx, bx
241+
// Read 2 consecutive sectors, so that, in FAT12, entry data
242+
// that may cross sector boundaries, can be correctly read.
243+
// This is not needed in FAT16 and FAT32 where entry data is
244+
// aligned on word boundaries.
245+
mov cx, 2 // mov cx, word ptr [bp+SectorsPerFat]
246+
247+
push es // The FAT12/16 bootsector ReadSectors destroys ES.
248+
call word ptr [bp-ReadSectorsOffset]
249+
pop es
250+
251+
LoadFatSectorAlreadyLoaded:
252+
pop bx // Put FAT entry offset (originally in CX) into BX
253+
mov ax, word ptr es:[bx] // Get FAT entry
181254
ret
182255

256+
FatSectorInCache: // This variable tells us which sector we currently have in memory
257+
.long HEX(0ffffffff) // There is no need to re-read the same sector if we don't have to
258+
183259

184260
// Returns CF = 1 if this is a FAT12 file system
185261
// Otherwise CF = 0 for FAT16

0 commit comments

Comments
 (0)