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