Update the GAS compatible fathelp.S file to reflect the latest changes to the origina...
[reactos.git] / reactos / boot / freeldr / freeldr / arch / amd64 / fathelp.S
1 // fathelp.S
2 // FAT12/16 Boot Sector Helper Code
3 // Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
4
5 .intel_syntax noprefix
6
7 //org 8000h
8
9 .text
10
11 .code16
12
13
14 #define BootSectorStackTop 0x7bf2
15 #define DataAreaStartHigh 0x2
16 #define DataAreaStartLow 0x4
17 #define BiosCHSDriveSizeHigh 0x6
18 #define BiosCHSDriveSizeLow 0x8
19 #define BiosCHSDriveSize 0x8
20 #define ReadSectorsOffset 0xa
21 #define ReadClusterOffset 0xc
22 #define PutCharsOffset 0xe
23
24 #define OEMName 3
25 #define BytesPerSector 11
26 #define SectsPerCluster 13
27 #define ReservedSectors 14
28 #define NumberOfFats 16
29 #define MaxRootEntries 17
30 #define TotalSectors 19
31 #define MediaDescriptor 21
32 #define SectorsPerFat 22
33 #define SectorsPerTrack 24
34 #define NumberOfHeads 26
35 #define HiddenSectors 28
36 #define TotalSectorsBig 32
37 #define BootDrive 36
38 #define Reserved 37
39 #define ExtendSig 38
40 #define SerialNumber 39
41 #define VolumeLabel 43
42 #define FileSystem 54
43
44 #define BootPartition 0x7dfd
45
46
47 // This code will be stored in the first 512 bytes
48 // of freeldr.sys. The first 3 bytes will be a jmp
49 // instruction to skip past the FAT helper code
50 // that is stored in the rest of the 512 bytes.
51 //
52 // This code is loaded at 0000:8000 so we have to
53 // encode a jmp instruction to jump to 0000:8200
54
55 .global _mainCRTStartup // For Mingw32 builds where the linker looks for this symbol
56 _mainCRTStartup:
57 .global start
58 start:
59 .byte 0xe9
60 .byte 0xfd
61 .byte 0x01
62
63 // Now starts the extra boot code that we will store
64 // in the first 512 bytes of freeldr.sys. This code
65 // allows the FAT12/16 bootsector to navigate the
66 // FAT table so that we can still load freeldr.sys
67 // even if it is fragmented.
68
69
70 FatHelperEntryPoint:
71
72 push ax // First save AX - the start cluster of freeldr.sys
73
74
75 // Display "Loading FreeLoader..." message
76 mov esi, offset msgLoading // Loading message
77 call [bp-PutCharsOffset] // Display it
78
79
80 call ReadFatIntoMemory
81
82 pop ax // Restore AX (start cluster)
83 // AX has start cluster of freeldr.sys
84
85 mov bx,0x800
86 mov es,bx
87
88 LoadFile:
89 push ax
90 call IsFat12
91 pop ax
92 jnc LoadFile2
93 cmp ax,0x0ff8 // Check to see if this is the last cluster in the chain
94 jmp LoadFile3
95 LoadFile2:
96 cmp ax,0x0fff8
97 LoadFile3:
98 jae LoadFile_Done // If so continue, if not then read then next one
99 push ax
100 xor bx,bx // Load ROSLDR starting at 0000:8000h
101 push es
102 call [bp-ReadClusterOffset]
103 pop es
104
105 xor bx,bx
106 mov bl, [bp+SectsPerCluster]
107 shl bx,5 // BX = BX * 512 / 16
108 mov ax,es // Increment the load address by
109 add ax,bx // The size of a cluster
110 mov es,ax
111
112 call IsFat12
113 pop ax
114 push es
115 jnc LoadFile4
116 call GetFatEntry12 // Get the next entry
117 jmp LoadFile5
118 LoadFile4:
119 call GetFatEntry16
120 LoadFile5:
121 pop es
122
123 jmp LoadFile // Load the next cluster (if any)
124
125 LoadFile_Done:
126 mov dl,BYTE PTR [bp+BootDrive] // Load the boot drive into DL
127 mov dh,[BootPartition] // Load the boot partition into DH
128
129 push 0 // push segment (0x0000)
130 mov bx, [0x8000 + 0xA8] // load the RVA of the EntryPoint into eax
131 add bx, 0x8000 // RVA -> VA and skip 3 bytes (jump to fathelper code)
132 push bx // push offset
133 retf // Transfer control to FreeLoader
134
135 // Reads the entire FAT into memory at 7000:0000
136 ReadFatIntoMemory:
137 mov ax, [bp+HiddenSectors]
138 mov dx, [bp+HiddenSectors+2]
139 add ax, [bp+ReservedSectors]
140 adc dx, 0
141 mov cx, [bp+SectorsPerFat]
142 mov bx,0x7000
143 mov es,bx
144 xor bx,bx
145 call [bp-ReadSectorsOffset]
146 ret
147
148
149 // Returns the FAT entry for a given cluster number for 16-bit FAT
150 // On entry AX has cluster number
151 // On return AX has FAT entry for that cluster
152 GetFatEntry16:
153
154 mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)
155 mul cx
156 shl dx,12
157
158 mov bx,0x7000
159 add bx,dx
160 mov es,bx
161 mov bx,ax // Restore FAT entry offset
162 mov ax, es:[bx] // Get FAT entry
163
164 ret
165
166
167 // Returns the FAT entry for a given cluster number for 12-bit FAT
168 // On entry AX has cluster number
169 // On return AX has FAT entry for that cluster
170 GetFatEntry12:
171
172 push ax
173 mov cx,ax
174 shr ax,1
175 add ax,cx // AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
176
177 mov bx,0x7000
178 mov es,bx
179 mov bx,ax // Put FAT entry offset into BX
180 mov ax, es:[bx] // Get FAT entry
181 pop cx // Get cluster number from stack
182 and cx,1
183 jz UseLow12Bits
184 and ax,0x0fff0
185 shr ax,4
186 jmp GetFatEntry12_Done
187
188 UseLow12Bits:
189 and ax,0x0fff
190
191 GetFatEntry12_Done:
192
193 ret
194
195
196 // Returns CF = 1 if this is a FAT12 file system
197 // Otherwise CF = 0 for FAT16
198 IsFat12:
199
200 mov ebx, [bp-DataAreaStartLow]
201 // EBX now has the number of the starting sector of the data area
202 // starting from the beginning of the disk, so subtrace hidden sectors
203 sub ebx, [bp+HiddenSectors]
204
205
206 xor eax,eax
207 mov ax, [bp+TotalSectors]
208 cmp ax, 0
209 jnz IsFat12_2
210 mov eax, [bp+TotalSectorsBig]
211
212 // EAX now contains the number of sectors on the volume
213
214 IsFat12_2:
215 sub eax,ebx // Subtract data area start sector
216 xor edx,edx // from total sectors of volume
217
218 // EDX:EAX now contains the number of data sectors on the volume
219 movzx ebx, byte ptr [bp+SectsPerCluster]
220 div ebx
221 // EAX now has the number of clusters on the volume
222 stc
223 cmp eax,4085
224 jb IsFat12_Done
225 clc
226
227 IsFat12_Done:
228 ret
229
230
231
232 msgLoading: .asciz "Loading FreeLoader...\r\n"
233
234 .org 0x1fe // Pad to 510 bytes
235 .word 0x0aa55 // BootSector signature