2 // FAT12/16 Boot Sector Helper Code
3 // Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
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
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
41 #define BootPartition HEX(7dfd)
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.
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)
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.
64 /* First save AX - the start cluster of freeldr.sys */
67 /* Display "Loading FreeLoader..." message */
68 mov si, offset msgLoading
69 call word ptr [bp-PutCharsOffset]
71 call ReadFatIntoMemory
73 /* Restore AX (start cluster) */
76 // AX has start cluster of freeldr.sys
77 mov bx, FREELDR_BASE / 16
85 cmp ax, HEX(0ff8) // Check to see if this is the last cluster in the chain
91 jae LoadFile_Done // If so continue, if not then read then next one
93 xor bx,bx // Load ROSLDR starting at 0000:8000h
95 call word ptr [bp-ReadClusterOffset]
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
109 call GetFatEntry12 // Get the next entry
116 jmp LoadFile // Load the next cluster (if any)
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
122 /* continue where other bootsectors start */
126 // Reads the entire FAT into memory at 7000:0000
128 mov ax, [bp+HiddenSectors]
129 mov dx, [bp+HiddenSectors+2]
130 add ax, [bp+ReservedSectors]
132 mov cx, [bp+SectorsPerFat]
136 call word ptr [bp-ReadSectorsOffset]
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
144 mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)
151 mov bx,ax // Restore FAT entry offset
152 mov ax, es:[bx] // Get FAT entry
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
164 add ax,cx // AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
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
175 jmp GetFatEntry12_Done
185 // Returns CF = 1 if this is a FAT12 file system
186 // Otherwise CF = 0 for FAT16
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]
196 mov ax, word ptr [bp+TotalSectors]
199 mov eax, dword ptr [bp+TotalSectorsBig]
201 // EAX now contains the number of sectors on the volume
204 sub eax,ebx // Subtract data area start sector
205 xor edx,edx // from total sectors of volume
207 // EDX:EAX now contains the number of data sectors on the volume
208 movzx ebx, byte ptr [bp+SectsPerCluster]
210 // EAX now has the number of clusters on the volume
221 .ascii "Loading FreeLoader...", CR, LF, NUL
223 .org 510 // Pad to 510 bytes
224 .word HEX(0aa55) // BootSector signature