2 // FAT12/16 Boot Sector Helper Code
3 // Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
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
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
40 #define SerialNumber 39
41 #define VolumeLabel 43
44 #define BootPartition 0x7dfd
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.
52 // This code is loaded at 0000:8000 so we have to
53 // encode a jmp instruction to jump to 0000:8200
55 .global _mainCRTStartup // For Mingw32 builds where the linker looks for this symbol
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.
72 push ax // First save AX - the start cluster of freeldr.sys
75 // Display "Loading FreeLoader..." message
76 mov esi, offset msgLoading // Loading message
77 call [bp-PutCharsOffset] // Display it
80 call ReadFatIntoMemory
82 pop ax // Restore AX (start cluster)
83 // AX has start cluster of freeldr.sys
93 cmp ax,0x0ff8 // Check to see if this is the last cluster in the chain
98 jae LoadFile_Done // If so continue, if not then read then next one
100 xor bx,bx // Load ROSLDR starting at 0000:8000h
102 call [bp-ReadClusterOffset]
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
116 call GetFatEntry12 // Get the next entry
123 jmp LoadFile // Load the next cluster (if any)
126 mov dl,BYTE PTR [bp+BootDrive] // Load the boot drive into DL
127 mov dh,[BootPartition] // Load the boot partition into DH
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
135 // Reads the entire FAT into memory at 7000:0000
137 mov ax, [bp+HiddenSectors]
138 mov dx, [bp+HiddenSectors+2]
139 add ax, [bp+ReservedSectors]
141 mov cx, [bp+SectorsPerFat]
145 call [bp-ReadSectorsOffset]
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
154 mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)
161 mov bx,ax // Restore FAT entry offset
162 mov ax, es:[bx] // Get FAT entry
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
175 add ax,cx // AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
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
186 jmp GetFatEntry12_Done
196 // Returns CF = 1 if this is a FAT12 file system
197 // Otherwise CF = 0 for FAT16
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]
207 mov ax, [bp+TotalSectors]
210 mov eax, [bp+TotalSectorsBig]
212 // EAX now contains the number of sectors on the volume
215 sub eax,ebx // Subtract data area start sector
216 xor edx,edx // from total sectors of volume
218 // EDX:EAX now contains the number of data sectors on the volume
219 movzx ebx, byte ptr [bp+SectsPerCluster]
221 // EAX now has the number of clusters on the volume
232 msgLoading: .asciz "Loading FreeLoader...\r\n"
234 .org 0x1fe // Pad to 510 bytes
235 .word 0x0aa55 // BootSector signature