2 ; FAT12/16 Boot Sector Helper Code
3 ; Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
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
26 SectsPerCluster equ 13
27 ReservedSectors equ 14
31 MediaDescriptor equ 21
33 SectorsPerTrack equ 24
36 TotalSectorsBig equ 32
44 BootPartition equ 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,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,0ff8h ; 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,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
116 call GetFatEntry12 ; Get the next entry
123 jmp LoadFile ; Load the next cluster (if any)
126 mov dl,BYTE [BYTE bp+BootDrive] ; Load the boot drive into DL
127 mov dh,[BootPartition] ; Load the boot partition into DH
129 push WORD 0x8000 ; We will do a far return to 0000:8000h
130 retf ; Transfer control to ROSLDR
133 ; Reads the entire FAT into memory at 7000:0000
135 mov ax,WORD [BYTE bp+HiddenSectors]
136 mov dx,WORD [BYTE bp+HiddenSectors+2]
137 add ax,WORD [BYTE bp+ReservedSectors]
139 mov cx,WORD [BYTE bp+SectorsPerFat]
143 call [bp-ReadSectorsOffset]
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
152 mov cx,2 ; AX = AX * 2 (since FAT16 entries are 2 bytes)
159 mov bx,ax ; Restore FAT entry offset
160 mov ax,WORD [es:bx] ; Get FAT entry
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
173 add ax,cx ; AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
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
184 jmp GetFatEntry12_Done
194 ; Returns CF = 1 if this is a FAT12 file system
195 ; Otherwise CF = 0 for FAT16
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]
205 mov ax,WORD [BYTE bp+TotalSectors]
208 mov eax,DWORD [BYTE bp+TotalSectorsBig]
210 ; EAX now contains the number of sectors on the volume
213 sub eax,ebx ; Subtract data area start sector
214 xor edx,edx ; from total sectors of volume
216 ; EDX:EAX now contains the number of data sectors on the volume
217 movzx ebx,BYTE [BYTE bp+SectsPerCluster]
219 ; EAX now has the number of clusters on the volume
230 msgLoading db 'Loading FreeLoader...',0dh,0ah,0
232 times 510-($-$$) db 0 ; Pad to 510 bytes
233 dw 0aa55h ; BootSector signature