Fix DOS interrupt error messages
[syslinux.git] / core / isolinux.asm
blob52d426f9bf485bc71e613d44d39470e8f6a84842
1 ; -*- fundamental -*- (asm-mode sucks)
2 ; ****************************************************************************
4 ; isolinux.asm
6 ; A program to boot Linux kernels off a CD-ROM using the El Torito
7 ; boot standard in "no emulation" mode, making the entire filesystem
8 ; available. It is based on the SYSLINUX boot loader for MS-DOS
9 ; floppies.
11 ; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
13 ; This program is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
16 ; Boston MA 02111-1307, USA; either version 2 of the License, or
17 ; (at your option) any later version; incorporated herein by reference.
19 ; ****************************************************************************
21 %define IS_ISOLINUX 1
22 %include "head.inc"
25 ; Some semi-configurable constants... change on your own risk.
27 my_id equ isolinux_id
28 FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
29 FILENAME_MAX equ (1 << FILENAME_MAX_LG2)
30 NULLFILE equ 0 ; Zero byte == null file name
31 NULLOFFSET equ 0 ; Position in which to look
32 retry_count equ 6 ; How patient are we with the BIOS?
33 %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
34 MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
35 MAX_OPEN equ (1 << MAX_OPEN_LG2)
36 SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement)
37 SECTOR_SIZE equ (1 << SECTOR_SHIFT)
40 ; This is what we need to do when idle
42 %macro RESET_IDLE 0
43 ; Nothing
44 %endmacro
45 %macro DO_IDLE 0
46 ; Nothing
47 %endmacro
50 ; The following structure is used for "virtual kernels"; i.e. LILO-style
51 ; option labels. The options we permit here are `kernel' and `append
52 ; Since there is no room in the bottom 64K for all of these, we
53 ; stick them in high memory and copy them down before we need them.
55 struc vkernel
56 vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
57 vk_rname: resb FILENAME_MAX ; Real name
58 vk_appendlen: resw 1
59 vk_type: resb 1 ; Type of file
60 alignb 4
61 vk_append: resb max_cmd_len+1 ; Command line
62 alignb 4
63 vk_end: equ $ ; Should be <= vk_size
64 endstruc
67 ; Segment assignments in the bottom 640K
68 ; 0000h - main code/data segment (and BIOS segment)
70 real_mode_seg equ 2000h
71 xfer_buf_seg equ 1000h ; Bounce buffer for I/O to high mem
72 comboot_seg equ real_mode_seg ; COMBOOT image loading zone
75 ; File structure. This holds the information for each currently open file.
77 struc open_file_t
78 file_sector resd 1 ; Sector pointer (0 = structure free)
79 file_bytesleft resd 1 ; Number of bytes left
80 file_left resd 1 ; Number of sectors left
81 resd 1 ; Unused
82 endstruc
84 %ifndef DEPEND
85 %if (open_file_t_size & (open_file_t_size-1))
86 %error "open_file_t is not a power of 2"
87 %endif
88 %endif
90 struc dir_t
91 dir_lba resd 1 ; Directory start (LBA)
92 dir_len resd 1 ; Length in bytes
93 dir_clust resd 1 ; Length in clusters
94 endstruc
96 ; ---------------------------------------------------------------------------
97 ; BEGIN CODE
98 ; ---------------------------------------------------------------------------
101 ; Memory below this point is reserved for the BIOS and the MBR
103 section .earlybss
104 trackbufsize equ 8192
105 trackbuf resb trackbufsize ; Track buffer goes here
106 ; ends at 2800h
108 ; Some of these are touched before the whole image
109 ; is loaded. DO NOT move this to .uibss.
110 section .bss2
111 alignb 4
112 ISOFileName resb 64 ; ISO filename canonicalization buffer
113 ISOFileNameEnd equ $
114 CurDir resb dir_t_size ; Current directory
115 RootDir resb dir_t_size ; Root directory
116 FirstSecSum resd 1 ; Checksum of bytes 64-2048
117 ImageDwords resd 1 ; isolinux.bin size, dwords
118 InitStack resd 1 ; Initial stack pointer (SS:SP)
119 DiskSys resw 1 ; Last INT 13h call
120 ImageSectors resw 1 ; isolinux.bin size, sectors
121 DiskError resb 1 ; Error code for disk I/O
122 DriveNumber resb 1 ; CD-ROM BIOS drive number
123 ISOFlags resb 1 ; Flags for ISO directory search
124 RetryCount resb 1 ; Used for disk access retries
126 _spec_start equ $
129 ; El Torito spec packet
132 alignb 8
133 spec_packet: resb 1 ; Size of packet
134 sp_media: resb 1 ; Media type
135 sp_drive: resb 1 ; Drive number
136 sp_controller: resb 1 ; Controller index
137 sp_lba: resd 1 ; LBA for emulated disk image
138 sp_devspec: resw 1 ; IDE/SCSI information
139 sp_buffer: resw 1 ; User-provided buffer
140 sp_loadseg: resw 1 ; Load segment
141 sp_sectors: resw 1 ; Sector count
142 sp_chs: resb 3 ; Simulated CHS geometry
143 sp_dummy: resb 1 ; Scratch, safe to overwrite
146 ; EBIOS drive parameter packet
148 alignb 8
149 drive_params: resw 1 ; Buffer size
150 dp_flags: resw 1 ; Information flags
151 dp_cyl: resd 1 ; Physical cylinders
152 dp_head: resd 1 ; Physical heads
153 dp_sec: resd 1 ; Physical sectors/track
154 dp_totalsec: resd 2 ; Total sectors
155 dp_secsize: resw 1 ; Bytes per sector
156 dp_dpte: resd 1 ; Device Parameter Table
157 dp_dpi_key: resw 1 ; 0BEDDh if rest valid
158 dp_dpi_len: resb 1 ; DPI len
159 resb 1
160 resw 1
161 dp_bus: resb 4 ; Host bus type
162 dp_interface: resb 8 ; Interface type
163 db_i_path: resd 2 ; Interface path
164 db_d_path: resd 2 ; Device path
165 resb 1
166 db_dpi_csum: resb 1 ; Checksum for DPI info
169 ; EBIOS disk address packet
171 alignb 8
172 dapa: resw 1 ; Packet size
173 .count: resw 1 ; Block count
174 .off: resw 1 ; Offset of buffer
175 .seg: resw 1 ; Segment of buffer
176 .lba: resd 2 ; LBA (LSW, MSW)
179 ; Spec packet for disk image emulation
181 alignb 8
182 dspec_packet: resb 1 ; Size of packet
183 dsp_media: resb 1 ; Media type
184 dsp_drive: resb 1 ; Drive number
185 dsp_controller: resb 1 ; Controller index
186 dsp_lba: resd 1 ; LBA for emulated disk image
187 dsp_devspec: resw 1 ; IDE/SCSI information
188 dsp_buffer: resw 1 ; User-provided buffer
189 dsp_loadseg: resw 1 ; Load segment
190 dsp_sectors: resw 1 ; Sector count
191 dsp_chs: resb 3 ; Simulated CHS geometry
192 dsp_dummy: resb 1 ; Scratch, safe to overwrite
194 alignb 4
195 _spec_end equ $
196 _spec_len equ _spec_end - _spec_start
198 alignb open_file_t_size
199 Files resb MAX_OPEN*open_file_t_size
201 section .text
203 ;; Primary entry point. Because BIOSes are buggy, we only load the first
204 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
205 ;; loading the rest.
207 StackBuf equ $-44 ; 44 bytes needed for
208 ; the bootsector chainloading
209 ; code!
210 OrigESDI equ StackBuf-4 ; The high dword on the stack
212 bootsec equ $
214 _start: ; Far jump makes sure we canonicalize the address
216 jmp 0:_start1
217 times 8-($-$$) nop ; Pad to file offset 8
219 ; This table hopefully gets filled in by mkisofs using the
220 ; -boot-info-table option. If not, the values in this
221 ; table are default values that we can use to get us what
222 ; we need, at least under a certain set of assumptions.
223 bi_pvd: dd 16 ; LBA of primary volume descriptor
224 bi_file: dd 0 ; LBA of boot file
225 bi_length: dd 0xdeadbeef ; Length of boot file
226 bi_csum: dd 0xdeadbeef ; Checksum of boot file
227 bi_reserved: times 10 dd 0xdeadbeef ; Reserved
229 _start1: mov [cs:InitStack],sp ; Save initial stack pointer
230 mov [cs:InitStack+2],ss
231 xor ax,ax
232 mov ss,ax
233 mov sp,StackBuf ; Set up stack
234 push es ; Save initial ES:DI -> $PnP pointer
235 push di
236 mov ds,ax
237 mov es,ax
238 mov fs,ax
239 mov gs,ax
243 ; Show signs of life
244 mov si,syslinux_banner
245 call writestr
246 %ifdef DEBUG_MESSAGES
247 mov si,copyright_str
248 call writestr
249 %endif
252 ; Before modifying any memory, get the checksum of bytes
253 ; 64-2048
255 initial_csum: xor edi,edi
256 mov si,_start1
257 mov cx,(SECTOR_SIZE-64) >> 2
258 .loop: lodsd
259 add edi,eax
260 loop .loop
261 mov [FirstSecSum],edi
263 mov [DriveNumber],dl
264 %ifdef DEBUG_MESSAGES
265 mov si,startup_msg
266 call writemsg
267 mov al,dl
268 call writehex2
269 call crlf
270 %endif
272 ; Initialize spec packet buffers
274 mov di,_spec_start
275 mov cx,_spec_len >> 2
276 xor eax,eax
277 rep stosd
279 ; Initialize length field of the various packets
280 mov byte [spec_packet],13h
281 mov byte [drive_params],30
282 mov byte [dapa],16
283 mov byte [dspec_packet],13h
285 ; Other nonzero fields
286 inc word [dsp_sectors]
288 ; Now figure out what we're actually doing
289 ; Note: use passed-in DL value rather than 7Fh because
290 ; at least some BIOSes will get the wrong value otherwise
291 mov ax,4B01h ; Get disk emulation status
292 mov dl,[DriveNumber]
293 mov si,spec_packet
294 call int13
295 jc award_hack ; changed for BrokenAwardHack
296 mov dl,[DriveNumber]
297 cmp [sp_drive],dl ; Should contain the drive number
298 jne spec_query_failed
300 %ifdef DEBUG_MESSAGES
301 mov si,spec_ok_msg
302 call writemsg
303 mov al,byte [sp_drive]
304 call writehex2
305 call crlf
306 %endif
308 found_drive:
309 ; Alright, we have found the drive. Now, try to find the
310 ; boot file itself. If we have a boot info table, life is
311 ; good; if not, we have to make some assumptions, and try
312 ; to figure things out ourselves. In particular, the
313 ; assumptions we have to make are:
314 ; - single session only
315 ; - only one boot entry (no menu or other alternatives)
317 cmp dword [bi_file],0 ; Address of code to load
318 jne found_file ; Boot info table present :)
320 %ifdef DEBUG_MESSAGES
321 mov si,noinfotable_msg
322 call writemsg
323 %endif
325 ; No such luck. See if the spec packet contained one.
326 mov eax,[sp_lba]
327 and eax,eax
328 jz set_file ; Good enough
330 %ifdef DEBUG_MESSAGES
331 mov si,noinfoinspec_msg
332 call writemsg
333 %endif
335 ; No such luck. Get the Boot Record Volume, assuming single
336 ; session disk, and that we're the first entry in the chain
337 mov eax,17 ; Assumed address of BRV
338 mov bx,trackbuf
339 call getonesec
341 mov eax,[trackbuf+47h] ; Get boot catalog address
342 mov bx,trackbuf
343 call getonesec ; Get boot catalog
345 mov eax,[trackbuf+28h] ; First boot entry
346 ; And hope and pray this is us...
348 ; Some BIOSes apparently have limitations on the size
349 ; that may be loaded (despite the El Torito spec being very
350 ; clear on the fact that it must all be loaded.) Therefore,
351 ; we load it ourselves, and *bleep* the BIOS.
353 set_file:
354 mov [bi_file],eax
356 found_file:
357 ; Set up boot file sizes
358 mov eax,[bi_length]
359 sub eax,SECTOR_SIZE-3
360 shr eax,2 ; bytes->dwords
361 mov [ImageDwords],eax ; boot file dwords
362 add eax,(2047 >> 2)
363 shr eax,9 ; dwords->sectors
364 mov [ImageSectors],ax ; boot file sectors
366 mov eax,[bi_file] ; Address of code to load
367 inc eax ; Don't reload bootstrap code
368 %ifdef DEBUG_MESSAGES
369 mov si,offset_msg
370 call writemsg
371 call writehex8
372 call crlf
373 %endif
375 ; Just in case some BIOSes have problems with
376 ; segment wraparound, use the normalized address
377 mov bx,((7C00h+2048) >> 4)
378 mov es,bx
379 xor bx,bx
380 mov bp,[ImageSectors]
381 %ifdef DEBUG_MESSAGES
382 push ax
383 mov si,size_msg
384 call writemsg
385 mov ax,bp
386 call writehex4
387 call crlf
388 pop ax
389 %endif
390 call getlinsec
392 push ds
393 pop es
395 %ifdef DEBUG_MESSAGES
396 mov si,loaded_msg
397 call writemsg
398 %endif
400 ; Verify the checksum on the loaded image.
401 verify_image:
402 mov si,7C00h+2048
403 mov bx,es
404 mov ecx,[ImageDwords]
405 mov edi,[FirstSecSum] ; First sector checksum
406 .loop es lodsd
407 add edi,eax
408 dec ecx
409 jz .done
410 and si,si
411 jnz .loop
412 ; SI wrapped around, advance ES
413 add bx,1000h
414 mov es,bx
415 jmp short .loop
416 .done: mov ax,ds
417 mov es,ax
418 cmp [bi_csum],edi
419 je integrity_ok
421 mov si,checkerr_msg
422 call writemsg
423 jmp kaboom
425 integrity_ok:
426 %ifdef DEBUG_MESSAGES
427 mov si,allread_msg
428 call writemsg
429 %endif
430 jmp all_read ; Jump to main code
432 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
433 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
434 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
436 ;; There is a problem with certain versions of the AWARD BIOS ...
437 ;; the boot sector will be loaded and executed correctly, but, because the
438 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
439 ;; load the spec packet will fail. We scan for the equivalent of
441 ;; mov ax,0201h
442 ;; mov bx,7c00h
443 ;; mov cx,0006h
444 ;; mov dx,0180h
445 ;; pushf
446 ;; call <direct far>
448 ;; and use <direct far> as the new vector for int 13. The code above is
449 ;; used to load the boot code into ram, and there should be no reason
450 ;; for anybody to change it now or in the future. There are no opcodes
451 ;; that use encodings relativ to IP, so scanning is easy. If we find the
452 ;; code above in the BIOS code we can be pretty sure to run on a machine
453 ;; with an broken AWARD BIOS ...
455 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
457 %ifdef DEBUG_MESSAGES ;;
459 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
460 award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
461 award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
462 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
463 award_not_fail db "BAH: FAILURE" ;;
464 award_not_crlf db CR,LF,0 ;;
466 %endif ;;
468 award_oldint13 dd 0 ;;
469 award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
471 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
472 award_hack: mov si,spec_err_msg ; Moved to this place from
473 call writemsg ; spec_query_faild
475 %ifdef DEBUG_MESSAGES ;
477 mov si,award_notice ; display our plan
478 call writemsg ;
479 mov si,award_not_orig ; display original int 13
480 call writemsg ; vector
481 %endif ;
482 mov eax,[13h*4] ;
483 mov [award_oldint13],eax ;
485 %ifdef DEBUG_MESSAGES ;
487 call writehex8 ;
488 mov si,award_not_crlf ;
489 call writestr ;
490 %endif ;
491 push es ; save ES
492 mov ax,0f000h ; ES = BIOS Seg
493 mov es,ax ;
494 cld ;
495 xor di,di ; start at ES:DI = f000:0
496 award_loop: push di ; save DI
497 mov si,award_string ; scan for award_string
498 mov cx,7 ; length of award_string = 7dw
499 repz cmpsw ; compare
500 pop di ; restore DI
501 jcxz award_found ; jmp if found
502 inc di ; not found, inc di
503 jno award_loop ;
505 award_failed: pop es ; No, not this way :-((
506 award_fail2: ;
508 %ifdef DEBUG_MESSAGES ;
510 mov si,award_not_fail ; display failure ...
511 call writemsg ;
512 %endif ;
513 mov eax,[award_oldint13] ; restore the original int
514 or eax,eax ; 13 vector if there is one
515 jz spec_query_failed ; and try other workarounds
516 mov [13h*4],eax ;
517 jmp spec_query_failed ;
519 award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
520 pop es ; restore ES
522 cmp eax,[award_oldint13] ; give up if this is the
523 jz award_failed ; active int 13 vector,
524 mov [13h*4],eax ; otherwise change 0:13h*4
527 %ifdef DEBUG_MESSAGES ;
529 push eax ; display message and
530 mov si,award_not_new ; new vector address
531 call writemsg ;
532 pop eax ;
533 call writehex8 ;
534 mov si,award_not_crlf ;
535 call writestr ;
536 %endif ;
537 mov ax,4B01h ; try to read the spec packet
538 mov dl,[DriveNumber] ; now ... it should not fail
539 mov si,spec_packet ; any longer
540 int 13h ;
541 jc award_fail2 ;
543 %ifdef DEBUG_MESSAGES ;
545 mov si,award_not_succ ; display our SUCCESS
546 call writemsg ;
547 %endif ;
548 jmp found_drive ; and leave error recovery code
550 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
551 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
552 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
555 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
556 ; Try to scan the entire 80h-FFh from the end.
558 spec_query_failed:
560 ; some code moved to BrokenAwardHack
562 mov dl,0FFh
563 .test_loop: pusha
564 mov ax,4B01h
565 mov si,spec_packet
566 mov byte [si],13h ; Size of buffer
567 call int13
568 popa
569 jc .still_broken
571 mov si,maybe_msg
572 call writemsg
573 mov al,dl
574 call writehex2
575 call crlf
577 cmp byte [sp_drive],dl
578 jne .maybe_broken
580 ; Okay, good enough...
581 mov si,alright_msg
582 call writemsg
583 .found_drive0: mov [DriveNumber],dl
584 .found_drive: jmp found_drive
586 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
587 ; but if this was the drive number originally passed in
588 ; DL then consider it "good enough"
589 .maybe_broken:
590 mov al,[DriveNumber]
591 cmp al,dl
592 je .found_drive
594 ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02
595 ; passes garbage in sp_drive, and the drive number originally
596 ; passed in DL does not have 80h bit set.
597 or al,80h
598 cmp al,dl
599 je .found_drive0
601 .still_broken: dec dx
602 cmp dl, 80h
603 jnb .test_loop
605 ; No spec packet anywhere. Some particularly pathetic
606 ; BIOSes apparently don't even implement function
607 ; 4B01h, so we can't query a spec packet no matter
608 ; what. If we got a drive number in DL, then try to
609 ; use it, and if it works, then well...
610 mov dl,[DriveNumber]
611 cmp dl,81h ; Should be 81-FF at least
612 jb fatal_error ; If not, it's hopeless
614 ; Write a warning to indicate we're on *very* thin ice now
615 mov si,nospec_msg
616 call writemsg
617 mov al,dl
618 call writehex2
619 call crlf
620 mov si,trysbm_msg
621 call writemsg
622 jmp .found_drive ; Pray that this works...
624 fatal_error:
625 mov si,nothing_msg
626 call writemsg
628 .norge: jmp short .norge
630 ; Information message (DS:SI) output
631 ; Prefix with "isolinux: "
633 writemsg: push ax
634 push si
635 mov si,isolinux_str
636 call writestr
637 pop si
638 call writestr
639 pop ax
643 ; Write a character to the screen. There is a more "sophisticated"
644 ; version of this in the subsequent code, so we patch the pointer
645 ; when appropriate.
648 writechr:
649 jmp near writechr_simple ; 3-byte jump
651 writechr_simple:
652 pushfd
653 pushad
654 mov ah,0Eh
655 xor bx,bx
656 int 10h
657 popad
658 popfd
662 ; int13: save all the segment registers and call INT 13h
663 ; Some CD-ROM BIOSes have been found to corrupt segment registers.
665 int13:
667 push ds
668 push es
669 push fs
670 push gs
671 int 13h
672 pop gs
673 pop fs
674 pop es
675 pop ds
679 ; Get one sector. Convenience entry point.
681 getonesec:
682 mov bp,1
683 ; Fall through to getlinsec
686 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
688 ; Note that we can't always do this as a single request, because at least
689 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
690 ; to 32 sectors (64K) per request.
692 ; Input:
693 ; EAX - Linear sector number
694 ; ES:BX - Target buffer
695 ; BP - Sector count
697 getlinsec:
698 mov si,dapa ; Load up the DAPA
699 mov [si+4],bx
700 mov bx,es
701 mov [si+6],bx
702 mov [si+8],eax
703 .loop:
704 push bp ; Sectors left
705 cmp bp,[MaxTransfer]
706 jbe .bp_ok
707 mov bp,[MaxTransfer]
708 .bp_ok:
709 mov [si+2],bp
710 push si
711 mov dl,[DriveNumber]
712 mov ah,42h ; Extended Read
713 call xint13
714 pop si
715 pop bp
716 movzx eax,word [si+2] ; Sectors we read
717 add [si+8],eax ; Advance sector pointer
718 sub bp,ax ; Sectors left
719 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
720 add [si+6],ax ; Advance buffer pointer
721 and bp,bp
722 jnz .loop
723 mov eax,[si+8] ; Next sector
726 ; INT 13h with retry
727 xint13: mov byte [RetryCount],retry_count
728 .try: pushad
729 call int13
730 jc .error
731 add sp,byte 8*4 ; Clean up stack
733 .error:
734 mov [DiskError],ah ; Save error code
735 popad
736 mov [DiskSys],ax ; Save system call number
737 dec byte [RetryCount]
738 jz .real_error
739 push ax
740 mov al,[RetryCount]
741 mov ah,[dapa+2] ; Sector transfer count
742 cmp al,2 ; Only 2 attempts left
743 ja .nodanger
744 mov ah,1 ; Drop transfer size to 1
745 jmp short .setsize
746 .nodanger:
747 cmp al,retry_count-2
748 ja .again ; First time, just try again
749 shr ah,1 ; Otherwise, try to reduce
750 adc ah,0 ; the max transfer size, but not to 0
751 .setsize:
752 mov [MaxTransfer],ah
753 mov [dapa+2],ah
754 .again:
755 pop ax
756 jmp .try
758 .real_error: mov si,diskerr_msg
759 call writemsg
760 mov al,[DiskError]
761 call writehex2
762 mov si,oncall_str
763 call writestr
764 mov ax,[DiskSys]
765 call writehex4
766 mov si,ondrive_str
767 call writestr
768 mov al,dl
769 call writehex2
770 call crlf
771 ; Fall through to kaboom
774 ; kaboom: write a message and bail out. Wait for a user keypress,
775 ; then do a hard reboot.
777 kaboom:
778 RESET_STACK_AND_SEGS AX
779 mov si,err_bootfailed
780 call cwritestr
781 call getchar
783 mov word [BIOS_magic],0 ; Cold reboot
784 jmp 0F000h:0FFF0h ; Reset vector address
786 ; -----------------------------------------------------------------------------
787 ; Common modules needed in the first sector
788 ; -----------------------------------------------------------------------------
790 %include "writestr.inc" ; String output
791 writestr equ cwritestr
792 %include "writehex.inc" ; Hexadecimal output
794 ; -----------------------------------------------------------------------------
795 ; Data that needs to be in the first sector
796 ; -----------------------------------------------------------------------------
798 syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0
799 copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
800 db CR, LF, 0
801 isolinux_str db 'isolinux: ', 0
802 %ifdef DEBUG_MESSAGES
803 startup_msg: db 'Starting up, DL = ', 0
804 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
805 secsize_msg: db 'Sector size appears to be ', 0
806 offset_msg: db 'Loading main image from LBA = ', 0
807 size_msg: db 'Sectors to load = ', 0
808 loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
809 verify_msg: db 'Image checksum verified.', CR, LF, 0
810 allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
811 %endif
812 noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
813 noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
814 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
815 maybe_msg: db 'Found something at drive = ', 0
816 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
817 nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
818 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
819 trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
820 diskerr_msg: db 'Disk error ', 0
821 oncall_str: db ', AX = ',0
822 ondrive_str: db ', drive ', 0
823 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
825 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
826 bailmsg equ err_bootfailed
827 crlf_msg db CR, LF
828 null_msg db 0
830 alignb 4, db 0
831 MaxTransfer dw 32 ; Max sectors per transfer
833 rl_checkpt equ $ ; Must be <= 800h
835 rl_checkpt_off equ ($-$$)
836 ;%ifndef DEPEND
837 ;%if rl_checkpt_off > 0x800
838 ;%error "Sector 0 overflow"
839 ;%endif
840 ;%endif
842 ; ----------------------------------------------------------------------------
843 ; End of code and data that have to be in the first sector
844 ; ----------------------------------------------------------------------------
846 all_read:
848 ; Test tracers
849 TRACER 'T'
850 TRACER '>'
853 ; Common initialization code
855 %include "init.inc"
856 %include "cpuinit.inc"
858 ; Patch the writechr routine to point to the full code
859 mov word [writechr+1], writechr_full-(writechr+3)
861 ; Tell the user we got this far...
862 %ifndef DEBUG_MESSAGES ; Gets messy with debugging on
863 mov si,copyright_str
864 call writestr
865 %endif
868 ; Now we're all set to start with our *real* business. First load the
869 ; configuration file (if any) and parse it.
871 ; In previous versions I avoided using 32-bit registers because of a
872 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
873 ; random. I figure, though, that if there are any of those still left
874 ; they probably won't be trying to install Linux on them...
876 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
877 ; to take'm out. In fact, we may want to put them back if we're going
878 ; to boot ELKS at some point.
882 ; Now, we need to sniff out the actual filesystem data structures.
883 ; mkisofs gave us a pointer to the primary volume descriptor
884 ; (which will be at 16 only for a single-session disk!); from the PVD
885 ; we should be able to find the rest of what we need to know.
887 get_fs_structures:
888 mov eax,[bi_pvd]
889 mov bx,trackbuf
890 call getonesec
892 mov eax,[trackbuf+156+2]
893 mov [RootDir+dir_lba],eax
894 mov [CurDir+dir_lba],eax
895 %ifdef DEBUG_MESSAGES
896 mov si,dbg_rootdir_msg
897 call writemsg
898 call writehex8
899 call crlf
900 %endif
901 mov eax,[trackbuf+156+10]
902 mov [RootDir+dir_len],eax
903 mov [CurDir+dir_len],eax
904 add eax,SECTOR_SIZE-1
905 shr eax,SECTOR_SHIFT
906 mov [RootDir+dir_clust],eax
907 mov [CurDir+dir_clust],eax
909 ; Look for an isolinux directory, and if found,
910 ; make it the current directory instead of the root
911 ; directory.
912 mov di,boot_dir ; Search for /boot/isolinux
913 mov al,02h
914 call searchdir_iso
915 jnz .found_dir
916 mov di,isolinux_dir
917 mov al,02h ; Search for /isolinux
918 call searchdir_iso
919 jz .no_isolinux_dir
920 .found_dir:
921 mov [CurDir+dir_len],eax
922 mov eax,[si+file_left]
923 mov [CurDir+dir_clust],eax
924 xor eax,eax ; Free this file pointer entry
925 xchg eax,[si+file_sector]
926 mov [CurDir+dir_lba],eax
927 %ifdef DEBUG_MESSAGES
928 push si
929 mov si,dbg_isodir_msg
930 call writemsg
931 pop si
932 call writehex8
933 call crlf
934 %endif
935 .no_isolinux_dir:
938 ; Locate the configuration file
940 load_config:
941 %ifdef DEBUG_MESSAGES
942 mov si,dbg_config_msg
943 call writemsg
944 %endif
946 mov si,config_name
947 mov di,ConfigName
948 call strcpy
950 mov di,ConfigName
951 call open
952 jz no_config_file ; Not found or empty
954 %ifdef DEBUG_MESSAGES
955 mov si,dbg_configok_msg
956 call writemsg
957 %endif
960 ; Now we have the config file open. Parse the config file and
961 ; run the user interface.
963 %include "ui.inc"
966 ; Enable disk emulation. The kind of disk we emulate is dependent on the
967 ; size of the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
969 is_disk_image:
970 TRACER CR
971 TRACER LF
972 TRACER 'D'
973 TRACER ':'
975 mov edx,eax ; File size
976 mov di,img_table
977 mov cx,img_table_count
978 mov eax,[si+file_sector] ; Starting LBA of file
979 mov [dsp_lba],eax ; Location of file
980 mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk
981 .search_table:
982 TRACER 't'
983 mov eax,[di+4]
984 cmp edx,[di]
985 je .type_found
986 add di,8
987 loop .search_table
989 ; Hard disk image. Need to examine the partition table
990 ; in order to deduce the C/H/S geometry. Sigh.
991 .hard_disk_image:
992 TRACER 'h'
993 cmp edx,512
994 jb .bad_image
996 mov bx,trackbuf
997 mov cx,1 ; Load 1 sector
998 call getfssec
1000 cmp word [trackbuf+510],0aa55h ; Boot signature
1001 jne .bad_image ; Image not bootable
1003 mov cx,4 ; 4 partition entries
1004 mov di,trackbuf+446 ; Start of partition table
1006 xor ax,ax ; Highest sector(al) head(ah)
1008 .part_scan:
1009 cmp byte [di+4], 0
1010 jz .part_loop
1011 lea si,[di+1]
1012 call .hs_check
1013 add si,byte 4
1014 call .hs_check
1015 .part_loop:
1016 add di,byte 16
1017 loop .part_scan
1019 push eax ; H/S
1020 push edx ; File size
1021 mov bl,ah
1022 xor bh,bh
1023 inc bx ; # of heads in BX
1024 xor ah,ah ; # of sectors in AX
1025 cwde ; EAX[31:16] <- 0
1026 mul bx
1027 shl eax,9 ; Convert to bytes
1028 ; Now eax contains the number of bytes per cylinder
1029 pop ebx ; File size
1030 xor edx,edx
1031 div ebx
1032 and edx,edx
1033 jz .no_remainder
1034 inc eax ; Fractional cylinder...
1035 ; Now (e)ax contains the number of cylinders
1036 .no_remainder: cmp eax,1024
1037 jna .ok_cyl
1038 mov ax,1024 ; Max possible #
1039 .ok_cyl: dec ax ; Convert to max cylinder no
1040 pop ebx ; S(bl) H(bh)
1041 shl ah,6
1042 or bl,ah
1043 xchg ax,bx
1044 shl eax,16
1045 mov ah,bl
1046 mov al,4 ; Hard disk boot
1047 mov byte [dsp_drive], 80h ; Drive 80h = hard disk
1049 .type_found:
1050 TRACER 'T'
1051 mov bl,[sp_media]
1052 and bl,0F0h ; Copy controller info bits
1053 or al,bl
1054 mov [dsp_media],al ; Emulation type
1055 shr eax,8
1056 mov [dsp_chs],eax ; C/H/S geometry
1057 mov ax,[sp_devspec] ; Copy device spec
1058 mov [dsp_devspec],ax
1059 mov al,[sp_controller] ; Copy controller index
1060 mov [dsp_controller],al
1062 TRACER 'V'
1063 call vgaclearmode ; Reset video
1065 mov ax,4C00h ; Enable emulation and boot
1066 mov si,dspec_packet
1067 mov dl,[DriveNumber]
1068 lss sp,[InitStack]
1069 TRACER 'X'
1071 call int13
1073 ; If this returns, we have problems
1074 .bad_image:
1075 mov si,err_disk_image
1076 call cwritestr
1077 jmp enter_command
1080 ; Look for the highest seen H/S geometry
1081 ; We compute cylinders separately
1083 .hs_check:
1084 mov bl,[si] ; Head #
1085 cmp bl,ah
1086 jna .done_track
1087 mov ah,bl ; New highest head #
1088 .done_track: mov bl,[si+1]
1089 and bl,3Fh ; Sector #
1090 cmp bl,al
1091 jna .done_sector
1092 mov al,bl
1093 .done_sector: ret
1096 ; close_file:
1097 ; Deallocates a file structure (pointer in SI)
1098 ; Assumes CS == DS.
1100 close_file:
1101 and si,si
1102 jz .closed
1103 mov dword [si],0 ; First dword == file_left
1104 xor si,si
1105 .closed: ret
1108 ; searchdir:
1110 ; Open a file
1112 ; On entry:
1113 ; DS:DI = filename
1114 ; If successful:
1115 ; ZF clear
1116 ; SI = file pointer
1117 ; EAX = file length in bytes
1118 ; If unsuccessful
1119 ; ZF set
1121 ; Assumes CS == DS == ES, and trashes BX and CX.
1123 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
1124 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
1125 ; for searching for directories.
1127 alloc_failure:
1128 xor ax,ax ; ZF <- 1
1131 searchdir:
1132 xor al,al
1133 searchdir_iso:
1134 mov [ISOFlags],al
1135 TRACER 'S'
1136 call allocate_file ; Temporary file structure for directory
1137 jnz alloc_failure
1138 push es
1139 push ds
1140 pop es ; ES = DS
1141 mov si,CurDir
1142 cmp byte [di],'/' ; If filename begins with slash
1143 jne .not_rooted
1144 inc di ; Skip leading slash
1145 mov si,RootDir ; Reference root directory instead
1146 .not_rooted:
1147 mov eax,[si+dir_clust]
1148 mov [bx+file_left],eax
1149 mov eax,[si+dir_lba]
1150 mov [bx+file_sector],eax
1151 mov edx,[si+dir_len]
1153 .look_for_slash:
1154 mov ax,di
1155 .scan:
1156 mov cl,[di]
1157 inc di
1158 and cl,cl
1159 jz .isfile
1160 cmp cl,'/'
1161 jne .scan
1162 mov [di-1],byte 0 ; Terminate at directory name
1163 mov cl,02h ; Search for directory
1164 xchg cl,[ISOFlags]
1166 push di ; Save these...
1167 push cx
1169 ; Create recursion stack frame...
1170 push word .resume ; Where to "return" to
1171 push es
1172 .isfile: xchg ax,di
1174 .getsome:
1175 ; Get a chunk of the directory
1176 ; This relies on the fact that ISOLINUX doesn't change SI
1177 mov si,trackbuf
1178 TRACER 'g'
1179 pushad
1180 xchg bx,si
1181 mov cx,[BufSafe]
1182 call getfssec
1183 popad
1185 .compare:
1186 movzx eax,byte [si] ; Length of directory entry
1187 cmp al,33
1188 jb .next_sector
1189 TRACER 'c'
1190 mov cl,[si+25]
1191 xor cl,[ISOFlags]
1192 test cl, byte 8Eh ; Unwanted file attributes!
1193 jnz .not_file
1194 pusha
1195 movzx cx,byte [si+32] ; File identifier length
1196 add si,byte 33 ; File identifier offset
1197 TRACER 'i'
1198 call iso_compare_names
1199 popa
1200 je .success
1201 .not_file:
1202 sub edx,eax ; Decrease bytes left
1203 jbe .failure
1204 add si,ax ; Advance pointer
1206 .check_overrun:
1207 ; Did we finish the buffer?
1208 cmp si,trackbuf+trackbufsize
1209 jb .compare ; No, keep going
1211 jmp short .getsome ; Get some more directory
1213 .next_sector:
1214 ; Advance to the beginning of next sector
1215 lea ax,[si+SECTOR_SIZE-1]
1216 and ax,~(SECTOR_SIZE-1)
1217 sub ax,si
1218 jmp short .not_file ; We still need to do length checks
1220 .failure: xor eax,eax ; ZF = 1
1221 mov [bx+file_sector],eax
1222 pop es
1225 .success:
1226 mov eax,[si+2] ; Location of extent
1227 mov [bx+file_sector],eax
1228 mov eax,[si+10] ; Data length
1229 mov [bx+file_bytesleft],eax
1230 push eax
1231 add eax,SECTOR_SIZE-1
1232 shr eax,SECTOR_SHIFT
1233 mov [bx+file_left],eax
1234 pop eax
1235 and bx,bx ; ZF = 0
1236 mov si,bx
1237 pop es
1240 .resume: ; We get here if we were only doing part of a lookup
1241 ; This relies on the fact that .success returns bx == si
1242 xchg edx,eax ; Directory length in edx
1243 pop cx ; Old ISOFlags
1244 pop di ; Next filename pointer
1245 mov byte [di-1], '/' ; Restore slash
1246 mov [ISOFlags],cl ; Restore the flags
1247 jz .failure ; Did we fail? If so fail for real!
1248 jmp .look_for_slash ; Otherwise, next level
1251 ; allocate_file: Allocate a file structure
1253 ; If successful:
1254 ; ZF set
1255 ; BX = file pointer
1256 ; In unsuccessful:
1257 ; ZF clear
1259 allocate_file:
1260 TRACER 'a'
1261 push cx
1262 mov bx,Files
1263 mov cx,MAX_OPEN
1264 .check: cmp dword [bx], byte 0
1265 je .found
1266 add bx,open_file_t_size ; ZF = 0
1267 loop .check
1268 ; ZF = 0 if we fell out of the loop
1269 .found: pop cx
1273 ; iso_compare_names:
1274 ; Compare the names DS:SI and DS:DI and report if they are
1275 ; equal from an ISO 9660 perspective. SI is the name from
1276 ; the filesystem; CX indicates its length, and ';' terminates.
1277 ; DI is expected to end with a null.
1279 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
1282 iso_compare_names:
1283 ; First, terminate and canonicalize input filename
1284 push di
1285 mov di,ISOFileName
1286 .canon_loop: jcxz .canon_end
1287 lodsb
1288 dec cx
1289 cmp al,';'
1290 je .canon_end
1291 and al,al
1292 je .canon_end
1293 stosb
1294 cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
1295 jb .canon_loop
1296 .canon_end:
1297 cmp di,ISOFileName
1298 jbe .canon_done
1299 cmp byte [di-1],'.' ; Remove terminal dots
1300 jne .canon_done
1301 dec di
1302 jmp short .canon_end
1303 .canon_done:
1304 mov [di],byte 0 ; Null-terminate string
1305 pop di
1306 mov si,ISOFileName
1307 .compare:
1308 lodsb
1309 mov ah,[di]
1310 inc di
1311 and ax,ax
1312 jz .success ; End of string for both
1313 and al,al ; Is either one end of string?
1314 jz .failure ; If so, failure
1315 and ah,ah
1316 jz .failure
1317 or ax,2020h ; Convert to lower case
1318 cmp al,ah
1319 je .compare
1320 .failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
1321 .success: ret
1324 ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
1325 ; to by ES:DI; ends on encountering any whitespace.
1326 ; DI is preserved.
1328 ; This verifies that a filename is < FILENAME_MAX characters,
1329 ; doesn't contain whitespace, zero-pads the output buffer,
1330 ; and removes trailing dots and redundant slashes,
1331 ; so "repe cmpsb" can do a compare, and the
1332 ; path-searching routine gets a bit of an easier job.
1334 mangle_name:
1335 push di
1336 push bx
1337 xor ax,ax
1338 mov cx,FILENAME_MAX-1
1339 mov bx,di
1341 .mn_loop:
1342 lodsb
1343 cmp al,' ' ; If control or space, end
1344 jna .mn_end
1345 cmp al,ah ; Repeated slash?
1346 je .mn_skip
1347 xor ah,ah
1348 cmp al,'/'
1349 jne .mn_ok
1350 mov ah,al
1351 .mn_ok stosb
1352 .mn_skip: loop .mn_loop
1353 .mn_end:
1354 cmp bx,di ; At the beginning of the buffer?
1355 jbe .mn_zero
1356 cmp byte [es:di-1],'.' ; Terminal dot?
1357 je .mn_kill
1358 cmp byte [es:di-1],'/' ; Terminal slash?
1359 jne .mn_zero
1360 .mn_kill: dec di ; If so, remove it
1361 inc cx
1362 jmp short .mn_end
1363 .mn_zero:
1364 inc cx ; At least one null byte
1365 xor ax,ax ; Zero-fill name
1366 rep stosb
1367 pop bx
1368 pop di
1369 ret ; Done
1372 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1373 ; filename to the conventional representation. This is needed
1374 ; for the BOOT_IMAGE= parameter for the kernel.
1376 ; DS:SI -> input mangled file name
1377 ; ES:DI -> output buffer
1379 ; On return, DI points to the first byte after the output name,
1380 ; which is set to a null byte.
1382 unmangle_name: call strcpy
1383 dec di ; Point to final null byte
1387 ; getfssec: Get multiple clusters from a file, given the file pointer.
1389 ; On entry:
1390 ; ES:BX -> Buffer
1391 ; SI -> File pointer
1392 ; CX -> Cluster count
1393 ; On exit:
1394 ; SI -> File pointer (or 0 on EOF)
1395 ; CF = 1 -> Hit EOF
1396 ; ECX -> Bytes actually read
1398 getfssec:
1399 TRACER 'F'
1401 push ds
1402 push cs
1403 pop ds ; DS <- CS
1405 movzx ecx,cx
1406 cmp ecx,[si+file_left]
1407 jna .ok_size
1408 mov ecx,[si+file_left]
1410 .ok_size:
1411 mov bp,cx
1412 push cx
1413 push si
1414 mov eax,[si+file_sector]
1415 TRACER 'l'
1416 call getlinsec
1417 xor ecx,ecx
1418 pop si
1419 pop cx
1421 add [si+file_sector],ecx
1422 sub [si+file_left],ecx
1423 ja .not_eof ; CF = 0
1426 .not_eof:
1427 pushf
1428 shl ecx,SECTOR_SHIFT ; Convert to bytes
1429 cmp ecx,[si+file_bytesleft]
1430 jb .not_all
1431 mov ecx,[si+file_bytesleft]
1432 .not_all: sub [si+file_bytesleft],ecx
1433 popf
1434 jnc .ret
1435 push eax
1436 xor eax,eax
1437 mov [si+file_sector],eax ; Unused
1438 mov si,ax
1439 pop eax
1441 .ret:
1442 pop ds
1443 TRACER 'f'
1446 ; -----------------------------------------------------------------------------
1447 ; Common modules
1448 ; -----------------------------------------------------------------------------
1450 %include "getc.inc" ; getc et al
1451 %include "conio.inc" ; Console I/O
1452 %include "configinit.inc" ; Initialize configuration
1453 %include "parseconfig.inc" ; High-level config file handling
1454 %include "parsecmd.inc" ; Low-level config file handling
1455 %include "bcopy32.inc" ; 32-bit bcopy
1456 %include "loadhigh.inc" ; Load a file into high memory
1457 %include "font.inc" ; VGA font stuff
1458 %include "graphics.inc" ; VGA graphics
1459 %include "highmem.inc" ; High memory sizing
1460 %include "strcpy.inc" ; strcpy()
1461 %include "rawcon.inc" ; Console I/O w/o using the console functions
1462 %include "adv.inc" ; Auxillary Data Vector
1463 %include "localboot.inc" ; Disk-based local boot
1465 ; -----------------------------------------------------------------------------
1466 ; Begin data section
1467 ; -----------------------------------------------------------------------------
1469 section .data
1471 default_str db 'default', 0
1472 default_len equ ($-default_str)
1473 boot_dir db '/boot' ; /boot/isolinux
1474 isolinux_dir db '/isolinux', 0
1475 config_name db 'isolinux.cfg', 0
1476 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
1478 %ifdef DEBUG_MESSAGES
1479 dbg_rootdir_msg db 'Root directory at LBA = ', 0
1480 dbg_isodir_msg db 'isolinux directory at LBA = ', 0
1481 dbg_config_msg db 'About to load config file...', CR, LF, 0
1482 dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
1483 %endif
1485 ; Command line options we'd like to take a look at
1487 ; mem= and vga= are handled as normal 32-bit integer values
1488 initrd_cmd db 'initrd='
1489 initrd_cmd_len equ 7
1492 ; Config file keyword table
1494 %include "keywords.inc"
1497 ; Extensions to search for (in *forward* order).
1499 align 4, db 0
1500 exten_table: db '.cbt' ; COMBOOT (specific)
1501 db '.img' ; Disk image
1502 db '.bin' ; CD boot sector
1503 db '.com' ; COMBOOT (same as DOS)
1504 db '.c32' ; COM32
1505 exten_table_end:
1506 dd 0, 0 ; Need 8 null bytes here
1509 ; Floppy image table
1511 align 4, db 0
1512 img_table_count equ 3
1513 img_table:
1514 dd 1200*1024 ; 1200K floppy
1515 db 1 ; Emulation type
1516 db 80-1 ; Max cylinder
1517 db 15 ; Max sector
1518 db 2-1 ; Max head
1520 dd 1440*1024 ; 1440K floppy
1521 db 2 ; Emulation type
1522 db 80-1 ; Max cylinder
1523 db 18 ; Max sector
1524 db 2-1 ; Max head
1526 dd 2880*1024 ; 2880K floppy
1527 db 3 ; Emulation type
1528 db 80-1 ; Max cylinder
1529 db 36 ; Max sector
1530 db 2-1 ; Max head
1533 ; Misc initialized (data) variables
1537 ; Variables that are uninitialized in SYSLINUX but initialized here
1539 ; **** ISOLINUX:: We may have to make this flexible, based on what the
1540 ; **** BIOS expects our "sector size" to be.
1542 alignb 4, db 0
1543 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
1544 BufSafeBytes dw trackbufsize ; = how many bytes?
1545 %ifndef DEPEND
1546 %if ( trackbufsize % SECTOR_SIZE ) != 0
1547 %error trackbufsize must be a multiple of SECTOR_SIZE
1548 %endif
1549 %endif