Adding upstream version 3.50~pre5.
[syslinux-debian/hramrach.git] / isolinux.asm
blob9bc1b45a7e256fadeb401aab6f69f969044937aa
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 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 3000h
71 vk_seg equ 2000h ; Virtual kernels
72 xfer_buf_seg equ 1000h ; Bounce buffer for I/O to high mem
73 comboot_seg equ real_mode_seg ; COMBOOT image loading zone
76 ; File structure. This holds the information for each currently open file.
78 struc open_file_t
79 file_sector resd 1 ; Sector pointer (0 = structure free)
80 file_left resd 1 ; Number of sectors left
81 endstruc
83 %ifndef DEPEND
84 %if (open_file_t_size & (open_file_t_size-1))
85 %error "open_file_t is not a power of 2"
86 %endif
87 %endif
89 struc dir_t
90 dir_lba resd 1 ; Directory start (LBA)
91 dir_len resd 1 ; Length in bytes
92 dir_clust resd 1 ; Length in clusters
93 endstruc
95 ; ---------------------------------------------------------------------------
96 ; BEGIN CODE
97 ; ---------------------------------------------------------------------------
100 ; Memory below this point is reserved for the BIOS and the MBR
102 section .earlybss
103 trackbufsize equ 8192
104 trackbuf resb trackbufsize ; Track buffer goes here
105 getcbuf resb trackbufsize
106 ; ends at 4800h
108 section .bss
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 DriveNo 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
200 ; Constants for the xfer_buf_seg
202 ; The xfer_buf_seg is also used to store message file buffers. We
203 ; need two trackbuffers (text and graphics), plus a work buffer
204 ; for the graphics decompressor.
206 xbs_textbuf equ 0 ; Also hard-coded, do not change
207 xbs_vgabuf equ trackbufsize
208 xbs_vgatmpbuf equ 2*trackbufsize
210 section .text
212 ;; Primary entry point. Because BIOSes are buggy, we only load the first
213 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
214 ;; loading the rest.
216 StackBuf equ $-44 ; 44 bytes needed for
217 ; the bootsector chainloading
218 ; code!
220 bootsec equ $
222 _start: ; Far jump makes sure we canonicalize the address
224 jmp 0:_start1
225 times 8-($-$$) nop ; Pad to file offset 8
227 ; This table hopefully gets filled in by mkisofs using the
228 ; -boot-info-table option. If not, the values in this
229 ; table are default values that we can use to get us what
230 ; we need, at least under a certain set of assumptions.
231 bi_pvd: dd 16 ; LBA of primary volume descriptor
232 bi_file: dd 0 ; LBA of boot file
233 bi_length: dd 0xdeadbeef ; Length of boot file
234 bi_csum: dd 0xdeadbeef ; Checksum of boot file
235 bi_reserved: times 10 dd 0xdeadbeef ; Reserved
237 _start1: mov [cs:InitStack],sp ; Save initial stack pointer
238 mov [cs:InitStack+2],ss
239 xor ax,ax
240 mov ss,ax
241 mov sp,StackBuf ; Set up stack
242 mov ds,ax
243 mov es,ax
244 mov fs,ax
245 mov gs,ax
249 ; Show signs of life
250 mov si,syslinux_banner
251 call writestr
252 %ifdef DEBUG_MESSAGES
253 mov si,copyright_str
254 call writestr
255 %endif
258 ; Before modifying any memory, get the checksum of bytes
259 ; 64-2048
261 initial_csum: xor edi,edi
262 mov si,_start1
263 mov cx,(SECTOR_SIZE-64) >> 2
264 .loop: lodsd
265 add edi,eax
266 loop .loop
267 mov [FirstSecSum],edi
269 mov [DriveNo],dl
270 %ifdef DEBUG_MESSAGES
271 mov si,startup_msg
272 call writemsg
273 mov al,dl
274 call writehex2
275 call crlf
276 %endif
278 ; Initialize spec packet buffers
280 mov di,_spec_start
281 mov cx,_spec_len >> 2
282 xor eax,eax
283 rep stosd
285 ; Initialize length field of the various packets
286 mov byte [spec_packet],13h
287 mov byte [drive_params],30
288 mov byte [dapa],16
289 mov byte [dspec_packet],13h
291 ; Other nonzero fields
292 inc word [dsp_sectors]
294 ; Now figure out what we're actually doing
295 ; Note: use passed-in DL value rather than 7Fh because
296 ; at least some BIOSes will get the wrong value otherwise
297 mov ax,4B01h ; Get disk emulation status
298 mov dl,[DriveNo]
299 mov si,spec_packet
300 int 13h
301 jc award_hack ; changed for BrokenAwardHack
302 mov dl,[DriveNo]
303 cmp [sp_drive],dl ; Should contain the drive number
304 jne spec_query_failed
306 %ifdef DEBUG_MESSAGES
307 mov si,spec_ok_msg
308 call writemsg
309 mov al,byte [sp_drive]
310 call writehex2
311 call crlf
312 %endif
314 found_drive:
315 ; Alright, we have found the drive. Now, try to find the
316 ; boot file itself. If we have a boot info table, life is
317 ; good; if not, we have to make some assumptions, and try
318 ; to figure things out ourselves. In particular, the
319 ; assumptions we have to make are:
320 ; - single session only
321 ; - only one boot entry (no menu or other alternatives)
323 cmp dword [bi_file],0 ; Address of code to load
324 jne found_file ; Boot info table present :)
326 %ifdef DEBUG_MESSAGES
327 mov si,noinfotable_msg
328 call writemsg
329 %endif
331 ; No such luck. See if the the spec packet contained one.
332 mov eax,[sp_lba]
333 and eax,eax
334 jz set_file ; Good enough
336 %ifdef DEBUG_MESSAGES
337 mov si,noinfoinspec_msg
338 call writemsg
339 %endif
341 ; No such luck. Get the Boot Record Volume, assuming single
342 ; session disk, and that we're the first entry in the chain
343 mov eax,17 ; Assumed address of BRV
344 mov bx,trackbuf
345 call getonesec
347 mov eax,[trackbuf+47h] ; Get boot catalog address
348 mov bx,trackbuf
349 call getonesec ; Get boot catalog
351 mov eax,[trackbuf+28h] ; First boot entry
352 ; And hope and pray this is us...
354 ; Some BIOSes apparently have limitations on the size
355 ; that may be loaded (despite the El Torito spec being very
356 ; clear on the fact that it must all be loaded.) Therefore,
357 ; we load it ourselves, and *bleep* the BIOS.
359 set_file:
360 mov [bi_file],eax
362 found_file:
363 ; Set up boot file sizes
364 mov eax,[bi_length]
365 sub eax,SECTOR_SIZE-3
366 shr eax,2 ; bytes->dwords
367 mov [ImageDwords],eax ; boot file dwords
368 add eax,(2047 >> 2)
369 shr eax,9 ; dwords->sectors
370 mov [ImageSectors],ax ; boot file sectors
372 mov eax,[bi_file] ; Address of code to load
373 inc eax ; Don't reload bootstrap code
374 %ifdef DEBUG_MESSAGES
375 mov si,offset_msg
376 call writemsg
377 call writehex8
378 call crlf
379 %endif
381 ; Just in case some BIOSes have problems with
382 ; segment wraparound, use the normalized address
383 mov bx,((7C00h+2048) >> 4)
384 mov es,bx
385 xor bx,bx
386 mov bp,[ImageSectors]
387 %ifdef DEBUG_MESSAGES
388 push ax
389 mov si,size_msg
390 call writemsg
391 mov ax,bp
392 call writehex4
393 call crlf
394 pop ax
395 %endif
396 call getlinsec
398 push ds
399 pop es
401 %ifdef DEBUG_MESSAGES
402 mov si,loaded_msg
403 call writemsg
404 %endif
406 ; Verify the checksum on the loaded image.
407 verify_image:
408 mov si,7C00h+2048
409 mov bx,es
410 mov ecx,[ImageDwords]
411 mov edi,[FirstSecSum] ; First sector checksum
412 .loop es lodsd
413 add edi,eax
414 dec ecx
415 jz .done
416 and si,si
417 jnz .loop
418 ; SI wrapped around, advance ES
419 add bx,1000h
420 mov es,bx
421 jmp short .loop
422 .done: mov ax,ds
423 mov es,ax
424 cmp [bi_csum],edi
425 je integrity_ok
427 mov si,checkerr_msg
428 call writemsg
429 jmp kaboom
431 integrity_ok:
432 %ifdef DEBUG_MESSAGES
433 mov si,allread_msg
434 call writemsg
435 %endif
436 jmp all_read ; Jump to main code
438 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
439 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
440 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
442 ;; There is a problem with certain versions of the AWARD BIOS ...
443 ;; the boot sector will be loaded and executed correctly, but, because the
444 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
445 ;; load the spec packet will fail. We scan for the equivalent of
447 ;; mov ax,0201h
448 ;; mov bx,7c00h
449 ;; mov cx,0006h
450 ;; mov dx,0180h
451 ;; pushf
452 ;; call <direct far>
454 ;; and use <direct far> as the new vector for int 13. The code above is
455 ;; used to load the boot code into ram, and there should be no reason
456 ;; for anybody to change it now or in the future. There are no opcodes
457 ;; that use encodings relativ to IP, so scanning is easy. If we find the
458 ;; code above in the BIOS code we can be pretty sure to run on a machine
459 ;; with an broken AWARD BIOS ...
461 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
463 %ifdef DEBUG_MESSAGES ;;
465 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
466 award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
467 award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
468 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
469 award_not_fail db "BAH: FAILURE" ;;
470 award_not_crlf db CR,LF,0 ;;
472 %endif ;;
474 award_oldint13 dd 0 ;;
475 award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
477 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
478 award_hack: mov si,spec_err_msg ; Moved to this place from
479 call writemsg ; spec_query_faild
481 %ifdef DEBUG_MESSAGES ;
483 mov si,award_notice ; display our plan
484 call writemsg ;
485 mov si,award_not_orig ; display original int 13
486 call writemsg ; vector
487 %endif ;
488 mov eax,[13h*4] ;
489 mov [award_oldint13],eax ;
491 %ifdef DEBUG_MESSAGES ;
493 call writehex8 ;
494 mov si,award_not_crlf ;
495 call writestr ;
496 %endif ;
497 push es ; save ES
498 mov ax,0f000h ; ES = BIOS Seg
499 mov es,ax ;
500 cld ;
501 xor di,di ; start at ES:DI = f000:0
502 award_loop: push di ; save DI
503 mov si,award_string ; scan for award_string
504 mov cx,7 ; length of award_string = 7dw
505 repz cmpsw ; compare
506 pop di ; restore DI
507 jcxz award_found ; jmp if found
508 inc di ; not found, inc di
509 jno award_loop ;
511 award_failed: pop es ; No, not this way :-((
512 award_fail2: ;
514 %ifdef DEBUG_MESSAGES ;
516 mov si,award_not_fail ; display failure ...
517 call writemsg ;
518 %endif ;
519 mov eax,[award_oldint13] ; restore the original int
520 or eax,eax ; 13 vector if there is one
521 jz spec_query_failed ; and try other workarounds
522 mov [13h*4],eax ;
523 jmp spec_query_failed ;
525 award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
526 pop es ; restore ES
528 cmp eax,[award_oldint13] ; give up if this is the
529 jz award_failed ; active int 13 vector,
530 mov [13h*4],eax ; otherwise change 0:13h*4
533 %ifdef DEBUG_MESSAGES ;
535 push eax ; display message and
536 mov si,award_not_new ; new vector address
537 call writemsg ;
538 pop eax ;
539 call writehex8 ;
540 mov si,award_not_crlf ;
541 call writestr ;
542 %endif ;
543 mov ax,4B01h ; try to read the spec packet
544 mov dl,[DriveNo] ; now ... it should not fail
545 mov si,spec_packet ; any longer
546 int 13h ;
547 jc award_fail2 ;
549 %ifdef DEBUG_MESSAGES ;
551 mov si,award_not_succ ; display our SUCCESS
552 call writemsg ;
553 %endif ;
554 jmp found_drive ; and leave error recovery code
556 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
557 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
558 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
561 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
562 ; Try to scan the entire 80h-FFh from the end.
564 spec_query_failed:
566 ; some code moved to BrokenAwardHack
568 mov dl,0FFh
569 .test_loop: pusha
570 mov ax,4B01h
571 mov si,spec_packet
572 mov byte [si],13 ; Size of buffer
573 int 13h
574 popa
575 jc .still_broken
577 mov si,maybe_msg
578 call writemsg
579 mov al,dl
580 call writehex2
581 call crlf
583 cmp byte [sp_drive],dl
584 jne .maybe_broken
586 ; Okay, good enough...
587 mov si,alright_msg
588 call writemsg
589 mov [DriveNo],dl
590 .found_drive: jmp found_drive
592 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
593 ; but if this was the drive number originally passed in
594 ; DL then consider it "good enough"
595 .maybe_broken:
596 cmp byte [DriveNo],dl
597 je .found_drive
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,[DriveNo]
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 ; Get one sector. Convenience entry point.
662 getonesec:
663 mov bp,1
664 ; Fall through to getlinsec
667 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
669 ; Note that we can't always do this as a single request, because at least
670 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
671 ; to 32 sectors (64K) per request.
673 ; Input:
674 ; EAX - Linear sector number
675 ; ES:BX - Target buffer
676 ; BP - Sector count
678 getlinsec:
679 mov si,dapa ; Load up the DAPA
680 mov [si+4],bx
681 mov bx,es
682 mov [si+6],bx
683 mov [si+8],eax
684 .loop:
685 push bp ; Sectors left
686 cmp bp,[MaxTransfer]
687 jbe .bp_ok
688 mov bp,[MaxTransfer]
689 .bp_ok:
690 mov [si+2],bp
691 push si
692 mov dl,[DriveNo]
693 mov ah,42h ; Extended Read
694 call xint13
695 pop si
696 pop bp
697 movzx eax,word [si+2] ; Sectors we read
698 add [si+8],eax ; Advance sector pointer
699 sub bp,ax ; Sectors left
700 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
701 add [si+6],ax ; Advance buffer pointer
702 and bp,bp
703 jnz .loop
704 mov eax,[si+8] ; Next sector
707 ; INT 13h with retry
708 xint13: mov byte [RetryCount],retry_count
709 .try: pushad
710 int 13h
711 jc .error
712 add sp,byte 8*4 ; Clean up stack
714 .error:
715 mov [DiskError],ah ; Save error code
716 popad
717 mov [DiskSys],ax ; Save system call number
718 dec byte [RetryCount]
719 jz .real_error
720 push ax
721 mov al,[RetryCount]
722 mov ah,[dapa+2] ; Sector transfer count
723 cmp al,2 ; Only 2 attempts left
724 ja .nodanger
725 mov ah,1 ; Drop transfer size to 1
726 jmp short .setsize
727 .nodanger:
728 cmp al,retry_count-2
729 ja .again ; First time, just try again
730 shr ah,1 ; Otherwise, try to reduce
731 adc ah,0 ; the max transfer size, but not to 0
732 .setsize:
733 mov [MaxTransfer],ah
734 mov [dapa+2],ah
735 .again:
736 pop ax
737 jmp .try
739 .real_error: mov si,diskerr_msg
740 call writemsg
741 mov al,[DiskError]
742 call writehex2
743 mov si,oncall_str
744 call writestr
745 mov ax,[DiskSys]
746 call writehex4
747 mov si,ondrive_str
748 call writestr
749 mov al,dl
750 call writehex2
751 call crlf
752 ; Fall through to kaboom
755 ; kaboom: write a message and bail out. Wait for a user keypress,
756 ; then do a hard reboot.
758 kaboom:
759 RESET_STACK_AND_SEGS AX
760 mov si,err_bootfailed
761 call cwritestr
762 call getchar
764 mov word [BIOS_magic],0 ; Cold reboot
765 jmp 0F000h:0FFF0h ; Reset vector address
767 ; -----------------------------------------------------------------------------
768 ; Common modules needed in the first sector
769 ; -----------------------------------------------------------------------------
771 %include "writestr.inc" ; String output
772 writestr equ cwritestr
773 %include "writehex.inc" ; Hexadecimal output
775 ; -----------------------------------------------------------------------------
776 ; Data that needs to be in the first sector
777 ; -----------------------------------------------------------------------------
779 syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0
780 copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
781 db CR, LF, 0
782 isolinux_str db 'isolinux: ', 0
783 %ifdef DEBUG_MESSAGES
784 startup_msg: db 'Starting up, DL = ', 0
785 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
786 secsize_msg: db 'Sector size appears to be ', 0
787 offset_msg: db 'Loading main image from LBA = ', 0
788 size_msg: db 'Sectors to load = ', 0
789 loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
790 verify_msg: db 'Image checksum verified.', CR, LF, 0
791 allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
792 %endif
793 noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
794 noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
795 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
796 maybe_msg: db 'Found something at drive = ', 0
797 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
798 nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
799 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
800 trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
801 diskerr_msg: db 'Disk error ', 0
802 oncall_str: db ', AX = ',0
803 ondrive_str: db ', drive ', 0
804 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
806 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
807 bailmsg equ err_bootfailed
808 crlf_msg db CR, LF
809 null_msg db 0
811 alignb 4, db 0
812 StackPtr dw StackBuf, 0 ; SS:SP for stack reset
813 MaxTransfer dw 32 ; Max sectors per transfer
815 rl_checkpt equ $ ; Must be <= 800h
817 rl_checkpt_off equ ($-$$)
818 ;%ifndef DEPEND
819 ;%if rl_checkpt_off > 0x800
820 ;%error "Sector 0 overflow"
821 ;%endif
822 ;%endif
824 ; ----------------------------------------------------------------------------
825 ; End of code and data that have to be in the first sector
826 ; ----------------------------------------------------------------------------
828 all_read:
830 ; Test tracers
831 TRACER 'T'
832 TRACER '>'
835 ; Common initialization code
837 %include "init.inc"
838 %include "cpuinit.inc"
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
850 ; Now we're all set to start with our *real* business. First load the
851 ; configuration file (if any) and parse it.
853 ; In previous versions I avoided using 32-bit registers because of a
854 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
855 ; random. I figure, though, that if there are any of those still left
856 ; they probably won't be trying to install Linux on them...
858 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
859 ; to take'm out. In fact, we may want to put them back if we're going
860 ; to boot ELKS at some point.
864 ; Now, we need to sniff out the actual filesystem data structures.
865 ; mkisofs gave us a pointer to the primary volume descriptor
866 ; (which will be at 16 only for a single-session disk!); from the PVD
867 ; we should be able to find the rest of what we need to know.
869 get_fs_structures:
870 mov eax,[bi_pvd]
871 mov bx,trackbuf
872 call getonesec
874 mov eax,[trackbuf+156+2]
875 mov [RootDir+dir_lba],eax
876 mov [CurDir+dir_lba],eax
877 %ifdef DEBUG_MESSAGES
878 mov si,dbg_rootdir_msg
879 call writemsg
880 call writehex8
881 call crlf
882 %endif
883 mov eax,[trackbuf+156+10]
884 mov [RootDir+dir_len],eax
885 mov [CurDir+dir_len],eax
886 add eax,SECTOR_SIZE-1
887 shr eax,SECTOR_SHIFT
888 mov [RootDir+dir_clust],eax
889 mov [CurDir+dir_clust],eax
891 ; Look for an isolinux directory, and if found,
892 ; make it the current directory instead of the root
893 ; directory.
894 mov di,boot_dir ; Search for /boot/isolinux
895 mov al,02h
896 call searchdir_iso
897 jnz .found_dir
898 mov di,isolinux_dir
899 mov al,02h ; Search for /isolinux
900 call searchdir_iso
901 jz .no_isolinux_dir
902 .found_dir:
903 mov [CurDir+dir_len],eax
904 mov eax,[si+file_left]
905 mov [CurDir+dir_clust],eax
906 xor eax,eax ; Free this file pointer entry
907 xchg eax,[si+file_sector]
908 mov [CurDir+dir_lba],eax
909 %ifdef DEBUG_MESSAGES
910 push si
911 mov si,dbg_isodir_msg
912 call writemsg
913 pop si
914 call writehex8
915 call crlf
916 %endif
917 .no_isolinux_dir:
920 ; Locate the configuration file
922 load_config:
923 %ifdef DEBUG_MESSAGES
924 mov si,dbg_config_msg
925 call writemsg
926 %endif
928 mov si,config_name
929 mov di,ConfigName
930 call strcpy
932 mov di,ConfigName
933 call open
934 jz no_config_file ; Not found or empty
936 %ifdef DEBUG_MESSAGES
937 mov si,dbg_configok_msg
938 call writemsg
939 %endif
942 ; Now we have the config file open. Parse the config file and
943 ; run the user interface.
945 %include "ui.inc"
948 ; Linux kernel loading code is common.
950 %include "runkernel.inc"
953 ; COMBOOT-loading code
955 %include "comboot.inc"
956 %include "com32.inc"
957 %include "cmdline.inc"
960 ; Boot sector loading code
962 %include "bootsect.inc"
965 ; Enable disk emulation. The kind of disk we emulate is dependent on the size of
966 ; the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
968 is_disk_image:
969 TRACER CR
970 TRACER LF
971 TRACER 'D'
972 TRACER ':'
974 shl edx,16
975 mov dx,ax ; Set EDX <- file size
976 mov di,img_table
977 mov cx,img_table_count
978 mov eax,[si+file_sector] ; Starting LBA of file
979 mov [dsp_lba],eax ; Location of file
980 mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk
981 .search_table:
982 TRACER 't'
983 mov eax,[di+4]
984 cmp edx,[di]
985 je .type_found
986 add di,8
987 loop .search_table
989 ; Hard disk image. Need to examine the partition table
990 ; in order to deduce the C/H/S geometry. Sigh.
991 .hard_disk_image:
992 TRACER 'h'
993 cmp edx,512
994 jb .bad_image
996 mov bx,trackbuf
997 mov cx,1 ; Load 1 sector
998 call getfssec
1000 cmp word [trackbuf+510],0aa55h ; Boot signature
1001 jne .bad_image ; Image not bootable
1003 mov cx,4 ; 4 partition entries
1004 mov di,trackbuf+446 ; Start of partition table
1006 xor ax,ax ; Highest sector(al) head(ah)
1008 .part_scan:
1009 cmp byte [di+4], 0
1010 jz .part_loop
1011 lea si,[di+1]
1012 call .hs_check
1013 add si,byte 4
1014 call .hs_check
1015 .part_loop:
1016 add di,byte 16
1017 loop .part_scan
1019 push eax ; H/S
1020 push edx ; File size
1021 mov bl,ah
1022 xor bh,bh
1023 inc bx ; # of heads in BX
1024 xor ah,ah ; # of sectors in AX
1025 cwde ; EAX[31:16] <- 0
1026 mul bx
1027 shl eax,9 ; Convert to bytes
1028 ; Now eax contains the number of bytes per cylinder
1029 pop ebx ; File size
1030 xor edx,edx
1031 div ebx
1032 and edx,edx
1033 jz .no_remainder
1034 inc eax ; Fractional cylinder...
1035 ; Now (e)ax contains the number of cylinders
1036 .no_remainder: cmp eax,1024
1037 jna .ok_cyl
1038 mov ax,1024 ; Max possible #
1039 .ok_cyl: dec ax ; Convert to max cylinder no
1040 pop ebx ; S(bl) H(bh)
1041 shl ah,6
1042 or bl,ah
1043 xchg ax,bx
1044 shl eax,16
1045 mov ah,bl
1046 mov al,4 ; Hard disk boot
1047 mov byte [dsp_drive], 80h ; Drive 80h = hard disk
1049 .type_found:
1050 TRACER 'T'
1051 mov bl,[sp_media]
1052 and bl,0F0h ; Copy controller info bits
1053 or al,bl
1054 mov [dsp_media],al ; Emulation type
1055 shr eax,8
1056 mov [dsp_chs],eax ; C/H/S geometry
1057 mov ax,[sp_devspec] ; Copy device spec
1058 mov [dsp_devspec],ax
1059 mov al,[sp_controller] ; Copy controller index
1060 mov [dsp_controller],al
1062 TRACER 'V'
1063 call vgaclearmode ; Reset video
1065 mov ax,4C00h ; Enable emulation and boot
1066 mov si,dspec_packet
1067 mov dl,[DriveNo]
1068 lss sp,[InitStack]
1069 TRACER 'X'
1071 int 13h
1073 ; If this returns, we have problems
1074 .bad_image:
1075 mov si,err_disk_image
1076 call cwritestr
1077 jmp enter_command
1080 ; Look for the highest seen H/S geometry
1081 ; We compute cylinders separately
1083 .hs_check:
1084 mov bl,[si] ; Head #
1085 cmp bl,ah
1086 jna .done_track
1087 mov ah,bl ; New highest head #
1088 .done_track: mov bl,[si+1]
1089 and bl,3Fh ; Sector #
1090 cmp bl,al
1091 jna .done_sector
1092 mov al,bl
1093 .done_sector: ret
1096 ; Boot a specified local disk. AX specifies the BIOS disk number; or
1097 ; 0xFFFF in case we should execute INT 18h ("next device.")
1099 local_boot:
1100 call vgaclearmode
1101 lss sp,[cs:Stack] ; Restore stack pointer
1102 xor dx,dx
1103 mov ds,dx
1104 mov es,dx
1105 mov fs,dx
1106 mov gs,dx
1107 mov si,localboot_msg
1108 call writestr
1109 cmp ax,-1
1110 je .int18
1112 ; Load boot sector from the specified BIOS device and jump to it.
1113 mov dl,al
1114 xor dh,dh
1115 push dx
1116 xor ax,ax ; Reset drive
1117 call xint13
1118 mov ax,0201h ; Read one sector
1119 mov cx,0001h ; C/H/S = 0/0/1 (first sector)
1120 mov bx,trackbuf
1121 call xint13
1122 pop dx
1123 cli ; Abandon hope, ye who enter here
1124 mov si,trackbuf
1125 mov di,07C00h
1126 mov cx,512 ; Probably overkill, but should be safe
1127 rep movsd
1128 lss sp,[cs:InitStack]
1129 jmp 0:07C00h ; Jump to new boot sector
1131 .int18:
1132 int 18h ; Hope this does the right thing...
1133 jmp kaboom ; If we returned, oh boy...
1136 ; Abort loading code
1138 %include "abort.inc"
1141 ; searchdir:
1143 ; Open a file
1145 ; On entry:
1146 ; DS:DI = filename
1147 ; If successful:
1148 ; ZF clear
1149 ; SI = file pointer
1150 ; DX:AX or EAX = file length in bytes
1151 ; If unsuccessful
1152 ; ZF set
1154 ; Assumes CS == DS == ES, and trashes BX and CX.
1156 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
1157 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
1158 ; for searching for directories.
1160 alloc_failure:
1161 xor ax,ax ; ZF <- 1
1164 searchdir:
1165 xor al,al
1166 searchdir_iso:
1167 mov [ISOFlags],al
1168 TRACER 'S'
1169 call allocate_file ; Temporary file structure for directory
1170 jnz alloc_failure
1171 push es
1172 push ds
1173 pop es ; ES = DS
1174 mov si,CurDir
1175 cmp byte [di],'/' ; If filename begins with slash
1176 jne .not_rooted
1177 inc di ; Skip leading slash
1178 mov si,RootDir ; Reference root directory instead
1179 .not_rooted:
1180 mov eax,[si+dir_clust]
1181 mov [bx+file_left],eax
1182 mov eax,[si+dir_lba]
1183 mov [bx+file_sector],eax
1184 mov edx,[si+dir_len]
1186 .look_for_slash:
1187 mov ax,di
1188 .scan:
1189 mov cl,[di]
1190 inc di
1191 and cl,cl
1192 jz .isfile
1193 cmp cl,'/'
1194 jne .scan
1195 mov [di-1],byte 0 ; Terminate at directory name
1196 mov cl,02h ; Search for directory
1197 xchg cl,[ISOFlags]
1199 push di ; Save these...
1200 push cx
1202 ; Create recursion stack frame...
1203 push word .resume ; Where to "return" to
1204 push es
1205 .isfile: xchg ax,di
1207 .getsome:
1208 ; Get a chunk of the directory
1209 ; This relies on the fact that ISOLINUX doesn't change SI
1210 mov si,trackbuf
1211 TRACER 'g'
1212 pushad
1213 xchg bx,si
1214 mov cx,[BufSafe]
1215 call getfssec
1216 popad
1218 .compare:
1219 movzx eax,byte [si] ; Length of directory entry
1220 cmp al,33
1221 jb .next_sector
1222 TRACER 'c'
1223 mov cl,[si+25]
1224 xor cl,[ISOFlags]
1225 test cl, byte 8Eh ; Unwanted file attributes!
1226 jnz .not_file
1227 pusha
1228 movzx cx,byte [si+32] ; File identifier length
1229 add si,byte 33 ; File identifier offset
1230 TRACER 'i'
1231 call iso_compare_names
1232 popa
1233 je .success
1234 .not_file:
1235 sub edx,eax ; Decrease bytes left
1236 jbe .failure
1237 add si,ax ; Advance pointer
1239 .check_overrun:
1240 ; Did we finish the buffer?
1241 cmp si,trackbuf+trackbufsize
1242 jb .compare ; No, keep going
1244 jmp short .getsome ; Get some more directory
1246 .next_sector:
1247 ; Advance to the beginning of next sector
1248 lea ax,[si+SECTOR_SIZE-1]
1249 and ax,~(SECTOR_SIZE-1)
1250 sub ax,si
1251 jmp short .not_file ; We still need to do length checks
1253 .failure: xor eax,eax ; ZF = 1
1254 mov [bx+file_sector],eax
1255 pop es
1258 .success:
1259 mov eax,[si+2] ; Location of extent
1260 mov [bx+file_sector],eax
1261 mov eax,[si+10] ; Data length
1262 push eax
1263 add eax,SECTOR_SIZE-1
1264 shr eax,SECTOR_SHIFT
1265 mov [bx+file_left],eax
1266 pop eax
1267 mov edx,eax
1268 shr edx,16
1269 and bx,bx ; ZF = 0
1270 mov si,bx
1271 pop es
1274 .resume: ; We get here if we were only doing part of a lookup
1275 ; This relies on the fact that .success returns bx == si
1276 xchg edx,eax ; Directory length in edx
1277 pop cx ; Old ISOFlags
1278 pop di ; Next filename pointer
1279 mov byte [di-1], '/' ; Restore slash
1280 mov [ISOFlags],cl ; Restore the flags
1281 jz .failure ; Did we fail? If so fail for real!
1282 jmp .look_for_slash ; Otherwise, next level
1285 ; allocate_file: Allocate a file structure
1287 ; If successful:
1288 ; ZF set
1289 ; BX = file pointer
1290 ; In unsuccessful:
1291 ; ZF clear
1293 allocate_file:
1294 TRACER 'a'
1295 push cx
1296 mov bx,Files
1297 mov cx,MAX_OPEN
1298 .check: cmp dword [bx], byte 0
1299 je .found
1300 add bx,open_file_t_size ; ZF = 0
1301 loop .check
1302 ; ZF = 0 if we fell out of the loop
1303 .found: pop cx
1307 ; iso_compare_names:
1308 ; Compare the names DS:SI and DS:DI and report if they are
1309 ; equal from an ISO 9660 perspective. SI is the name from
1310 ; the filesystem; CX indicates its length, and ';' terminates.
1311 ; DI is expected to end with a null.
1313 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
1316 iso_compare_names:
1317 ; First, terminate and canonicalize input filename
1318 push di
1319 mov di,ISOFileName
1320 .canon_loop: jcxz .canon_end
1321 lodsb
1322 dec cx
1323 cmp al,';'
1324 je .canon_end
1325 and al,al
1326 je .canon_end
1327 stosb
1328 cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
1329 jb .canon_loop
1330 .canon_end:
1331 cmp di,ISOFileName
1332 jbe .canon_done
1333 cmp byte [di-1],'.' ; Remove terminal dots
1334 jne .canon_done
1335 dec di
1336 jmp short .canon_end
1337 .canon_done:
1338 mov [di],byte 0 ; Null-terminate string
1339 pop di
1340 mov si,ISOFileName
1341 .compare:
1342 lodsb
1343 mov ah,[di]
1344 inc di
1345 and ax,ax
1346 jz .success ; End of string for both
1347 and al,al ; Is either one end of string?
1348 jz .failure ; If so, failure
1349 and ah,ah
1350 jz .failure
1351 or ax,2020h ; Convert to lower case
1352 cmp al,ah
1353 je .compare
1354 .failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
1355 .success: ret
1358 ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
1359 ; to by ES:DI; ends on encountering any whitespace.
1360 ; DI is preserved.
1362 ; This verifies that a filename is < FILENAME_MAX characters,
1363 ; doesn't contain whitespace, zero-pads the output buffer,
1364 ; and removes trailing dots and redundant slashes,
1365 ; so "repe cmpsb" can do a compare, and the
1366 ; path-searching routine gets a bit of an easier job.
1368 mangle_name:
1369 push di
1370 push bx
1371 xor ax,ax
1372 mov cx,FILENAME_MAX-1
1373 mov bx,di
1375 .mn_loop:
1376 lodsb
1377 cmp al,' ' ; If control or space, end
1378 jna .mn_end
1379 cmp al,ah ; Repeated slash?
1380 je .mn_skip
1381 xor ah,ah
1382 cmp al,'/'
1383 jne .mn_ok
1384 mov ah,al
1385 .mn_ok stosb
1386 .mn_skip: loop .mn_loop
1387 .mn_end:
1388 cmp bx,di ; At the beginning of the buffer?
1389 jbe .mn_zero
1390 cmp byte [es:di-1],'.' ; Terminal dot?
1391 je .mn_kill
1392 cmp byte [es:di-1],'/' ; Terminal slash?
1393 jne .mn_zero
1394 .mn_kill: dec di ; If so, remove it
1395 inc cx
1396 jmp short .mn_end
1397 .mn_zero:
1398 inc cx ; At least one null byte
1399 xor ax,ax ; Zero-fill name
1400 rep stosb
1401 pop bx
1402 pop di
1403 ret ; Done
1406 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1407 ; filename to the conventional representation. This is needed
1408 ; for the BOOT_IMAGE= parameter for the kernel.
1409 ; NOTE: A 13-byte buffer is mandatory, even if the string is
1410 ; known to be shorter.
1412 ; DS:SI -> input mangled file name
1413 ; ES:DI -> output buffer
1415 ; On return, DI points to the first byte after the output name,
1416 ; which is set to a null byte.
1418 unmangle_name: call strcpy
1419 dec di ; Point to final null byte
1423 ; getfssec: Get multiple clusters from a file, given the file pointer.
1425 ; On entry:
1426 ; ES:BX -> Buffer
1427 ; SI -> File pointer
1428 ; CX -> Cluster count
1429 ; On exit:
1430 ; SI -> File pointer (or 0 on EOF)
1431 ; CF = 1 -> Hit EOF
1433 getfssec:
1434 TRACER 'F'
1436 push ds
1437 push cs
1438 pop ds ; DS <- CS
1440 movzx ecx,cx
1441 cmp ecx,[si+file_left]
1442 jna .ok_size
1443 mov ecx,[si+file_left]
1444 .ok_size:
1446 mov bp,cx
1447 push cx
1448 push si
1449 mov eax,[si+file_sector]
1450 TRACER 'l'
1451 call getlinsec
1452 xor ecx,ecx
1453 pop si
1454 pop cx
1456 add [si+file_sector],ecx
1457 sub [si+file_left],ecx
1458 ja .not_eof ; CF = 0
1460 xor ecx,ecx
1461 mov [si+file_sector],ecx ; Mark as unused
1462 xor si,si
1465 .not_eof:
1466 pop ds
1467 TRACER 'f'
1470 ; -----------------------------------------------------------------------------
1471 ; Common modules
1472 ; -----------------------------------------------------------------------------
1474 %include "getc.inc" ; getc et al
1475 %include "conio.inc" ; Console I/O
1476 %include "configinit.inc" ; Initialize configuration
1477 %include "parseconfig.inc" ; High-level config file handling
1478 %include "parsecmd.inc" ; Low-level config file handling
1479 %include "bcopy32.inc" ; 32-bit bcopy
1480 %include "loadhigh.inc" ; Load a file into high memory
1481 %include "font.inc" ; VGA font stuff
1482 %include "graphics.inc" ; VGA graphics
1483 %include "highmem.inc" ; High memory sizing
1484 %include "strcpy.inc" ; strcpy()
1485 %include "rawcon.inc" ; Console I/O w/o using the console functions
1487 ; -----------------------------------------------------------------------------
1488 ; Begin data section
1489 ; -----------------------------------------------------------------------------
1491 section .data
1493 boot_prompt db 'boot: ', 0
1494 wipe_char db BS, ' ', BS, 0
1495 err_notfound db 'Could not find kernel image: ',0
1496 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
1497 err_noram db 'It appears your computer has less than '
1498 asciidec dosram_k
1499 db 'K of low ("DOS")'
1500 db CR, LF
1501 db 'RAM. Linux needs at least this amount to boot. If you get'
1502 db CR, LF
1503 db 'this message in error, hold down the Ctrl key while'
1504 db CR, LF
1505 db 'booting, and I will take your word for it.', CR, LF, 0
1506 err_badcfg db 'Unknown keyword in config file.', CR, LF, 0
1507 err_noparm db 'Missing parameter in config file.', CR, LF, 0
1508 err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
1509 err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0
1510 err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0
1511 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
1512 db CR, LF, 0
1513 err_notdos db ': attempted DOS system call', CR, LF, 0
1514 err_comlarge db 'COMBOOT image too large.', CR, LF, 0
1515 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
1516 notfound_msg db 'not found', CR, LF, 0
1517 localboot_msg db 'Booting from local disk...', CR, LF, 0
1518 cmdline_msg db 'Command line: ', CR, LF, 0
1519 ready_msg db 'Ready.', CR, LF, 0
1520 trying_msg db 'Trying to load: ', 0
1521 crlfloading_msg db CR, LF ; Fall through
1522 loading_msg db 'Loading ', 0
1523 dotdot_msg db '.'
1524 dot_msg db '.', 0
1525 fourbs_msg db BS, BS, BS, BS, 0
1526 aborted_msg db ' aborted.', CR, LF, 0
1527 crff_msg db CR, FF, 0
1528 default_str db 'default', 0
1529 default_len equ ($-default_str)
1530 boot_dir db '/boot' ; /boot/isolinux
1531 isolinux_dir db '/isolinux', 0
1532 config_name db 'isolinux.cfg', 0
1533 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
1535 %ifdef DEBUG_MESSAGES
1536 dbg_rootdir_msg db 'Root directory at LBA = ', 0
1537 dbg_isodir_msg db 'isolinux directory at LBA = ', 0
1538 dbg_config_msg db 'About to load config file...', CR, LF, 0
1539 dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
1540 %endif
1542 ; Command line options we'd like to take a look at
1544 ; mem= and vga= are handled as normal 32-bit integer values
1545 initrd_cmd db 'initrd='
1546 initrd_cmd_len equ 7
1549 ; Config file keyword table
1551 %include "keywords.inc"
1554 ; Extensions to search for (in *forward* order).
1556 align 4, db 0
1557 exten_table: db '.cbt' ; COMBOOT (specific)
1558 db '.img' ; Disk image
1559 db '.bin' ; CD boot sector
1560 db '.com' ; COMBOOT (same as DOS)
1561 db '.c32' ; COM32
1562 exten_table_end:
1563 dd 0, 0 ; Need 8 null bytes here
1566 ; Floppy image table
1568 align 4, db 0
1569 img_table_count equ 3
1570 img_table:
1571 dd 1200*1024 ; 1200K floppy
1572 db 1 ; Emulation type
1573 db 80-1 ; Max cylinder
1574 db 15 ; Max sector
1575 db 2-1 ; Max head
1577 dd 1440*1024 ; 1440K floppy
1578 db 2 ; Emulation type
1579 db 80-1 ; Max cylinder
1580 db 18 ; Max sector
1581 db 2-1 ; Max head
1583 dd 2880*1024 ; 2880K floppy
1584 db 3 ; Emulation type
1585 db 80-1 ; Max cylinder
1586 db 36 ; Max sector
1587 db 2-1 ; Max head
1590 ; Misc initialized (data) variables
1594 ; Variables that are uninitialized in SYSLINUX but initialized here
1596 ; **** ISOLINUX:: We may have to make this flexible, based on what the
1597 ; **** BIOS expects our "sector size" to be.
1599 alignb 4, db 0
1600 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
1601 BufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?
1602 BufSafeBytes dw trackbufsize ; = how many bytes?
1603 EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
1604 %ifndef DEPEND
1605 %if ( trackbufsize % SECTOR_SIZE ) != 0
1606 %error trackbufsize must be a multiple of SECTOR_SIZE
1607 %endif
1608 %endif