Better describe what this macro does (comment fix.)
[syslinux.git] / isolinux.asm
blob4d2a47281ebed6fe942b152622f005f6851adc22
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 $
217 bootsec equ $
219 _start: ; Far jump makes sure we canonicalize the address
221 jmp 0:_start1
222 times 8-($-$$) nop ; Pad to file offset 8
224 ; This table hopefully gets filled in by mkisofs using the
225 ; -boot-info-table option. If not, the values in this
226 ; table are default values that we can use to get us what
227 ; we need, at least under a certain set of assumptions.
228 bi_pvd: dd 16 ; LBA of primary volume descriptor
229 bi_file: dd 0 ; LBA of boot file
230 bi_length: dd 0xdeadbeef ; Length of boot file
231 bi_csum: dd 0xdeadbeef ; Checksum of boot file
232 bi_reserved: times 10 dd 0xdeadbeef ; Reserved
234 _start1: mov [cs:InitStack],sp ; Save initial stack pointer
235 mov [cs:InitStack+2],ss
236 xor ax,ax
237 mov ss,ax
238 mov sp,StackBuf ; Set up stack
239 mov ds,ax
240 mov es,ax
241 mov fs,ax
242 mov gs,ax
246 ; Show signs of life
247 mov si,syslinux_banner
248 call writestr
249 %ifdef DEBUG_MESSAGES
250 mov si,copyright_str
251 call writestr
252 %endif
255 ; Before modifying any memory, get the checksum of bytes
256 ; 64-2048
258 initial_csum: xor edi,edi
259 mov si,_start1
260 mov cx,(SECTOR_SIZE-64) >> 2
261 .loop: lodsd
262 add edi,eax
263 loop .loop
264 mov [FirstSecSum],edi
266 mov [DriveNo],dl
267 %ifdef DEBUG_MESSAGES
268 mov si,startup_msg
269 call writemsg
270 mov al,dl
271 call writehex2
272 call crlf
273 %endif
275 ; Initialize spec packet buffers
277 mov di,_spec_start
278 mov cx,_spec_len >> 2
279 xor eax,eax
280 rep stosd
282 ; Initialize length field of the various packets
283 mov byte [spec_packet],13h
284 mov byte [drive_params],30
285 mov byte [dapa],16
286 mov byte [dspec_packet],13h
288 ; Other nonzero fields
289 inc word [dsp_sectors]
291 ; Now figure out what we're actually doing
292 ; Note: use passed-in DL value rather than 7Fh because
293 ; at least some BIOSes will get the wrong value otherwise
294 mov ax,4B01h ; Get disk emulation status
295 mov dl,[DriveNo]
296 mov si,spec_packet
297 int 13h
298 jc award_hack ; changed for BrokenAwardHack
299 mov dl,[DriveNo]
300 cmp [sp_drive],dl ; Should contain the drive number
301 jne spec_query_failed
303 %ifdef DEBUG_MESSAGES
304 mov si,spec_ok_msg
305 call writemsg
306 mov al,byte [sp_drive]
307 call writehex2
308 call crlf
309 %endif
311 found_drive:
312 ; Alright, we have found the drive. Now, try to find the
313 ; boot file itself. If we have a boot info table, life is
314 ; good; if not, we have to make some assumptions, and try
315 ; to figure things out ourselves. In particular, the
316 ; assumptions we have to make are:
317 ; - single session only
318 ; - only one boot entry (no menu or other alternatives)
320 cmp dword [bi_file],0 ; Address of code to load
321 jne found_file ; Boot info table present :)
323 %ifdef DEBUG_MESSAGES
324 mov si,noinfotable_msg
325 call writemsg
326 %endif
328 ; No such luck. See if the the spec packet contained one.
329 mov eax,[sp_lba]
330 and eax,eax
331 jz set_file ; Good enough
333 %ifdef DEBUG_MESSAGES
334 mov si,noinfoinspec_msg
335 call writemsg
336 %endif
338 ; No such luck. Get the Boot Record Volume, assuming single
339 ; session disk, and that we're the first entry in the chain
340 mov eax,17 ; Assumed address of BRV
341 mov bx,trackbuf
342 call getonesec
344 mov eax,[trackbuf+47h] ; Get boot catalog address
345 mov bx,trackbuf
346 call getonesec ; Get boot catalog
348 mov eax,[trackbuf+28h] ; First boot entry
349 ; And hope and pray this is us...
351 ; Some BIOSes apparently have limitations on the size
352 ; that may be loaded (despite the El Torito spec being very
353 ; clear on the fact that it must all be loaded.) Therefore,
354 ; we load it ourselves, and *bleep* the BIOS.
356 set_file:
357 mov [bi_file],eax
359 found_file:
360 ; Set up boot file sizes
361 mov eax,[bi_length]
362 sub eax,SECTOR_SIZE-3
363 shr eax,2 ; bytes->dwords
364 mov [ImageDwords],eax ; boot file dwords
365 add eax,(2047 >> 2)
366 shr eax,9 ; dwords->sectors
367 mov [ImageSectors],ax ; boot file sectors
369 mov eax,[bi_file] ; Address of code to load
370 inc eax ; Don't reload bootstrap code
371 %ifdef DEBUG_MESSAGES
372 mov si,offset_msg
373 call writemsg
374 call writehex8
375 call crlf
376 %endif
378 ; Just in case some BIOSes have problems with
379 ; segment wraparound, use the normalized address
380 mov bx,((7C00h+2048) >> 4)
381 mov es,bx
382 xor bx,bx
383 mov bp,[ImageSectors]
384 %ifdef DEBUG_MESSAGES
385 push ax
386 mov si,size_msg
387 call writemsg
388 mov ax,bp
389 call writehex4
390 call crlf
391 pop ax
392 %endif
393 call getlinsec
395 push ds
396 pop es
398 %ifdef DEBUG_MESSAGES
399 mov si,loaded_msg
400 call writemsg
401 %endif
403 ; Verify the checksum on the loaded image.
404 verify_image:
405 mov si,7C00h+2048
406 mov bx,es
407 mov ecx,[ImageDwords]
408 mov edi,[FirstSecSum] ; First sector checksum
409 .loop es lodsd
410 add edi,eax
411 dec ecx
412 jz .done
413 and si,si
414 jnz .loop
415 ; SI wrapped around, advance ES
416 add bx,1000h
417 mov es,bx
418 jmp short .loop
419 .done: mov ax,ds
420 mov es,ax
421 cmp [bi_csum],edi
422 je integrity_ok
424 mov si,checkerr_msg
425 call writemsg
426 jmp kaboom
428 integrity_ok:
429 %ifdef DEBUG_MESSAGES
430 mov si,allread_msg
431 call writemsg
432 %endif
433 jmp all_read ; Jump to main code
435 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
436 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
437 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
439 ;; There is a problem with certain versions of the AWARD BIOS ...
440 ;; the boot sector will be loaded and executed correctly, but, because the
441 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
442 ;; load the spec packet will fail. We scan for the equivalent of
444 ;; mov ax,0201h
445 ;; mov bx,7c00h
446 ;; mov cx,0006h
447 ;; mov dx,0180h
448 ;; pushf
449 ;; call <direct far>
451 ;; and use <direct far> as the new vector for int 13. The code above is
452 ;; used to load the boot code into ram, and there should be no reason
453 ;; for anybody to change it now or in the future. There are no opcodes
454 ;; that use encodings relativ to IP, so scanning is easy. If we find the
455 ;; code above in the BIOS code we can be pretty sure to run on a machine
456 ;; with an broken AWARD BIOS ...
458 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
460 %ifdef DEBUG_MESSAGES ;;
462 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
463 award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
464 award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
465 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
466 award_not_fail db "BAH: FAILURE" ;;
467 award_not_crlf db CR,LF,0 ;;
469 %endif ;;
471 award_oldint13 dd 0 ;;
472 award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
474 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
475 award_hack: mov si,spec_err_msg ; Moved to this place from
476 call writemsg ; spec_query_faild
478 %ifdef DEBUG_MESSAGES ;
480 mov si,award_notice ; display our plan
481 call writemsg ;
482 mov si,award_not_orig ; display original int 13
483 call writemsg ; vector
484 %endif ;
485 mov eax,[13h*4] ;
486 mov [award_oldint13],eax ;
488 %ifdef DEBUG_MESSAGES ;
490 call writehex8 ;
491 mov si,award_not_crlf ;
492 call writestr ;
493 %endif ;
494 push es ; save ES
495 mov ax,0f000h ; ES = BIOS Seg
496 mov es,ax ;
497 cld ;
498 xor di,di ; start at ES:DI = f000:0
499 award_loop: push di ; save DI
500 mov si,award_string ; scan for award_string
501 mov cx,7 ; length of award_string = 7dw
502 repz cmpsw ; compare
503 pop di ; restore DI
504 jcxz award_found ; jmp if found
505 inc di ; not found, inc di
506 jno award_loop ;
508 award_failed: pop es ; No, not this way :-((
509 award_fail2: ;
511 %ifdef DEBUG_MESSAGES ;
513 mov si,award_not_fail ; display failure ...
514 call writemsg ;
515 %endif ;
516 mov eax,[award_oldint13] ; restore the original int
517 or eax,eax ; 13 vector if there is one
518 jz spec_query_failed ; and try other workarounds
519 mov [13h*4],eax ;
520 jmp spec_query_failed ;
522 award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
523 pop es ; restore ES
525 cmp eax,[award_oldint13] ; give up if this is the
526 jz award_failed ; active int 13 vector,
527 mov [13h*4],eax ; otherwise change 0:13h*4
530 %ifdef DEBUG_MESSAGES ;
532 push eax ; display message and
533 mov si,award_not_new ; new vector address
534 call writemsg ;
535 pop eax ;
536 call writehex8 ;
537 mov si,award_not_crlf ;
538 call writestr ;
539 %endif ;
540 mov ax,4B01h ; try to read the spec packet
541 mov dl,[DriveNo] ; now ... it should not fail
542 mov si,spec_packet ; any longer
543 int 13h ;
544 jc award_fail2 ;
546 %ifdef DEBUG_MESSAGES ;
548 mov si,award_not_succ ; display our SUCCESS
549 call writemsg ;
550 %endif ;
551 jmp found_drive ; and leave error recovery code
553 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
554 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
555 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
558 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
559 ; Try to scan the entire 80h-FFh from the end.
561 spec_query_failed:
563 ; some code moved to BrokenAwardHack
565 mov dl,0FFh
566 .test_loop: pusha
567 mov ax,4B01h
568 mov si,spec_packet
569 mov byte [si],13 ; Size of buffer
570 int 13h
571 popa
572 jc .still_broken
574 mov si,maybe_msg
575 call writemsg
576 mov al,dl
577 call writehex2
578 call crlf
580 cmp byte [sp_drive],dl
581 jne .maybe_broken
583 ; Okay, good enough...
584 mov si,alright_msg
585 call writemsg
586 mov [DriveNo],dl
587 .found_drive: jmp found_drive
589 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
590 ; but if this was the drive number originally passed in
591 ; DL then consider it "good enough"
592 .maybe_broken:
593 cmp byte [DriveNo],dl
594 je .found_drive
596 .still_broken: dec dx
597 cmp dl, 80h
598 jnb .test_loop
600 ; No spec packet anywhere. Some particularly pathetic
601 ; BIOSes apparently don't even implement function
602 ; 4B01h, so we can't query a spec packet no matter
603 ; what. If we got a drive number in DL, then try to
604 ; use it, and if it works, then well...
605 mov dl,[DriveNo]
606 cmp dl,81h ; Should be 81-FF at least
607 jb fatal_error ; If not, it's hopeless
609 ; Write a warning to indicate we're on *very* thin ice now
610 mov si,nospec_msg
611 call writemsg
612 mov al,dl
613 call writehex2
614 call crlf
615 mov si,trysbm_msg
616 call writemsg
617 jmp .found_drive ; Pray that this works...
619 fatal_error:
620 mov si,nothing_msg
621 call writemsg
623 .norge: jmp short .norge
625 ; Information message (DS:SI) output
626 ; Prefix with "isolinux: "
628 writemsg: push ax
629 push si
630 mov si,isolinux_str
631 call writestr
632 pop si
633 call writestr
634 pop ax
638 ; Write a character to the screen. There is a more "sophisticated"
639 ; version of this in the subsequent code, so we patch the pointer
640 ; when appropriate.
643 writechr:
644 jmp near writechr_simple ; 3-byte jump
646 writechr_simple:
647 pushfd
648 pushad
649 mov ah,0Eh
650 xor bx,bx
651 int 10h
652 popad
653 popfd
657 ; Get one sector. Convenience entry point.
659 getonesec:
660 mov bp,1
661 ; Fall through to getlinsec
664 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
666 ; Note that we can't always do this as a single request, because at least
667 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
668 ; to 32 sectors (64K) per request.
670 ; Input:
671 ; EAX - Linear sector number
672 ; ES:BX - Target buffer
673 ; BP - Sector count
675 getlinsec:
676 mov si,dapa ; Load up the DAPA
677 mov [si+4],bx
678 mov bx,es
679 mov [si+6],bx
680 mov [si+8],eax
681 .loop:
682 push bp ; Sectors left
683 cmp bp,[MaxTransfer]
684 jbe .bp_ok
685 mov bp,[MaxTransfer]
686 .bp_ok:
687 mov [si+2],bp
688 push si
689 mov dl,[DriveNo]
690 mov ah,42h ; Extended Read
691 call xint13
692 pop si
693 pop bp
694 movzx eax,word [si+2] ; Sectors we read
695 add [si+8],eax ; Advance sector pointer
696 sub bp,ax ; Sectors left
697 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
698 add [si+6],ax ; Advance buffer pointer
699 and bp,bp
700 jnz .loop
701 mov eax,[si+8] ; Next sector
704 ; INT 13h with retry
705 xint13: mov byte [RetryCount],retry_count
706 .try: pushad
707 int 13h
708 jc .error
709 add sp,byte 8*4 ; Clean up stack
711 .error:
712 mov [DiskError],ah ; Save error code
713 popad
714 mov [DiskSys],ax ; Save system call number
715 dec byte [RetryCount]
716 jz .real_error
717 push ax
718 mov al,[RetryCount]
719 mov ah,[dapa+2] ; Sector transfer count
720 cmp al,2 ; Only 2 attempts left
721 ja .nodanger
722 mov ah,1 ; Drop transfer size to 1
723 jmp short .setsize
724 .nodanger:
725 cmp al,retry_count-2
726 ja .again ; First time, just try again
727 shr ah,1 ; Otherwise, try to reduce
728 adc ah,0 ; the max transfer size, but not to 0
729 .setsize:
730 mov [MaxTransfer],ah
731 mov [dapa+2],ah
732 .again:
733 pop ax
734 jmp .try
736 .real_error: mov si,diskerr_msg
737 call writemsg
738 mov al,[DiskError]
739 call writehex2
740 mov si,oncall_str
741 call writestr
742 mov ax,[DiskSys]
743 call writehex4
744 mov si,ondrive_str
745 call writestr
746 mov al,dl
747 call writehex2
748 call crlf
749 ; Fall through to kaboom
752 ; kaboom: write a message and bail out. Wait for a user keypress,
753 ; then do a hard reboot.
755 kaboom:
756 lss sp,[cs:StackPtr]
757 mov ax,cs
758 mov ds,ax
759 mov es,ax
760 mov fs,ax
761 mov gs,ax
763 mov si,err_bootfailed
764 call cwritestr
765 call getchar
767 mov word [BIOS_magic],0 ; Cold reboot
768 jmp 0F000h:0FFF0h ; Reset vector address
770 ; -----------------------------------------------------------------------------
771 ; Common modules needed in the first sector
772 ; -----------------------------------------------------------------------------
774 %include "writestr.inc" ; String output
775 writestr equ cwritestr
776 %include "writehex.inc" ; Hexadecimal output
778 ; -----------------------------------------------------------------------------
779 ; Data that needs to be in the first sector
780 ; -----------------------------------------------------------------------------
782 syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0
783 copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
784 db CR, LF, 0
785 isolinux_str db 'isolinux: ', 0
786 %ifdef DEBUG_MESSAGES
787 startup_msg: db 'Starting up, DL = ', 0
788 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
789 secsize_msg: db 'Sector size appears to be ', 0
790 offset_msg: db 'Loading main image from LBA = ', 0
791 size_msg: db 'Sectors to load = ', 0
792 loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
793 verify_msg: db 'Image checksum verified.', CR, LF, 0
794 allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
795 %endif
796 noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
797 noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
798 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
799 maybe_msg: db 'Found something at drive = ', 0
800 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
801 nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
802 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
803 trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
804 diskerr_msg: db 'Disk error ', 0
805 oncall_str: db ', AX = ',0
806 ondrive_str: db ', drive ', 0
807 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
809 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
810 bailmsg equ err_bootfailed
811 crlf_msg db CR, LF
812 null_msg db 0
814 alignb 4, db 0
815 StackPtr dw StackBuf, 0 ; SS:SP for stack reset
816 MaxTransfer dw 32 ; Max sectors per transfer
818 rl_checkpt equ $ ; Must be <= 800h
820 rl_checkpt_off equ ($-$$)
821 ;%ifndef DEPEND
822 ;%if rl_checkpt_off > 0x800
823 ;%error "Sector 0 overflow"
824 ;%endif
825 ;%endif
827 ; ----------------------------------------------------------------------------
828 ; End of code and data that have to be in the first sector
829 ; ----------------------------------------------------------------------------
831 all_read:
833 ; Initialize screen (if we're using one)
835 ; Now set up screen parameters
836 call adjust_screen
838 ; Wipe the F-key area
839 mov al,NULLFILE
840 mov di,FKeyName
841 mov cx,10*(1 << FILENAME_MAX_LG2)
842 rep stosb
844 ; Patch the writechr routine to point to the full code
845 mov word [writechr+1], writechr_full-(writechr+3)
847 ; Tell the user we got this far...
848 %ifndef DEBUG_MESSAGES ; Gets messy with debugging on
849 mov si,copyright_str
850 call writestr
851 %endif
853 ; Test tracers
854 TRACER 'T'
855 TRACER '>'
858 ; Common initialization code
860 %include "init.inc"
861 %include "cpuinit.inc"
864 ; Now we're all set to start with our *real* business. First load the
865 ; configuration file (if any) and parse it.
867 ; In previous versions I avoided using 32-bit registers because of a
868 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
869 ; random. I figure, though, that if there are any of those still left
870 ; they probably won't be trying to install Linux on them...
872 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
873 ; to take'm out. In fact, we may want to put them back if we're going
874 ; to boot ELKS at some point.
878 ; Now, we need to sniff out the actual filesystem data structures.
879 ; mkisofs gave us a pointer to the primary volume descriptor
880 ; (which will be at 16 only for a single-session disk!); from the PVD
881 ; we should be able to find the rest of what we need to know.
883 get_fs_structures:
884 mov eax,[bi_pvd]
885 mov bx,trackbuf
886 call getonesec
888 mov eax,[trackbuf+156+2]
889 mov [RootDir+dir_lba],eax
890 mov [CurDir+dir_lba],eax
891 %ifdef DEBUG_MESSAGES
892 mov si,dbg_rootdir_msg
893 call writemsg
894 call writehex8
895 call crlf
896 %endif
897 mov eax,[trackbuf+156+10]
898 mov [RootDir+dir_len],eax
899 mov [CurDir+dir_len],eax
900 add eax,SECTOR_SIZE-1
901 shr eax,SECTOR_SHIFT
902 mov [RootDir+dir_clust],eax
903 mov [CurDir+dir_clust],eax
905 ; Look for an isolinux directory, and if found,
906 ; make it the current directory instead of the root
907 ; directory.
908 mov di,boot_dir ; Search for /boot/isolinux
909 mov al,02h
910 call searchdir_iso
911 jnz .found_dir
912 mov di,isolinux_dir
913 mov al,02h ; Search for /isolinux
914 call searchdir_iso
915 jz .no_isolinux_dir
916 .found_dir:
917 mov [CurDir+dir_len],eax
918 mov eax,[si+file_left]
919 mov [CurDir+dir_clust],eax
920 xor eax,eax ; Free this file pointer entry
921 xchg eax,[si+file_sector]
922 mov [CurDir+dir_lba],eax
923 %ifdef DEBUG_MESSAGES
924 push si
925 mov si,dbg_isodir_msg
926 call writemsg
927 pop si
928 call writehex8
929 call crlf
930 %endif
931 .no_isolinux_dir:
934 ; Locate the configuration file
936 load_config:
937 %ifdef DEBUG_MESSAGES
938 mov si,dbg_config_msg
939 call writemsg
940 %endif
942 mov di,isolinux_cfg
943 call open
944 jz no_config_file ; Not found or empty
946 %ifdef DEBUG_MESSAGES
947 mov si,dbg_configok_msg
948 call writemsg
949 %endif
952 ; Now we have the config file open. Parse the config file and
953 ; run the user interface.
955 %include "ui.inc"
958 ; Linux kernel loading code is common.
960 %include "runkernel.inc"
963 ; COMBOOT-loading code
965 %include "comboot.inc"
966 %include "com32.inc"
967 %include "cmdline.inc"
970 ; Boot sector loading code
972 %include "bootsect.inc"
975 ; Enable disk emulation. The kind of disk we emulate is dependent on the size of
976 ; the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
978 is_disk_image:
979 TRACER CR
980 TRACER LF
981 TRACER 'D'
982 TRACER ':'
984 shl edx,16
985 mov dx,ax ; Set EDX <- file size
986 mov di,img_table
987 mov cx,img_table_count
988 mov eax,[si+file_sector] ; Starting LBA of file
989 mov [dsp_lba],eax ; Location of file
990 mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk
991 .search_table:
992 TRACER 't'
993 mov eax,[di+4]
994 cmp edx,[di]
995 je .type_found
996 add di,8
997 loop .search_table
999 ; Hard disk image. Need to examine the partition table
1000 ; in order to deduce the C/H/S geometry. Sigh.
1001 .hard_disk_image:
1002 TRACER 'h'
1003 cmp edx,512
1004 jb .bad_image
1006 mov bx,trackbuf
1007 mov cx,1 ; Load 1 sector
1008 call getfssec
1010 cmp word [trackbuf+510],0aa55h ; Boot signature
1011 jne .bad_image ; Image not bootable
1013 mov cx,4 ; 4 partition entries
1014 mov di,trackbuf+446 ; Start of partition table
1016 xor ax,ax ; Highest sector(al) head(ah)
1018 .part_scan:
1019 cmp byte [di+4], 0
1020 jz .part_loop
1021 lea si,[di+1]
1022 call .hs_check
1023 add si,byte 4
1024 call .hs_check
1025 .part_loop:
1026 add di,byte 16
1027 loop .part_scan
1029 push eax ; H/S
1030 push edx ; File size
1031 mov bl,ah
1032 xor bh,bh
1033 inc bx ; # of heads in BX
1034 xor ah,ah ; # of sectors in AX
1035 cwde ; EAX[31:16] <- 0
1036 mul bx
1037 shl eax,9 ; Convert to bytes
1038 ; Now eax contains the number of bytes per cylinder
1039 pop ebx ; File size
1040 xor edx,edx
1041 div ebx
1042 and edx,edx
1043 jz .no_remainder
1044 inc eax ; Fractional cylinder...
1045 ; Now (e)ax contains the number of cylinders
1046 .no_remainder: cmp eax,1024
1047 jna .ok_cyl
1048 mov ax,1024 ; Max possible #
1049 .ok_cyl: dec ax ; Convert to max cylinder no
1050 pop ebx ; S(bl) H(bh)
1051 shl ah,6
1052 or bl,ah
1053 xchg ax,bx
1054 shl eax,16
1055 mov ah,bl
1056 mov al,4 ; Hard disk boot
1057 mov byte [dsp_drive], 80h ; Drive 80h = hard disk
1059 .type_found:
1060 TRACER 'T'
1061 mov bl,[sp_media]
1062 and bl,0F0h ; Copy controller info bits
1063 or al,bl
1064 mov [dsp_media],al ; Emulation type
1065 shr eax,8
1066 mov [dsp_chs],eax ; C/H/S geometry
1067 mov ax,[sp_devspec] ; Copy device spec
1068 mov [dsp_devspec],ax
1069 mov al,[sp_controller] ; Copy controller index
1070 mov [dsp_controller],al
1072 TRACER 'V'
1073 call vgaclearmode ; Reset video
1075 mov ax,4C00h ; Enable emulation and boot
1076 mov si,dspec_packet
1077 mov dl,[DriveNo]
1078 lss sp,[InitStack]
1079 TRACER 'X'
1081 int 13h
1083 ; If this returns, we have problems
1084 .bad_image:
1085 mov si,err_disk_image
1086 call cwritestr
1087 jmp enter_command
1090 ; Look for the highest seen H/S geometry
1091 ; We compute cylinders separately
1093 .hs_check:
1094 mov bl,[si] ; Head #
1095 cmp bl,ah
1096 jna .done_track
1097 mov ah,bl ; New highest head #
1098 .done_track: mov bl,[si+1]
1099 and bl,3Fh ; Sector #
1100 cmp bl,al
1101 jna .done_sector
1102 mov al,bl
1103 .done_sector: ret
1106 ; Boot a specified local disk. AX specifies the BIOS disk number; or
1107 ; 0xFFFF in case we should execute INT 18h ("next device.")
1109 local_boot:
1110 call vgaclearmode
1111 lss sp,[cs:Stack] ; Restore stack pointer
1112 xor dx,dx
1113 mov ds,dx
1114 mov es,dx
1115 mov fs,dx
1116 mov gs,dx
1117 mov si,localboot_msg
1118 call writestr
1119 cmp ax,-1
1120 je .int18
1122 ; Load boot sector from the specified BIOS device and jump to it.
1123 mov dl,al
1124 xor dh,dh
1125 push dx
1126 xor ax,ax ; Reset drive
1127 call xint13
1128 mov ax,0201h ; Read one sector
1129 mov cx,0001h ; C/H/S = 0/0/1 (first sector)
1130 mov bx,trackbuf
1131 call xint13
1132 pop dx
1133 cli ; Abandon hope, ye who enter here
1134 mov si,trackbuf
1135 mov di,07C00h
1136 mov cx,512 ; Probably overkill, but should be safe
1137 rep movsd
1138 lss sp,[cs:InitStack]
1139 jmp 0:07C00h ; Jump to new boot sector
1141 .int18:
1142 int 18h ; Hope this does the right thing...
1143 jmp kaboom ; If we returned, oh boy...
1146 ; Abort loading code
1148 %include "abort.inc"
1151 ; searchdir:
1153 ; Open a file
1155 ; On entry:
1156 ; DS:DI = filename
1157 ; If successful:
1158 ; ZF clear
1159 ; SI = file pointer
1160 ; DX:AX or EAX = file length in bytes
1161 ; If unsuccessful
1162 ; ZF set
1164 ; Assumes CS == DS == ES, and trashes BX and CX.
1166 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
1167 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
1168 ; for searching for directories.
1170 alloc_failure:
1171 xor ax,ax ; ZF <- 1
1174 searchdir:
1175 xor al,al
1176 searchdir_iso:
1177 mov [ISOFlags],al
1178 TRACER 'S'
1179 call allocate_file ; Temporary file structure for directory
1180 jnz alloc_failure
1181 push es
1182 push ds
1183 pop es ; ES = DS
1184 mov si,CurDir
1185 cmp byte [di],'/' ; If filename begins with slash
1186 jne .not_rooted
1187 inc di ; Skip leading slash
1188 mov si,RootDir ; Reference root directory instead
1189 .not_rooted:
1190 mov eax,[si+dir_clust]
1191 mov [bx+file_left],eax
1192 mov eax,[si+dir_lba]
1193 mov [bx+file_sector],eax
1194 mov edx,[si+dir_len]
1196 .look_for_slash:
1197 mov ax,di
1198 .scan:
1199 mov cl,[di]
1200 inc di
1201 and cl,cl
1202 jz .isfile
1203 cmp cl,'/'
1204 jne .scan
1205 mov [di-1],byte 0 ; Terminate at directory name
1206 mov cl,02h ; Search for directory
1207 xchg cl,[ISOFlags]
1209 push di ; Save these...
1210 push cx
1212 ; Create recursion stack frame...
1213 push word .resume ; Where to "return" to
1214 push es
1215 .isfile: xchg ax,di
1217 .getsome:
1218 ; Get a chunk of the directory
1219 ; This relies on the fact that ISOLINUX doesn't change SI
1220 mov si,trackbuf
1221 TRACER 'g'
1222 pushad
1223 xchg bx,si
1224 mov cx,[BufSafe]
1225 call getfssec
1226 popad
1228 .compare:
1229 movzx eax,byte [si] ; Length of directory entry
1230 cmp al,33
1231 jb .next_sector
1232 TRACER 'c'
1233 mov cl,[si+25]
1234 xor cl,[ISOFlags]
1235 test cl, byte 8Eh ; Unwanted file attributes!
1236 jnz .not_file
1237 pusha
1238 movzx cx,byte [si+32] ; File identifier length
1239 add si,byte 33 ; File identifier offset
1240 TRACER 'i'
1241 call iso_compare_names
1242 popa
1243 je .success
1244 .not_file:
1245 sub edx,eax ; Decrease bytes left
1246 jbe .failure
1247 add si,ax ; Advance pointer
1249 .check_overrun:
1250 ; Did we finish the buffer?
1251 cmp si,trackbuf+trackbufsize
1252 jb .compare ; No, keep going
1254 jmp short .getsome ; Get some more directory
1256 .next_sector:
1257 ; Advance to the beginning of next sector
1258 lea ax,[si+SECTOR_SIZE-1]
1259 and ax,~(SECTOR_SIZE-1)
1260 sub ax,si
1261 jmp short .not_file ; We still need to do length checks
1263 .failure: xor eax,eax ; ZF = 1
1264 mov [bx+file_sector],eax
1265 pop es
1268 .success:
1269 mov eax,[si+2] ; Location of extent
1270 mov [bx+file_sector],eax
1271 mov eax,[si+10] ; Data length
1272 push eax
1273 add eax,SECTOR_SIZE-1
1274 shr eax,SECTOR_SHIFT
1275 mov [bx+file_left],eax
1276 pop eax
1277 mov edx,eax
1278 shr edx,16
1279 and bx,bx ; ZF = 0
1280 mov si,bx
1281 pop es
1284 .resume: ; We get here if we were only doing part of a lookup
1285 ; This relies on the fact that .success returns bx == si
1286 xchg edx,eax ; Directory length in edx
1287 pop cx ; Old ISOFlags
1288 pop di ; Next filename pointer
1289 mov byte [di-1], '/' ; Restore slash
1290 mov [ISOFlags],cl ; Restore the flags
1291 jz .failure ; Did we fail? If so fail for real!
1292 jmp .look_for_slash ; Otherwise, next level
1295 ; allocate_file: Allocate a file structure
1297 ; If successful:
1298 ; ZF set
1299 ; BX = file pointer
1300 ; In unsuccessful:
1301 ; ZF clear
1303 allocate_file:
1304 TRACER 'a'
1305 push cx
1306 mov bx,Files
1307 mov cx,MAX_OPEN
1308 .check: cmp dword [bx], byte 0
1309 je .found
1310 add bx,open_file_t_size ; ZF = 0
1311 loop .check
1312 ; ZF = 0 if we fell out of the loop
1313 .found: pop cx
1317 ; iso_compare_names:
1318 ; Compare the names DS:SI and DS:DI and report if they are
1319 ; equal from an ISO 9660 perspective. SI is the name from
1320 ; the filesystem; CX indicates its length, and ';' terminates.
1321 ; DI is expected to end with a null.
1323 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
1326 iso_compare_names:
1327 ; First, terminate and canonicalize input filename
1328 push di
1329 mov di,ISOFileName
1330 .canon_loop: jcxz .canon_end
1331 lodsb
1332 dec cx
1333 cmp al,';'
1334 je .canon_end
1335 and al,al
1336 je .canon_end
1337 stosb
1338 cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
1339 jb .canon_loop
1340 .canon_end:
1341 cmp di,ISOFileName
1342 jbe .canon_done
1343 cmp byte [di-1],'.' ; Remove terminal dots
1344 jne .canon_done
1345 dec di
1346 jmp short .canon_end
1347 .canon_done:
1348 mov [di],byte 0 ; Null-terminate string
1349 pop di
1350 mov si,ISOFileName
1351 .compare:
1352 lodsb
1353 mov ah,[di]
1354 inc di
1355 and ax,ax
1356 jz .success ; End of string for both
1357 and al,al ; Is either one end of string?
1358 jz .failure ; If so, failure
1359 and ah,ah
1360 jz .failure
1361 or ax,2020h ; Convert to lower case
1362 cmp al,ah
1363 je .compare
1364 .failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
1365 .success: ret
1368 ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
1369 ; to by ES:DI; ends on encountering any whitespace.
1371 ; This verifies that a filename is < FILENAME_MAX characters,
1372 ; doesn't contain whitespace, zero-pads the output buffer,
1373 ; and removes trailing dots and redundant slashes,
1374 ; so "repe cmpsb" can do a compare, and the
1375 ; path-searching routine gets a bit of an easier job.
1377 mangle_name:
1378 push bx
1379 xor ax,ax
1380 mov cx,FILENAME_MAX-1
1381 mov bx,di
1383 .mn_loop:
1384 lodsb
1385 cmp al,' ' ; If control or space, end
1386 jna .mn_end
1387 cmp al,ah ; Repeated slash?
1388 je .mn_skip
1389 xor ah,ah
1390 cmp al,'/'
1391 jne .mn_ok
1392 mov ah,al
1393 .mn_ok stosb
1394 .mn_skip: loop .mn_loop
1395 .mn_end:
1396 cmp bx,di ; At the beginning of the buffer?
1397 jbe .mn_zero
1398 cmp byte [di-1],'.' ; Terminal dot?
1399 je .mn_kill
1400 cmp byte [di-1],'/' ; Terminal slash?
1401 jne .mn_zero
1402 .mn_kill: dec di ; If so, remove it
1403 inc cx
1404 jmp short .mn_end
1405 .mn_zero:
1406 inc cx ; At least one null byte
1407 xor ax,ax ; Zero-fill name
1408 rep stosb
1409 pop bx
1410 ret ; Done
1413 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1414 ; filename to the conventional representation. This is needed
1415 ; for the BOOT_IMAGE= parameter for the kernel.
1416 ; NOTE: A 13-byte buffer is mandatory, even if the string is
1417 ; known to be shorter.
1419 ; DS:SI -> input mangled file name
1420 ; ES:DI -> output buffer
1422 ; On return, DI points to the first byte after the output name,
1423 ; which is set to a null byte.
1425 unmangle_name: call strcpy
1426 dec di ; Point to final null byte
1430 ; getfssec: Get multiple clusters from a file, given the file pointer.
1432 ; On entry:
1433 ; ES:BX -> Buffer
1434 ; SI -> File pointer
1435 ; CX -> Cluster count
1436 ; On exit:
1437 ; SI -> File pointer (or 0 on EOF)
1438 ; CF = 1 -> Hit EOF
1440 getfssec:
1441 TRACER 'F'
1443 push ds
1444 push cs
1445 pop ds ; DS <- CS
1447 movzx ecx,cx
1448 cmp ecx,[si+file_left]
1449 jna .ok_size
1450 mov ecx,[si+file_left]
1451 .ok_size:
1453 mov bp,cx
1454 push cx
1455 push si
1456 mov eax,[si+file_sector]
1457 TRACER 'l'
1458 call getlinsec
1459 xor ecx,ecx
1460 pop si
1461 pop cx
1463 add [si+file_sector],ecx
1464 sub [si+file_left],ecx
1465 ja .not_eof ; CF = 0
1467 xor ecx,ecx
1468 mov [si+file_sector],ecx ; Mark as unused
1469 xor si,si
1472 .not_eof:
1473 pop ds
1474 TRACER 'f'
1477 ; -----------------------------------------------------------------------------
1478 ; Common modules
1479 ; -----------------------------------------------------------------------------
1481 %include "getc.inc" ; getc et al
1482 %include "conio.inc" ; Console I/O
1483 %include "parseconfig.inc" ; High-level config file handling
1484 %include "parsecmd.inc" ; Low-level config file handling
1485 %include "bcopy32.inc" ; 32-bit bcopy
1486 %include "loadhigh.inc" ; Load a file into high memory
1487 %include "font.inc" ; VGA font stuff
1488 %include "graphics.inc" ; VGA graphics
1489 %include "highmem.inc" ; High memory sizing
1490 %include "strcpy.inc" ; strcpy()
1491 %include "rawcon.inc" ; Console I/O w/o using the console functions
1493 ; -----------------------------------------------------------------------------
1494 ; Begin data section
1495 ; -----------------------------------------------------------------------------
1497 section .data
1499 boot_prompt db 'boot: ', 0
1500 wipe_char db BS, ' ', BS, 0
1501 err_notfound db 'Could not find kernel image: ',0
1502 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
1503 err_noram db 'It appears your computer has less than '
1504 asciidec dosram_k
1505 db 'K of low ("DOS")'
1506 db CR, LF
1507 db 'RAM. Linux needs at least this amount to boot. If you get'
1508 db CR, LF
1509 db 'this message in error, hold down the Ctrl key while'
1510 db CR, LF
1511 db 'booting, and I will take your word for it.', CR, LF, 0
1512 err_badcfg db 'Unknown keyword in config file.', CR, LF, 0
1513 err_noparm db 'Missing parameter in config file.', CR, LF, 0
1514 err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
1515 err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0
1516 err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0
1517 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
1518 db CR, LF, 0
1519 err_notdos db ': attempted DOS system call', CR, LF, 0
1520 err_comlarge db 'COMBOOT image too large.', CR, LF, 0
1521 err_bssimage db 'BSS images not supported.', CR, LF, 0
1522 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
1523 notfound_msg db 'not found', CR, LF, 0
1524 localboot_msg db 'Booting from local disk...', CR, LF, 0
1525 cmdline_msg db 'Command line: ', CR, LF, 0
1526 ready_msg db 'Ready.', CR, LF, 0
1527 trying_msg db 'Trying to load: ', 0
1528 crlfloading_msg db CR, LF ; Fall through
1529 loading_msg db 'Loading ', 0
1530 dotdot_msg db '.'
1531 dot_msg db '.', 0
1532 fourbs_msg db BS, BS, BS, BS, 0
1533 aborted_msg db ' aborted.', CR, LF, 0
1534 crff_msg db CR, FF, 0
1535 default_str db 'default', 0
1536 default_len equ ($-default_str)
1537 boot_dir db '/boot' ; /boot/isolinux
1538 isolinux_dir db '/isolinux', 0
1539 ConfigName equ $
1540 isolinux_cfg db 'isolinux.cfg', 0
1541 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
1543 %ifdef DEBUG_MESSAGES
1544 dbg_rootdir_msg db 'Root directory at LBA = ', 0
1545 dbg_isodir_msg db 'isolinux directory at LBA = ', 0
1546 dbg_config_msg db 'About to load config file...', CR, LF, 0
1547 dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
1548 %endif
1550 ; Command line options we'd like to take a look at
1552 ; mem= and vga= are handled as normal 32-bit integer values
1553 initrd_cmd db 'initrd='
1554 initrd_cmd_len equ 7
1557 ; Config file keyword table
1559 %include "keywords.inc"
1562 ; Extensions to search for (in *forward* order).
1564 align 4, db 0
1565 exten_table: db '.cbt' ; COMBOOT (specific)
1566 db '.img' ; Disk image
1567 db '.bin' ; CD boot sector
1568 db '.com' ; COMBOOT (same as DOS)
1569 db '.c32' ; COM32
1570 exten_table_end:
1571 dd 0, 0 ; Need 8 null bytes here
1574 ; Floppy image table
1576 align 4, db 0
1577 img_table_count equ 3
1578 img_table:
1579 dd 1200*1024 ; 1200K floppy
1580 db 1 ; Emulation type
1581 db 80-1 ; Max cylinder
1582 db 15 ; Max sector
1583 db 2-1 ; Max head
1585 dd 1440*1024 ; 1440K floppy
1586 db 2 ; Emulation type
1587 db 80-1 ; Max cylinder
1588 db 18 ; Max sector
1589 db 2-1 ; Max head
1591 dd 2880*1024 ; 2880K floppy
1592 db 3 ; Emulation type
1593 db 80-1 ; Max cylinder
1594 db 36 ; Max sector
1595 db 2-1 ; Max head
1598 ; Misc initialized (data) variables
1602 ; Variables that are uninitialized in SYSLINUX but initialized here
1604 ; **** ISOLINUX:: We may have to make this flexible, based on what the
1605 ; **** BIOS expects our "sector size" to be.
1607 alignb 4, db 0
1608 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
1609 BufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?
1610 BufSafeBytes dw trackbufsize ; = how many bytes?
1611 EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
1612 %ifndef DEPEND
1613 %if ( trackbufsize % SECTOR_SIZE ) != 0
1614 %error trackbufsize must be a multiple of SECTOR_SIZE
1615 %endif
1616 %endif