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 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,WORD [BYTE bp+HiddenSectors]
138 mov dx,WORD [BYTE bp+HiddenSectors+2]
139 add ax,WORD [BYTE bp+ReservedSectors]
141 mov cx,WORD [BYTE 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,WORD [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,WORD [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,DWORD [BYTE 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,DWORD [BYTE bp+HiddenSectors]
207 mov ax,WORD [BYTE bp+TotalSectors]
210 mov eax,DWORD [BYTE 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 [BYTE bp+SectsPerCluster]
221 ; EAX now has the number of clusters on the volume
232 msgLoading db 'Loading FreeLoader...',0dh,0ah,0
234 times 510-($-$$) db 0 ; Pad to 510 bytes
235 dw 0aa55h ; BootSector signature