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 F AT 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 + SectorsPerF at ]
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 F AT entry for a given cluster number for 16 - bit F AT
140- // On entry AX has cluster number
129+ // On entry DX : AX has cluster number
141130// On return AX has F AT entry for th at cluster
142131GetFatEntry16:
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 F AT entry offset
151- mov ax , es : [ bx ] // Get F AT 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 ] // F AT 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 ] // F AT Sector Number + = HiddenSectors
155+ adc dx , word ptr [ bp + HiddenSectors + 2 ]
156+ add ax , word ptr [ bp + ReservedSectors ] // F AT Sector Number + = ReservedSectors
157+ adc dx , 0
158+
159+ dec bx
160+ and cx , bx // F AT Offset Within Sector = CX % BytesPerSector
161+ // DX : AX holds logical F AT sector number
162+ // CX holds F AT entry offset
163+
164+ call LoadFatSector // Get F AT 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 F AT entry offset into BX
168- mov ax , es : [ bx ] // Get F AT entry
178+ mov cx , ax // Save this for later in CX
179+
180+ xor dx , dx // Dividend
181+ mov bx , word ptr [ bp + BytesPerSector ] // F AT Sector Number = original AX / BytesPerSector
182+ div bx
183+
184+ xor dx , dx
185+ add ax , word ptr [ bp + HiddenSectors ] // F AT Sector Number + = HiddenSectors
186+ adc dx , word ptr [ bp + HiddenSectors + 2 ]
187+ add ax , word ptr [ bp + ReservedSectors ] // F AT Sector Number + = ReservedSectors
188+ adc dx , 0
189+
190+ dec bx
191+ and cx , bx // F AT Offset Within Sector = CX % BytesPerSector
192+ // DX : AX holds logical F AT sector number
193+ // CX holds F AT entry offset
194+
195+ call LoadFatSector // Get F AT 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
179207GetFatEntry12_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 F AT logical sector number.
214+ * CX : F AT entry offset.
215+ * /
216+ LoadFatSector:
217+ push cx // Save F AT 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 F AT 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 th at , in FAT12 , entry data
242+ // th at 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 + SectorsPerF at ]
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 F AT entry offset (originally in CX ) into BX
253+ mov ax , word ptr es : [ bx ] // Get F AT 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