wok view BootProg/stuff/boot32.asm @ rev 25485

BootProg/fat32: active fat support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Nov 01 16:13:12 2022 +0000 (18 months ago)
parents 4c101652eb90
children f7324cde07d7
line source
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; ;;
3 ;; "BootProg" Loader v 1.5 by Alexey Frunze (c) 2000-2015 ;;
4 ;; 2-clause BSD license. ;;
5 ;; ;;
6 ;; ;;
7 ;; How to Compile: ;;
8 ;; ~~~~~~~~~~~~~~~ ;;
9 ;; nasm boot32.asm -f bin -o boot32.bin ;;
10 ;; ;;
11 ;; ;;
12 ;; Features: ;;
13 ;; ~~~~~~~~~ ;;
14 ;; - FAT32 supported using BIOS int 13h function 42h (IOW, it will only ;;
15 ;; work with modern BIOSes supporting HDDs bigger than 8 GB) ;;
16 ;; ;;
17 ;; - Loads a 16-bit executable file in the MS-DOS .COM or .EXE format ;;
18 ;; from the root directory of a disk and transfers control to it ;;
19 ;; (the "ProgramName" variable holds the name of the file to be loaded) ;;
20 ;; Its maximum size can be up to 637KB without Extended BIOS Data area. ;;
21 ;; ;;
22 ;; - Prints an error if the file isn't found or couldn't be read ;;
23 ;; ("File not found" or "Read error") ;;
24 ;; and waits for a key to be pressed, then executes the Int 19h ;;
25 ;; instruction and lets the BIOS continue bootstrap. ;;
26 ;; ;;
27 ;; ;;
28 ;; Known Bugs: ;;
29 ;; ~~~~~~~~~~~ ;;
30 ;; - All bugs are fixed as far as I know. The boot sector has been tested ;;
31 ;; on my HDD and an 8GB USB stick. ;;
32 ;; ;;
33 ;; ;;
34 ;; Memory Layout: ;;
35 ;; ~~~~~~~~~~~~~~ ;;
36 ;; The diagram below shows the typical memory layout. The actual location ;;
37 ;; of the boot sector and its stack may be lower than A0000H if the BIOS ;;
38 ;; reserves memory for its Extended BIOS Data Area just below A0000H and ;;
39 ;; reports less than 640 KB of RAM via its Int 12H function. ;;
40 ;; ;;
41 ;; physical address ;;
42 ;; +------------------------+ 00000H ;;
43 ;; | Interrupt Vector Table | ;;
44 ;; +------------------------+ 00400H ;;
45 ;; | BIOS Data Area | ;;
46 ;; +------------------------+ 00500H ;;
47 ;; | PrtScr Status / Unused | ;;
48 ;; +------------------------+ 00600H ;;
49 ;; | Loaded Image | ;;
50 ;; +------------------------+ nnnnnH ;;
51 ;; | Available Memory | ;;
52 ;; +------------------------+ A0000H - 1KB ;;
53 ;; | Boot Sector | ;;
54 ;; +------------------------+ A0000H - 0.5KB ;;
55 ;; | 0.5KB Boot Stack | ;;
56 ;; +------------------------+ A0000H ;;
57 ;; | Video RAM | ;;
58 ;; ;;
59 ;; ;;
60 ;; Boot Image Startup (register values): ;;
61 ;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;;
62 ;; ax = 0ffffh (both FCB in the PSP don't have a valid drive identifier), ;;
63 ;; bx = 0, dl = BIOS boot drive number (e.g. 0, 80H) ;;
64 ;; cs:ip = program entry point ;;
65 ;; ss:sp = program stack (don't confuse with boot sector's stack) ;;
66 ;; COM program defaults: cs = ds = es = ss = 50h, sp = 0, ip = 100h ;;
67 ;; EXE program defaults: ds = es = EXE data - 10h (fake MS-DOS psp), ;;
68 ;; cs:ip and ss:sp depends on EXE header ;;
69 ;; Magic numbers: ;;
70 ;; si = 16381 (prime number 2**14-3) ;;
71 ;; di = 32749 (prime number 2**15-19) ;;
72 ;; bp = 65521 (prime number 2**16-15) ;;
73 ;; The magic numbers let the program know whether it has been loaded by ;;
74 ;; this boot sector or by MS-DOS, which may be handy for universal, bare- ;;
75 ;; metal and MS-DOS programs. ;;
76 ;; The command line contains no arguments. ;;
77 ;; ;;
78 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
80 %define bx(label) bx+label-boot
81 %define si(label) si+label-boot
82 ExtraBootSector equ 1
83 ClusterMask equ 1 ; +9 bytes
84 NullEntryCheck equ 1 ; +5 bytes
85 CheckAttrib equ 1 ; +6 bytes
86 NonMirroredFATs equ 1 ; +18 bytes
87 ReadRetry equ 1 ; +7 bytes
88 LBA48bits equ 1 ; +15 bytes
89 CHSsupport equ 1 ; +27 bytes max 16MB, 32MB or 8GB
90 CHSupTo32MB equ 1 ; +6 bytes
91 CHSupTo8GB equ 1 ; +14 bytes
92 SectorOf512Bytes equ 0 ; -5 bytes
93 Always2FATs equ 0 ; -4 bytes
95 [BITS 16]
97 ImageLoadSeg equ 60h ; <=07Fh because of "push byte ImageLoadSeg" instructions
98 StackSize equ 512
100 [SECTION .text]
101 [ORG 0]
103 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
104 ;; Boot sector starts here ;;
105 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
107 boot:
108 DriveNumber equ boot+0
109 HiLBA equ boot+2
110 jmp short start ; MS-DOS/Windows checks for this jump
111 nop
112 bsOemName DB "BootProg" ; 0x03
114 ;;;;;;;;;;;;;;;;;;;;;;
115 ;; BPB1 starts here ;;
116 ;;;;;;;;;;;;;;;;;;;;;;
118 bpbBytesPerSector DW 0 ; 0x0B
119 bpbSectorsPerCluster DB 0 ; 0x0D
120 bpbReservedSectors DW 0 ; 0x0E
121 bpbNumberOfFATs DB 0 ; 0x10
122 bpbRootEntries DW 0 ; 0x11
123 bpbTotalSectors DW 0 ; 0x13
124 bpbMedia DB 0 ; 0x15
125 bpbSectorsPerFAT DW 0 ; 0x16
126 bpbSectorsPerTrack DW 0 ; 0x18
127 bpbHeadsPerCylinder DW 0 ; 0x1A
128 bpbHiddenSectors DD 0 ; 0x1C
129 bpbTotalSectorsBig DD 0 ; 0x20
131 ;;;;;;;;;;;;;;;;;;;;
132 ;; BPB1 ends here ;;
133 ;;;;;;;;;;;;;;;;;;;;
135 ;;;;;;;;;;;;;;;;;;;;;;
136 ;; BPB2 starts here ;;
137 ;;;;;;;;;;;;;;;;;;;;;;
139 bsSectorsPerFAT32 DD 0 ; 0x24
140 bsExtendedFlags DW 0 ; 0x28
141 bsFSVersion DW 0 ; 0x2A
142 bsRootDirectoryClusterNo DD 0 ; 0x2C
143 bsFSInfoSectorNo DW 0 ; 0x30
144 bsBackupBootSectorNo DW 0 ; 0x32
145 bsreserved times 12 DB 0 ; 0x34
146 bsDriveNumber DB 0 ; 0x40
147 bsreserved1 DB 0 ; 0x41
148 bsExtendedBootSignature DB 0 ; 0x42
149 bsVolumeSerialNumber DD 0 ; 0x43
150 bsVolumeLabel times 11 DB " " ; 0x47 "NO NAME "
151 bsFileSystemName times 8 DB " " ; 0x52 "FAT32 "
153 ;;;;;;;;;;;;;;;;;;;;
154 ;; BPB2 ends here ;;
155 ;;;;;;;;;;;;;;;;;;;;
157 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
158 ;; Boot sector code starts here ;;
159 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
161 start:
162 cld
164 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
165 ;; How much RAM is there? ;;
166 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
168 int 12h ; get conventional memory size (in KBs)
169 dec ax ; reserve 1K bytes for the code and the stack
170 mov cx, 106h
171 shl ax, cl ; and convert it to 16-byte paragraphs
173 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
174 ;; Reserve memory for the boot sector and its stack ;;
175 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
177 mov es, ax ; cs:0 = ds:0 = ss:0 -> top - 512 - StackSize
178 %if ExtraBootSector == 0
179 mov ss, ax
180 mov sp, 512+StackSize ; bytes 0-511 are reserved for the boot code
181 %endif
183 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
184 ;; Copy ourselves to top of memory ;;
185 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
187 mov si, 7C00h
188 xor di, di
189 mov ds, di
190 push es
191 mov [si(DriveNumber)], dx ; store BIOS boot drive number
192 rep movsw
194 ;;;;;;;;;;;;;;;;;;;;;;
195 ;; Jump to the copy ;;
196 ;;;;;;;;;;;;;;;;;;;;;;
198 push byte main
199 push es
200 pop ds
201 retf
203 main:
204 xor ebx, ebx
205 %if ExtraBootSector != 0
206 add al, 32
207 mov es, ax
208 mov eax, [bx(bpbHiddenSectors)]
209 inc eax
210 %if LBA48bits != 0
211 mov [bx(HiLBA)], bx
212 %endif
213 call ReadSectorBoot
214 push ds
215 pop ss
216 mov sp, 512+StackSize ; bytes 0-511 are reserved for the boot code
217 %endif
219 %if ClusterMask != 0
220 and byte [bx(bsRootDirectoryClusterNo+3)], 0Fh ; mask cluster value
221 %endif
222 mov esi, [bx(bsRootDirectoryClusterNo)] ; esi=cluster # of root dir
224 push byte ImageLoadSeg
225 pop es
227 RootDirReadContinue:
228 call ReadClusterSector ; read one sector of the root dir
230 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
231 ;; Look for the COM/EXE file to load and run ;;
232 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
234 xor di, di ; es:di -> root entries array
236 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
237 ;; Looks for a file/dir by its name ;;
238 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
239 ;; Input: DS:SI -> file name (11 chars) ;;
240 ;; ES:DI -> root directory array ;;
241 ;; BP = paragraphs in sector ;;
242 ;; Output: ESI = cluster number ;;
243 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
245 FindNameCycle:
246 %if NullEntryCheck != 0
247 cmp byte [es:di], bh
248 je ErrFind ; end of root directory (NULL entry found)
249 %endif
250 pusha
251 mov cl, NameLength
252 mov si, ProgramName ; ds:si -> program name
253 repe cmpsb
254 %if CheckAttrib != 0
255 VolumeLabel equ 8
256 SubDirectory equ 10h
257 jnz SkipFindName
258 test byte [es:di], VolumeLabel+SubDirectory
259 SkipFindName:
260 %endif
261 je FindNameFound
262 popa
263 add di, byte 32
264 dec bp
265 dec bp
266 jnz FindNameCycle ; next root entry
267 loop RootDirReadContinue ; next sector in cluster
268 cmp esi, 0FFFFFF6h ; carry=0 if last cluster, and carry=1 otherwise
269 jnc RootDirReadContinue ; continue to the next root dir cluster
270 ErrFind:
271 call Error ; end of root directory (dir end reached)
272 db "File not found."
273 FindNameFound:
274 push word [es:di+14h-11]
275 push word [es:di+1Ah-11]
276 pop esi ; esi = cluster no. cx = 0
278 dec dword [es:di+1Ch-11] ; load ((n - 1)/256)*16 +1 paragraphs
279 imul di, [es:di+1Ch+1-11], byte 16 ; file size in paragraphs (full pages)
281 ;;;;;;;;;;;;;;;;;;;;;;;;;;
282 ;; Load the entire file ;;
283 ;;;;;;;;;;;;;;;;;;;;;;;;;;
285 push es
286 FileReadContinue:
287 push di
288 call ReadClusterSector ; read one sector of the boot file
289 dec cx
290 mov di, es
291 add di, bp
292 mov es, di ; es:bx updated
293 pop di
295 sub di, bp
296 jae FileReadContinue
297 xor ax, ax
298 pop bp
300 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
301 ;; Type detection, .COM or .EXE? ;;
302 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
304 mov ds, bp ; bp=ds=seg the file is loaded to
306 add bp, [bx+08h] ; bp = image base
307 mov di, [bx+18h] ; di = reloc table pointer
309 cmp word [bx], 5A4Dh ; "MZ" signature?
310 je RelocateEXE ; yes, it's an EXE program
312 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
313 ;; Setup and run a .COM program ;;
314 ;; Set CS=DS=ES=SS SP=0 IP=100h ;;
315 ;; AX=0ffffh BX=0 DX=drive and ;;
316 ;; cmdline=void ;;
317 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
319 mov di, 100h ; ip
320 mov bp, ImageLoadSeg-10h ; "org 100h" stuff :)
321 mov ss, bp
322 xor sp, sp
323 push bp ; cs, ds and es
324 %if ExtraBootSector != 0
325 jmp Run
326 %macro BootFileName 0
327 %else
328 jmp short Run
329 %endif
331 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
332 ;; Relocate, setup and run a .EXE program ;;
333 ;; Set CS:IP, SS:SP, DS, ES and AX according ;;
334 ;; to wiki.osdev.org/MZ#Initial_Program_State ;;
335 ;; AX=0ffffh BX=0 DX=drive cmdline=void ;;
336 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
338 ReloCycle:
339 add [di+2], bp ; item seg (abs)
340 les si, [di] ; si = item ofs, es = item seg
341 add [es:si], bp ; fixup
342 scasw ; di += 2
343 scasw ; point to next entry
345 RelocateEXE:
346 dec word [bx+06h] ; reloc items, 32768 max (128KB table)
347 jns ReloCycle
349 les si, [bx+0Eh]
350 add si, bp
351 mov ss, si ; ss for EXE
352 mov sp, es ; sp for EXE
354 lea si, [bp-10h] ; ds and es both point to the segment
355 push si ; containing the PSP structure
357 add bp, [bx+16h] ; cs for EXE
358 mov di, [bx+14h] ; ip for EXE
359 Run:
360 pop ds
361 push bp
362 push di
363 push ds
364 pop es
365 mov [80h], ax ; clear cmdline
366 dec ax ; both FCB in the PSP don't have a valid drive identifier
368 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
369 ;; Set the magic numbers so the program knows that it ;;
370 ;; has been loaded by this bootsector and not by MS-DOS ;;
371 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
372 mov si, 16381 ; prime number 2**14-3
373 mov di, 32749 ; prime number 2**15-19
374 mov bp, 65521 ; prime number 2**16-15
376 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
377 ;; All done, transfer control to the program now ;;
378 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
379 retf
380 %if ExtraBootSector != 0
381 %endm
382 %endif
384 ;;;;;;;;;;;;;;;;;;;;;;;;;;
385 ;; Error Messaging Code ;;
386 ;;;;;;;;;;;;;;;;;;;;;;;;;;
388 Error:
389 pop si
390 puts:
391 mov ah, 0Eh
392 mov bl, 7
393 lodsb
394 int 10h
395 cmp al, '.'
396 jne puts
397 cbw
398 int 16h ; wait for a key...
399 int 19h ; bootstrap
401 Stop:
402 hlt
403 jmp short Stop
405 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
406 ;; Reads a FAT32 sector ;;
407 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
408 ;; Inout: ES:BX -> buffer ;;
409 ;; EAX = prev sector ;;
410 ;; CX = rem sectors in cluster ;;
411 ;; ESI = next cluster ;;
412 ;; Output: EAX = current sector ;;
413 ;; CX = rem sectors in cluster ;;
414 ;; ESI = next cluster ;;
415 ;; BP -> para / sector ;;
416 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
418 ReadClusterSector:
419 %if SectorOf512Bytes != 0
420 mov bp, 32 ; bp = paragraphs per sector
421 %else
422 mov bp, [bx(bpbBytesPerSector)]
423 shr bp, 4 ; bp = paragraphs per sector
424 %endif
425 mov dx, 1 ; adjust LBA for next sector
426 inc cx
427 loop ReadSectorLBA
429 mul ebx ; edx:eax = 0
430 %if SectorOf512Bytes != 0
431 mov al, 128 ; ax=# of FAT32 entries per sector
432 %else
433 imul ax, bp, byte 4 ; ax=# of FAT32 entries per sector
434 %endif
435 lea edi, [esi-2] ; esi=cluster #
436 xchg eax, esi
437 div esi ; eax=FAT sector #, edx=entry # in sector
439 imul si, dx, byte 4 ; si=entry # in sector, clear C
440 %if NonMirroredFATs != 0
441 cwde
442 or dl, byte [bx(bsExtendedFlags)]
443 jns MirroredFATs ; Non-mirrored FATs ?
444 and dl, 0Fh
445 imul edx, dword [bx(bsSectorsPerFAT32)] ; we need to read the active one
446 add eax, edx
447 MirroredFATs:
448 cwde
449 %else
450 %if LBA48bits != 0
451 xor dx, dx
452 %endif
453 %endif
454 call ReadSectorLBAfromFAT ; read 1 FAT32 sector
456 %if ClusterMask != 0
457 and byte [es:si+3], 0Fh ; mask cluster value
458 %endif
459 mov esi, [es:si] ; esi=next cluster #
461 %if Always2FATs != 0
462 imul eax, dword [bx(bsSectorsPerFAT32)], 2
463 %else
464 movzx eax, byte [bx(bpbNumberOfFATs)]
465 mul dword [bx(bsSectorsPerFAT32)]
466 %endif
468 xchg eax, edi
469 movzx ecx, byte [bx(bpbSectorsPerCluster)] ; 8..128
470 mul ecx ; edx:eax=sector number in data area
471 add eax, edi
472 %if LBA48bits != 0
473 adc dx, bx
474 %endif
476 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
477 ;; Reads a sector form the start of FAT ;;
478 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
480 ReadSectorLBAfromFAT:
481 add eax, [bx(bpbHiddenSectors)]
482 %if LBA48bits != 0
483 adc dx, bx
484 mov word [bx(HiLBA)], dx
485 %endif
486 mov dx, [bx(bpbReservedSectors)]
488 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
489 ;; Reads a sector using BIOS Int 13h fn 42h ;;
490 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
491 ;; Input: EAX = LBA ;;
492 ;; CX = sector count ;;
493 ;; ES:BX -> buffer address ;;
494 ;; Output: CF = 0 if no more sectors ;;
495 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
497 ReadSectorLBA:
498 add eax, edx
499 %if LBA48bits != 0
500 adc word [bx(HiLBA)], bx
501 %endif
502 ReadSectorBoot:
503 mov dx, [bx(DriveNumber)] ; restore BIOS boot drive number
504 pusha
506 push bx
507 %if LBA48bits != 0
508 push word [bx(HiLBA)] ; 48-bit LBA
509 %else
510 push bx
511 %endif
512 push eax
513 push es
514 push bx
515 push byte 1 ; sector count word = 1
516 push byte 16 ; packet size byte = 16, reserved byte = 0
518 %if CHSsupport != 0
519 %if CHSupTo8GB != 0
520 push eax
521 pop cx ; save low LBA
522 pop ax ; get high LBA
523 cwd ; clear dx (assume LBA offset <1TB)
524 idiv word [bx(bpbSectorsPerTrack)] ; up to 8GB disks, avoid divide error
526 xchg ax, cx ; restore low LBA, save high LBA / SPT
527 %else
528 ; Busybox mkdosfs creates fat32 for floppies.
529 ; Floppies may support CHS only.
530 %if CHSupTo32MB != 0
531 xor dx, dx ; clear dx (LBA offset <32MB)
532 %else
533 cwd ; clear dx (LBA offset <16MB)
534 %endif
535 xor cx, cx ; high LBA / SPT = 0
536 %endif
537 idiv word [bx(bpbSectorsPerTrack)]
538 ; ax = LBA / SPT
539 ; dx = LBA % SPT = sector - 1
540 inc dx
542 xchg cx, dx ; restore high LBA / SPT, save sector no.
543 idiv word [bx(bpbHeadsPerCylinder)]
544 ; ax = (LBA / SPT) / HPC = cylinder
545 ; dx = (LBA / SPT) % HPC = head
547 xchg ch, al ; clear al
548 ; ch = LSB 0...7 of cylinder no.
549 %if CHSupTo8GB != 0 || CHSupTo32MB != 0
550 shr ax, 2
551 or cl, al
552 ; cl = MSB 8...9 of cylinder no. + sector no.
553 %endif
554 mov dh, dl
555 ; dh = head no.
556 mov dl, [bx(DriveNumber)] ; restore BIOS boot drive number
557 %endif
559 ReadSectorRetry:
560 mov si, sp
561 mov ah, 42h ; ah = 42h = extended read function no.
562 int 13h ; extended read sectors (DL, DS:SI)
563 jnc ReadSuccess ; CF = 0 if no error
565 %if CHSsupport != 0
566 mov ax, 201h ; al = sector count = 1
567 ; ah = 2 = read function no.
568 int 13h ; read sectors (AL, CX, DX, ES:BX)
570 jnc ReadSuccess ; CF = 0 if no error
571 %endif
572 %if ReadRetry != 0
573 %if CHSsupport != 0
574 cbw ; ah = 0 = reset function
575 %else
576 xor ax, ax ; ah = 0 = reset function
577 %endif
578 int 13h ; reset drive (DL)
580 dec bp ; up to 32 retries
581 jnz ReadSectorRetry
582 %endif
584 call Error
585 db "Read error."
587 ReadSuccess:
589 popa ; sp += 16
590 popa
591 ret
593 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
594 ;; Fill free space with zeroes ;;
595 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
597 times (512-13-($-$$)) db 0
599 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
600 ;; Name of the file to load and run ;;
601 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
603 NameLength equ 11
604 ProgramName times NameLength db 0 ; name and extension
606 ;;;;;;;;;;;;;;;;;;;;;;;;;;
607 ;; End of the sector ID ;;
608 ;;;;;;;;;;;;;;;;;;;;;;;;;;
610 dw 0AA55h ; BIOS checks for this ID
612 %if ExtraBootSector != 0
613 dd 61415252h ; "RRaA"
614 BootFileName
615 times (996-($-$$)) db 0
616 ; dd 41617272h ; "rrAa"
617 %endif