1 ; -*- fundamental -*- (asm-mode sucks)
2 ; ****************************************************************************
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
11 ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
12 ; Copyright 2009 Intel Corporation; author: H. Peter Anvin
14 ; This program is free software; you can redistribute it and/or modify
15 ; it under the terms of the GNU General Public License as published by
16 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
17 ; Boston MA 02111-1307, USA; either version 2 of the License, or
18 ; (at your option) any later version; incorporated herein by reference.
20 ; ****************************************************************************
26 ; Some semi-configurable constants... change on your own risk.
29 NULLFILE equ 0 ; Zero byte == null file name
30 NULLOFFSET equ 0 ; Position in which to look
31 retry_count equ 6 ; How patient are we with the BIOS?
32 %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
33 SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement)
34 SECTOR_SIZE equ (1 << SECTOR_SHIFT)
36 ROOT_DIR_WORD equ 0x002F
39 ; The following structure is used for "virtual kernels"; i.e. LILO-style
40 ; option labels. The options we permit here are `kernel' and `append
41 ; Since there is no room in the bottom 64K for all of these, we
42 ; stick them in high memory and copy them down before we need them.
45 vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
46 vk_rname: resb FILENAME_MAX ; Real name
48 vk_type: resb 1 ; Type of file
50 vk_append: resb max_cmd_len+1 ; Command line
52 vk_end: equ $ ; Should be <= vk_size
55 ; ---------------------------------------------------------------------------
57 ; ---------------------------------------------------------------------------
60 ; Memory below this point is reserved for the BIOS and the MBR
65 trackbuf resb trackbufsize ; Track buffer goes here
68 ; Some of these are touched before the whole image
69 ; is loaded. DO NOT move this to .bss16/.uibss.
72 FirstSecSum resd 1 ; Checksum of bytes 64-2048
73 ImageDwords resd 1 ; isolinux.bin size, dwords
74 InitStack resd 1 ; Initial stack pointer (SS:SP)
75 DiskSys resw 1 ; Last INT 13h call
76 ImageSectors resw 1 ; isolinux.bin size, sectors
77 ; These following two are accessed as a single dword...
78 GetlinsecPtr resw 1 ; The sector-read pointer
79 BIOSName resw 1 ; Display string for BIOS type
80 %define HAVE_BIOSNAME 1
82 DiskError resb 1 ; Error code for disk I/O
83 DriveNumber resb 1 ; CD-ROM BIOS drive number
84 ISOFlags resb 1 ; Flags for ISO directory search
85 RetryCount resb 1 ; Used for disk access retries
88 Hidden resq 1 ; Used in hybrid mode
89 bsSecPerTrack resw 1 ; Used in hybrid mode
90 bsHeads resw 1 ; Used in hybrid mode
94 ; El Torito spec packet
99 spec_packet: resb 1 ; Size of packet
100 sp_media: resb 1 ; Media type
101 sp_drive: resb 1 ; Drive number
102 sp_controller: resb 1 ; Controller index
103 sp_lba: resd 1 ; LBA for emulated disk image
104 sp_devspec: resw 1 ; IDE/SCSI information
105 sp_buffer: resw 1 ; User-provided buffer
106 sp_loadseg: resw 1 ; Load segment
107 sp_sectors: resw 1 ; Sector count
108 sp_chs: resb 3 ; Simulated CHS geometry
109 sp_dummy: resb 1 ; Scratch, safe to overwrite
112 ; EBIOS drive parameter packet
115 drive_params: resw 1 ; Buffer size
116 dp_flags: resw 1 ; Information flags
117 dp_cyl: resd 1 ; Physical cylinders
118 dp_head: resd 1 ; Physical heads
119 dp_sec: resd 1 ; Physical sectors/track
120 dp_totalsec: resd 2 ; Total sectors
121 dp_secsize: resw 1 ; Bytes per sector
122 dp_dpte: resd 1 ; Device Parameter Table
123 dp_dpi_key: resw 1 ; 0BEDDh if rest valid
124 dp_dpi_len: resb 1 ; DPI len
127 dp_bus: resb 4 ; Host bus type
128 dp_interface: resb 8 ; Interface type
129 db_i_path: resd 2 ; Interface path
130 db_d_path: resd 2 ; Device path
132 db_dpi_csum: resb 1 ; Checksum for DPI info
135 ; EBIOS disk address packet
138 dapa: resw 1 ; Packet size
139 .count: resw 1 ; Block count
140 .off: resw 1 ; Offset of buffer
141 .seg: resw 1 ; Segment of buffer
142 .lba: resd 2 ; LBA (LSW, MSW)
145 ; Spec packet for disk image emulation
148 dspec_packet: resb 1 ; Size of packet
149 dsp_media: resb 1 ; Media type
150 dsp_drive: resb 1 ; Drive number
151 dsp_controller: resb 1 ; Controller index
152 dsp_lba: resd 1 ; LBA for emulated disk image
153 dsp_devspec: resw 1 ; IDE/SCSI information
154 dsp_buffer: resw 1 ; User-provided buffer
155 dsp_loadseg: resw 1 ; Load segment
156 dsp_sectors: resw 1 ; Sector count
157 dsp_chs: resb 3 ; Simulated CHS geometry
158 dsp_dummy: resb 1 ; Scratch, safe to overwrite
162 _spec_len equ _spec_end - _spec_start
166 ;; Primary entry point. Because BIOSes are buggy, we only load the first
167 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
170 StackBuf equ STACK_TOP-44 ; 44 bytes needed for
171 ; the bootsector chainloading
173 OrigESDI equ StackBuf-4 ; The high dword on the stack
174 StackHome equ OrigESDI
178 _start: ; Far jump makes sure we canonicalize the address
181 times 8-($-$$) nop ; Pad to file offset 8
183 ; This table hopefully gets filled in by mkisofs using the
184 ; -boot-info-table option. If not, the values in this
185 ; table are default values that we can use to get us what
186 ; we need, at least under a certain set of assumptions.
189 bi_pvd: dd 16 ; LBA of primary volume descriptor
190 bi_file: dd 0 ; LBA of boot file
191 bi_length: dd 0xdeadbeef ; Length of boot file
192 bi_csum: dd 0xdeadbeef ; Checksum of boot file
193 bi_reserved: times 10 dd 0xdeadbeef ; Reserved
196 ; Custom entry point for the hybrid-mode disk.
197 ; The following values will have been pushed onto the
199 ; - partition offset (qword)
202 ; - DX (including drive number)
208 ; If we had an old isohybrid, the partition offset will
209 ; be missing; we can check for that with sp >= 0x7c00.
210 ; Serious hack alert.
211 %ifndef DEBUG_MESSAGES
213 dd 0x7078c0fb ; An arbitrary number...
217 pop word [cs:bsSecPerTrack]
218 pop word [cs:bsHeads]
240 mov [cs:InitStack],sp ; Save initial stack pointer
241 mov [cs:InitStack+2],ss
244 mov sp,StackBuf ; Set up stack
245 push es ; Save initial ES:DI -> $PnP pointer
259 mov [GetlinsecPtr],eax
262 mov si,syslinux_banner
264 %ifdef DEBUG_MESSAGES
272 ; Before modifying any memory, get the checksum of bytes
275 initial_csum: xor edi,edi
277 mov cx,(SECTOR_SIZE-64) >> 2
281 mov [FirstSecSum],edi
284 %ifdef DEBUG_MESSAGES
292 ; Initialize spec packet buffers
295 mov cx,_spec_len >> 2
299 ; Initialize length field of the various packets
300 mov byte [spec_packet],13h
301 mov byte [drive_params],30
303 mov byte [dspec_packet],13h
305 ; Other nonzero fields
306 inc word [dsp_sectors]
308 ; Are we just pretending to be a CD-ROM?
309 cmp word [BIOSType],bios_cdrom
310 jne found_drive ; If so, no spec packet...
312 ; Now figure out what we're actually doing
313 ; Note: use passed-in DL value rather than 7Fh because
314 ; at least some BIOSes will get the wrong value otherwise
315 mov ax,4B01h ; Get disk emulation status
319 jc award_hack ; changed for BrokenAwardHack
321 cmp [sp_drive],dl ; Should contain the drive number
322 jne spec_query_failed
324 %ifdef DEBUG_MESSAGES
327 mov al,byte [sp_drive]
333 ; Alright, we have found the drive. Now, try to find the
334 ; boot file itself. If we have a boot info table, life is
335 ; good; if not, we have to make some assumptions, and try
336 ; to figure things out ourselves. In particular, the
337 ; assumptions we have to make are:
338 ; - single session only
339 ; - only one boot entry (no menu or other alternatives)
341 cmp dword [bi_file],0 ; Address of code to load
342 jne found_file ; Boot info table present :)
344 %ifdef DEBUG_MESSAGES
345 mov si,noinfotable_msg
349 ; No such luck. See if the spec packet contained one.
352 jz set_file ; Good enough
354 %ifdef DEBUG_MESSAGES
355 mov si,noinfoinspec_msg
359 ; No such luck. Get the Boot Record Volume, assuming single
360 ; session disk, and that we're the first entry in the chain.
361 mov eax,17 ; Assumed address of BRV
365 mov eax,[trackbuf+47h] ; Get boot catalog address
367 call getonesec ; Get boot catalog
369 mov eax,[trackbuf+28h] ; First boot entry
370 ; And hope and pray this is us...
372 ; Some BIOSes apparently have limitations on the size
373 ; that may be loaded (despite the El Torito spec being very
374 ; clear on the fact that it must all be loaded.) Therefore,
375 ; we load it ourselves, and *bleep* the BIOS.
381 ; Set up boot file sizes
383 sub eax,SECTOR_SIZE-3 ; ... minus sector loaded
384 shr eax,2 ; bytes->dwords
385 mov [ImageDwords],eax ; boot file dwords
386 add eax,((SECTOR_SIZE-1) >> 2)
387 shr eax,SECTOR_SHIFT-2 ; dwords->sectors
388 mov [ImageSectors],ax ; boot file sectors
390 mov eax,[bi_file] ; Address of code to load
391 inc eax ; Don't reload bootstrap code
392 %ifdef DEBUG_MESSAGES
399 ; Load the rest of the file. However, just in case there
400 ; are still BIOSes with 64K wraparound problems, we have to
401 ; take some extra precautions. Since the normal load
402 ; address (TEXT_START) is *not* 2K-sector-aligned, we round
403 ; the target address upward to a sector boundary,
404 ; and then move the entire thing down as a unit.
405 MaxLMA equ 384*1024 ; Reasonable limit (384K)
407 mov bx,((TEXT_START+2*SECTOR_SIZE-1) & ~(SECTOR_SIZE-1)) >> 4
408 mov bp,[ImageSectors]
409 push bx ; Load segment address
412 push bx ; Segment address
413 push bp ; Sector count
419 shr cx,SECTOR_SHIFT - 4
421 mov cx,0x10000 >> SECTOR_SHIFT ; Full 64K segment possible
435 shl cx,SECTOR_SHIFT - 4
440 ; Move the image into place, and also verify the
442 pop ax ; Load segment address
443 mov bx,(TEXT_START + SECTOR_SIZE) >> 4
444 mov ecx,[ImageDwords]
445 mov edi,[FirstSecSum] ; First sector checksum
468 ; Verify the checksum on the loaded image.
477 %ifdef DEBUG_MESSAGES
481 jmp all_read ; Jump to main code
483 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
484 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
485 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
487 ;; There is a problem with certain versions of the AWARD BIOS ...
488 ;; the boot sector will be loaded and executed correctly, but, because the
489 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
490 ;; load the spec packet will fail. We scan for the equivalent of
499 ;; and use <direct far> as the new vector for int 13. The code above is
500 ;; used to load the boot code into ram, and there should be no reason
501 ;; for anybody to change it now or in the future. There are no opcodes
502 ;; that use encodings relativ to IP, so scanning is easy. If we find the
503 ;; code above in the BIOS code we can be pretty sure to run on a machine
504 ;; with an broken AWARD BIOS ...
506 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
508 %ifdef DEBUG_MESSAGES ;;
510 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
511 award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
512 award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
513 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
514 award_not_fail db "BAH: FAILURE" ;;
515 award_not_crlf db CR,LF,0 ;;
519 award_oldint13 dd 0 ;;
520 award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
522 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
523 award_hack: mov si,spec_err_msg ; Moved to this place from
524 call writemsg ; spec_query_faild
526 %ifdef DEBUG_MESSAGES ;
528 mov si,award_notice ; display our plan
530 mov si,award_not_orig ; display original int 13
531 call writemsg ; vector
534 mov [award_oldint13],eax ;
536 %ifdef DEBUG_MESSAGES ;
539 mov si,award_not_crlf ;
540 call writestr_early ;
543 mov ax,0f000h ; ES = BIOS Seg
546 xor di,di ; start at ES:DI = f000:0
547 award_loop: push di ; save DI
548 mov si,award_string ; scan for award_string
549 mov cx,7 ; length of award_string = 7dw
552 jcxz award_found ; jmp if found
553 inc di ; not found, inc di
556 award_failed: pop es ; No, not this way :-((
559 %ifdef DEBUG_MESSAGES ;
561 mov si,award_not_fail ; display failure ...
564 mov eax,[award_oldint13] ; restore the original int
565 or eax,eax ; 13 vector if there is one
566 jz spec_query_failed ; and try other workarounds
568 jmp spec_query_failed ;
570 award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
573 cmp eax,[award_oldint13] ; give up if this is the
574 jz award_failed ; active int 13 vector,
575 mov [13h*4],eax ; otherwise change 0:13h*4
578 %ifdef DEBUG_MESSAGES ;
580 push eax ; display message and
581 mov si,award_not_new ; new vector address
585 mov si,award_not_crlf ;
586 call writestr_early ;
588 mov ax,4B01h ; try to read the spec packet
589 mov dl,[DriveNumber] ; now ... it should not fail
590 mov si,spec_packet ; any longer
594 %ifdef DEBUG_MESSAGES ;
596 mov si,award_not_succ ; display our SUCCESS
599 jmp found_drive ; and leave error recovery code
601 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
602 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
603 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
606 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
607 ; Try to scan the entire 80h-FFh from the end.
611 ; some code moved to BrokenAwardHack
617 mov byte [si],13h ; Size of buffer
628 cmp byte [sp_drive],dl
631 ; Okay, good enough...
634 .found_drive0: mov [DriveNumber],dl
635 .found_drive: jmp found_drive
637 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
638 ; but if this was the drive number originally passed in
639 ; DL then consider it "good enough"
645 ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02
646 ; passes garbage in sp_drive, and the drive number originally
647 ; passed in DL does not have 80h bit set.
652 .still_broken: dec dx
656 ; No spec packet anywhere. Some particularly pathetic
657 ; BIOSes apparently don't even implement function
658 ; 4B01h, so we can't query a spec packet no matter
659 ; what. If we got a drive number in DL, then try to
660 ; use it, and if it works, then well...
662 cmp dl,81h ; Should be 81-FF at least
663 jb fatal_error ; If not, it's hopeless
665 ; Write a warning to indicate we're on *very* thin ice now
673 jmp .found_drive ; Pray that this works...
679 .norge: jmp short .norge
681 ; Information message (DS:SI) output
682 ; Prefix with "isolinux: "
694 ; Write a character to the screen. There is a more "sophisticated"
695 ; version of this in the subsequent code, so we patch the pointer
711 ; int13: save all the segment registers and call INT 13h.
712 ; Some CD-ROM BIOSes have been found to corrupt segment registers
713 ; and/or disable interrupts.
724 setc [bp+10] ; Propagate CF to the caller
734 ; Get one sector. Convenience entry point.
738 ; Fall through to getlinsec
741 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
744 ; EAX - Linear sector number
745 ; ES:BX - Target buffer
749 getlinsec: jmp word [cs:GetlinsecPtr]
751 %ifndef DEBUG_MESSAGES
754 ; First, the variants that we use when actually loading off a disk
755 ; (hybrid mode.) These are adapted versions of the equivalent routines
762 ; getlinsec implementation for floppy/HDD EBIOS (EDD)
767 shl eax,2 ; Convert to HDD sectors
773 push bp ; Sectors left
775 call maxtrans ; Enforce maximum transfer size
776 movzx edi,bp ; Sectors we are about to read
793 mov ah,42h ; Extended Read
797 lea sp,[si+16] ; Remove DAPA
800 add eax,edi ; Advance sector pointer
802 sub bp,di ; Sectors left
803 shl di,9 ; 512-byte sectors
804 add bx,di ; Advance buffer pointer
811 ; Some systems seem to get "stuck" in an error state when
812 ; using EBIOS. Doesn't happen when using CBIOS, which is
813 ; good, since some other systems get timeout failures
814 ; waiting for the floppy disk to spin up.
816 pushad ; Try resetting the device
821 loop .retry ; CX-- and jump if not zero
823 ;shr word [MaxTransfer],1 ; Reduce the transfer size
826 ; Total failure. Try falling back to CBIOS.
827 mov word [GetlinsecPtr], getlinsec_cbios
828 ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer
831 jmp getlinsec_cbios.loop
836 ; getlinsec implementation for legacy CBIOS
840 shl eax,2 ; Convert to HDD sectors
850 movzx esi,word [bsSecPerTrack]
851 movzx edi,word [bsHeads]
853 ; Dividing by sectors to get (track,sector): we may have
854 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
858 xchg cx,dx ; CX <- sector index (0-based)
861 div edi ; Convert track to head/cyl
863 ; We should test this, but it doesn't fit...
868 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
869 ; BP = sectors to transfer, SI = bsSecPerTrack,
870 ; ES:BX = data target
873 call maxtrans ; Enforce maximum transfer size
875 ; Must not cross track boundaries, so BP <= SI-CX
882 shl ah,6 ; Because IBM was STOOPID
883 ; and thought 8 bits were enough
884 ; then thought 10 bits were enough...
885 inc cx ; Sector numbers are 1-based, sigh
890 xchg ax,bp ; Sector to transfer count
891 mov ah,02h ; Read sectors
899 movzx ecx,al ; ECX <- sectors transferred
900 shl ax,9 ; Convert sectors in AL to bytes in AX
915 xchg ax,bp ; Sectors transferred <- 0
916 shr word [MaxTransfer],1
921 ; Truncate BP to MaxTransfer
932 ; This is the variant we use for real CD-ROMs:
933 ; LBA, 2K sectors, some special error handling.
936 mov si,dapa ; Load up the DAPA
941 push bp ; Sectors left
942 cmp bp,[MaxTransferCD]
944 mov bp,[MaxTransferCD]
949 mov ah,42h ; Extended Read
953 movzx eax,word [si+2] ; Sectors we read
954 add [si+8],eax ; Advance sector pointer
955 sub bp,ax ; Sectors left
956 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
957 add [si+6],ax ; Advance buffer pointer
960 mov eax,[si+8] ; Next sector
964 xint13: mov byte [RetryCount],retry_count
968 add sp,byte 8*4 ; Clean up stack
971 mov [DiskError],ah ; Save error code
973 mov [DiskSys],ax ; Save system call number
974 dec byte [RetryCount]
978 mov ah,[dapa+2] ; Sector transfer count
979 cmp al,2 ; Only 2 attempts left
981 mov ah,1 ; Drop transfer size to 1
985 ja .again ; First time, just try again
986 shr ah,1 ; Otherwise, try to reduce
987 adc ah,0 ; the max transfer size, but not to 0
989 mov [MaxTransferCD],ah
995 .real_error: mov si,diskerr_msg
1008 ; Fall through to kaboom
1011 ; kaboom: write a message and bail out. Wait for a user keypress,
1012 ; then do a hard reboot.
1017 RESET_STACK_AND_SEGS AX
1018 mov si,err_bootfailed
1022 mov word [BIOS_magic],0 ; Cold reboot
1023 jmp 0F000h:0FFF0h ; Reset vector address
1025 ; -----------------------------------------------------------------------------
1026 ; Common modules needed in the first sector
1027 ; -----------------------------------------------------------------------------
1029 %include "writestr.inc" ; String output
1030 writestr_early equ writestr
1031 %include "writehex.inc" ; Hexadecimal output
1033 ; -----------------------------------------------------------------------------
1034 ; Data that needs to be in the first sector
1035 ; -----------------------------------------------------------------------------
1037 syslinux_banner db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', DATE_STR, ' ', 0
1038 copyright_str db ' Copyright (C) 1994-'
1040 db ' H. Peter Anvin et al', CR, LF, 0
1041 isolinux_str db 'isolinux: ', 0
1042 %ifdef DEBUG_MESSAGES
1043 startup_msg: db 'Starting up, DL = ', 0
1044 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
1045 secsize_msg: db 'Sector size ', 0
1046 offset_msg: db 'Main image LBA = ', 0
1047 verify_msg: db 'Image checksum verified.', CR, LF, 0
1048 allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
1050 noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
1051 noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
1052 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
1053 maybe_msg: db 'Found something at drive = ', 0
1054 alright_msg: db 'Looks reasonable, continuing...', CR, LF, 0
1055 nospec_msg db 'Extremely broken BIOS detected, last attempt with drive = ', 0
1056 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
1057 trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
1058 diskerr_msg: db 'Disk error ', 0
1059 oncall_str: db ', AX = ',0
1060 ondrive_str: db ', drive ', 0
1061 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
1063 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
1064 bailmsg equ err_bootfailed
1068 bios_cdrom_str db 'ETCD', 0
1069 %ifndef DEBUG_MESSAGES
1070 bios_cbios_str db 'CHDD', 0
1071 bios_ebios_str db 'EHDD' ,0
1075 bios_cdrom: dw getlinsec_cdrom, bios_cdrom_str
1076 %ifndef DEBUG_MESSAGES
1077 bios_cbios: dw getlinsec_cbios, bios_cbios_str
1078 bios_ebios: dw getlinsec_ebios, bios_ebios_str
1081 ; Maximum transfer size
1082 MaxTransfer dw 127 ; Hard disk modes
1083 MaxTransferCD dw 32 ; CD mode
1085 rl_checkpt equ $ ; Must be <= 800h
1087 ; This pads to the end of sector 0 and errors out on
1089 times 2048-($-$$) db 0
1091 ; ----------------------------------------------------------------------------
1092 ; End of code and data that have to be in the first sector
1093 ; ----------------------------------------------------------------------------
1104 ; Common initialization code
1108 ; Patch the writechr routine to point to the full code
1112 mov ax,writechr_full-2
1116 ; Tell the user we got this far...
1117 %ifndef DEBUG_MESSAGES ; Gets messy with debugging on
1118 mov si,copyright_str
1123 ; Now we're all set to start with our *real* business. First load the
1124 ; configuration file (if any) and parse it.
1126 ; In previous versions I avoided using 32-bit registers because of a
1127 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
1128 ; random. I figure, though, that if there are any of those still left
1129 ; they probably won't be trying to install Linux on them...
1131 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
1132 ; to take'm out. In fact, we may want to put them back if we're going
1133 ; to boot ELKS at some point.
1137 ; Now, we need to sniff out the actual filesystem data structures.
1138 ; mkisofs gave us a pointer to the primary volume descriptor
1139 ; (which will be at 16 only for a single-session disk!); from the PVD
1140 ; we should be able to find the rest of what we need to know.
1145 mov dl,[DriveNumber]
1146 cmp word [BIOSType],bios_cdrom
1147 sete dh ; 1 for cdrom, 0 for hybrid mode
1149 movzx ebp,word [MaxTransferCD]
1152 movzx ebp,word [MaxTransfer]
1157 mov di,[bsSecPerTrack]
1171 ; Locate the configuration file
1173 pm_call pm_load_config
1177 ; Now we have the config file open. Parse the config file and
1178 ; run the user interface.
1182 ; -----------------------------------------------------------------------------
1184 ; -----------------------------------------------------------------------------
1186 %include "common.inc" ; Universal modules
1187 %include "rawcon.inc" ; Console I/O w/o using the console functions
1188 %include "localboot.inc" ; Disk-based local boot
1190 ; -----------------------------------------------------------------------------
1191 ; Begin data section
1192 ; -----------------------------------------------------------------------------
1195 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
1198 ; Config file keyword table
1200 %include "keywords.inc"
1203 ; Extensions to search for (in *forward* order).
1206 exten_table: db '.cbt' ; COMBOOT (specific)
1207 db '.bin' ; CD boot sector
1208 db '.com' ; COMBOOT (same as DOS)
1211 dd 0, 0 ; Need 8 null bytes here