Support LOCALBOOT (ISOLINUX-style) in SYSLINUX/EXTLINUX
[syslinux.git] / isolinux.asm
blob57ca1d420c7d5b550ea7930cf8a33947a6119331
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_left resd 1 ; Number of sectors left
80 endstruc
82 %ifndef DEPEND
83 %if (open_file_t_size & (open_file_t_size-1))
84 %error "open_file_t is not a power of 2"
85 %endif
86 %endif
88 struc dir_t
89 dir_lba resd 1 ; Directory start (LBA)
90 dir_len resd 1 ; Length in bytes
91 dir_clust resd 1 ; Length in clusters
92 endstruc
94 ; ---------------------------------------------------------------------------
95 ; BEGIN CODE
96 ; ---------------------------------------------------------------------------
99 ; Memory below this point is reserved for the BIOS and the MBR
101 section .earlybss
102 trackbufsize equ 8192
103 trackbuf resb trackbufsize ; Track buffer goes here
104 ; ends at 2800h
106 ; Some of these are touched before the whole image
107 ; is loaded. DO NOT move this to .uibss.
108 section .bss1
109 alignb 4
110 ISOFileName resb 64 ; ISO filename canonicalization buffer
111 ISOFileNameEnd equ $
112 CurDir resb dir_t_size ; Current directory
113 RootDir resb dir_t_size ; Root directory
114 FirstSecSum resd 1 ; Checksum of bytes 64-2048
115 ImageDwords resd 1 ; isolinux.bin size, dwords
116 InitStack resd 1 ; Initial stack pointer (SS:SP)
117 DiskSys resw 1 ; Last INT 13h call
118 ImageSectors resw 1 ; isolinux.bin size, sectors
119 DiskError resb 1 ; Error code for disk I/O
120 DriveNumber resb 1 ; CD-ROM BIOS drive number
121 ISOFlags resb 1 ; Flags for ISO directory search
122 RetryCount resb 1 ; Used for disk access retries
124 _spec_start equ $
127 ; El Torito spec packet
130 alignb 8
131 spec_packet: resb 1 ; Size of packet
132 sp_media: resb 1 ; Media type
133 sp_drive: resb 1 ; Drive number
134 sp_controller: resb 1 ; Controller index
135 sp_lba: resd 1 ; LBA for emulated disk image
136 sp_devspec: resw 1 ; IDE/SCSI information
137 sp_buffer: resw 1 ; User-provided buffer
138 sp_loadseg: resw 1 ; Load segment
139 sp_sectors: resw 1 ; Sector count
140 sp_chs: resb 3 ; Simulated CHS geometry
141 sp_dummy: resb 1 ; Scratch, safe to overwrite
144 ; EBIOS drive parameter packet
146 alignb 8
147 drive_params: resw 1 ; Buffer size
148 dp_flags: resw 1 ; Information flags
149 dp_cyl: resd 1 ; Physical cylinders
150 dp_head: resd 1 ; Physical heads
151 dp_sec: resd 1 ; Physical sectors/track
152 dp_totalsec: resd 2 ; Total sectors
153 dp_secsize: resw 1 ; Bytes per sector
154 dp_dpte: resd 1 ; Device Parameter Table
155 dp_dpi_key: resw 1 ; 0BEDDh if rest valid
156 dp_dpi_len: resb 1 ; DPI len
157 resb 1
158 resw 1
159 dp_bus: resb 4 ; Host bus type
160 dp_interface: resb 8 ; Interface type
161 db_i_path: resd 2 ; Interface path
162 db_d_path: resd 2 ; Device path
163 resb 1
164 db_dpi_csum: resb 1 ; Checksum for DPI info
167 ; EBIOS disk address packet
169 alignb 8
170 dapa: resw 1 ; Packet size
171 .count: resw 1 ; Block count
172 .off: resw 1 ; Offset of buffer
173 .seg: resw 1 ; Segment of buffer
174 .lba: resd 2 ; LBA (LSW, MSW)
177 ; Spec packet for disk image emulation
179 alignb 8
180 dspec_packet: resb 1 ; Size of packet
181 dsp_media: resb 1 ; Media type
182 dsp_drive: resb 1 ; Drive number
183 dsp_controller: resb 1 ; Controller index
184 dsp_lba: resd 1 ; LBA for emulated disk image
185 dsp_devspec: resw 1 ; IDE/SCSI information
186 dsp_buffer: resw 1 ; User-provided buffer
187 dsp_loadseg: resw 1 ; Load segment
188 dsp_sectors: resw 1 ; Sector count
189 dsp_chs: resb 3 ; Simulated CHS geometry
190 dsp_dummy: resb 1 ; Scratch, safe to overwrite
192 alignb 4
193 _spec_end equ $
194 _spec_len equ _spec_end - _spec_start
196 alignb open_file_t_size
197 Files resb MAX_OPEN*open_file_t_size
199 section .text
201 ;; Primary entry point. Because BIOSes are buggy, we only load the first
202 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
203 ;; loading the rest.
205 StackBuf equ $-44 ; 44 bytes needed for
206 ; the bootsector chainloading
207 ; code!
208 OrigESDI equ StackBuf-4 ; The high dword on the stack
210 bootsec equ $
212 _start: ; Far jump makes sure we canonicalize the address
214 jmp 0:_start1
215 times 8-($-$$) nop ; Pad to file offset 8
217 ; This table hopefully gets filled in by mkisofs using the
218 ; -boot-info-table option. If not, the values in this
219 ; table are default values that we can use to get us what
220 ; we need, at least under a certain set of assumptions.
221 bi_pvd: dd 16 ; LBA of primary volume descriptor
222 bi_file: dd 0 ; LBA of boot file
223 bi_length: dd 0xdeadbeef ; Length of boot file
224 bi_csum: dd 0xdeadbeef ; Checksum of boot file
225 bi_reserved: times 10 dd 0xdeadbeef ; Reserved
227 _start1: mov [cs:InitStack],sp ; Save initial stack pointer
228 mov [cs:InitStack+2],ss
229 xor ax,ax
230 mov ss,ax
231 mov sp,StackBuf ; Set up stack
232 push es ; Save initial ES:DI -> $PnP pointer
233 push di
234 mov ds,ax
235 mov es,ax
236 mov fs,ax
237 mov gs,ax
241 ; Show signs of life
242 mov si,syslinux_banner
243 call writestr
244 %ifdef DEBUG_MESSAGES
245 mov si,copyright_str
246 call writestr
247 %endif
250 ; Before modifying any memory, get the checksum of bytes
251 ; 64-2048
253 initial_csum: xor edi,edi
254 mov si,_start1
255 mov cx,(SECTOR_SIZE-64) >> 2
256 .loop: lodsd
257 add edi,eax
258 loop .loop
259 mov [FirstSecSum],edi
261 mov [DriveNumber],dl
262 %ifdef DEBUG_MESSAGES
263 mov si,startup_msg
264 call writemsg
265 mov al,dl
266 call writehex2
267 call crlf
268 %endif
270 ; Initialize spec packet buffers
272 mov di,_spec_start
273 mov cx,_spec_len >> 2
274 xor eax,eax
275 rep stosd
277 ; Initialize length field of the various packets
278 mov byte [spec_packet],13h
279 mov byte [drive_params],30
280 mov byte [dapa],16
281 mov byte [dspec_packet],13h
283 ; Other nonzero fields
284 inc word [dsp_sectors]
286 ; Now figure out what we're actually doing
287 ; Note: use passed-in DL value rather than 7Fh because
288 ; at least some BIOSes will get the wrong value otherwise
289 mov ax,4B01h ; Get disk emulation status
290 mov dl,[DriveNumber]
291 mov si,spec_packet
292 call int13
293 jc award_hack ; changed for BrokenAwardHack
294 mov dl,[DriveNumber]
295 cmp [sp_drive],dl ; Should contain the drive number
296 jne spec_query_failed
298 %ifdef DEBUG_MESSAGES
299 mov si,spec_ok_msg
300 call writemsg
301 mov al,byte [sp_drive]
302 call writehex2
303 call crlf
304 %endif
306 found_drive:
307 ; Alright, we have found the drive. Now, try to find the
308 ; boot file itself. If we have a boot info table, life is
309 ; good; if not, we have to make some assumptions, and try
310 ; to figure things out ourselves. In particular, the
311 ; assumptions we have to make are:
312 ; - single session only
313 ; - only one boot entry (no menu or other alternatives)
315 cmp dword [bi_file],0 ; Address of code to load
316 jne found_file ; Boot info table present :)
318 %ifdef DEBUG_MESSAGES
319 mov si,noinfotable_msg
320 call writemsg
321 %endif
323 ; No such luck. See if the spec packet contained one.
324 mov eax,[sp_lba]
325 and eax,eax
326 jz set_file ; Good enough
328 %ifdef DEBUG_MESSAGES
329 mov si,noinfoinspec_msg
330 call writemsg
331 %endif
333 ; No such luck. Get the Boot Record Volume, assuming single
334 ; session disk, and that we're the first entry in the chain
335 mov eax,17 ; Assumed address of BRV
336 mov bx,trackbuf
337 call getonesec
339 mov eax,[trackbuf+47h] ; Get boot catalog address
340 mov bx,trackbuf
341 call getonesec ; Get boot catalog
343 mov eax,[trackbuf+28h] ; First boot entry
344 ; And hope and pray this is us...
346 ; Some BIOSes apparently have limitations on the size
347 ; that may be loaded (despite the El Torito spec being very
348 ; clear on the fact that it must all be loaded.) Therefore,
349 ; we load it ourselves, and *bleep* the BIOS.
351 set_file:
352 mov [bi_file],eax
354 found_file:
355 ; Set up boot file sizes
356 mov eax,[bi_length]
357 sub eax,SECTOR_SIZE-3
358 shr eax,2 ; bytes->dwords
359 mov [ImageDwords],eax ; boot file dwords
360 add eax,(2047 >> 2)
361 shr eax,9 ; dwords->sectors
362 mov [ImageSectors],ax ; boot file sectors
364 mov eax,[bi_file] ; Address of code to load
365 inc eax ; Don't reload bootstrap code
366 %ifdef DEBUG_MESSAGES
367 mov si,offset_msg
368 call writemsg
369 call writehex8
370 call crlf
371 %endif
373 ; Just in case some BIOSes have problems with
374 ; segment wraparound, use the normalized address
375 mov bx,((7C00h+2048) >> 4)
376 mov es,bx
377 xor bx,bx
378 mov bp,[ImageSectors]
379 %ifdef DEBUG_MESSAGES
380 push ax
381 mov si,size_msg
382 call writemsg
383 mov ax,bp
384 call writehex4
385 call crlf
386 pop ax
387 %endif
388 call getlinsec
390 push ds
391 pop es
393 %ifdef DEBUG_MESSAGES
394 mov si,loaded_msg
395 call writemsg
396 %endif
398 ; Verify the checksum on the loaded image.
399 verify_image:
400 mov si,7C00h+2048
401 mov bx,es
402 mov ecx,[ImageDwords]
403 mov edi,[FirstSecSum] ; First sector checksum
404 .loop es lodsd
405 add edi,eax
406 dec ecx
407 jz .done
408 and si,si
409 jnz .loop
410 ; SI wrapped around, advance ES
411 add bx,1000h
412 mov es,bx
413 jmp short .loop
414 .done: mov ax,ds
415 mov es,ax
416 cmp [bi_csum],edi
417 je integrity_ok
419 mov si,checkerr_msg
420 call writemsg
421 jmp kaboom
423 integrity_ok:
424 %ifdef DEBUG_MESSAGES
425 mov si,allread_msg
426 call writemsg
427 %endif
428 jmp all_read ; Jump to main code
430 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
431 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
432 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
434 ;; There is a problem with certain versions of the AWARD BIOS ...
435 ;; the boot sector will be loaded and executed correctly, but, because the
436 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
437 ;; load the spec packet will fail. We scan for the equivalent of
439 ;; mov ax,0201h
440 ;; mov bx,7c00h
441 ;; mov cx,0006h
442 ;; mov dx,0180h
443 ;; pushf
444 ;; call <direct far>
446 ;; and use <direct far> as the new vector for int 13. The code above is
447 ;; used to load the boot code into ram, and there should be no reason
448 ;; for anybody to change it now or in the future. There are no opcodes
449 ;; that use encodings relativ to IP, so scanning is easy. If we find the
450 ;; code above in the BIOS code we can be pretty sure to run on a machine
451 ;; with an broken AWARD BIOS ...
453 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
455 %ifdef DEBUG_MESSAGES ;;
457 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
458 award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
459 award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
460 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
461 award_not_fail db "BAH: FAILURE" ;;
462 award_not_crlf db CR,LF,0 ;;
464 %endif ;;
466 award_oldint13 dd 0 ;;
467 award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
469 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
470 award_hack: mov si,spec_err_msg ; Moved to this place from
471 call writemsg ; spec_query_faild
473 %ifdef DEBUG_MESSAGES ;
475 mov si,award_notice ; display our plan
476 call writemsg ;
477 mov si,award_not_orig ; display original int 13
478 call writemsg ; vector
479 %endif ;
480 mov eax,[13h*4] ;
481 mov [award_oldint13],eax ;
483 %ifdef DEBUG_MESSAGES ;
485 call writehex8 ;
486 mov si,award_not_crlf ;
487 call writestr ;
488 %endif ;
489 push es ; save ES
490 mov ax,0f000h ; ES = BIOS Seg
491 mov es,ax ;
492 cld ;
493 xor di,di ; start at ES:DI = f000:0
494 award_loop: push di ; save DI
495 mov si,award_string ; scan for award_string
496 mov cx,7 ; length of award_string = 7dw
497 repz cmpsw ; compare
498 pop di ; restore DI
499 jcxz award_found ; jmp if found
500 inc di ; not found, inc di
501 jno award_loop ;
503 award_failed: pop es ; No, not this way :-((
504 award_fail2: ;
506 %ifdef DEBUG_MESSAGES ;
508 mov si,award_not_fail ; display failure ...
509 call writemsg ;
510 %endif ;
511 mov eax,[award_oldint13] ; restore the original int
512 or eax,eax ; 13 vector if there is one
513 jz spec_query_failed ; and try other workarounds
514 mov [13h*4],eax ;
515 jmp spec_query_failed ;
517 award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
518 pop es ; restore ES
520 cmp eax,[award_oldint13] ; give up if this is the
521 jz award_failed ; active int 13 vector,
522 mov [13h*4],eax ; otherwise change 0:13h*4
525 %ifdef DEBUG_MESSAGES ;
527 push eax ; display message and
528 mov si,award_not_new ; new vector address
529 call writemsg ;
530 pop eax ;
531 call writehex8 ;
532 mov si,award_not_crlf ;
533 call writestr ;
534 %endif ;
535 mov ax,4B01h ; try to read the spec packet
536 mov dl,[DriveNumber] ; now ... it should not fail
537 mov si,spec_packet ; any longer
538 int 13h ;
539 jc award_fail2 ;
541 %ifdef DEBUG_MESSAGES ;
543 mov si,award_not_succ ; display our SUCCESS
544 call writemsg ;
545 %endif ;
546 jmp found_drive ; and leave error recovery code
548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
549 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
550 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
553 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
554 ; Try to scan the entire 80h-FFh from the end.
556 spec_query_failed:
558 ; some code moved to BrokenAwardHack
560 mov dl,0FFh
561 .test_loop: pusha
562 mov ax,4B01h
563 mov si,spec_packet
564 mov byte [si],13h ; Size of buffer
565 call int13
566 popa
567 jc .still_broken
569 mov si,maybe_msg
570 call writemsg
571 mov al,dl
572 call writehex2
573 call crlf
575 cmp byte [sp_drive],dl
576 jne .maybe_broken
578 ; Okay, good enough...
579 mov si,alright_msg
580 call writemsg
581 .found_drive0: mov [DriveNumber],dl
582 .found_drive: jmp found_drive
584 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
585 ; but if this was the drive number originally passed in
586 ; DL then consider it "good enough"
587 .maybe_broken:
588 mov al,[DriveNumber]
589 cmp al,dl
590 je .found_drive
592 ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02
593 ; passes garbage in sp_drive, and the drive number originally
594 ; passed in DL does not have 80h bit set.
595 or al,80h
596 cmp al,dl
597 je .found_drive0
599 .still_broken: dec dx
600 cmp dl, 80h
601 jnb .test_loop
603 ; No spec packet anywhere. Some particularly pathetic
604 ; BIOSes apparently don't even implement function
605 ; 4B01h, so we can't query a spec packet no matter
606 ; what. If we got a drive number in DL, then try to
607 ; use it, and if it works, then well...
608 mov dl,[DriveNumber]
609 cmp dl,81h ; Should be 81-FF at least
610 jb fatal_error ; If not, it's hopeless
612 ; Write a warning to indicate we're on *very* thin ice now
613 mov si,nospec_msg
614 call writemsg
615 mov al,dl
616 call writehex2
617 call crlf
618 mov si,trysbm_msg
619 call writemsg
620 jmp .found_drive ; Pray that this works...
622 fatal_error:
623 mov si,nothing_msg
624 call writemsg
626 .norge: jmp short .norge
628 ; Information message (DS:SI) output
629 ; Prefix with "isolinux: "
631 writemsg: push ax
632 push si
633 mov si,isolinux_str
634 call writestr
635 pop si
636 call writestr
637 pop ax
641 ; Write a character to the screen. There is a more "sophisticated"
642 ; version of this in the subsequent code, so we patch the pointer
643 ; when appropriate.
646 writechr:
647 jmp near writechr_simple ; 3-byte jump
649 writechr_simple:
650 pushfd
651 pushad
652 mov ah,0Eh
653 xor bx,bx
654 int 10h
655 popad
656 popfd
660 ; int13: save all the segment registers and call INT 13h
661 ; Some CD-ROM BIOSes have been found to corrupt segment registers.
663 int13:
665 push ds
666 push es
667 push fs
668 push gs
669 int 13h
670 pop gs
671 pop fs
672 pop es
673 pop ds
677 ; Get one sector. Convenience entry point.
679 getonesec:
680 mov bp,1
681 ; Fall through to getlinsec
684 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
686 ; Note that we can't always do this as a single request, because at least
687 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
688 ; to 32 sectors (64K) per request.
690 ; Input:
691 ; EAX - Linear sector number
692 ; ES:BX - Target buffer
693 ; BP - Sector count
695 getlinsec:
696 mov si,dapa ; Load up the DAPA
697 mov [si+4],bx
698 mov bx,es
699 mov [si+6],bx
700 mov [si+8],eax
701 .loop:
702 push bp ; Sectors left
703 cmp bp,[MaxTransfer]
704 jbe .bp_ok
705 mov bp,[MaxTransfer]
706 .bp_ok:
707 mov [si+2],bp
708 push si
709 mov dl,[DriveNumber]
710 mov ah,42h ; Extended Read
711 call xint13
712 pop si
713 pop bp
714 movzx eax,word [si+2] ; Sectors we read
715 add [si+8],eax ; Advance sector pointer
716 sub bp,ax ; Sectors left
717 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
718 add [si+6],ax ; Advance buffer pointer
719 and bp,bp
720 jnz .loop
721 mov eax,[si+8] ; Next sector
724 ; INT 13h with retry
725 xint13: mov byte [RetryCount],retry_count
726 .try: pushad
727 call int13
728 jc .error
729 add sp,byte 8*4 ; Clean up stack
731 .error:
732 mov [DiskError],ah ; Save error code
733 popad
734 mov [DiskSys],ax ; Save system call number
735 dec byte [RetryCount]
736 jz .real_error
737 push ax
738 mov al,[RetryCount]
739 mov ah,[dapa+2] ; Sector transfer count
740 cmp al,2 ; Only 2 attempts left
741 ja .nodanger
742 mov ah,1 ; Drop transfer size to 1
743 jmp short .setsize
744 .nodanger:
745 cmp al,retry_count-2
746 ja .again ; First time, just try again
747 shr ah,1 ; Otherwise, try to reduce
748 adc ah,0 ; the max transfer size, but not to 0
749 .setsize:
750 mov [MaxTransfer],ah
751 mov [dapa+2],ah
752 .again:
753 pop ax
754 jmp .try
756 .real_error: mov si,diskerr_msg
757 call writemsg
758 mov al,[DiskError]
759 call writehex2
760 mov si,oncall_str
761 call writestr
762 mov ax,[DiskSys]
763 call writehex4
764 mov si,ondrive_str
765 call writestr
766 mov al,dl
767 call writehex2
768 call crlf
769 ; Fall through to kaboom
772 ; kaboom: write a message and bail out. Wait for a user keypress,
773 ; then do a hard reboot.
775 kaboom:
776 RESET_STACK_AND_SEGS AX
777 mov si,err_bootfailed
778 call cwritestr
779 call getchar
781 mov word [BIOS_magic],0 ; Cold reboot
782 jmp 0F000h:0FFF0h ; Reset vector address
784 ; -----------------------------------------------------------------------------
785 ; Common modules needed in the first sector
786 ; -----------------------------------------------------------------------------
788 %include "writestr.inc" ; String output
789 writestr equ cwritestr
790 %include "writehex.inc" ; Hexadecimal output
792 ; -----------------------------------------------------------------------------
793 ; Data that needs to be in the first sector
794 ; -----------------------------------------------------------------------------
796 syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0
797 copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
798 db CR, LF, 0
799 isolinux_str db 'isolinux: ', 0
800 %ifdef DEBUG_MESSAGES
801 startup_msg: db 'Starting up, DL = ', 0
802 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
803 secsize_msg: db 'Sector size appears to be ', 0
804 offset_msg: db 'Loading main image from LBA = ', 0
805 size_msg: db 'Sectors to load = ', 0
806 loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
807 verify_msg: db 'Image checksum verified.', CR, LF, 0
808 allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
809 %endif
810 noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
811 noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
812 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
813 maybe_msg: db 'Found something at drive = ', 0
814 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
815 nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
816 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
817 trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
818 diskerr_msg: db 'Disk error ', 0
819 oncall_str: db ', AX = ',0
820 ondrive_str: db ', drive ', 0
821 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
823 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
824 bailmsg equ err_bootfailed
825 crlf_msg db CR, LF
826 null_msg db 0
828 alignb 4, db 0
829 MaxTransfer dw 32 ; Max sectors per transfer
831 rl_checkpt equ $ ; Must be <= 800h
833 rl_checkpt_off equ ($-$$)
834 ;%ifndef DEPEND
835 ;%if rl_checkpt_off > 0x800
836 ;%error "Sector 0 overflow"
837 ;%endif
838 ;%endif
840 ; ----------------------------------------------------------------------------
841 ; End of code and data that have to be in the first sector
842 ; ----------------------------------------------------------------------------
844 all_read:
846 ; Test tracers
847 TRACER 'T'
848 TRACER '>'
851 ; Common initialization code
853 %include "init.inc"
854 %include "cpuinit.inc"
856 ; Patch the writechr routine to point to the full code
857 mov word [writechr+1], writechr_full-(writechr+3)
859 ; Tell the user we got this far...
860 %ifndef DEBUG_MESSAGES ; Gets messy with debugging on
861 mov si,copyright_str
862 call writestr
863 %endif
866 ; Now we're all set to start with our *real* business. First load the
867 ; configuration file (if any) and parse it.
869 ; In previous versions I avoided using 32-bit registers because of a
870 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
871 ; random. I figure, though, that if there are any of those still left
872 ; they probably won't be trying to install Linux on them...
874 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
875 ; to take'm out. In fact, we may want to put them back if we're going
876 ; to boot ELKS at some point.
880 ; Now, we need to sniff out the actual filesystem data structures.
881 ; mkisofs gave us a pointer to the primary volume descriptor
882 ; (which will be at 16 only for a single-session disk!); from the PVD
883 ; we should be able to find the rest of what we need to know.
885 get_fs_structures:
886 mov eax,[bi_pvd]
887 mov bx,trackbuf
888 call getonesec
890 mov eax,[trackbuf+156+2]
891 mov [RootDir+dir_lba],eax
892 mov [CurDir+dir_lba],eax
893 %ifdef DEBUG_MESSAGES
894 mov si,dbg_rootdir_msg
895 call writemsg
896 call writehex8
897 call crlf
898 %endif
899 mov eax,[trackbuf+156+10]
900 mov [RootDir+dir_len],eax
901 mov [CurDir+dir_len],eax
902 add eax,SECTOR_SIZE-1
903 shr eax,SECTOR_SHIFT
904 mov [RootDir+dir_clust],eax
905 mov [CurDir+dir_clust],eax
907 ; Look for an isolinux directory, and if found,
908 ; make it the current directory instead of the root
909 ; directory.
910 mov di,boot_dir ; Search for /boot/isolinux
911 mov al,02h
912 call searchdir_iso
913 jnz .found_dir
914 mov di,isolinux_dir
915 mov al,02h ; Search for /isolinux
916 call searchdir_iso
917 jz .no_isolinux_dir
918 .found_dir:
919 mov [CurDir+dir_len],eax
920 mov eax,[si+file_left]
921 mov [CurDir+dir_clust],eax
922 xor eax,eax ; Free this file pointer entry
923 xchg eax,[si+file_sector]
924 mov [CurDir+dir_lba],eax
925 %ifdef DEBUG_MESSAGES
926 push si
927 mov si,dbg_isodir_msg
928 call writemsg
929 pop si
930 call writehex8
931 call crlf
932 %endif
933 .no_isolinux_dir:
936 ; Locate the configuration file
938 load_config:
939 %ifdef DEBUG_MESSAGES
940 mov si,dbg_config_msg
941 call writemsg
942 %endif
944 mov si,config_name
945 mov di,ConfigName
946 call strcpy
948 mov di,ConfigName
949 call open
950 jz no_config_file ; Not found or empty
952 %ifdef DEBUG_MESSAGES
953 mov si,dbg_configok_msg
954 call writemsg
955 %endif
958 ; Now we have the config file open. Parse the config file and
959 ; run the user interface.
961 %include "ui.inc"
964 ; Enable disk emulation. The kind of disk we emulate is dependent on the size of
965 ; the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
967 is_disk_image:
968 TRACER CR
969 TRACER LF
970 TRACER 'D'
971 TRACER ':'
973 shl edx,16
974 mov dx,ax ; Set EDX <- file size
975 mov di,img_table
976 mov cx,img_table_count
977 mov eax,[si+file_sector] ; Starting LBA of file
978 mov [dsp_lba],eax ; Location of file
979 mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk
980 .search_table:
981 TRACER 't'
982 mov eax,[di+4]
983 cmp edx,[di]
984 je .type_found
985 add di,8
986 loop .search_table
988 ; Hard disk image. Need to examine the partition table
989 ; in order to deduce the C/H/S geometry. Sigh.
990 .hard_disk_image:
991 TRACER 'h'
992 cmp edx,512
993 jb .bad_image
995 mov bx,trackbuf
996 mov cx,1 ; Load 1 sector
997 call getfssec
999 cmp word [trackbuf+510],0aa55h ; Boot signature
1000 jne .bad_image ; Image not bootable
1002 mov cx,4 ; 4 partition entries
1003 mov di,trackbuf+446 ; Start of partition table
1005 xor ax,ax ; Highest sector(al) head(ah)
1007 .part_scan:
1008 cmp byte [di+4], 0
1009 jz .part_loop
1010 lea si,[di+1]
1011 call .hs_check
1012 add si,byte 4
1013 call .hs_check
1014 .part_loop:
1015 add di,byte 16
1016 loop .part_scan
1018 push eax ; H/S
1019 push edx ; File size
1020 mov bl,ah
1021 xor bh,bh
1022 inc bx ; # of heads in BX
1023 xor ah,ah ; # of sectors in AX
1024 cwde ; EAX[31:16] <- 0
1025 mul bx
1026 shl eax,9 ; Convert to bytes
1027 ; Now eax contains the number of bytes per cylinder
1028 pop ebx ; File size
1029 xor edx,edx
1030 div ebx
1031 and edx,edx
1032 jz .no_remainder
1033 inc eax ; Fractional cylinder...
1034 ; Now (e)ax contains the number of cylinders
1035 .no_remainder: cmp eax,1024
1036 jna .ok_cyl
1037 mov ax,1024 ; Max possible #
1038 .ok_cyl: dec ax ; Convert to max cylinder no
1039 pop ebx ; S(bl) H(bh)
1040 shl ah,6
1041 or bl,ah
1042 xchg ax,bx
1043 shl eax,16
1044 mov ah,bl
1045 mov al,4 ; Hard disk boot
1046 mov byte [dsp_drive], 80h ; Drive 80h = hard disk
1048 .type_found:
1049 TRACER 'T'
1050 mov bl,[sp_media]
1051 and bl,0F0h ; Copy controller info bits
1052 or al,bl
1053 mov [dsp_media],al ; Emulation type
1054 shr eax,8
1055 mov [dsp_chs],eax ; C/H/S geometry
1056 mov ax,[sp_devspec] ; Copy device spec
1057 mov [dsp_devspec],ax
1058 mov al,[sp_controller] ; Copy controller index
1059 mov [dsp_controller],al
1061 TRACER 'V'
1062 call vgaclearmode ; Reset video
1064 mov ax,4C00h ; Enable emulation and boot
1065 mov si,dspec_packet
1066 mov dl,[DriveNumber]
1067 lss sp,[InitStack]
1068 TRACER 'X'
1070 call int13
1072 ; If this returns, we have problems
1073 .bad_image:
1074 mov si,err_disk_image
1075 call cwritestr
1076 jmp enter_command
1079 ; Look for the highest seen H/S geometry
1080 ; We compute cylinders separately
1082 .hs_check:
1083 mov bl,[si] ; Head #
1084 cmp bl,ah
1085 jna .done_track
1086 mov ah,bl ; New highest head #
1087 .done_track: mov bl,[si+1]
1088 and bl,3Fh ; Sector #
1089 cmp bl,al
1090 jna .done_sector
1091 mov al,bl
1092 .done_sector: ret
1095 ; close_file:
1096 ; Deallocates a file structure (pointer in SI)
1097 ; Assumes CS == DS.
1099 close_file:
1100 and si,si
1101 jz .closed
1102 mov dword [si],0 ; First dword == file_left
1103 .closed: ret
1106 ; searchdir:
1108 ; Open a file
1110 ; On entry:
1111 ; DS:DI = filename
1112 ; If successful:
1113 ; ZF clear
1114 ; SI = file pointer
1115 ; DX:AX or EAX = file length in bytes
1116 ; If unsuccessful
1117 ; ZF set
1119 ; Assumes CS == DS == ES, and trashes BX and CX.
1121 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
1122 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
1123 ; for searching for directories.
1125 alloc_failure:
1126 xor ax,ax ; ZF <- 1
1129 searchdir:
1130 xor al,al
1131 searchdir_iso:
1132 mov [ISOFlags],al
1133 TRACER 'S'
1134 call allocate_file ; Temporary file structure for directory
1135 jnz alloc_failure
1136 push es
1137 push ds
1138 pop es ; ES = DS
1139 mov si,CurDir
1140 cmp byte [di],'/' ; If filename begins with slash
1141 jne .not_rooted
1142 inc di ; Skip leading slash
1143 mov si,RootDir ; Reference root directory instead
1144 .not_rooted:
1145 mov eax,[si+dir_clust]
1146 mov [bx+file_left],eax
1147 mov eax,[si+dir_lba]
1148 mov [bx+file_sector],eax
1149 mov edx,[si+dir_len]
1151 .look_for_slash:
1152 mov ax,di
1153 .scan:
1154 mov cl,[di]
1155 inc di
1156 and cl,cl
1157 jz .isfile
1158 cmp cl,'/'
1159 jne .scan
1160 mov [di-1],byte 0 ; Terminate at directory name
1161 mov cl,02h ; Search for directory
1162 xchg cl,[ISOFlags]
1164 push di ; Save these...
1165 push cx
1167 ; Create recursion stack frame...
1168 push word .resume ; Where to "return" to
1169 push es
1170 .isfile: xchg ax,di
1172 .getsome:
1173 ; Get a chunk of the directory
1174 ; This relies on the fact that ISOLINUX doesn't change SI
1175 mov si,trackbuf
1176 TRACER 'g'
1177 pushad
1178 xchg bx,si
1179 mov cx,[BufSafe]
1180 call getfssec
1181 popad
1183 .compare:
1184 movzx eax,byte [si] ; Length of directory entry
1185 cmp al,33
1186 jb .next_sector
1187 TRACER 'c'
1188 mov cl,[si+25]
1189 xor cl,[ISOFlags]
1190 test cl, byte 8Eh ; Unwanted file attributes!
1191 jnz .not_file
1192 pusha
1193 movzx cx,byte [si+32] ; File identifier length
1194 add si,byte 33 ; File identifier offset
1195 TRACER 'i'
1196 call iso_compare_names
1197 popa
1198 je .success
1199 .not_file:
1200 sub edx,eax ; Decrease bytes left
1201 jbe .failure
1202 add si,ax ; Advance pointer
1204 .check_overrun:
1205 ; Did we finish the buffer?
1206 cmp si,trackbuf+trackbufsize
1207 jb .compare ; No, keep going
1209 jmp short .getsome ; Get some more directory
1211 .next_sector:
1212 ; Advance to the beginning of next sector
1213 lea ax,[si+SECTOR_SIZE-1]
1214 and ax,~(SECTOR_SIZE-1)
1215 sub ax,si
1216 jmp short .not_file ; We still need to do length checks
1218 .failure: xor eax,eax ; ZF = 1
1219 mov [bx+file_sector],eax
1220 pop es
1223 .success:
1224 mov eax,[si+2] ; Location of extent
1225 mov [bx+file_sector],eax
1226 mov eax,[si+10] ; Data length
1227 push eax
1228 add eax,SECTOR_SIZE-1
1229 shr eax,SECTOR_SHIFT
1230 mov [bx+file_left],eax
1231 pop eax
1232 mov edx,eax
1233 shr edx,16
1234 and bx,bx ; ZF = 0
1235 mov si,bx
1236 pop es
1239 .resume: ; We get here if we were only doing part of a lookup
1240 ; This relies on the fact that .success returns bx == si
1241 xchg edx,eax ; Directory length in edx
1242 pop cx ; Old ISOFlags
1243 pop di ; Next filename pointer
1244 mov byte [di-1], '/' ; Restore slash
1245 mov [ISOFlags],cl ; Restore the flags
1246 jz .failure ; Did we fail? If so fail for real!
1247 jmp .look_for_slash ; Otherwise, next level
1250 ; allocate_file: Allocate a file structure
1252 ; If successful:
1253 ; ZF set
1254 ; BX = file pointer
1255 ; In unsuccessful:
1256 ; ZF clear
1258 allocate_file:
1259 TRACER 'a'
1260 push cx
1261 mov bx,Files
1262 mov cx,MAX_OPEN
1263 .check: cmp dword [bx], byte 0
1264 je .found
1265 add bx,open_file_t_size ; ZF = 0
1266 loop .check
1267 ; ZF = 0 if we fell out of the loop
1268 .found: pop cx
1272 ; iso_compare_names:
1273 ; Compare the names DS:SI and DS:DI and report if they are
1274 ; equal from an ISO 9660 perspective. SI is the name from
1275 ; the filesystem; CX indicates its length, and ';' terminates.
1276 ; DI is expected to end with a null.
1278 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
1281 iso_compare_names:
1282 ; First, terminate and canonicalize input filename
1283 push di
1284 mov di,ISOFileName
1285 .canon_loop: jcxz .canon_end
1286 lodsb
1287 dec cx
1288 cmp al,';'
1289 je .canon_end
1290 and al,al
1291 je .canon_end
1292 stosb
1293 cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
1294 jb .canon_loop
1295 .canon_end:
1296 cmp di,ISOFileName
1297 jbe .canon_done
1298 cmp byte [di-1],'.' ; Remove terminal dots
1299 jne .canon_done
1300 dec di
1301 jmp short .canon_end
1302 .canon_done:
1303 mov [di],byte 0 ; Null-terminate string
1304 pop di
1305 mov si,ISOFileName
1306 .compare:
1307 lodsb
1308 mov ah,[di]
1309 inc di
1310 and ax,ax
1311 jz .success ; End of string for both
1312 and al,al ; Is either one end of string?
1313 jz .failure ; If so, failure
1314 and ah,ah
1315 jz .failure
1316 or ax,2020h ; Convert to lower case
1317 cmp al,ah
1318 je .compare
1319 .failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
1320 .success: ret
1323 ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
1324 ; to by ES:DI; ends on encountering any whitespace.
1325 ; DI is preserved.
1327 ; This verifies that a filename is < FILENAME_MAX characters,
1328 ; doesn't contain whitespace, zero-pads the output buffer,
1329 ; and removes trailing dots and redundant slashes,
1330 ; so "repe cmpsb" can do a compare, and the
1331 ; path-searching routine gets a bit of an easier job.
1333 mangle_name:
1334 push di
1335 push bx
1336 xor ax,ax
1337 mov cx,FILENAME_MAX-1
1338 mov bx,di
1340 .mn_loop:
1341 lodsb
1342 cmp al,' ' ; If control or space, end
1343 jna .mn_end
1344 cmp al,ah ; Repeated slash?
1345 je .mn_skip
1346 xor ah,ah
1347 cmp al,'/'
1348 jne .mn_ok
1349 mov ah,al
1350 .mn_ok stosb
1351 .mn_skip: loop .mn_loop
1352 .mn_end:
1353 cmp bx,di ; At the beginning of the buffer?
1354 jbe .mn_zero
1355 cmp byte [es:di-1],'.' ; Terminal dot?
1356 je .mn_kill
1357 cmp byte [es:di-1],'/' ; Terminal slash?
1358 jne .mn_zero
1359 .mn_kill: dec di ; If so, remove it
1360 inc cx
1361 jmp short .mn_end
1362 .mn_zero:
1363 inc cx ; At least one null byte
1364 xor ax,ax ; Zero-fill name
1365 rep stosb
1366 pop bx
1367 pop di
1368 ret ; Done
1371 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1372 ; filename to the conventional representation. This is needed
1373 ; for the BOOT_IMAGE= parameter for the kernel.
1375 ; DS:SI -> input mangled file name
1376 ; ES:DI -> output buffer
1378 ; On return, DI points to the first byte after the output name,
1379 ; which is set to a null byte.
1381 unmangle_name: call strcpy
1382 dec di ; Point to final null byte
1386 ; getfssec: Get multiple clusters from a file, given the file pointer.
1388 ; On entry:
1389 ; ES:BX -> Buffer
1390 ; SI -> File pointer
1391 ; CX -> Cluster count
1392 ; On exit:
1393 ; SI -> File pointer (or 0 on EOF)
1394 ; CF = 1 -> Hit EOF
1396 getfssec:
1397 TRACER 'F'
1399 push ds
1400 push cs
1401 pop ds ; DS <- CS
1403 movzx ecx,cx
1404 cmp ecx,[si+file_left]
1405 jna .ok_size
1406 mov ecx,[si+file_left]
1407 .ok_size:
1409 mov bp,cx
1410 push cx
1411 push si
1412 mov eax,[si+file_sector]
1413 TRACER 'l'
1414 call getlinsec
1415 xor ecx,ecx
1416 pop si
1417 pop cx
1419 add [si+file_sector],ecx
1420 sub [si+file_left],ecx
1421 ja .not_eof ; CF = 0
1423 xor ecx,ecx
1424 mov [si+file_sector],ecx ; Mark as unused
1425 xor si,si
1428 .not_eof:
1429 pop ds
1430 TRACER 'f'
1433 ; -----------------------------------------------------------------------------
1434 ; Common modules
1435 ; -----------------------------------------------------------------------------
1437 %include "getc.inc" ; getc et al
1438 %include "conio.inc" ; Console I/O
1439 %include "configinit.inc" ; Initialize configuration
1440 %include "parseconfig.inc" ; High-level config file handling
1441 %include "parsecmd.inc" ; Low-level config file handling
1442 %include "bcopy32.inc" ; 32-bit bcopy
1443 %include "loadhigh.inc" ; Load a file into high memory
1444 %include "font.inc" ; VGA font stuff
1445 %include "graphics.inc" ; VGA graphics
1446 %include "highmem.inc" ; High memory sizing
1447 %include "strcpy.inc" ; strcpy()
1448 %include "rawcon.inc" ; Console I/O w/o using the console functions
1449 %include "adv.inc" ; Auxillary Data Vector
1450 %include "localboot.inc" ; Disk-based local boot
1452 ; -----------------------------------------------------------------------------
1453 ; Begin data section
1454 ; -----------------------------------------------------------------------------
1456 section .data
1458 default_str db 'default', 0
1459 default_len equ ($-default_str)
1460 boot_dir db '/boot' ; /boot/isolinux
1461 isolinux_dir db '/isolinux', 0
1462 config_name db 'isolinux.cfg', 0
1463 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
1465 %ifdef DEBUG_MESSAGES
1466 dbg_rootdir_msg db 'Root directory at LBA = ', 0
1467 dbg_isodir_msg db 'isolinux directory at LBA = ', 0
1468 dbg_config_msg db 'About to load config file...', CR, LF, 0
1469 dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
1470 %endif
1472 ; Command line options we'd like to take a look at
1474 ; mem= and vga= are handled as normal 32-bit integer values
1475 initrd_cmd db 'initrd='
1476 initrd_cmd_len equ 7
1479 ; Config file keyword table
1481 %include "keywords.inc"
1484 ; Extensions to search for (in *forward* order).
1486 align 4, db 0
1487 exten_table: db '.cbt' ; COMBOOT (specific)
1488 db '.img' ; Disk image
1489 db '.bin' ; CD boot sector
1490 db '.com' ; COMBOOT (same as DOS)
1491 db '.c32' ; COM32
1492 exten_table_end:
1493 dd 0, 0 ; Need 8 null bytes here
1496 ; Floppy image table
1498 align 4, db 0
1499 img_table_count equ 3
1500 img_table:
1501 dd 1200*1024 ; 1200K floppy
1502 db 1 ; Emulation type
1503 db 80-1 ; Max cylinder
1504 db 15 ; Max sector
1505 db 2-1 ; Max head
1507 dd 1440*1024 ; 1440K floppy
1508 db 2 ; Emulation type
1509 db 80-1 ; Max cylinder
1510 db 18 ; Max sector
1511 db 2-1 ; Max head
1513 dd 2880*1024 ; 2880K floppy
1514 db 3 ; Emulation type
1515 db 80-1 ; Max cylinder
1516 db 36 ; Max sector
1517 db 2-1 ; Max head
1520 ; Misc initialized (data) variables
1524 ; Variables that are uninitialized in SYSLINUX but initialized here
1526 ; **** ISOLINUX:: We may have to make this flexible, based on what the
1527 ; **** BIOS expects our "sector size" to be.
1529 alignb 4, db 0
1530 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
1531 BufSafeBytes dw trackbufsize ; = how many bytes?
1532 %ifndef DEPEND
1533 %if ( trackbufsize % SECTOR_SIZE ) != 0
1534 %error trackbufsize must be a multiple of SECTOR_SIZE
1535 %endif
1536 %endif