Allow specifying * instead of any of the MENU COLOR fields.
[syslinux.git] / isolinux.asm
blobfd7cb75ac8386f2584332b038264c1efe759facb
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 (C) 1994-2006 H. Peter Anvin
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 at vk_seg:0000 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 alignb 4
60 vk_append: resb max_cmd_len+1 ; Command line
61 alignb 4
62 vk_end: equ $ ; Should be <= vk_size
63 endstruc
66 ; Segment assignments in the bottom 640K
67 ; 0000h - main code/data segment (and BIOS segment)
69 real_mode_seg equ 3000h
70 vk_seg equ 2000h ; Virtual kernels
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 getcbuf resb trackbufsize
105 ; ends at 4800h
107 section .bss
108 alignb 4
109 ISOFileName resb 64 ; ISO filename canonicalization buffer
110 ISOFileNameEnd equ $
111 CurDir resb dir_t_size ; Current directory
112 RootDir resb dir_t_size ; Root directory
113 FirstSecSum resd 1 ; Checksum of bytes 64-2048
114 ImageDwords resd 1 ; isolinux.bin size, dwords
115 InitStack resd 1 ; Initial stack pointer (SS:SP)
116 DiskSys resw 1 ; Last INT 13h call
117 ImageSectors resw 1 ; isolinux.bin size, sectors
118 DiskError resb 1 ; Error code for disk I/O
119 DriveNo resb 1 ; CD-ROM BIOS drive number
120 ISOFlags resb 1 ; Flags for ISO directory search
121 RetryCount resb 1 ; Used for disk access retries
123 _spec_start equ $
126 ; El Torito spec packet
129 alignb 8
130 spec_packet: resb 1 ; Size of packet
131 sp_media: resb 1 ; Media type
132 sp_drive: resb 1 ; Drive number
133 sp_controller: resb 1 ; Controller index
134 sp_lba: resd 1 ; LBA for emulated disk image
135 sp_devspec: resw 1 ; IDE/SCSI information
136 sp_buffer: resw 1 ; User-provided buffer
137 sp_loadseg: resw 1 ; Load segment
138 sp_sectors: resw 1 ; Sector count
139 sp_chs: resb 3 ; Simulated CHS geometry
140 sp_dummy: resb 1 ; Scratch, safe to overwrite
143 ; EBIOS drive parameter packet
145 alignb 8
146 drive_params: resw 1 ; Buffer size
147 dp_flags: resw 1 ; Information flags
148 dp_cyl: resd 1 ; Physical cylinders
149 dp_head: resd 1 ; Physical heads
150 dp_sec: resd 1 ; Physical sectors/track
151 dp_totalsec: resd 2 ; Total sectors
152 dp_secsize: resw 1 ; Bytes per sector
153 dp_dpte: resd 1 ; Device Parameter Table
154 dp_dpi_key: resw 1 ; 0BEDDh if rest valid
155 dp_dpi_len: resb 1 ; DPI len
156 resb 1
157 resw 1
158 dp_bus: resb 4 ; Host bus type
159 dp_interface: resb 8 ; Interface type
160 db_i_path: resd 2 ; Interface path
161 db_d_path: resd 2 ; Device path
162 resb 1
163 db_dpi_csum: resb 1 ; Checksum for DPI info
166 ; EBIOS disk address packet
168 alignb 8
169 dapa: resw 1 ; Packet size
170 .count: resw 1 ; Block count
171 .off: resw 1 ; Offset of buffer
172 .seg: resw 1 ; Segment of buffer
173 .lba: resd 2 ; LBA (LSW, MSW)
176 ; Spec packet for disk image emulation
178 alignb 8
179 dspec_packet: resb 1 ; Size of packet
180 dsp_media: resb 1 ; Media type
181 dsp_drive: resb 1 ; Drive number
182 dsp_controller: resb 1 ; Controller index
183 dsp_lba: resd 1 ; LBA for emulated disk image
184 dsp_devspec: resw 1 ; IDE/SCSI information
185 dsp_buffer: resw 1 ; User-provided buffer
186 dsp_loadseg: resw 1 ; Load segment
187 dsp_sectors: resw 1 ; Sector count
188 dsp_chs: resb 3 ; Simulated CHS geometry
189 dsp_dummy: resb 1 ; Scratch, safe to overwrite
191 alignb 4
192 _spec_end equ $
193 _spec_len equ _spec_end - _spec_start
195 alignb open_file_t_size
196 Files resb MAX_OPEN*open_file_t_size
199 ; Constants for the xfer_buf_seg
201 ; The xfer_buf_seg is also used to store message file buffers. We
202 ; need two trackbuffers (text and graphics), plus a work buffer
203 ; for the graphics decompressor.
205 xbs_textbuf equ 0 ; Also hard-coded, do not change
206 xbs_vgabuf equ trackbufsize
207 xbs_vgatmpbuf equ 2*trackbufsize
209 section .text
211 ;; Primary entry point. Because BIOSes are buggy, we only load the first
212 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
213 ;; loading the rest.
215 StackBuf equ $-44 ; 44 bytes needed for
216 ; the bootsector chainloading
217 ; code!
219 bootsec equ $
221 _start: ; Far jump makes sure we canonicalize the address
223 jmp 0:_start1
224 times 8-($-$$) nop ; Pad to file offset 8
226 ; This table hopefully gets filled in by mkisofs using the
227 ; -boot-info-table option. If not, the values in this
228 ; table are default values that we can use to get us what
229 ; we need, at least under a certain set of assumptions.
230 bi_pvd: dd 16 ; LBA of primary volume descriptor
231 bi_file: dd 0 ; LBA of boot file
232 bi_length: dd 0xdeadbeef ; Length of boot file
233 bi_csum: dd 0xdeadbeef ; Checksum of boot file
234 bi_reserved: times 10 dd 0xdeadbeef ; Reserved
236 _start1: mov [cs:InitStack],sp ; Save initial stack pointer
237 mov [cs:InitStack+2],ss
238 xor ax,ax
239 mov ss,ax
240 mov sp,StackBuf ; Set up stack
241 mov ds,ax
242 mov es,ax
243 mov fs,ax
244 mov gs,ax
248 ; Show signs of life
249 mov si,syslinux_banner
250 call writestr
251 %ifdef DEBUG_MESSAGES
252 mov si,copyright_str
253 call writestr
254 %endif
257 ; Before modifying any memory, get the checksum of bytes
258 ; 64-2048
260 initial_csum: xor edi,edi
261 mov si,_start1
262 mov cx,(SECTOR_SIZE-64) >> 2
263 .loop: lodsd
264 add edi,eax
265 loop .loop
266 mov [FirstSecSum],edi
268 mov [DriveNo],dl
269 %ifdef DEBUG_MESSAGES
270 mov si,startup_msg
271 call writemsg
272 mov al,dl
273 call writehex2
274 call crlf
275 %endif
277 ; Initialize spec packet buffers
279 mov di,_spec_start
280 mov cx,_spec_len >> 2
281 xor eax,eax
282 rep stosd
284 ; Initialize length field of the various packets
285 mov byte [spec_packet],13h
286 mov byte [drive_params],30
287 mov byte [dapa],16
288 mov byte [dspec_packet],13h
290 ; Other nonzero fields
291 inc word [dsp_sectors]
293 ; Now figure out what we're actually doing
294 ; Note: use passed-in DL value rather than 7Fh because
295 ; at least some BIOSes will get the wrong value otherwise
296 mov ax,4B01h ; Get disk emulation status
297 mov dl,[DriveNo]
298 mov si,spec_packet
299 int 13h
300 jc award_hack ; changed for BrokenAwardHack
301 mov dl,[DriveNo]
302 cmp [sp_drive],dl ; Should contain the drive number
303 jne spec_query_failed
305 %ifdef DEBUG_MESSAGES
306 mov si,spec_ok_msg
307 call writemsg
308 mov al,byte [sp_drive]
309 call writehex2
310 call crlf
311 %endif
313 found_drive:
314 ; Alright, we have found the drive. Now, try to find the
315 ; boot file itself. If we have a boot info table, life is
316 ; good; if not, we have to make some assumptions, and try
317 ; to figure things out ourselves. In particular, the
318 ; assumptions we have to make are:
319 ; - single session only
320 ; - only one boot entry (no menu or other alternatives)
322 cmp dword [bi_file],0 ; Address of code to load
323 jne found_file ; Boot info table present :)
325 %ifdef DEBUG_MESSAGES
326 mov si,noinfotable_msg
327 call writemsg
328 %endif
330 ; No such luck. See if the the spec packet contained one.
331 mov eax,[sp_lba]
332 and eax,eax
333 jz set_file ; Good enough
335 %ifdef DEBUG_MESSAGES
336 mov si,noinfoinspec_msg
337 call writemsg
338 %endif
340 ; No such luck. Get the Boot Record Volume, assuming single
341 ; session disk, and that we're the first entry in the chain
342 mov eax,17 ; Assumed address of BRV
343 mov bx,trackbuf
344 call getonesec
346 mov eax,[trackbuf+47h] ; Get boot catalog address
347 mov bx,trackbuf
348 call getonesec ; Get boot catalog
350 mov eax,[trackbuf+28h] ; First boot entry
351 ; And hope and pray this is us...
353 ; Some BIOSes apparently have limitations on the size
354 ; that may be loaded (despite the El Torito spec being very
355 ; clear on the fact that it must all be loaded.) Therefore,
356 ; we load it ourselves, and *bleep* the BIOS.
358 set_file:
359 mov [bi_file],eax
361 found_file:
362 ; Set up boot file sizes
363 mov eax,[bi_length]
364 sub eax,SECTOR_SIZE-3
365 shr eax,2 ; bytes->dwords
366 mov [ImageDwords],eax ; boot file dwords
367 add eax,(2047 >> 2)
368 shr eax,9 ; dwords->sectors
369 mov [ImageSectors],ax ; boot file sectors
371 mov eax,[bi_file] ; Address of code to load
372 inc eax ; Don't reload bootstrap code
373 %ifdef DEBUG_MESSAGES
374 mov si,offset_msg
375 call writemsg
376 call writehex8
377 call crlf
378 %endif
380 ; Just in case some BIOSes have problems with
381 ; segment wraparound, use the normalized address
382 mov bx,((7C00h+2048) >> 4)
383 mov es,bx
384 xor bx,bx
385 mov bp,[ImageSectors]
386 %ifdef DEBUG_MESSAGES
387 push ax
388 mov si,size_msg
389 call writemsg
390 mov ax,bp
391 call writehex4
392 call crlf
393 pop ax
394 %endif
395 call getlinsec
397 push ds
398 pop es
400 %ifdef DEBUG_MESSAGES
401 mov si,loaded_msg
402 call writemsg
403 %endif
405 ; Verify the checksum on the loaded image.
406 verify_image:
407 mov si,7C00h+2048
408 mov bx,es
409 mov ecx,[ImageDwords]
410 mov edi,[FirstSecSum] ; First sector checksum
411 .loop es lodsd
412 add edi,eax
413 dec ecx
414 jz .done
415 and si,si
416 jnz .loop
417 ; SI wrapped around, advance ES
418 add bx,1000h
419 mov es,bx
420 jmp short .loop
421 .done: mov ax,ds
422 mov es,ax
423 cmp [bi_csum],edi
424 je integrity_ok
426 mov si,checkerr_msg
427 call writemsg
428 jmp kaboom
430 integrity_ok:
431 %ifdef DEBUG_MESSAGES
432 mov si,allread_msg
433 call writemsg
434 %endif
435 jmp all_read ; Jump to main code
437 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
438 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
439 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
441 ;; There is a problem with certain versions of the AWARD BIOS ...
442 ;; the boot sector will be loaded and executed correctly, but, because the
443 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
444 ;; load the spec packet will fail. We scan for the equivalent of
446 ;; mov ax,0201h
447 ;; mov bx,7c00h
448 ;; mov cx,0006h
449 ;; mov dx,0180h
450 ;; pushf
451 ;; call <direct far>
453 ;; and use <direct far> as the new vector for int 13. The code above is
454 ;; used to load the boot code into ram, and there should be no reason
455 ;; for anybody to change it now or in the future. There are no opcodes
456 ;; that use encodings relativ to IP, so scanning is easy. If we find the
457 ;; code above in the BIOS code we can be pretty sure to run on a machine
458 ;; with an broken AWARD BIOS ...
460 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
462 %ifdef DEBUG_MESSAGES ;;
464 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
465 award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
466 award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
467 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
468 award_not_fail db "BAH: FAILURE" ;;
469 award_not_crlf db CR,LF,0 ;;
471 %endif ;;
473 award_oldint13 dd 0 ;;
474 award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
476 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
477 award_hack: mov si,spec_err_msg ; Moved to this place from
478 call writemsg ; spec_query_faild
480 %ifdef DEBUG_MESSAGES ;
482 mov si,award_notice ; display our plan
483 call writemsg ;
484 mov si,award_not_orig ; display original int 13
485 call writemsg ; vector
486 %endif ;
487 mov eax,[13h*4] ;
488 mov [award_oldint13],eax ;
490 %ifdef DEBUG_MESSAGES ;
492 call writehex8 ;
493 mov si,award_not_crlf ;
494 call writestr ;
495 %endif ;
496 push es ; save ES
497 mov ax,0f000h ; ES = BIOS Seg
498 mov es,ax ;
499 cld ;
500 xor di,di ; start at ES:DI = f000:0
501 award_loop: push di ; save DI
502 mov si,award_string ; scan for award_string
503 mov cx,7 ; length of award_string = 7dw
504 repz cmpsw ; compare
505 pop di ; restore DI
506 jcxz award_found ; jmp if found
507 inc di ; not found, inc di
508 jno award_loop ;
510 award_failed: pop es ; No, not this way :-((
511 award_fail2: ;
513 %ifdef DEBUG_MESSAGES ;
515 mov si,award_not_fail ; display failure ...
516 call writemsg ;
517 %endif ;
518 mov eax,[award_oldint13] ; restore the original int
519 or eax,eax ; 13 vector if there is one
520 jz spec_query_failed ; and try other workarounds
521 mov [13h*4],eax ;
522 jmp spec_query_failed ;
524 award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
525 pop es ; restore ES
527 cmp eax,[award_oldint13] ; give up if this is the
528 jz award_failed ; active int 13 vector,
529 mov [13h*4],eax ; otherwise change 0:13h*4
532 %ifdef DEBUG_MESSAGES ;
534 push eax ; display message and
535 mov si,award_not_new ; new vector address
536 call writemsg ;
537 pop eax ;
538 call writehex8 ;
539 mov si,award_not_crlf ;
540 call writestr ;
541 %endif ;
542 mov ax,4B01h ; try to read the spec packet
543 mov dl,[DriveNo] ; now ... it should not fail
544 mov si,spec_packet ; any longer
545 int 13h ;
546 jc award_fail2 ;
548 %ifdef DEBUG_MESSAGES ;
550 mov si,award_not_succ ; display our SUCCESS
551 call writemsg ;
552 %endif ;
553 jmp found_drive ; and leave error recovery code
555 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
556 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
557 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
560 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
561 ; Try to scan the entire 80h-FFh from the end.
563 spec_query_failed:
565 ; some code moved to BrokenAwardHack
567 mov dl,0FFh
568 .test_loop: pusha
569 mov ax,4B01h
570 mov si,spec_packet
571 mov byte [si],13 ; Size of buffer
572 int 13h
573 popa
574 jc .still_broken
576 mov si,maybe_msg
577 call writemsg
578 mov al,dl
579 call writehex2
580 call crlf
582 cmp byte [sp_drive],dl
583 jne .maybe_broken
585 ; Okay, good enough...
586 mov si,alright_msg
587 call writemsg
588 mov [DriveNo],dl
589 .found_drive: jmp found_drive
591 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
592 ; but if this was the drive number originally passed in
593 ; DL then consider it "good enough"
594 .maybe_broken:
595 cmp byte [DriveNo],dl
596 je .found_drive
598 .still_broken: dec dx
599 cmp dl, 80h
600 jnb .test_loop
602 ; No spec packet anywhere. Some particularly pathetic
603 ; BIOSes apparently don't even implement function
604 ; 4B01h, so we can't query a spec packet no matter
605 ; what. If we got a drive number in DL, then try to
606 ; use it, and if it works, then well...
607 mov dl,[DriveNo]
608 cmp dl,81h ; Should be 81-FF at least
609 jb fatal_error ; If not, it's hopeless
611 ; Write a warning to indicate we're on *very* thin ice now
612 mov si,nospec_msg
613 call writemsg
614 mov al,dl
615 call writehex2
616 call crlf
617 mov si,trysbm_msg
618 call writemsg
619 jmp .found_drive ; Pray that this works...
621 fatal_error:
622 mov si,nothing_msg
623 call writemsg
625 .norge: jmp short .norge
627 ; Information message (DS:SI) output
628 ; Prefix with "isolinux: "
630 writemsg: push ax
631 push si
632 mov si,isolinux_str
633 call writestr
634 pop si
635 call writestr
636 pop ax
640 ; Write a character to the screen. There is a more "sophisticated"
641 ; version of this in the subsequent code, so we patch the pointer
642 ; when appropriate.
645 writechr:
646 jmp near writechr_simple ; 3-byte jump
648 writechr_simple:
649 pushfd
650 pushad
651 mov ah,0Eh
652 xor bx,bx
653 int 10h
654 popad
655 popfd
659 ; Get one sector. Convenience entry point.
661 getonesec:
662 mov bp,1
663 ; Fall through to getlinsec
666 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
668 ; Note that we can't always do this as a single request, because at least
669 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
670 ; to 32 sectors (64K) per request.
672 ; Input:
673 ; EAX - Linear sector number
674 ; ES:BX - Target buffer
675 ; BP - Sector count
677 getlinsec:
678 mov si,dapa ; Load up the DAPA
679 mov [si+4],bx
680 mov bx,es
681 mov [si+6],bx
682 mov [si+8],eax
683 .loop:
684 push bp ; Sectors left
685 cmp bp,[MaxTransfer]
686 jbe .bp_ok
687 mov bp,[MaxTransfer]
688 .bp_ok:
689 mov [si+2],bp
690 push si
691 mov dl,[DriveNo]
692 mov ah,42h ; Extended Read
693 call xint13
694 pop si
695 pop bp
696 movzx eax,word [si+2] ; Sectors we read
697 add [si+8],eax ; Advance sector pointer
698 sub bp,ax ; Sectors left
699 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
700 add [si+6],ax ; Advance buffer pointer
701 and bp,bp
702 jnz .loop
703 mov eax,[si+8] ; Next sector
706 ; INT 13h with retry
707 xint13: mov byte [RetryCount],retry_count
708 .try: pushad
709 int 13h
710 jc .error
711 add sp,byte 8*4 ; Clean up stack
713 .error:
714 mov [DiskError],ah ; Save error code
715 popad
716 mov [DiskSys],ax ; Save system call number
717 dec byte [RetryCount]
718 jz .real_error
719 push ax
720 mov al,[RetryCount]
721 mov ah,[dapa+2] ; Sector transfer count
722 cmp al,2 ; Only 2 attempts left
723 ja .nodanger
724 mov ah,1 ; Drop transfer size to 1
725 jmp short .setsize
726 .nodanger:
727 cmp al,retry_count-2
728 ja .again ; First time, just try again
729 shr ah,1 ; Otherwise, try to reduce
730 adc ah,0 ; the max transfer size, but not to 0
731 .setsize:
732 mov [MaxTransfer],ah
733 mov [dapa+2],ah
734 .again:
735 pop ax
736 jmp .try
738 .real_error: mov si,diskerr_msg
739 call writemsg
740 mov al,[DiskError]
741 call writehex2
742 mov si,oncall_str
743 call writestr
744 mov ax,[DiskSys]
745 call writehex4
746 mov si,ondrive_str
747 call writestr
748 mov al,dl
749 call writehex2
750 call crlf
751 ; Fall through to kaboom
754 ; kaboom: write a message and bail out. Wait for a user keypress,
755 ; then do a hard reboot.
757 kaboom:
758 RESET_STACK_AND_SEGS AX
759 mov si,err_bootfailed
760 call cwritestr
761 call getchar
763 mov word [BIOS_magic],0 ; Cold reboot
764 jmp 0F000h:0FFF0h ; Reset vector address
766 ; -----------------------------------------------------------------------------
767 ; Common modules needed in the first sector
768 ; -----------------------------------------------------------------------------
770 %include "writestr.inc" ; String output
771 writestr equ cwritestr
772 %include "writehex.inc" ; Hexadecimal output
774 ; -----------------------------------------------------------------------------
775 ; Data that needs to be in the first sector
776 ; -----------------------------------------------------------------------------
778 syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0
779 copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
780 db CR, LF, 0
781 isolinux_str db 'isolinux: ', 0
782 %ifdef DEBUG_MESSAGES
783 startup_msg: db 'Starting up, DL = ', 0
784 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
785 secsize_msg: db 'Sector size appears to be ', 0
786 offset_msg: db 'Loading main image from LBA = ', 0
787 size_msg: db 'Sectors to load = ', 0
788 loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
789 verify_msg: db 'Image checksum verified.', CR, LF, 0
790 allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
791 %endif
792 noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
793 noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
794 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
795 maybe_msg: db 'Found something at drive = ', 0
796 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
797 nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
798 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
799 trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
800 diskerr_msg: db 'Disk error ', 0
801 oncall_str: db ', AX = ',0
802 ondrive_str: db ', drive ', 0
803 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
805 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
806 bailmsg equ err_bootfailed
807 crlf_msg db CR, LF
808 null_msg db 0
810 alignb 4, db 0
811 StackPtr dw StackBuf, 0 ; SS:SP for stack reset
812 MaxTransfer dw 32 ; Max sectors per transfer
814 rl_checkpt equ $ ; Must be <= 800h
816 rl_checkpt_off equ ($-$$)
817 ;%ifndef DEPEND
818 ;%if rl_checkpt_off > 0x800
819 ;%error "Sector 0 overflow"
820 ;%endif
821 ;%endif
823 ; ----------------------------------------------------------------------------
824 ; End of code and data that have to be in the first sector
825 ; ----------------------------------------------------------------------------
827 all_read:
829 ; Initialize screen (if we're using one)
831 ; Now set up screen parameters
832 call adjust_screen
834 ; Wipe the F-key area
835 mov al,NULLFILE
836 mov di,FKeyName
837 mov cx,10*(1 << FILENAME_MAX_LG2)
838 rep stosb
840 ; Patch the writechr routine to point to the full code
841 mov word [writechr+1], writechr_full-(writechr+3)
843 ; Tell the user we got this far...
844 %ifndef DEBUG_MESSAGES ; Gets messy with debugging on
845 mov si,copyright_str
846 call writestr
847 %endif
849 ; Test tracers
850 TRACER 'T'
851 TRACER '>'
854 ; Common initialization code
856 %include "init.inc"
857 %include "cpuinit.inc"
860 ; Now we're all set to start with our *real* business. First load the
861 ; configuration file (if any) and parse it.
863 ; In previous versions I avoided using 32-bit registers because of a
864 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
865 ; random. I figure, though, that if there are any of those still left
866 ; they probably won't be trying to install Linux on them...
868 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
869 ; to take'm out. In fact, we may want to put them back if we're going
870 ; to boot ELKS at some point.
874 ; Now, we need to sniff out the actual filesystem data structures.
875 ; mkisofs gave us a pointer to the primary volume descriptor
876 ; (which will be at 16 only for a single-session disk!); from the PVD
877 ; we should be able to find the rest of what we need to know.
879 get_fs_structures:
880 mov eax,[bi_pvd]
881 mov bx,trackbuf
882 call getonesec
884 mov eax,[trackbuf+156+2]
885 mov [RootDir+dir_lba],eax
886 mov [CurDir+dir_lba],eax
887 %ifdef DEBUG_MESSAGES
888 mov si,dbg_rootdir_msg
889 call writemsg
890 call writehex8
891 call crlf
892 %endif
893 mov eax,[trackbuf+156+10]
894 mov [RootDir+dir_len],eax
895 mov [CurDir+dir_len],eax
896 add eax,SECTOR_SIZE-1
897 shr eax,SECTOR_SHIFT
898 mov [RootDir+dir_clust],eax
899 mov [CurDir+dir_clust],eax
901 ; Look for an isolinux directory, and if found,
902 ; make it the current directory instead of the root
903 ; directory.
904 mov di,boot_dir ; Search for /boot/isolinux
905 mov al,02h
906 call searchdir_iso
907 jnz .found_dir
908 mov di,isolinux_dir
909 mov al,02h ; Search for /isolinux
910 call searchdir_iso
911 jz .no_isolinux_dir
912 .found_dir:
913 mov [CurDir+dir_len],eax
914 mov eax,[si+file_left]
915 mov [CurDir+dir_clust],eax
916 xor eax,eax ; Free this file pointer entry
917 xchg eax,[si+file_sector]
918 mov [CurDir+dir_lba],eax
919 %ifdef DEBUG_MESSAGES
920 push si
921 mov si,dbg_isodir_msg
922 call writemsg
923 pop si
924 call writehex8
925 call crlf
926 %endif
927 .no_isolinux_dir:
930 ; Locate the configuration file
932 load_config:
933 %ifdef DEBUG_MESSAGES
934 mov si,dbg_config_msg
935 call writemsg
936 %endif
938 mov di,isolinux_cfg
939 call open
940 jz no_config_file ; Not found or empty
942 %ifdef DEBUG_MESSAGES
943 mov si,dbg_configok_msg
944 call writemsg
945 %endif
948 ; Now we have the config file open. Parse the config file and
949 ; run the user interface.
951 %include "ui.inc"
954 ; Linux kernel loading code is common.
956 %include "runkernel.inc"
959 ; COMBOOT-loading code
961 %include "comboot.inc"
962 %include "com32.inc"
963 %include "cmdline.inc"
966 ; Boot sector loading code
968 %include "bootsect.inc"
971 ; Enable disk emulation. The kind of disk we emulate is dependent on the size of
972 ; the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
974 is_disk_image:
975 TRACER CR
976 TRACER LF
977 TRACER 'D'
978 TRACER ':'
980 shl edx,16
981 mov dx,ax ; Set EDX <- file size
982 mov di,img_table
983 mov cx,img_table_count
984 mov eax,[si+file_sector] ; Starting LBA of file
985 mov [dsp_lba],eax ; Location of file
986 mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk
987 .search_table:
988 TRACER 't'
989 mov eax,[di+4]
990 cmp edx,[di]
991 je .type_found
992 add di,8
993 loop .search_table
995 ; Hard disk image. Need to examine the partition table
996 ; in order to deduce the C/H/S geometry. Sigh.
997 .hard_disk_image:
998 TRACER 'h'
999 cmp edx,512
1000 jb .bad_image
1002 mov bx,trackbuf
1003 mov cx,1 ; Load 1 sector
1004 call getfssec
1006 cmp word [trackbuf+510],0aa55h ; Boot signature
1007 jne .bad_image ; Image not bootable
1009 mov cx,4 ; 4 partition entries
1010 mov di,trackbuf+446 ; Start of partition table
1012 xor ax,ax ; Highest sector(al) head(ah)
1014 .part_scan:
1015 cmp byte [di+4], 0
1016 jz .part_loop
1017 lea si,[di+1]
1018 call .hs_check
1019 add si,byte 4
1020 call .hs_check
1021 .part_loop:
1022 add di,byte 16
1023 loop .part_scan
1025 push eax ; H/S
1026 push edx ; File size
1027 mov bl,ah
1028 xor bh,bh
1029 inc bx ; # of heads in BX
1030 xor ah,ah ; # of sectors in AX
1031 cwde ; EAX[31:16] <- 0
1032 mul bx
1033 shl eax,9 ; Convert to bytes
1034 ; Now eax contains the number of bytes per cylinder
1035 pop ebx ; File size
1036 xor edx,edx
1037 div ebx
1038 and edx,edx
1039 jz .no_remainder
1040 inc eax ; Fractional cylinder...
1041 ; Now (e)ax contains the number of cylinders
1042 .no_remainder: cmp eax,1024
1043 jna .ok_cyl
1044 mov ax,1024 ; Max possible #
1045 .ok_cyl: dec ax ; Convert to max cylinder no
1046 pop ebx ; S(bl) H(bh)
1047 shl ah,6
1048 or bl,ah
1049 xchg ax,bx
1050 shl eax,16
1051 mov ah,bl
1052 mov al,4 ; Hard disk boot
1053 mov byte [dsp_drive], 80h ; Drive 80h = hard disk
1055 .type_found:
1056 TRACER 'T'
1057 mov bl,[sp_media]
1058 and bl,0F0h ; Copy controller info bits
1059 or al,bl
1060 mov [dsp_media],al ; Emulation type
1061 shr eax,8
1062 mov [dsp_chs],eax ; C/H/S geometry
1063 mov ax,[sp_devspec] ; Copy device spec
1064 mov [dsp_devspec],ax
1065 mov al,[sp_controller] ; Copy controller index
1066 mov [dsp_controller],al
1068 TRACER 'V'
1069 call vgaclearmode ; Reset video
1071 mov ax,4C00h ; Enable emulation and boot
1072 mov si,dspec_packet
1073 mov dl,[DriveNo]
1074 lss sp,[InitStack]
1075 TRACER 'X'
1077 int 13h
1079 ; If this returns, we have problems
1080 .bad_image:
1081 mov si,err_disk_image
1082 call cwritestr
1083 jmp enter_command
1086 ; Look for the highest seen H/S geometry
1087 ; We compute cylinders separately
1089 .hs_check:
1090 mov bl,[si] ; Head #
1091 cmp bl,ah
1092 jna .done_track
1093 mov ah,bl ; New highest head #
1094 .done_track: mov bl,[si+1]
1095 and bl,3Fh ; Sector #
1096 cmp bl,al
1097 jna .done_sector
1098 mov al,bl
1099 .done_sector: ret
1102 ; Boot a specified local disk. AX specifies the BIOS disk number; or
1103 ; 0xFFFF in case we should execute INT 18h ("next device.")
1105 local_boot:
1106 call vgaclearmode
1107 lss sp,[cs:Stack] ; Restore stack pointer
1108 xor dx,dx
1109 mov ds,dx
1110 mov es,dx
1111 mov fs,dx
1112 mov gs,dx
1113 mov si,localboot_msg
1114 call writestr
1115 cmp ax,-1
1116 je .int18
1118 ; Load boot sector from the specified BIOS device and jump to it.
1119 mov dl,al
1120 xor dh,dh
1121 push dx
1122 xor ax,ax ; Reset drive
1123 call xint13
1124 mov ax,0201h ; Read one sector
1125 mov cx,0001h ; C/H/S = 0/0/1 (first sector)
1126 mov bx,trackbuf
1127 call xint13
1128 pop dx
1129 cli ; Abandon hope, ye who enter here
1130 mov si,trackbuf
1131 mov di,07C00h
1132 mov cx,512 ; Probably overkill, but should be safe
1133 rep movsd
1134 lss sp,[cs:InitStack]
1135 jmp 0:07C00h ; Jump to new boot sector
1137 .int18:
1138 int 18h ; Hope this does the right thing...
1139 jmp kaboom ; If we returned, oh boy...
1142 ; Abort loading code
1144 %include "abort.inc"
1147 ; searchdir:
1149 ; Open a file
1151 ; On entry:
1152 ; DS:DI = filename
1153 ; If successful:
1154 ; ZF clear
1155 ; SI = file pointer
1156 ; DX:AX or EAX = file length in bytes
1157 ; If unsuccessful
1158 ; ZF set
1160 ; Assumes CS == DS == ES, and trashes BX and CX.
1162 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
1163 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
1164 ; for searching for directories.
1166 alloc_failure:
1167 xor ax,ax ; ZF <- 1
1170 searchdir:
1171 xor al,al
1172 searchdir_iso:
1173 mov [ISOFlags],al
1174 TRACER 'S'
1175 call allocate_file ; Temporary file structure for directory
1176 jnz alloc_failure
1177 push es
1178 push ds
1179 pop es ; ES = DS
1180 mov si,CurDir
1181 cmp byte [di],'/' ; If filename begins with slash
1182 jne .not_rooted
1183 inc di ; Skip leading slash
1184 mov si,RootDir ; Reference root directory instead
1185 .not_rooted:
1186 mov eax,[si+dir_clust]
1187 mov [bx+file_left],eax
1188 mov eax,[si+dir_lba]
1189 mov [bx+file_sector],eax
1190 mov edx,[si+dir_len]
1192 .look_for_slash:
1193 mov ax,di
1194 .scan:
1195 mov cl,[di]
1196 inc di
1197 and cl,cl
1198 jz .isfile
1199 cmp cl,'/'
1200 jne .scan
1201 mov [di-1],byte 0 ; Terminate at directory name
1202 mov cl,02h ; Search for directory
1203 xchg cl,[ISOFlags]
1205 push di ; Save these...
1206 push cx
1208 ; Create recursion stack frame...
1209 push word .resume ; Where to "return" to
1210 push es
1211 .isfile: xchg ax,di
1213 .getsome:
1214 ; Get a chunk of the directory
1215 ; This relies on the fact that ISOLINUX doesn't change SI
1216 mov si,trackbuf
1217 TRACER 'g'
1218 pushad
1219 xchg bx,si
1220 mov cx,[BufSafe]
1221 call getfssec
1222 popad
1224 .compare:
1225 movzx eax,byte [si] ; Length of directory entry
1226 cmp al,33
1227 jb .next_sector
1228 TRACER 'c'
1229 mov cl,[si+25]
1230 xor cl,[ISOFlags]
1231 test cl, byte 8Eh ; Unwanted file attributes!
1232 jnz .not_file
1233 pusha
1234 movzx cx,byte [si+32] ; File identifier length
1235 add si,byte 33 ; File identifier offset
1236 TRACER 'i'
1237 call iso_compare_names
1238 popa
1239 je .success
1240 .not_file:
1241 sub edx,eax ; Decrease bytes left
1242 jbe .failure
1243 add si,ax ; Advance pointer
1245 .check_overrun:
1246 ; Did we finish the buffer?
1247 cmp si,trackbuf+trackbufsize
1248 jb .compare ; No, keep going
1250 jmp short .getsome ; Get some more directory
1252 .next_sector:
1253 ; Advance to the beginning of next sector
1254 lea ax,[si+SECTOR_SIZE-1]
1255 and ax,~(SECTOR_SIZE-1)
1256 sub ax,si
1257 jmp short .not_file ; We still need to do length checks
1259 .failure: xor eax,eax ; ZF = 1
1260 mov [bx+file_sector],eax
1261 pop es
1264 .success:
1265 mov eax,[si+2] ; Location of extent
1266 mov [bx+file_sector],eax
1267 mov eax,[si+10] ; Data length
1268 push eax
1269 add eax,SECTOR_SIZE-1
1270 shr eax,SECTOR_SHIFT
1271 mov [bx+file_left],eax
1272 pop eax
1273 mov edx,eax
1274 shr edx,16
1275 and bx,bx ; ZF = 0
1276 mov si,bx
1277 pop es
1280 .resume: ; We get here if we were only doing part of a lookup
1281 ; This relies on the fact that .success returns bx == si
1282 xchg edx,eax ; Directory length in edx
1283 pop cx ; Old ISOFlags
1284 pop di ; Next filename pointer
1285 mov byte [di-1], '/' ; Restore slash
1286 mov [ISOFlags],cl ; Restore the flags
1287 jz .failure ; Did we fail? If so fail for real!
1288 jmp .look_for_slash ; Otherwise, next level
1291 ; allocate_file: Allocate a file structure
1293 ; If successful:
1294 ; ZF set
1295 ; BX = file pointer
1296 ; In unsuccessful:
1297 ; ZF clear
1299 allocate_file:
1300 TRACER 'a'
1301 push cx
1302 mov bx,Files
1303 mov cx,MAX_OPEN
1304 .check: cmp dword [bx], byte 0
1305 je .found
1306 add bx,open_file_t_size ; ZF = 0
1307 loop .check
1308 ; ZF = 0 if we fell out of the loop
1309 .found: pop cx
1313 ; iso_compare_names:
1314 ; Compare the names DS:SI and DS:DI and report if they are
1315 ; equal from an ISO 9660 perspective. SI is the name from
1316 ; the filesystem; CX indicates its length, and ';' terminates.
1317 ; DI is expected to end with a null.
1319 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
1322 iso_compare_names:
1323 ; First, terminate and canonicalize input filename
1324 push di
1325 mov di,ISOFileName
1326 .canon_loop: jcxz .canon_end
1327 lodsb
1328 dec cx
1329 cmp al,';'
1330 je .canon_end
1331 and al,al
1332 je .canon_end
1333 stosb
1334 cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
1335 jb .canon_loop
1336 .canon_end:
1337 cmp di,ISOFileName
1338 jbe .canon_done
1339 cmp byte [di-1],'.' ; Remove terminal dots
1340 jne .canon_done
1341 dec di
1342 jmp short .canon_end
1343 .canon_done:
1344 mov [di],byte 0 ; Null-terminate string
1345 pop di
1346 mov si,ISOFileName
1347 .compare:
1348 lodsb
1349 mov ah,[di]
1350 inc di
1351 and ax,ax
1352 jz .success ; End of string for both
1353 and al,al ; Is either one end of string?
1354 jz .failure ; If so, failure
1355 and ah,ah
1356 jz .failure
1357 or ax,2020h ; Convert to lower case
1358 cmp al,ah
1359 je .compare
1360 .failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
1361 .success: ret
1364 ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
1365 ; to by ES:DI; ends on encountering any whitespace.
1367 ; This verifies that a filename is < FILENAME_MAX characters,
1368 ; doesn't contain whitespace, zero-pads the output buffer,
1369 ; and removes trailing dots and redundant slashes,
1370 ; so "repe cmpsb" can do a compare, and the
1371 ; path-searching routine gets a bit of an easier job.
1373 mangle_name:
1374 push bx
1375 xor ax,ax
1376 mov cx,FILENAME_MAX-1
1377 mov bx,di
1379 .mn_loop:
1380 lodsb
1381 cmp al,' ' ; If control or space, end
1382 jna .mn_end
1383 cmp al,ah ; Repeated slash?
1384 je .mn_skip
1385 xor ah,ah
1386 cmp al,'/'
1387 jne .mn_ok
1388 mov ah,al
1389 .mn_ok stosb
1390 .mn_skip: loop .mn_loop
1391 .mn_end:
1392 cmp bx,di ; At the beginning of the buffer?
1393 jbe .mn_zero
1394 cmp byte [di-1],'.' ; Terminal dot?
1395 je .mn_kill
1396 cmp byte [di-1],'/' ; Terminal slash?
1397 jne .mn_zero
1398 .mn_kill: dec di ; If so, remove it
1399 inc cx
1400 jmp short .mn_end
1401 .mn_zero:
1402 inc cx ; At least one null byte
1403 xor ax,ax ; Zero-fill name
1404 rep stosb
1405 pop bx
1406 ret ; Done
1409 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1410 ; filename to the conventional representation. This is needed
1411 ; for the BOOT_IMAGE= parameter for the kernel.
1412 ; NOTE: A 13-byte buffer is mandatory, even if the string is
1413 ; known to be shorter.
1415 ; DS:SI -> input mangled file name
1416 ; ES:DI -> output buffer
1418 ; On return, DI points to the first byte after the output name,
1419 ; which is set to a null byte.
1421 unmangle_name: call strcpy
1422 dec di ; Point to final null byte
1426 ; getfssec: Get multiple clusters from a file, given the file pointer.
1428 ; On entry:
1429 ; ES:BX -> Buffer
1430 ; SI -> File pointer
1431 ; CX -> Cluster count
1432 ; On exit:
1433 ; SI -> File pointer (or 0 on EOF)
1434 ; CF = 1 -> Hit EOF
1436 getfssec:
1437 TRACER 'F'
1439 push ds
1440 push cs
1441 pop ds ; DS <- CS
1443 movzx ecx,cx
1444 cmp ecx,[si+file_left]
1445 jna .ok_size
1446 mov ecx,[si+file_left]
1447 .ok_size:
1449 mov bp,cx
1450 push cx
1451 push si
1452 mov eax,[si+file_sector]
1453 TRACER 'l'
1454 call getlinsec
1455 xor ecx,ecx
1456 pop si
1457 pop cx
1459 add [si+file_sector],ecx
1460 sub [si+file_left],ecx
1461 ja .not_eof ; CF = 0
1463 xor ecx,ecx
1464 mov [si+file_sector],ecx ; Mark as unused
1465 xor si,si
1468 .not_eof:
1469 pop ds
1470 TRACER 'f'
1473 ; -----------------------------------------------------------------------------
1474 ; Common modules
1475 ; -----------------------------------------------------------------------------
1477 %include "getc.inc" ; getc et al
1478 %include "conio.inc" ; Console I/O
1479 %include "parseconfig.inc" ; High-level config file handling
1480 %include "parsecmd.inc" ; Low-level config file handling
1481 %include "bcopy32.inc" ; 32-bit bcopy
1482 %include "loadhigh.inc" ; Load a file into high memory
1483 %include "font.inc" ; VGA font stuff
1484 %include "graphics.inc" ; VGA graphics
1485 %include "highmem.inc" ; High memory sizing
1486 %include "strcpy.inc" ; strcpy()
1487 %include "rawcon.inc" ; Console I/O w/o using the console functions
1489 ; -----------------------------------------------------------------------------
1490 ; Begin data section
1491 ; -----------------------------------------------------------------------------
1493 section .data
1495 boot_prompt db 'boot: ', 0
1496 wipe_char db BS, ' ', BS, 0
1497 err_notfound db 'Could not find kernel image: ',0
1498 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
1499 err_noram db 'It appears your computer has less than '
1500 asciidec dosram_k
1501 db 'K of low ("DOS")'
1502 db CR, LF
1503 db 'RAM. Linux needs at least this amount to boot. If you get'
1504 db CR, LF
1505 db 'this message in error, hold down the Ctrl key while'
1506 db CR, LF
1507 db 'booting, and I will take your word for it.', CR, LF, 0
1508 err_badcfg db 'Unknown keyword in config file.', CR, LF, 0
1509 err_noparm db 'Missing parameter in config file.', CR, LF, 0
1510 err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
1511 err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0
1512 err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0
1513 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
1514 db CR, LF, 0
1515 err_notdos db ': attempted DOS system call', CR, LF, 0
1516 err_comlarge db 'COMBOOT image too large.', CR, LF, 0
1517 err_bssimage db 'BSS images not supported.', CR, LF, 0
1518 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
1519 notfound_msg db 'not found', CR, LF, 0
1520 localboot_msg db 'Booting from local disk...', CR, LF, 0
1521 cmdline_msg db 'Command line: ', CR, LF, 0
1522 ready_msg db 'Ready.', CR, LF, 0
1523 trying_msg db 'Trying to load: ', 0
1524 crlfloading_msg db CR, LF ; Fall through
1525 loading_msg db 'Loading ', 0
1526 dotdot_msg db '.'
1527 dot_msg db '.', 0
1528 fourbs_msg db BS, BS, BS, BS, 0
1529 aborted_msg db ' aborted.', CR, LF, 0
1530 crff_msg db CR, FF, 0
1531 default_str db 'default', 0
1532 default_len equ ($-default_str)
1533 boot_dir db '/boot' ; /boot/isolinux
1534 isolinux_dir db '/isolinux', 0
1535 ConfigName equ $
1536 isolinux_cfg db 'isolinux.cfg', 0
1537 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
1539 %ifdef DEBUG_MESSAGES
1540 dbg_rootdir_msg db 'Root directory at LBA = ', 0
1541 dbg_isodir_msg db 'isolinux directory at LBA = ', 0
1542 dbg_config_msg db 'About to load config file...', CR, LF, 0
1543 dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
1544 %endif
1546 ; Command line options we'd like to take a look at
1548 ; mem= and vga= are handled as normal 32-bit integer values
1549 initrd_cmd db 'initrd='
1550 initrd_cmd_len equ 7
1553 ; Config file keyword table
1555 %include "keywords.inc"
1558 ; Extensions to search for (in *forward* order).
1560 align 4, db 0
1561 exten_table: db '.cbt' ; COMBOOT (specific)
1562 db '.img' ; Disk image
1563 db '.bin' ; CD boot sector
1564 db '.com' ; COMBOOT (same as DOS)
1565 db '.c32' ; COM32
1566 exten_table_end:
1567 dd 0, 0 ; Need 8 null bytes here
1570 ; Floppy image table
1572 align 4, db 0
1573 img_table_count equ 3
1574 img_table:
1575 dd 1200*1024 ; 1200K floppy
1576 db 1 ; Emulation type
1577 db 80-1 ; Max cylinder
1578 db 15 ; Max sector
1579 db 2-1 ; Max head
1581 dd 1440*1024 ; 1440K floppy
1582 db 2 ; Emulation type
1583 db 80-1 ; Max cylinder
1584 db 18 ; Max sector
1585 db 2-1 ; Max head
1587 dd 2880*1024 ; 2880K floppy
1588 db 3 ; Emulation type
1589 db 80-1 ; Max cylinder
1590 db 36 ; Max sector
1591 db 2-1 ; Max head
1594 ; Misc initialized (data) variables
1598 ; Variables that are uninitialized in SYSLINUX but initialized here
1600 ; **** ISOLINUX:: We may have to make this flexible, based on what the
1601 ; **** BIOS expects our "sector size" to be.
1603 alignb 4, db 0
1604 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
1605 BufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?
1606 BufSafeBytes dw trackbufsize ; = how many bytes?
1607 EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
1608 %ifndef DEPEND
1609 %if ( trackbufsize % SECTOR_SIZE ) != 0
1610 %error trackbufsize must be a multiple of SECTOR_SIZE
1611 %endif
1612 %endif