Revert part of r45817 to try to fix build
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / fathelp.asm
1 ; FATHELP.ASM
2 ; FAT12/16 Boot Sector Helper Code
3 ; Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
4
5
6
7 ;org 8000h
8
9 segment .text
10
11 bits 16
12
13
14 BootSectorStackTop equ 0x7bf2
15 DataAreaStartHigh equ 0x2
16 DataAreaStartLow equ 0x4
17 BiosCHSDriveSizeHigh equ 0x6
18 BiosCHSDriveSizeLow equ 0x8
19 BiosCHSDriveSize equ 0x8
20 ReadSectorsOffset equ 0xa
21 ReadClusterOffset equ 0xc
22 PutCharsOffset equ 0xe
23
24 OEMName equ 3
25 BytesPerSector equ 11
26 SectsPerCluster equ 13
27 ReservedSectors equ 14
28 NumberOfFats equ 16
29 MaxRootEntries equ 17
30 TotalSectors equ 19
31 MediaDescriptor equ 21
32 SectorsPerFat equ 22
33 SectorsPerTrack equ 24
34 NumberOfHeads equ 26
35 HiddenSectors equ 28
36 TotalSectorsBig equ 32
37 BootDrive equ 36
38 Reserved equ 37
39 ExtendSig equ 38
40 SerialNumber equ 39
41 VolumeLabel equ 43
42 FileSystem equ 54
43
44 BootPartition equ 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 db 0xe9
60 db 0xfd
61 db 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,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,800h
86 mov es,bx
87
88 LoadFile:
89 push ax
90 call IsFat12
91 pop ax
92 jnc LoadFile2
93 cmp ax,0ff8h ; Check to see if this is the last cluster in the chain
94 jmp LoadFile3
95 LoadFile2:
96 cmp ax,0fff8h
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,BYTE [BYTE 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 [BYTE bp+BootDrive] ; Load the boot drive into DL
127 mov dh,[BootPartition] ; Load the boot partition into DH
128 push WORD 0x0000
129 push WORD 0x8000 ; We will do a far return to 0000:8000h
130 retf ; Transfer control to ROSLDR
131
132
133 ; Reads the entire FAT into memory at 7000:0000
134 ReadFatIntoMemory:
135 mov ax,WORD [BYTE bp+HiddenSectors]
136 mov dx,WORD [BYTE bp+HiddenSectors+2]
137 add ax,WORD [BYTE bp+ReservedSectors]
138 adc dx,byte 0
139 mov cx,WORD [BYTE bp+SectorsPerFat]
140 mov bx,7000h
141 mov es,bx
142 xor bx,bx
143 call [bp-ReadSectorsOffset]
144 ret
145
146
147 ; Returns the FAT entry for a given cluster number for 16-bit FAT
148 ; On entry AX has cluster number
149 ; On return AX has FAT entry for that cluster
150 GetFatEntry16:
151
152 mov cx,2 ; AX = AX * 2 (since FAT16 entries are 2 bytes)
153 mul cx
154 shl dx,12
155
156 mov bx,7000h
157 add bx,dx
158 mov es,bx
159 mov bx,ax ; Restore FAT entry offset
160 mov ax,WORD [es:bx] ; Get FAT entry
161
162 ret
163
164
165 ; Returns the FAT entry for a given cluster number for 12-bit FAT
166 ; On entry AX has cluster number
167 ; On return AX has FAT entry for that cluster
168 GetFatEntry12:
169
170 push ax
171 mov cx,ax
172 shr ax,1
173 add ax,cx ; AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
174
175 mov bx,7000h
176 mov es,bx
177 mov bx,ax ; Put FAT entry offset into BX
178 mov ax,WORD [es:bx] ; Get FAT entry
179 pop cx ; Get cluster number from stack
180 and cx,1
181 jz UseLow12Bits
182 and ax,0fff0h
183 shr ax,4
184 jmp GetFatEntry12_Done
185
186 UseLow12Bits:
187 and ax,0fffh
188
189 GetFatEntry12_Done:
190
191 ret
192
193
194 ; Returns CF = 1 if this is a FAT12 file system
195 ; Otherwise CF = 0 for FAT16
196 IsFat12:
197
198 mov ebx,DWORD [BYTE bp-DataAreaStartLow]
199 ; EBX now has the number of the starting sector of the data area
200 ; starting from the beginning of the disk, so subtrace hidden sectors
201 sub ebx,DWORD [BYTE bp+HiddenSectors]
202
203
204 xor eax,eax
205 mov ax,WORD [BYTE bp+TotalSectors]
206 cmp ax,byte 0
207 jnz IsFat12_2
208 mov eax,DWORD [BYTE bp+TotalSectorsBig]
209
210 ; EAX now contains the number of sectors on the volume
211
212 IsFat12_2:
213 sub eax,ebx ; Subtract data area start sector
214 xor edx,edx ; from total sectors of volume
215
216 ; EDX:EAX now contains the number of data sectors on the volume
217 movzx ebx,BYTE [BYTE bp+SectsPerCluster]
218 div ebx
219 ; EAX now has the number of clusters on the volume
220 stc
221 cmp eax,4085
222 jb IsFat12_Done
223 clc
224
225 IsFat12_Done:
226 ret
227
228
229
230 msgLoading db 'Loading FreeLoader...',0dh,0ah,0
231
232 times 510-($-$$) db 0 ; Pad to 510 bytes
233 dw 0aa55h ; BootSector signature