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 Hidden 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
]
256 mov [cs:InitStack
],sp ; Save initial stack pointer
257 mov [cs:InitStack
+2],ss
260 mov sp,StackBuf
; Set up stack
261 push es ; Save initial ES:DI -> $PnP pointer
275 mov [GetlinsecPtr
],eax
278 mov si,syslinux_banner
280 %ifdef DEBUG_MESSAGES
288 ; Before modifying any memory, get the checksum of bytes
291 initial_csum: xor edi,edi
293 mov cx,(SECTOR_SIZE
-64) >> 2
297 mov [FirstSecSum
],edi
300 %ifdef DEBUG_MESSAGES
308 ; Initialize spec packet buffers
311 mov cx,_spec_len
>> 2
315 ; Initialize length field of the various packets
316 mov byte [spec_packet
],13h
317 mov byte [drive_params
],30
319 mov byte [dspec_packet
],13h
321 ; Other nonzero fields
322 inc word [dsp_sectors
]
324 ; Are we just pretending to be a CD-ROM?
325 cmp word [BIOSType
],bios_cdrom
326 jne found_drive
; If so, no spec packet...
328 ; Now figure out what we're actually doing
329 ; Note: use passed-in DL value rather than 7Fh because
330 ; at least some BIOSes will get the wrong value otherwise
331 mov ax,4B01h ; Get disk emulation status
335 jc award_hack
; changed for BrokenAwardHack
337 cmp [sp_drive
],dl ; Should contain the drive number
338 jne spec_query_failed
340 %ifdef DEBUG_MESSAGES
343 mov al,byte [sp_drive
]
349 ; Alright, we have found the drive. Now, try to find the
350 ; boot file itself. If we have a boot info table, life is
351 ; good; if not, we have to make some assumptions, and try
352 ; to figure things out ourselves. In particular, the
353 ; assumptions we have to make are:
354 ; - single session only
355 ; - only one boot entry (no menu or other alternatives)
357 cmp dword [bi_file
],0 ; Address of code to load
358 jne found_file
; Boot info table present :)
360 %ifdef DEBUG_MESSAGES
361 mov si,noinfotable_msg
365 ; No such luck. See if the spec packet contained one.
368 jz set_file
; Good enough
370 %ifdef DEBUG_MESSAGES
371 mov si,noinfoinspec_msg
375 ; No such luck. Get the Boot Record Volume, assuming single
376 ; session disk, and that we're the first entry in the chain.
377 mov eax,17 ; Assumed address of BRV
381 mov eax,[trackbuf
+47h] ; Get boot catalog address
383 call getonesec
; Get boot catalog
385 mov eax,[trackbuf
+28h] ; First boot entry
386 ; And hope and pray this is us...
388 ; Some BIOSes apparently have limitations on the size
389 ; that may be loaded (despite the El Torito spec being very
390 ; clear on the fact that it must all be loaded.) Therefore,
391 ; we load it ourselves, and *bleep* the BIOS.
397 ; Set up boot file sizes
399 sub eax,SECTOR_SIZE
-3 ; ... minus sector loaded
400 shr eax,2 ; bytes->dwords
401 mov [ImageDwords
],eax ; boot file dwords
402 add eax,((SECTOR_SIZE
-1) >> 2)
403 shr eax,SECTOR_SHIFT
-2 ; dwords->sectors
404 mov [ImageSectors
],ax ; boot file sectors
406 mov eax,[bi_file
] ; Address of code to load
407 inc eax ; Don't reload bootstrap code
408 %ifdef DEBUG_MESSAGES
415 ; Load the rest of the file. However, just in case there
416 ; are still BIOSes with 64K wraparound problems, we have to
417 ; take some extra precautions. Since the normal load
418 ; address (TEXT_START) is *not* 2K-sector-aligned, we round
419 ; the target address upward to a sector boundary,
420 ; and then move the entire thing down as a unit.
421 MaxLMA
equ 384*1024 ; Reasonable limit (384K)
423 mov bx,((TEXT_START
+2*SECTOR_SIZE
-1) & ~
(SECTOR_SIZE
-1)) >> 4
424 mov bp,[ImageSectors
]
425 push bx ; Load segment address
428 push bx ; Segment address
429 push bp ; Sector count
435 shr cx,SECTOR_SHIFT
- 4
437 mov cx,0x10000 >> SECTOR_SHIFT
; Full 64K segment possible
451 shl cx,SECTOR_SHIFT
- 4
456 ; Move the image into place, and also verify the
458 pop ax ; Load segment address
459 mov bx,(TEXT_START
+ SECTOR_SIZE
) >> 4
460 mov ecx,[ImageDwords
]
461 mov edi,[FirstSecSum
] ; First sector checksum
484 ; Verify the checksum on the loaded image.
493 %ifdef DEBUG_MESSAGES
497 jmp all_read
; Jump to main code
499 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
500 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
501 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
503 ;; There is a problem with certain versions of the AWARD BIOS ...
504 ;; the boot sector will be loaded and executed correctly, but, because the
505 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
506 ;; load the spec packet will fail. We scan for the equivalent of
515 ;; and use <direct far> as the new vector for int 13. The code above is
516 ;; used to load the boot code into ram, and there should be no reason
517 ;; for anybody to change it now or in the future. There are no opcodes
518 ;; that use encodings relativ to IP, so scanning is easy. If we find the
519 ;; code above in the BIOS code we can be pretty sure to run on a machine
520 ;; with an broken AWARD BIOS ...
522 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
524 %ifdef DEBUG_MESSAGES
;;
526 award_notice
db "Trying BrokenAwardHack first ...",CR
,LF
,0 ;;
527 award_not_orig
db "BAH: Original Int 13 vector : ",0 ;;
528 award_not_new
db "BAH: Int 13 vector changed to : ",0 ;;
529 award_not_succ
db "BAH: SUCCESS",CR
,LF
,0 ;;
530 award_not_fail
db "BAH: FAILURE" ;;
531 award_not_crlf
db CR
,LF
,0 ;;
535 award_oldint13
dd 0 ;;
536 award_string
db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah
,80h,1,09ch,09ah ;;
538 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
539 award_hack: mov si,spec_err_msg
; Moved to this place from
540 call writemsg
; spec_query_faild
542 %ifdef DEBUG_MESSAGES
;
544 mov si,award_notice
; display our plan
546 mov si,award_not_orig
; display original int 13
547 call writemsg
; vector
550 mov [award_oldint13
],eax ;
552 %ifdef DEBUG_MESSAGES
;
555 mov si,award_not_crlf
;
556 call writestr_early
;
559 mov ax,0f000h
; ES = BIOS Seg
562 xor di,di ; start at ES:DI = f000:0
563 award_loop: push di ; save DI
564 mov si,award_string
; scan for award_string
565 mov cx,7 ; length of award_string = 7dw
568 jcxz award_found
; jmp if found
569 inc di ; not found, inc di
572 award_failed: pop es ; No, not this way :-((
575 %ifdef DEBUG_MESSAGES
;
577 mov si,award_not_fail
; display failure ...
580 mov eax,[award_oldint13
] ; restore the original int
581 or eax,eax ; 13 vector if there is one
582 jz spec_query_failed
; and try other workarounds
584 jmp spec_query_failed
;
586 award_found: mov eax,[es:di+0eh
] ; load possible int 13 addr
589 cmp eax,[award_oldint13
] ; give up if this is the
590 jz award_failed
; active int 13 vector,
591 mov [13h*4],eax ; otherwise change 0:13h*4
594 %ifdef DEBUG_MESSAGES
;
596 push eax ; display message and
597 mov si,award_not_new
; new vector address
601 mov si,award_not_crlf
;
602 call writestr_early
;
604 mov ax,4B01h ; try to read the spec packet
605 mov dl,[DriveNumber
] ; now ... it should not fail
606 mov si,spec_packet
; any longer
610 %ifdef DEBUG_MESSAGES
;
612 mov si,award_not_succ
; display our SUCCESS
615 jmp found_drive
; and leave error recovery code
617 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
618 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
619 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
622 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
623 ; Try to scan the entire 80h-FFh from the end.
627 ; some code moved to BrokenAwardHack
633 mov byte [si],13h ; Size of buffer
644 cmp byte [sp_drive
],dl
647 ; Okay, good enough...
650 .
found_drive0: mov [DriveNumber
],dl
651 .
found_drive: jmp found_drive
653 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
654 ; but if this was the drive number originally passed in
655 ; DL then consider it "good enough"
661 ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02
662 ; passes garbage in sp_drive, and the drive number originally
663 ; passed in DL does not have 80h bit set.
668 .
still_broken: dec dx
672 ; No spec packet anywhere. Some particularly pathetic
673 ; BIOSes apparently don't even implement function
674 ; 4B01h, so we can't query a spec packet no matter
675 ; what. If we got a drive number in DL, then try to
676 ; use it, and if it works, then well...
678 cmp dl,81h ; Should be 81-FF at least
679 jb fatal_error
; If not, it's hopeless
681 ; Write a warning to indicate we're on *very* thin ice now
689 jmp .found_drive
; Pray that this works...
695 .
norge: jmp short .norge
697 ; Information message (DS:SI) output
698 ; Prefix with "isolinux: "
710 ; Write a character to the screen. There is a more "sophisticated"
711 ; version of this in the subsequent code, so we patch the pointer
727 ; int13: save all the segment registers and call INT 13h.
728 ; Some CD-ROM BIOSes have been found to corrupt segment registers
729 ; and/or disable interrupts.
740 setc [bp+10] ; Propagate CF to the caller
750 ; Get one sector. Convenience entry point.
754 ; Fall through to getlinsec
757 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
760 ; EAX - Linear sector number
761 ; ES:BX - Target buffer
765 getlinsec: jmp word [cs:GetlinsecPtr
]
767 %ifndef DEBUG_MESSAGES
770 ; First, the variants that we use when actually loading off a disk
771 ; (hybrid mode.) These are adapted versions of the equivalent routines
778 ; getlinsec implementation for floppy/HDD EBIOS (EDD)
783 shl eax,2 ; Convert to HDD sectors
789 push bp ; Sectors left
791 call maxtrans
; Enforce maximum transfer size
792 movzx edi,bp ; Sectors we are about to read
809 mov ah,42h ; Extended Read
813 lea sp,[si+16] ; Remove DAPA
816 add eax,edi ; Advance sector pointer
818 sub bp,di ; Sectors left
819 shl di,9 ; 512-byte sectors
820 add bx,di ; Advance buffer pointer
827 ; Some systems seem to get "stuck" in an error state when
828 ; using EBIOS. Doesn't happen when using CBIOS, which is
829 ; good, since some other systems get timeout failures
830 ; waiting for the floppy disk to spin up.
832 pushad ; Try resetting the device
837 loop .retry
; CX-- and jump if not zero
839 ;shr word [MaxTransfer],1 ; Reduce the transfer size
842 ; Total failure. Try falling back to CBIOS.
843 mov word [GetlinsecPtr
], getlinsec_cbios
844 ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer
847 jmp getlinsec_cbios.
loop
852 ; getlinsec implementation for legacy CBIOS
856 shl eax,2 ; Convert to HDD sectors
866 movzx esi,word [bsSecPerTrack
]
867 movzx edi,word [bsHeads
]
869 ; Dividing by sectors to get (track,sector): we may have
870 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
874 xchg cx,dx ; CX <- sector index (0-based)
877 div edi ; Convert track to head/cyl
879 ; We should test this, but it doesn't fit...
884 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
885 ; BP = sectors to transfer, SI = bsSecPerTrack,
886 ; ES:BX = data target
889 call maxtrans
; Enforce maximum transfer size
891 ; Must not cross track boundaries, so BP <= SI-CX
898 shl ah,6 ; Because IBM was STOOPID
899 ; and thought 8 bits were enough
900 ; then thought 10 bits were enough...
901 inc cx ; Sector numbers are 1-based, sigh
906 xchg ax,bp ; Sector to transfer count
907 mov ah,02h ; Read sectors
915 movzx ecx,al ; ECX <- sectors transferred
916 shl ax,9 ; Convert sectors in AL to bytes in AX
931 xchg ax,bp ; Sectors transferred <- 0
932 shr word [MaxTransfer
],1
937 ; Truncate BP to MaxTransfer
948 ; This is the variant we use for real CD-ROMs:
949 ; LBA, 2K sectors, some special error handling.
952 mov si,dapa
; Load up the DAPA
957 push bp ; Sectors left
958 cmp bp,[MaxTransferCD
]
960 mov bp,[MaxTransferCD
]
965 mov ah,42h ; Extended Read
969 movzx eax,word [si+2] ; Sectors we read
970 add [si+8],eax ; Advance sector pointer
971 sub bp,ax ; Sectors left
972 shl ax,SECTOR_SHIFT
-4 ; 2048-byte sectors -> segment
973 add [si+6],ax ; Advance buffer pointer
976 mov eax,[si+8] ; Next sector
980 xint13: mov byte [RetryCount
],retry_count
984 add sp,byte 8*4 ; Clean up stack
987 mov [DiskError
],ah ; Save error code
989 mov [DiskSys
],ax ; Save system call number
990 dec byte [RetryCount
]
994 mov ah,[dapa
+2] ; Sector transfer count
995 cmp al,2 ; Only 2 attempts left
997 mov ah,1 ; Drop transfer size to 1
1000 cmp al,retry_count
-2
1001 ja .again
; First time, just try again
1002 shr ah,1 ; Otherwise, try to reduce
1003 adc ah,0 ; the max transfer size, but not to 0
1005 mov [MaxTransferCD
],ah
1011 .
real_error: mov si,diskerr_msg
1024 ; Fall through to kaboom
1027 ; kaboom: write a message and bail out. Wait for a user keypress,
1028 ; then do a hard reboot.
1033 RESET_STACK_AND_SEGS
AX
1034 mov si,err_bootfailed
1038 mov word [BIOS_magic
],0 ; Cold reboot
1039 jmp 0F000h:0FFF0h
; Reset vector address
1041 ; -----------------------------------------------------------------------------
1042 ; Common modules needed in the first sector
1043 ; -----------------------------------------------------------------------------
1045 %include "writestr.inc" ; String output
1046 writestr_early
equ writestr
1047 %include "writehex.inc" ; Hexadecimal output
1049 ; -----------------------------------------------------------------------------
1050 ; Data that needs to be in the first sector
1051 ; -----------------------------------------------------------------------------
1053 syslinux_banner
db CR
, LF
, MY_NAME
, ' ', VERSION_STR
, ' ', DATE_STR
, ' ', 0
1054 copyright_str
db ' Copyright (C) 1994-'
1056 db ' H. Peter Anvin et al', CR
, LF
, 0
1057 isolinux_str
db 'isolinux: ', 0
1058 %ifdef DEBUG_MESSAGES
1059 startup_msg: db 'Starting up, DL = ', 0
1060 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
1061 secsize_msg: db 'Sector size ', 0
1062 offset_msg: db 'Main image LBA = ', 0
1063 verify_msg: db 'Image checksum verified.', CR
, LF
, 0
1064 allread_msg
db 'Main image read, jumping to main code...', CR
, LF
, 0
1066 noinfotable_msg
db 'No boot info table, assuming single session disk...', CR
, LF
, 0
1067 noinfoinspec_msg
db 'Spec packet missing LBA information, trying to wing it...', CR
, LF
, 0
1068 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR
, LF
, 0
1069 maybe_msg: db 'Found something at drive = ', 0
1070 alright_msg: db 'Looks reasonable, continuing...', CR
, LF
, 0
1071 nospec_msg
db 'Extremely broken BIOS detected, last attempt with drive = ', 0
1072 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR
, LF
1073 trysbm_msg
db 'See http://syslinux.zytor.com/sbm for more information.', CR
, LF
, 0
1074 diskerr_msg: db 'Disk error ', 0
1075 oncall_str: db ', AX = ',0
1076 ondrive_str: db ', drive ', 0
1077 checkerr_msg: db 'Image checksum error, sorry...', CR
, LF
, 0
1079 err_bootfailed
db CR
, LF
, 'Boot failed: press a key to retry...'
1080 bailmsg
equ err_bootfailed
1084 bios_cdrom_str
db 'ETCD', 0
1085 %ifndef DEBUG_MESSAGES
1086 bios_cbios_str
db 'CHDD', 0
1087 bios_ebios_str
db 'EHDD' ,0
1091 bios_cdrom: dw getlinsec_cdrom
, bios_cdrom_str
1092 %ifndef DEBUG_MESSAGES
1093 bios_cbios: dw getlinsec_cbios
, bios_cbios_str
1094 bios_ebios: dw getlinsec_ebios
, bios_ebios_str
1097 ; Maximum transfer size
1098 MaxTransfer
dw 127 ; Hard disk modes
1099 MaxTransferCD
dw 32 ; CD mode
1101 rl_checkpt
equ $
; Must be <= 800h
1103 ; This pads to the end of sector 0 and errors out on
1105 times
2048-($
-$$
) db 0
1107 ; ----------------------------------------------------------------------------
1108 ; End of code and data that have to be in the first sector
1109 ; ----------------------------------------------------------------------------
1120 ; Common initialization code
1124 ; Patch the writechr routine to point to the full code
1128 mov ax,writechr_full
-2
1132 ; Tell the user we got this far...
1133 %ifndef DEBUG_MESSAGES
; Gets messy with debugging on
1134 mov si,copyright_str
1139 ; Now we're all set to start with our *real* business. First load the
1140 ; configuration file (if any) and parse it.
1142 ; In previous versions I avoided using 32-bit registers because of a
1143 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
1144 ; random. I figure, though, that if there are any of those still left
1145 ; they probably won't be trying to install Linux on them...
1147 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
1148 ; to take'm out. In fact, we may want to put them back if we're going
1149 ; to boot ELKS at some point.
1153 ; Now, we need to sniff out the actual filesystem data structures.
1154 ; mkisofs gave us a pointer to the primary volume descriptor
1155 ; (which will be at 16 only for a single-session disk!); from the PVD
1156 ; we should be able to find the rest of what we need to know.
1161 mov dl,[DriveNumber
]
1162 cmp word [BIOSType
],bios_cdrom
1163 sete dh ; 1 for cdrom, 0 for hybrid mode
1165 movzx ebp,word [MaxTransferCD
]
1168 movzx ebp,word [MaxTransfer
]
1173 mov di,[bsSecPerTrack
]
1187 ; Locate the configuration file
1189 pm_call pm_load_config
1193 ; Now we have the config file open. Parse the config file and
1194 ; run the user interface.
1199 ; Enable disk emulation. The kind of disk we emulate is dependent on the
1200 ; size of the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
1208 mov edx,eax ; File size
1210 mov cx,img_table_count
1211 mov eax,[si+file_sector
] ; Starting LBA of file
1212 mov [dsp_lba
],eax ; Location of file
1213 mov byte [dsp_drive
], 0 ; 00h floppy, 80h hard disk
1222 ; Hard disk image. Need to examine the partition table
1223 ; in order to deduce the C/H/S geometry. Sigh.
1230 mov cx,1 ; Load 1 sector
1233 cmp word [trackbuf
+510],0aa55h
; Boot signature
1234 jne .bad_image
; Image not bootable
1236 mov cx,4 ; 4 partition entries
1237 mov di,trackbuf
+446 ; Start of partition table
1239 xor ax,ax ; Highest sector(al) head(ah)
1253 push edx ; File size
1256 inc bx ; # of heads in BX
1257 xor ah,ah ; # of sectors in AX
1258 cwde ; EAX[31:16] <- 0
1260 shl eax,9 ; Convert to bytes
1261 ; Now eax contains the number of bytes per cylinder
1267 inc eax ; Fractional cylinder...
1268 ; Now (e)ax contains the number of cylinders
1269 .
no_remainder: cmp eax,1024
1271 mov ax,1024 ; Max possible #
1272 .
ok_cyl: dec ax ; Convert to max cylinder no
1273 pop ebx ; S(bl) H(bh)
1279 mov al,4 ; Hard disk boot
1280 mov byte [dsp_drive
], 80h ; Drive 80h = hard disk
1285 and bl,0F0h
; Copy controller info bits
1287 mov [dsp_media
],al ; Emulation type
1289 mov [dsp_chs
],eax ; C/H/S geometry
1290 mov ax,[sp_devspec
] ; Copy device spec
1291 mov [dsp_devspec
],ax
1292 mov al,[sp_controller
] ; Copy controller index
1293 mov [dsp_controller
],al
1296 call vgaclearmode
; Reset video
1298 mov ax,4C00h
; Enable emulation and boot
1300 mov dl,[DriveNumber
]
1306 ; If this returns, we have problems
1308 mov si,err_disk_image
1313 ; Look for the highest seen H/S geometry
1314 ; We compute cylinders separately
1317 mov bl,[si] ; Head #
1320 mov ah,bl ; New highest head #
1321 .
done_track: mov bl,[si+1]
1322 and bl,3Fh
; Sector #
1330 ; -----------------------------------------------------------------------------
1332 ; -----------------------------------------------------------------------------
1334 %include "common.inc" ; Universal modules
1335 %include "rawcon.inc" ; Console I/O w/o using the console functions
1336 %include "localboot.inc" ; Disk-based local boot
1338 ; -----------------------------------------------------------------------------
1339 ; Begin data section
1340 ; -----------------------------------------------------------------------------
1343 err_disk_image
db 'Cannot load disk image (invalid file)?', CR
, LF
, 0
1346 ; Config file keyword table
1348 %include "keywords.inc"
1351 ; Extensions to search for (in *forward* order).
1354 exten_table: db '.cbt' ; COMBOOT (specific)
1355 db '.img' ; Disk image
1356 db '.bin' ; CD boot sector
1357 db '.com' ; COMBOOT (same as DOS)
1360 dd 0, 0 ; Need 8 null bytes here
1363 ; Floppy image table
1366 img_table_count
equ 3
1368 dd 1200*1024 ; 1200K floppy
1369 db 1 ; Emulation type
1370 db 80-1 ; Max cylinder
1374 dd 1440*1024 ; 1440K floppy
1375 db 2 ; Emulation type
1376 db 80-1 ; Max cylinder
1380 dd 2880*1024 ; 2880K floppy
1381 db 3 ; Emulation type
1382 db 80-1 ; Max cylinder