2 // FAT12/16 Boot Sector Helper Code
3 // Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
11 #define BootSectorStackTop 0x7bf2
12 #define DataAreaStartHigh 0x2
13 #define DataAreaStartLow 0x4
14 #define BiosCHSDriveSizeHigh 0x6
15 #define BiosCHSDriveSizeLow 0x8
16 #define BiosCHSDriveSize 0x8
17 #define ReadSectorsOffset 0xa
18 #define ReadClusterOffset 0xc
19 #define PutCharsOffset 0xe
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
37 #define SerialNumber 39
38 #define VolumeLabel 43
42 // This code will be stored in the first 512 bytes
43 // of freeldr.sys. The first 3 bytes will be a jmp
44 // instruction to skip past the FAT helper code
45 // that is stored in the rest of the 512 bytes.
47 // This code is loaded at 0000:8000 so we have to
48 // encode a jmp instruction to jump to 0000:8200
51 .global _mainCRTStartup // For Mingw32 builds where the linker looks for this symbol
59 // Now starts the extra boot code that we will store
60 // in the first 512 bytes of freeldr.sys. This code
61 // allows the FAT12/16 bootsector to navigate the
62 // FAT table so that we can still load freeldr.sys
63 // even if it is fragmented.
68 push ax // First save AX - the start cluster of freeldr.sys
71 // Display "Loading FreeLoader..." message
72 mov esi, offset msgLoading // Loading message
73 call [bp-PutCharsOffset] // Display it
76 call ReadFatIntoMemory
78 pop ax // Restore AX (start cluster)
79 // AX has start cluster of freeldr.sys
89 cmp ax,0x0ff8 // Check to see if this is the last cluster in the chain
94 jae LoadFile_Done // If so continue, if not then read then next one
96 xor bx,bx // Load ROSLDR starting at 0000:8000h
98 call [bp-ReadClusterOffset]
102 mov bl, [bp+SectsPerCluster]
103 shl bx,5 // BX = BX * 512 / 16
104 mov ax,es // Increment the load address by
105 add ax,bx // The size of a cluster
112 call GetFatEntry12 // Get the next entry
119 jmp LoadFile // Load the next cluster (if any)
122 mov dl, [bp+BootDrive] // Load the boot drive into DL
123 mov dh, BootPartition // Load the boot partition into DH
125 push word ptr 0x8000 // We will do a far return to 0000:8000h
127 // retf // Transfer control to ROSLDR
128 .byte 0xcb // == retf
131 // Reads the entire FAT into memory at 7000:0000
133 mov ax, [bp+HiddenSectors]
134 mov dx, [bp+HiddenSectors+2]
135 add ax, [bp+ReservedSectors]
137 mov cx, [bp+SectorsPerFat]
141 call [bp-ReadSectorsOffset]
145 // Returns the FAT entry for a given cluster number for 16-bit FAT
146 // On entry AX has cluster number
147 // On return AX has FAT entry for that cluster
150 mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)
157 mov bx,ax // Restore FAT entry offset
158 mov ax, [es:bx] // Get FAT entry
163 // Returns the FAT entry for a given cluster number for 12-bit FAT
164 // On entry AX has cluster number
165 // On return AX has FAT entry for that cluster
171 add ax,cx // AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
175 mov bx,ax // Put FAT entry offset into BX
176 mov ax, [es:bx] // Get FAT entry
177 pop cx // Get cluster number from stack
182 jmp GetFatEntry12_Done
192 // Returns CF = 1 if this is a FAT12 file system
193 // Otherwise CF = 0 for FAT16
196 mov ebx, [bp-DataAreaStartLow]
197 // EBX now has the number of the starting sector of the data area
198 // starting from the beginning of the disk, so subtrace hidden sectors
199 sub ebx, [bp+HiddenSectors]
203 mov ax, [bp+TotalSectors]
206 mov eax, [bp+TotalSectorsBig]
208 // EAX now contains the number of sectors on the volume
211 sub eax,ebx // Subtract data area start sector
212 xor edx,edx // from total sectors of volume
214 // EDX:EAX now contains the number of data sectors on the volume
215 movzx ebx, byte ptr [bp+SectsPerCluster]
217 // EAX now has the number of clusters on the volume
229 .ascii "Loading FreeLoader..."
232 // times 510-($-$$) db 0 // Pad to 510 bytes
234 .word 0x0aa55 // BootSector signature