3 ; Copyright (c) 1998, 2000 Brian Palmer
20 MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
21 TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
22 MediaDescriptor db 0f8h
23 SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
32 RootDirStartCluster dd 0
35 Reserved1 times 12 db 0
36 ; End FAT32 Inserted Info
40 SerialNumber dd 00000000h
41 VolumeLabel db 'FreeLoader!'
42 FileSystem db 'FAT32 '
49 mov sp,7c00h ; Setup a stack
50 mov ax,cs ; Setup segment registers
51 mov ds,ax ; Make DS correct
52 mov es,ax ; Make ES correct
56 mov [BootDrive],dl ; Save the boot drive
57 xor ax,ax ; Zero out AX
59 ; Reset disk controller
62 jmp BadBoot ; Reset failed...
65 ; First we have to load our extra boot code at
66 ; sector 14 into memory at [0000:7e00h]
69 add ax,WORD [HiddenSectors]
70 adc dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors
73 mov es,bx ; Read sector to [0000:7e00h]
81 ; Now we must get the first cluster of the root directory
82 mov eax,DWORD [RootDirStartCluster]
83 cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
84 jb Continue2 ; If not continue, if so BadBoot
88 mov es,bx ; Read cluster to [0000:8000h]
89 call ReadCluster ; Read the cluster
92 ; Now we have to find our way through the root directory to
93 ; The OSLOADER.SYS file
95 mov bl,[SectsPerCluster]
96 shl bx,4 ; BX = BX * 512 / 32
97 mov ax,800h ; We loaded at 0800:0000
102 rep cmpsb ; Compare filenames
103 jz FoundFile ; If same we found it
109 mov ax,es ; We didn't find it in the previous dir entry
110 add ax,2 ; So lets move to the next one
111 mov es,ax ; And search again
115 rep cmpsb ; Compare filenames
116 jz FoundFile ; If same we found it
117 dec bx ; Keep searching till we run out of dir entries
118 jnz FindFile ; Last entry?
120 ; Get the next root dir cluster and try again until we run out of clusters
121 mov eax,DWORD [RootDirStartCluster]
123 mov [RootDirStartCluster],eax
127 xor di,di ; ES:DI has dir entry
129 mov ax,WORD [es:di+14h] ; Get start cluster high word
131 mov ax,WORD [es:di+1ah] ; Get start cluster low word
137 cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
138 jae FoundFile3 ; If so continue, if not then read then next one
140 xor bx,bx ; Load ROSLDR starting at 0000:8000h
146 mov bl,[SectsPerCluster]
147 shl bx,5 ; BX = BX * 512 / 16
148 mov ax,es ; Increment the load address by
149 add ax,bx ; The size of a cluster
154 call GetFatEntry ; Get the next entry
157 jmp FoundFile2 ; Load the next cluster (if any)
164 push ax ; We will do a far return to 0000:8000h
165 retf ; Transfer control to ROSLDR
169 ; Reads logical sectors into [ES:BX]
170 ; DX:AX has logical sector number to read
171 ; CX has number of sectors to read
172 ; CarryFlag set on error
180 div WORD [SectorsPerTrack]
182 div WORD [SectorsPerTrack] ; Divide logical by SectorsPerTrack
183 inc dx ; Sectors numbering starts at 1 not 0
185 div WORD [NumberOfHeads] ; Number of heads
186 mov dh,dl ; Head to DH, drive to DL
187 mov dl,[BootDrive] ; Drive number
188 mov ch,al ; Cylinder in CX
189 ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits
190 ror ah,1 ; in CL shifted to bits 6 & 7
191 or cl,ah ; Or with sector number
193 int 13h ; DISK - READ SECTORS INTO MEMORY
194 ; AL = number of sectors to read, CH = track, CL = sector
195 ; DH = head, DL = drive, ES:BX -> buffer to fill
196 ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
201 inc ax ;Increment Sector to Read
212 ; Increment read buffer for next sector
213 loop ReadSectors ; Read next sector
222 ; Displays a bad boot message
225 mov si,msgDiskError ; Bad boot disk message
226 call PutChars ; Display it
227 mov si,msgAnyKey ; Press any key message
228 call PutChars ; Display it
232 ; Displays an error message
235 mov si,msgFreeLdr ; FreeLdr not found message
236 call PutChars ; Display it
237 mov si,msgAnyKey ; Press any key message
238 call PutChars ; Display it
242 int 16h ; Wait for a keypress
256 msgDiskError db 'Disk error',0dh,0ah,0
257 msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0
258 msgAnyKey db 'Press any key to continue.',0dh,0ah,0
259 filename db 'FREELDR SYS'
261 times 510-($-$$) db 0 ; Pad to 510 bytes
262 dw 0aa55h ; BootSector signature
267 ; Now starts the extra boot code that we will store
268 ; at sector 14 on a FAT32 volume
270 ; To remain multi-boot compatible with other operating
271 ; systems we must not overwrite anything other than
272 ; the bootsector which means we will have to use
273 ; a different sector like 14 to store our extra boot code
275 ; Note: Win2k uses sector 12 for this purpose
278 ; Returns the FAT entry for a given cluster number
279 ; On entry EAX has cluster number
280 ; On return EAX has FAT entry for that cluster
283 shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)
284 mov ecx,eax ; Save this for later in ECX
286 movzx ebx,WORD [BytesPerSector]
288 div ebx ; FAT Sector Number = EAX / BytesPerSector
289 movzx ebx,WORD [ReservedSectors]
290 add eax,ebx ; FAT Sector Number += ReservedSectors
291 movzx ebx,WORD [HiddenSectors]
292 add eax,ebx ; FAT Sector Number += HiddenSectors
295 and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
296 ; EAX holds logical FAT sector number
297 ; ECX holds FAT entry offset
302 ; DX:AX holds logical FAT sector number
305 xor bx,bx ; We will load it to [7000:0000h]
314 mov eax,DWORD [es:ecx] ; Get FAT entry
315 and eax,0fffffffh ; Mask off reserved bits
320 ; Reads cluster number in EAX into [ES:0000]
322 ; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
327 movzx ebx,BYTE [SectsPerCluster]
331 movzx eax,BYTE [NumberOfFats]
332 mul DWORD [SectorsPerFatBig]
333 movzx ebx,WORD [ReservedSectors]
335 add eax,DWORD [HiddenSectors]
337 add eax,ebx ; EAX now contains the logical sector number of the cluster
341 xor bx,bx ; We will load it to [ES:0000], ES loaded before function call
342 movzx cx,BYTE [SectsPerCluster]
350 times 1022-($-$$) db 0 ; Pad to 1022 bytes
351 dw 0aa55h ; BootSector signature