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
56 ; File structure. This holds the information for each currently open file.
59 file_sector resd
1 ; Sector pointer (0 = structure free)
60 file_bytesleft resd
1 ; Number of bytes left
61 file_left resd
1 ; Number of sectors left
66 %if
(open_file_t_size
& (open_file_t_size
-1))
67 %error
"open_file_t is not a power of 2"
71 ; ---------------------------------------------------------------------------
73 ; ---------------------------------------------------------------------------
76 ; Memory below this point is reserved for the BIOS and the MBR
81 trackbuf resb trackbufsize
; Track buffer goes here
84 ; Some of these are touched before the whole image
85 ; is loaded. DO NOT move this to .bss16/.uibss.
88 FirstSecSum resd
1 ; Checksum of bytes 64-2048
89 ImageDwords resd
1 ; isolinux.bin size, dwords
90 InitStack resd
1 ; Initial stack pointer (SS:SP)
91 DiskSys resw
1 ; Last INT 13h call
92 ImageSectors resw
1 ; isolinux.bin size, sectors
93 ; These following two are accessed as a single dword...
94 GetlinsecPtr resw
1 ; The sector-read pointer
95 BIOSName resw
1 ; Display string for BIOS type
96 %define HAVE_BIOSNAME
1
98 DiskError resb
1 ; Error code for disk I/O
99 DriveNumber resb
1 ; CD-ROM BIOS drive number
100 ISOFlags resb
1 ; Flags for ISO directory search
101 RetryCount resb
1 ; Used for disk access retries
104 bsHidden resq
1 ; Used in hybrid mode
105 bsSecPerTrack resw
1 ; Used in hybrid mode
106 bsHeads resw
1 ; Used in hybrid mode
110 ; El Torito spec packet
115 spec_packet: resb
1 ; Size of packet
116 sp_media: resb
1 ; Media type
117 sp_drive: resb
1 ; Drive number
118 sp_controller: resb
1 ; Controller index
119 sp_lba: resd
1 ; LBA for emulated disk image
120 sp_devspec: resw
1 ; IDE/SCSI information
121 sp_buffer: resw
1 ; User-provided buffer
122 sp_loadseg: resw
1 ; Load segment
123 sp_sectors: resw
1 ; Sector count
124 sp_chs: resb
3 ; Simulated CHS geometry
125 sp_dummy: resb
1 ; Scratch, safe to overwrite
128 ; EBIOS drive parameter packet
131 drive_params: resw
1 ; Buffer size
132 dp_flags: resw
1 ; Information flags
133 dp_cyl: resd
1 ; Physical cylinders
134 dp_head: resd
1 ; Physical heads
135 dp_sec: resd
1 ; Physical sectors/track
136 dp_totalsec: resd
2 ; Total sectors
137 dp_secsize: resw
1 ; Bytes per sector
138 dp_dpte: resd
1 ; Device Parameter Table
139 dp_dpi_key: resw
1 ; 0BEDDh if rest valid
140 dp_dpi_len: resb
1 ; DPI len
143 dp_bus: resb
4 ; Host bus type
144 dp_interface: resb
8 ; Interface type
145 db_i_path: resd
2 ; Interface path
146 db_d_path: resd
2 ; Device path
148 db_dpi_csum: resb
1 ; Checksum for DPI info
151 ; EBIOS disk address packet
154 dapa: resw
1 ; Packet size
155 .
count: resw
1 ; Block count
156 .
off: resw
1 ; Offset of buffer
157 .
seg: resw
1 ; Segment of buffer
158 .
lba: resd
2 ; LBA (LSW, MSW)
161 ; Spec packet for disk image emulation
164 dspec_packet: resb
1 ; Size of packet
165 dsp_media: resb
1 ; Media type
166 dsp_drive: resb
1 ; Drive number
167 dsp_controller: resb
1 ; Controller index
168 dsp_lba: resd
1 ; LBA for emulated disk image
169 dsp_devspec: resw
1 ; IDE/SCSI information
170 dsp_buffer: resw
1 ; User-provided buffer
171 dsp_loadseg: resw
1 ; Load segment
172 dsp_sectors: resw
1 ; Sector count
173 dsp_chs: resb
3 ; Simulated CHS geometry
174 dsp_dummy: resb
1 ; Scratch, safe to overwrite
178 _spec_len
equ _spec_end
- _spec_start
182 ;; Primary entry point. Because BIOSes are buggy, we only load the first
183 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
186 StackBuf
equ STACK_TOP
-44 ; 44 bytes needed for
187 ; the bootsector chainloading
189 OrigESDI
equ StackBuf
-4 ; The high dword on the stack
190 StackHome
equ OrigESDI
194 _start: ; Far jump makes sure we canonicalize the address
197 times
8-($
-$$
) nop ; Pad to file offset 8
199 ; This table hopefully gets filled in by mkisofs using the
200 ; -boot-info-table option. If not, the values in this
201 ; table are default values that we can use to get us what
202 ; we need, at least under a certain set of assumptions.
205 bi_pvd: dd 16 ; LBA of primary volume descriptor
206 bi_file: dd 0 ; LBA of boot file
207 bi_length: dd 0xdeadbeef ; Length of boot file
208 bi_csum: dd 0xdeadbeef ; Checksum of boot file
209 bi_reserved: times
10 dd 0xdeadbeef ; Reserved
212 ; Custom entry point for the hybrid-mode disk.
213 ; The following values will have been pushed onto the
215 ; - partition offset (qword)
218 ; - DX (including drive number)
224 ; If we had an old isohybrid, the partition offset will
225 ; be missing; we can check for that with sp >= 0x7c00.
226 ; Serious hack alert.
227 %ifndef DEBUG_MESSAGES
229 dd 0x7078c0fb ; An arbitrary number...
233 pop word [cs:bsSecPerTrack
]
234 pop word [cs:bsHeads
]
245 mov [cs:bsHidden
],eax
246 mov [cs:bsHidden
+4],ebx
257 mov [cs:InitStack
],sp ; Save initial stack pointer
258 mov [cs:InitStack
+2],ss
261 mov sp,StackBuf
; Set up stack
262 push es ; Save initial ES:DI -> $PnP pointer
273 mov [GetlinsecPtr
],eax
276 mov si,syslinux_banner
278 %ifdef DEBUG_MESSAGES
286 ; Before modifying any memory, get the checksum of bytes
289 initial_csum: xor edi,edi
291 mov cx,(SECTOR_SIZE
-64) >> 2
295 mov [FirstSecSum
],edi
298 %ifdef DEBUG_MESSAGES
306 ; Initialize spec packet buffers
309 mov cx,_spec_len
>> 2
313 ; Initialize length field of the various packets
314 mov byte [spec_packet
],13h
315 mov byte [drive_params
],30
317 mov byte [dspec_packet
],13h
319 ; Other nonzero fields
320 inc word [dsp_sectors
]
322 ; Are we just pretending to be a CD-ROM?
323 cmp word [BIOSType
],bios_cdrom
324 jne found_drive
; If so, no spec packet...
326 ; Now figure out what we're actually doing
327 ; Note: use passed-in DL value rather than 7Fh because
328 ; at least some BIOSes will get the wrong value otherwise
329 mov ax,4B01h ; Get disk emulation status
333 jc award_hack
; changed for BrokenAwardHack
335 cmp [sp_drive
],dl ; Should contain the drive number
336 jne spec_query_failed
338 %ifdef DEBUG_MESSAGES
341 mov al,byte [sp_drive
]
347 ; Alright, we have found the drive. Now, try to find the
348 ; boot file itself. If we have a boot info table, life is
349 ; good; if not, we have to make some assumptions, and try
350 ; to figure things out ourselves. In particular, the
351 ; assumptions we have to make are:
352 ; - single session only
353 ; - only one boot entry (no menu or other alternatives)
355 cmp dword [bi_file
],0 ; Address of code to load
356 jne found_file
; Boot info table present :)
358 %ifdef DEBUG_MESSAGES
359 mov si,noinfotable_msg
363 ; No such luck. See if the spec packet contained one.
366 jz set_file
; Good enough
368 %ifdef DEBUG_MESSAGES
369 mov si,noinfoinspec_msg
373 ; No such luck. Get the Boot Record Volume, assuming single
374 ; session disk, and that we're the first entry in the chain.
375 mov eax,17 ; Assumed address of BRV
379 mov eax,[trackbuf
+47h] ; Get boot catalog address
381 call getonesec
; Get boot catalog
383 mov eax,[trackbuf
+28h] ; First boot entry
384 ; And hope and pray this is us...
386 ; Some BIOSes apparently have limitations on the size
387 ; that may be loaded (despite the El Torito spec being very
388 ; clear on the fact that it must all be loaded.) Therefore,
389 ; we load it ourselves, and *bleep* the BIOS.
395 ; Set up boot file sizes
397 sub eax,SECTOR_SIZE
-3 ; ... minus sector loaded
398 shr eax,2 ; bytes->dwords
399 mov [ImageDwords
],eax ; boot file dwords
400 add eax,((SECTOR_SIZE
-1) >> 2)
401 shr eax,SECTOR_SHIFT
-2 ; dwords->sectors
402 mov [ImageSectors
],ax ; boot file sectors
404 mov eax,[bi_file
] ; Address of code to load
405 inc eax ; Don't reload bootstrap code
406 %ifdef DEBUG_MESSAGES
413 ; Load the rest of the file. However, just in case there
414 ; are still BIOSes with 64K wraparound problems, we have to
415 ; take some extra precautions. Since the normal load
416 ; address (TEXT_START) is *not* 2K-sector-aligned, we round
417 ; the target address upward to a sector boundary,
418 ; and then move the entire thing down as a unit.
419 MaxLMA
equ 384*1024 ; Reasonable limit (384K)
421 mov bx,((TEXT_START
+2*SECTOR_SIZE
-1) & ~
(SECTOR_SIZE
-1)) >> 4
422 mov bp,[ImageSectors
]
423 push bx ; Load segment address
426 push bx ; Segment address
427 push bp ; Sector count
433 shr cx,SECTOR_SHIFT
- 4
435 mov cx,0x10000 >> SECTOR_SHIFT
; Full 64K segment possible
449 shl cx,SECTOR_SHIFT
- 4
454 ; Move the image into place, and also verify the
456 pop ax ; Load segment address
457 mov bx,(TEXT_START
+ SECTOR_SIZE
) >> 4
458 mov ecx,[ImageDwords
]
459 mov edi,[FirstSecSum
] ; First sector checksum
482 ; Verify the checksum on the loaded image.
491 %ifdef DEBUG_MESSAGES
495 jmp all_read
; Jump to main code
497 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
498 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
499 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
501 ;; There is a problem with certain versions of the AWARD BIOS ...
502 ;; the boot sector will be loaded and executed correctly, but, because the
503 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
504 ;; load the spec packet will fail. We scan for the equivalent of
513 ;; and use <direct far> as the new vector for int 13. The code above is
514 ;; used to load the boot code into ram, and there should be no reason
515 ;; for anybody to change it now or in the future. There are no opcodes
516 ;; that use encodings relativ to IP, so scanning is easy. If we find the
517 ;; code above in the BIOS code we can be pretty sure to run on a machine
518 ;; with an broken AWARD BIOS ...
520 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
522 %ifdef DEBUG_MESSAGES
;;
524 award_notice
db "Trying BrokenAwardHack first ...",CR
,LF
,0 ;;
525 award_not_orig
db "BAH: Original Int 13 vector : ",0 ;;
526 award_not_new
db "BAH: Int 13 vector changed to : ",0 ;;
527 award_not_succ
db "BAH: SUCCESS",CR
,LF
,0 ;;
528 award_not_fail
db "BAH: FAILURE" ;;
529 award_not_crlf
db CR
,LF
,0 ;;
533 award_oldint13
dd 0 ;;
534 award_string
db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah
,80h,1,09ch,09ah ;;
536 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
537 award_hack: mov si,spec_err_msg
; Moved to this place from
538 call writemsg
; spec_query_faild
540 %ifdef DEBUG_MESSAGES
;
542 mov si,award_notice
; display our plan
544 mov si,award_not_orig
; display original int 13
545 call writemsg
; vector
548 mov [award_oldint13
],eax ;
550 %ifdef DEBUG_MESSAGES
;
553 mov si,award_not_crlf
;
554 call writestr_early
;
557 mov ax,0f000h
; ES = BIOS Seg
560 xor di,di ; start at ES:DI = f000:0
561 award_loop: push di ; save DI
562 mov si,award_string
; scan for award_string
563 mov cx,7 ; length of award_string = 7dw
566 jcxz award_found
; jmp if found
567 inc di ; not found, inc di
570 award_failed: pop es ; No, not this way :-((
573 %ifdef DEBUG_MESSAGES
;
575 mov si,award_not_fail
; display failure ...
578 mov eax,[award_oldint13
] ; restore the original int
579 or eax,eax ; 13 vector if there is one
580 jz spec_query_failed
; and try other workarounds
582 jmp spec_query_failed
;
584 award_found: mov eax,[es:di+0eh
] ; load possible int 13 addr
587 cmp eax,[award_oldint13
] ; give up if this is the
588 jz award_failed
; active int 13 vector,
589 mov [13h*4],eax ; otherwise change 0:13h*4
592 %ifdef DEBUG_MESSAGES
;
594 push eax ; display message and
595 mov si,award_not_new
; new vector address
599 mov si,award_not_crlf
;
600 call writestr_early
;
602 mov ax,4B01h ; try to read the spec packet
603 mov dl,[DriveNumber
] ; now ... it should not fail
604 mov si,spec_packet
; any longer
608 %ifdef DEBUG_MESSAGES
;
610 mov si,award_not_succ
; display our SUCCESS
613 jmp found_drive
; and leave error recovery code
615 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
616 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
617 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
620 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
621 ; Try to scan the entire 80h-FFh from the end.
625 ; some code moved to BrokenAwardHack
631 mov byte [si],13h ; Size of buffer
642 cmp byte [sp_drive
],dl
645 ; Okay, good enough...
648 .
found_drive0: mov [DriveNumber
],dl
649 .
found_drive: jmp found_drive
651 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
652 ; but if this was the drive number originally passed in
653 ; DL then consider it "good enough"
659 ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02
660 ; passes garbage in sp_drive, and the drive number originally
661 ; passed in DL does not have 80h bit set.
666 .
still_broken: dec dx
670 ; No spec packet anywhere. Some particularly pathetic
671 ; BIOSes apparently don't even implement function
672 ; 4B01h, so we can't query a spec packet no matter
673 ; what. If we got a drive number in DL, then try to
674 ; use it, and if it works, then well...
676 cmp dl,81h ; Should be 81-FF at least
677 jb fatal_error
; If not, it's hopeless
679 ; Write a warning to indicate we're on *very* thin ice now
687 jmp .found_drive
; Pray that this works...
693 .
norge: jmp short .norge
695 ; Information message (DS:SI) output
696 ; Prefix with "isolinux: "
708 ; Write a character to the screen. There is a more "sophisticated"
709 ; version of this in the subsequent code, so we patch the pointer
725 ; int13: save all the segment registers and call INT 13h.
726 ; Some CD-ROM BIOSes have been found to corrupt segment registers
727 ; and/or disable interrupts.
738 setc [bp+10] ; Propagate CF to the caller
748 ; Get one sector. Convenience entry point.
752 ; Fall through to getlinsec
755 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
758 ; EAX - Linear sector number
759 ; ES:BX - Target buffer
763 getlinsec: jmp word [cs:GetlinsecPtr
]
765 %ifndef DEBUG_MESSAGES
768 ; First, the variants that we use when actually loading off a disk
769 ; (hybrid mode.) These are adapted versions of the equivalent routines
776 ; getlinsec implementation for floppy/HDD EBIOS (EDD)
781 shl eax,2 ; Convert to HDD sectors
787 push bp ; Sectors left
789 call maxtrans
; Enforce maximum transfer size
790 movzx edi,bp ; Sectors we are about to read
807 mov ah,42h ; Extended Read
811 lea sp,[si+16] ; Remove DAPA
814 add eax,edi ; Advance sector pointer
816 sub bp,di ; Sectors left
817 shl di,9 ; 512-byte sectors
818 add bx,di ; Advance buffer pointer
825 ; Some systems seem to get "stuck" in an error state when
826 ; using EBIOS. Doesn't happen when using CBIOS, which is
827 ; good, since some other systems get timeout failures
828 ; waiting for the floppy disk to spin up.
830 pushad ; Try resetting the device
835 loop .retry
; CX-- and jump if not zero
837 ;shr word [MaxTransfer],1 ; Reduce the transfer size
840 ; Total failure. Try falling back to CBIOS.
841 mov word [GetlinsecPtr
], getlinsec_cbios
842 ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer
845 jmp getlinsec_cbios.
loop
850 ; getlinsec implementation for legacy CBIOS
854 shl eax,2 ; Convert to HDD sectors
864 movzx esi,word [bsSecPerTrack
]
865 movzx edi,word [bsHeads
]
867 ; Dividing by sectors to get (track,sector): we may have
868 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
872 xchg cx,dx ; CX <- sector index (0-based)
875 div edi ; Convert track to head/cyl
877 ; We should test this, but it doesn't fit...
882 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
883 ; BP = sectors to transfer, SI = bsSecPerTrack,
884 ; ES:BX = data target
887 call maxtrans
; Enforce maximum transfer size
889 ; Must not cross track boundaries, so BP <= SI-CX
896 shl ah,6 ; Because IBM was STOOPID
897 ; and thought 8 bits were enough
898 ; then thought 10 bits were enough...
899 inc cx ; Sector numbers are 1-based, sigh
904 xchg ax,bp ; Sector to transfer count
905 mov ah,02h ; Read sectors
913 movzx ecx,al ; ECX <- sectors transferred
914 shl ax,9 ; Convert sectors in AL to bytes in AX
929 xchg ax,bp ; Sectors transferred <- 0
930 shr word [MaxTransfer
],1
935 ; Truncate BP to MaxTransfer
946 ; This is the variant we use for real CD-ROMs:
947 ; LBA, 2K sectors, some special error handling.
950 mov si,dapa
; Load up the DAPA
955 push bp ; Sectors left
956 cmp bp,[MaxTransferCD
]
958 mov bp,[MaxTransferCD
]
963 mov ah,42h ; Extended Read
967 movzx eax,word [si+2] ; Sectors we read
968 add [si+8],eax ; Advance sector pointer
969 sub bp,ax ; Sectors left
970 shl ax,SECTOR_SHIFT
-4 ; 2048-byte sectors -> segment
971 add [si+6],ax ; Advance buffer pointer
974 mov eax,[si+8] ; Next sector
978 xint13: mov byte [RetryCount
],retry_count
982 add sp,byte 8*4 ; Clean up stack
985 mov [DiskError
],ah ; Save error code
987 mov [DiskSys
],ax ; Save system call number
988 dec byte [RetryCount
]
992 mov ah,[dapa
+2] ; Sector transfer count
993 cmp al,2 ; Only 2 attempts left
995 mov ah,1 ; Drop transfer size to 1
999 ja .again
; First time, just try again
1000 shr ah,1 ; Otherwise, try to reduce
1001 adc ah,0 ; the max transfer size, but not to 0
1003 mov [MaxTransferCD
],ah
1009 .
real_error: mov si,diskerr_msg
1022 ; Fall through to kaboom
1025 ; kaboom: write a message and bail out. Wait for a user keypress,
1026 ; then do a hard reboot.
1031 RESET_STACK_AND_SEGS
AX
1032 mov si,err_bootfailed
1036 mov word [BIOS_magic
],0 ; Cold reboot
1037 jmp 0F000h:0FFF0h
; Reset vector address
1039 ; -----------------------------------------------------------------------------
1040 ; Common modules needed in the first sector
1041 ; -----------------------------------------------------------------------------
1043 %include "writestr.inc" ; String output
1044 writestr_early
equ writestr
1045 %include "writehex.inc" ; Hexadecimal output
1047 ; -----------------------------------------------------------------------------
1048 ; Data that needs to be in the first sector
1049 ; -----------------------------------------------------------------------------
1051 syslinux_banner
db CR
, LF
, MY_NAME
, ' ', VERSION_STR
, ' ', DATE_STR
, ' ', 0
1052 copyright_str
db ' Copyright (C) 1994-'
1054 db ' H. Peter Anvin et al', CR
, LF
, 0
1055 isolinux_str
db 'isolinux: ', 0
1056 %ifdef DEBUG_MESSAGES
1057 startup_msg: db 'Starting up, DL = ', 0
1058 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
1059 secsize_msg: db 'Sector size ', 0
1060 offset_msg: db 'Main image LBA = ', 0
1061 verify_msg: db 'Image checksum verified.', CR
, LF
, 0
1062 allread_msg
db 'Main image read, jumping to main code...', CR
, LF
, 0
1064 noinfotable_msg
db 'No boot info table, assuming single session disk...', CR
, LF
, 0
1065 noinfoinspec_msg
db 'Spec packet missing LBA information, trying to wing it...', CR
, LF
, 0
1066 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR
, LF
, 0
1067 maybe_msg: db 'Found something at drive = ', 0
1068 alright_msg: db 'Looks reasonable, continuing...', CR
, LF
, 0
1069 nospec_msg
db 'Extremely broken BIOS detected, last attempt with drive = ', 0
1070 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR
, LF
1071 trysbm_msg
db 'See http://syslinux.zytor.com/sbm for more information.', CR
, LF
, 0
1072 diskerr_msg: db 'Disk error ', 0
1073 oncall_str: db ', AX = ',0
1074 ondrive_str: db ', drive ', 0
1075 checkerr_msg: db 'Image checksum error, sorry...', CR
, LF
, 0
1077 err_bootfailed
db CR
, LF
, 'Boot failed: press a key to retry...'
1078 bailmsg
equ err_bootfailed
1082 bios_cdrom_str
db 'ETCD', 0
1083 %ifndef DEBUG_MESSAGES
1084 bios_cbios_str
db 'CHDD', 0
1085 bios_ebios_str
db 'EHDD' ,0
1089 bios_cdrom: dw getlinsec_cdrom
, bios_cdrom_str
1090 %ifndef DEBUG_MESSAGES
1091 bios_cbios: dw getlinsec_cbios
, bios_cbios_str
1092 bios_ebios: dw getlinsec_ebios
, bios_ebios_str
1095 ; Maximum transfer size
1096 MaxTransfer
dw 127 ; Hard disk modes
1097 MaxTransferCD
dw 32 ; CD mode
1099 rl_checkpt
equ $
; Must be <= 800h
1101 ; This pads to the end of sector 0 and errors out on
1103 times
2048-($
-$$
) db 0
1105 ; ----------------------------------------------------------------------------
1106 ; End of code and data that have to be in the first sector
1107 ; ----------------------------------------------------------------------------
1118 ; Common initialization code
1122 ; Patch the writechr routine to point to the full code
1126 mov ax,writechr_full
-2
1130 ; Tell the user we got this far...
1131 %ifndef DEBUG_MESSAGES
; Gets messy with debugging on
1132 mov si,copyright_str
1137 ; Now we're all set to start with our *real* business. First load the
1138 ; configuration file (if any) and parse it.
1140 ; In previous versions I avoided using 32-bit registers because of a
1141 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
1142 ; random. I figure, though, that if there are any of those still left
1143 ; they probably won't be trying to install Linux on them...
1145 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
1146 ; to take'm out. In fact, we may want to put them back if we're going
1147 ; to boot ELKS at some point.
1151 ; Now, we need to sniff out the actual filesystem data structures.
1152 ; mkisofs gave us a pointer to the primary volume descriptor
1153 ; (which will be at 16 only for a single-session disk!); from the PVD
1154 ; we should be able to find the rest of what we need to know.
1159 mov dl,[DriveNumber
]
1160 cmp word [BIOSType
],bios_cdrom
1161 sete dh ; 1 for cdrom, 0 for hybrid mode
1163 movzx ebp,word [MaxTransferCD
]
1166 movzx ebp,word [MaxTransfer
]
1169 mov ebx,[bsHidden
+4]
1171 mov di,[bsSecPerTrack
]
1185 ; Locate the configuration file
1190 ; Now we have the config file open. Parse the config file and
1191 ; run the user interface.
1196 ; Enable disk emulation. The kind of disk we emulate is dependent on the
1197 ; size of the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
1205 mov edx,eax ; File size
1207 mov cx,img_table_count
1208 mov eax,[si+file_sector
] ; Starting LBA of file
1209 mov [dsp_lba
],eax ; Location of file
1210 mov byte [dsp_drive
], 0 ; 00h floppy, 80h hard disk
1219 ; Hard disk image. Need to examine the partition table
1220 ; in order to deduce the C/H/S geometry. Sigh.
1227 mov cx,1 ; Load 1 sector
1230 cmp word [trackbuf
+510],0aa55h
; Boot signature
1231 jne .bad_image
; Image not bootable
1233 mov cx,4 ; 4 partition entries
1234 mov di,trackbuf
+446 ; Start of partition table
1236 xor ax,ax ; Highest sector(al) head(ah)
1250 push edx ; File size
1253 inc bx ; # of heads in BX
1254 xor ah,ah ; # of sectors in AX
1255 cwde ; EAX[31:16] <- 0
1257 shl eax,9 ; Convert to bytes
1258 ; Now eax contains the number of bytes per cylinder
1264 inc eax ; Fractional cylinder...
1265 ; Now (e)ax contains the number of cylinders
1266 .
no_remainder: cmp eax,1024
1268 mov ax,1024 ; Max possible #
1269 .
ok_cyl: dec ax ; Convert to max cylinder no
1270 pop ebx ; S(bl) H(bh)
1276 mov al,4 ; Hard disk boot
1277 mov byte [dsp_drive
], 80h ; Drive 80h = hard disk
1282 and bl,0F0h
; Copy controller info bits
1284 mov [dsp_media
],al ; Emulation type
1286 mov [dsp_chs
],eax ; C/H/S geometry
1287 mov ax,[sp_devspec
] ; Copy device spec
1288 mov [dsp_devspec
],ax
1289 mov al,[sp_controller
] ; Copy controller index
1290 mov [dsp_controller
],al
1293 call vgaclearmode
; Reset video
1295 mov ax,4C00h
; Enable emulation and boot
1297 mov dl,[DriveNumber
]
1303 ; If this returns, we have problems
1305 mov si,err_disk_image
1310 ; Look for the highest seen H/S geometry
1311 ; We compute cylinders separately
1314 mov bl,[si] ; Head #
1317 mov ah,bl ; New highest head #
1318 .
done_track: mov bl,[si+1]
1319 and bl,3Fh
; Sector #
1327 ; -----------------------------------------------------------------------------
1329 ; -----------------------------------------------------------------------------
1331 %include "common.inc" ; Universal modules
1332 %include "rawcon.inc" ; Console I/O w/o using the console functions
1333 %include "localboot.inc" ; Disk-based local boot
1335 ; -----------------------------------------------------------------------------
1336 ; Begin data section
1337 ; -----------------------------------------------------------------------------
1340 err_disk_image
db 'Cannot load disk image (invalid file)?', CR
, LF
, 0
1343 ; Config file keyword table
1345 %include "keywords.inc"
1348 ; Extensions to search for (in *forward* order).
1351 exten_table: db '.cbt' ; COMBOOT (specific)
1352 db '.img' ; Disk image
1353 db '.bin' ; CD boot sector
1354 db '.com' ; COMBOOT (same as DOS)
1357 dd 0, 0 ; Need 8 null bytes here
1360 ; Floppy image table
1363 img_table_count
equ 3
1365 dd 1200*1024 ; 1200K floppy
1366 db 1 ; Emulation type
1367 db 80-1 ; Max cylinder
1371 dd 1440*1024 ; 1440K floppy
1372 db 2 ; Emulation type
1373 db 80-1 ; Max cylinder
1377 dd 2880*1024 ; 2880K floppy
1378 db 3 ; Emulation type
1379 db 80-1 ; Max cylinder