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.
73 FirstSecSum resd
1 ; Checksum of bytes 64-2048
74 ImageDwords resd
1 ; isolinux.bin size, dwords
75 InitStack resd
1 ; Initial stack pointer (SS:SP)
76 DiskSys resw
1 ; Last INT 13h call
77 ImageSectors resw
1 ; isolinux.bin size, sectors
78 ; These following two are accessed as a single dword...
79 GetlinsecPtr resw
1 ; The sector-read pointer
80 BIOSName resw
1 ; Display string for BIOS type
81 %define HAVE_BIOSNAME
1
84 DiskError resb
1 ; Error code for disk I/O
86 DriveNumber resb
1 ; CD-ROM BIOS drive number
87 ISOFlags resb
1 ; Flags for ISO directory search
88 RetryCount resb
1 ; Used for disk access retries
92 Hidden resq
1 ; Used in hybrid mode
93 bsSecPerTrack resw
1 ; Used in hybrid mode
94 bsHeads resw
1 ; Used in hybrid mode
98 ; El Torito spec packet
104 spec_packet: resb
1 ; Size of packet
105 sp_media: resb
1 ; Media type
106 sp_drive: resb
1 ; Drive number
107 sp_controller: resb
1 ; Controller index
108 sp_lba: resd
1 ; LBA for emulated disk image
109 sp_devspec: resw
1 ; IDE/SCSI information
110 sp_buffer: resw
1 ; User-provided buffer
111 sp_loadseg: resw
1 ; Load segment
112 sp_sectors: resw
1 ; Sector count
113 sp_chs: resb
3 ; Simulated CHS geometry
114 sp_dummy: resb
1 ; Scratch, safe to overwrite
117 ; EBIOS drive parameter packet
120 drive_params: resw
1 ; Buffer size
121 dp_flags: resw
1 ; Information flags
122 dp_cyl: resd
1 ; Physical cylinders
123 dp_head: resd
1 ; Physical heads
124 dp_sec: resd
1 ; Physical sectors/track
125 dp_totalsec: resd
2 ; Total sectors
126 dp_secsize: resw
1 ; Bytes per sector
127 dp_dpte: resd
1 ; Device Parameter Table
128 dp_dpi_key: resw
1 ; 0BEDDh if rest valid
129 dp_dpi_len: resb
1 ; DPI len
132 dp_bus: resb
4 ; Host bus type
133 dp_interface: resb
8 ; Interface type
134 db_i_path: resd
2 ; Interface path
135 db_d_path: resd
2 ; Device path
137 db_dpi_csum: resb
1 ; Checksum for DPI info
140 ; EBIOS disk address packet
143 dapa: resw
1 ; Packet size
144 .
count: resw
1 ; Block count
145 .
off: resw
1 ; Offset of buffer
146 .
seg: resw
1 ; Segment of buffer
147 .
lba: resd
2 ; LBA (LSW, MSW)
150 ; Spec packet for disk image emulation
153 dspec_packet: resb
1 ; Size of packet
154 dsp_media: resb
1 ; Media type
155 dsp_drive: resb
1 ; Drive number
156 dsp_controller: resb
1 ; Controller index
157 dsp_lba: resd
1 ; LBA for emulated disk image
158 dsp_devspec: resw
1 ; IDE/SCSI information
159 dsp_buffer: resw
1 ; User-provided buffer
160 dsp_loadseg: resw
1 ; Load segment
161 dsp_sectors: resw
1 ; Sector count
162 dsp_chs: resb
3 ; Simulated CHS geometry
163 dsp_dummy: resb
1 ; Scratch, safe to overwrite
167 _spec_len
equ _spec_end
- _spec_start
171 ;; Primary entry point. Because BIOSes are buggy, we only load the first
172 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
176 StackBuf
equ STACK_TOP
-44 ; 44 bytes needed for
177 ; the bootsector chainloading
180 OrigESDI
equ StackBuf
-4 ; The high dword on the stack
181 StackHome
equ OrigESDI
185 _start: ; Far jump makes sure we canonicalize the address
188 times
8-($
-$$
) nop ; Pad to file offset 8
190 ; This table hopefully gets filled in by mkisofs using the
191 ; -boot-info-table option. If not, the values in this
192 ; table are default values that we can use to get us what
193 ; we need, at least under a certain set of assumptions.
196 bi_pvd: dd 16 ; LBA of primary volume descriptor
197 bi_file: dd 0 ; LBA of boot file
198 bi_length: dd 0xdeadbeef ; Length of boot file
199 bi_csum: dd 0xdeadbeef ; Checksum of boot file
200 bi_reserved: times
10 dd 0xdeadbeef ; Reserved
203 ; Custom entry point for the hybrid-mode disk.
204 ; The following values will have been pushed onto the
206 ; - partition offset (qword)
209 ; - DX (including drive number)
215 ; If we had an old isohybrid, the partition offset will
216 ; be missing; we can check for that with sp >= 0x7c00.
217 ; Serious hack alert.
218 %ifndef DEBUG_MESSAGES
220 dd 0x7078c0fb ; An arbitrary number...
224 pop word [cs:bsSecPerTrack
]
225 pop word [cs:bsHeads
]
247 mov [cs:InitStack
],sp ; Save initial stack pointer
248 mov [cs:InitStack
+2],ss
251 mov sp,StackBuf
; Set up stack
252 push es ; Save initial ES:DI -> $PnP pointer
266 mov [GetlinsecPtr
],eax
269 mov si,syslinux_banner
271 %ifdef DEBUG_MESSAGES
279 ; Before modifying any memory, get the checksum of bytes
282 initial_csum: xor edi,edi
284 mov cx,(SECTOR_SIZE
-64) >> 2
288 mov [FirstSecSum
],edi
291 %ifdef DEBUG_MESSAGES
299 ; Initialize spec packet buffers
302 mov cx,_spec_len
>> 2
306 ; Initialize length field of the various packets
307 mov byte [spec_packet
],13h
308 mov byte [drive_params
],30
310 mov byte [dspec_packet
],13h
312 ; Other nonzero fields
313 inc word [dsp_sectors
]
315 ; Are we just pretending to be a CD-ROM?
316 cmp word [BIOSType
],bios_cdrom
317 jne found_drive
; If so, no spec packet...
319 ; Now figure out what we're actually doing
320 ; Note: use passed-in DL value rather than 7Fh because
321 ; at least some BIOSes will get the wrong value otherwise
322 mov ax,4B01h ; Get disk emulation status
326 jc award_hack
; changed for BrokenAwardHack
328 cmp [sp_drive
],dl ; Should contain the drive number
329 jne spec_query_failed
331 %ifdef DEBUG_MESSAGES
334 mov al,byte [sp_drive
]
340 ; Alright, we have found the drive. Now, try to find the
341 ; boot file itself. If we have a boot info table, life is
342 ; good; if not, we have to make some assumptions, and try
343 ; to figure things out ourselves. In particular, the
344 ; assumptions we have to make are:
345 ; - single session only
346 ; - only one boot entry (no menu or other alternatives)
348 cmp dword [bi_file
],0 ; Address of code to load
349 jne found_file
; Boot info table present :)
351 %ifdef DEBUG_MESSAGES
352 mov si,noinfotable_msg
356 ; No such luck. See if the spec packet contained one.
359 jz set_file
; Good enough
361 %ifdef DEBUG_MESSAGES
362 mov si,noinfoinspec_msg
366 ; No such luck. Get the Boot Record Volume, assuming single
367 ; session disk, and that we're the first entry in the chain.
368 mov eax,17 ; Assumed address of BRV
372 mov eax,[trackbuf
+47h] ; Get boot catalog address
374 call getonesec
; Get boot catalog
376 mov eax,[trackbuf
+28h] ; First boot entry
377 ; And hope and pray this is us...
379 ; Some BIOSes apparently have limitations on the size
380 ; that may be loaded (despite the El Torito spec being very
381 ; clear on the fact that it must all be loaded.) Therefore,
382 ; we load it ourselves, and *bleep* the BIOS.
388 ; Set up boot file sizes
390 sub eax,SECTOR_SIZE
-3 ; ... minus sector loaded
391 shr eax,2 ; bytes->dwords
392 mov [ImageDwords
],eax ; boot file dwords
393 add eax,((SECTOR_SIZE
-1) >> 2)
394 shr eax,SECTOR_SHIFT
-2 ; dwords->sectors
395 mov [ImageSectors
],ax ; boot file sectors
397 mov eax,[bi_file
] ; Address of code to load
398 inc eax ; Don't reload bootstrap code
399 %ifdef DEBUG_MESSAGES
406 ; Load the rest of the file. However, just in case there
407 ; are still BIOSes with 64K wraparound problems, we have to
408 ; take some extra precautions. Since the normal load
409 ; address (TEXT_START) is *not* 2K-sector-aligned, we round
410 ; the target address upward to a sector boundary,
411 ; and then move the entire thing down as a unit.
412 MaxLMA
equ 384*1024 ; Reasonable limit (384K)
414 mov bx,((TEXT_START
+2*SECTOR_SIZE
-1) & ~
(SECTOR_SIZE
-1)) >> 4
415 mov bp,[ImageSectors
]
416 push bx ; Load segment address
419 push bx ; Segment address
420 push bp ; Sector count
426 shr cx,SECTOR_SHIFT
- 4
428 mov cx,0x10000 >> SECTOR_SHIFT
; Full 64K segment possible
444 shl cx,SECTOR_SHIFT
- 4
450 ; Move the image into place, and also verify the
452 pop ax ; Load segment address
453 mov bx,(TEXT_START
+ SECTOR_SIZE
) >> 4
454 mov ecx,[ImageDwords
]
455 mov edi,[FirstSecSum
] ; First sector checksum
478 ; Verify the checksum on the loaded image.
487 %ifdef DEBUG_MESSAGES
491 jmp all_read
; Jump to main code
493 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
494 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
495 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
497 ;; There is a problem with certain versions of the AWARD BIOS ...
498 ;; the boot sector will be loaded and executed correctly, but, because the
499 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
500 ;; load the spec packet will fail. We scan for the equivalent of
509 ;; and use <direct far> as the new vector for int 13. The code above is
510 ;; used to load the boot code into ram, and there should be no reason
511 ;; for anybody to change it now or in the future. There are no opcodes
512 ;; that use encodings relativ to IP, so scanning is easy. If we find the
513 ;; code above in the BIOS code we can be pretty sure to run on a machine
514 ;; with an broken AWARD BIOS ...
516 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
518 %ifdef DEBUG_MESSAGES
;;
520 award_notice
db "Trying BrokenAwardHack first ...",CR
,LF
,0 ;;
521 award_not_orig
db "BAH: Original Int 13 vector : ",0 ;;
522 award_not_new
db "BAH: Int 13 vector changed to : ",0 ;;
523 award_not_succ
db "BAH: SUCCESS",CR
,LF
,0 ;;
524 award_not_fail
db "BAH: FAILURE" ;;
525 award_not_crlf
db CR
,LF
,0 ;;
529 award_oldint13
dd 0 ;;
530 award_string
db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah
,80h,1,09ch,09ah ;;
532 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
533 award_hack: mov si,spec_err_msg
; Moved to this place from
534 call writemsg
; spec_query_failed
536 %ifdef DEBUG_MESSAGES
;
538 mov si,award_notice
; display our plan
540 mov si,award_not_orig
; display original int 13
541 call writemsg
; vector
544 mov [award_oldint13
],eax ;
546 %ifdef DEBUG_MESSAGES
;
549 mov si,award_not_crlf
;
550 call writestr_early
;
553 mov ax,0f000h
; ES = BIOS Seg
556 xor di,di ; start at ES:DI = f000:0
557 award_loop: push di ; save DI
558 mov si,award_string
; scan for award_string
559 mov cx,7 ; length of award_string = 7dw
562 jcxz award_found
; jmp if found
563 inc di ; not found, inc di
566 award_failed: pop es ; No, not this way :-((
569 %ifdef DEBUG_MESSAGES
;
571 mov si,award_not_fail
; display failure ...
574 mov eax,[award_oldint13
] ; restore the original int
575 or eax,eax ; 13 vector if there is one
576 jz spec_query_failed
; and try other workarounds
578 jmp spec_query_failed
;
580 award_found: mov eax,[es:di+0eh
] ; load possible int 13 addr
583 cmp eax,[award_oldint13
] ; give up if this is the
584 jz award_failed
; active int 13 vector,
585 mov [13h*4],eax ; otherwise change 0:13h*4
588 %ifdef DEBUG_MESSAGES
;
590 push eax ; display message and
591 mov si,award_not_new
; new vector address
595 mov si,award_not_crlf
;
596 call writestr_early
;
598 mov ax,4B01h ; try to read the spec packet
599 mov dl,[DriveNumber
] ; now ... it should not fail
600 mov si,spec_packet
; any longer
604 %ifdef DEBUG_MESSAGES
;
606 mov si,award_not_succ
; display our SUCCESS
609 jmp found_drive
; and leave error recovery code
611 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
612 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
613 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
616 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
617 ; Try to scan the entire 80h-FFh from the end.
621 ; some code moved to BrokenAwardHack
627 mov byte [si],13h ; Size of buffer
638 cmp byte [sp_drive
],dl
641 ; Okay, good enough...
644 .
found_drive0: mov [DriveNumber
],dl
645 .
found_drive: jmp found_drive
647 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
648 ; but if this was the drive number originally passed in
649 ; DL then consider it "good enough"
655 ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02
656 ; passes garbage in sp_drive, and the drive number originally
657 ; passed in DL does not have 80h bit set.
662 .
still_broken: dec dx
666 ; No spec packet anywhere. Some particularly pathetic
667 ; BIOSes apparently don't even implement function
668 ; 4B01h, so we can't query a spec packet no matter
669 ; what. If we got a drive number in DL, then try to
670 ; use it, and if it works, then well...
672 cmp dl,81h ; Should be 81-FF at least
673 jb fatal_error
; If not, it's hopeless
675 ; Write a warning to indicate we're on *very* thin ice now
683 jmp .found_drive
; Pray that this works...
689 .
norge: jmp short .norge
691 ; Information message (DS:SI) output
692 ; Prefix with "isolinux: "
724 ; Write a character to the screen. There is a more "sophisticated"
725 ; version of this in the subsequent code, so we patch the pointer
741 ; int13: save all the segment registers and call INT 13h.
742 ; Some CD-ROM BIOSes have been found to corrupt segment registers
743 ; and/or disable interrupts.
754 setc [bp+10] ; Propagate CF to the caller
764 ; Get one sector. Convenience entry point.
768 ; Fall through to getlinsec
771 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
774 ; EAX - Linear sector number
775 ; ES:BX - Target buffer
779 getlinsec: jmp word [cs:GetlinsecPtr
]
781 %ifndef DEBUG_MESSAGES
784 ; First, the variants that we use when actually loading off a disk
785 ; (hybrid mode.) These are adapted versions of the equivalent routines
792 ; getlinsec implementation for floppy/HDD EBIOS (EDD)
797 shl eax,2 ; Convert to HDD sectors
803 push bp ; Sectors left
805 call maxtrans
; Enforce maximum transfer size
806 movzx edi,bp ; Sectors we are about to read
823 mov ah,42h ; Extended Read
827 lea sp,[si+16] ; Remove DAPA
830 add eax,edi ; Advance sector pointer
832 sub bp,di ; Sectors left
833 shl di,9 ; 512-byte sectors
834 add bx,di ; Advance buffer pointer
841 ; Some systems seem to get "stuck" in an error state when
842 ; using EBIOS. Doesn't happen when using CBIOS, which is
843 ; good, since some other systems get timeout failures
844 ; waiting for the floppy disk to spin up.
846 pushad ; Try resetting the device
851 loop .retry
; CX-- and jump if not zero
853 ;shr word [MaxTransfer],1 ; Reduce the transfer size
856 ; Total failure. Try falling back to CBIOS.
857 mov word [GetlinsecPtr
], getlinsec_cbios
858 ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer
861 jmp getlinsec_cbios.
loop
866 ; getlinsec implementation for legacy CBIOS
870 shl eax,2 ; Convert to HDD sectors
880 movzx esi,word [bsSecPerTrack
]
881 movzx edi,word [bsHeads
]
883 ; Dividing by sectors to get (track,sector): we may have
884 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
888 xchg cx,dx ; CX <- sector index (0-based)
891 div edi ; Convert track to head/cyl
893 ; We should test this, but it doesn't fit...
898 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
899 ; BP = sectors to transfer, SI = bsSecPerTrack,
900 ; ES:BX = data target
903 call maxtrans
; Enforce maximum transfer size
905 ; Must not cross track boundaries, so BP <= SI-CX
912 shl ah,6 ; Because IBM was STOOPID
913 ; and thought 8 bits were enough
914 ; then thought 10 bits were enough...
915 inc cx ; Sector numbers are 1-based, sigh
920 xchg ax,bp ; Sector to transfer count
921 mov ah,02h ; Read sectors
929 movzx ecx,al ; ECX <- sectors transferred
930 shl ax,9 ; Convert sectors in AL to bytes in AX
945 xchg ax,bp ; Sectors transferred <- 0
946 shr word [MaxTransfer
],1
951 ; Truncate BP to MaxTransfer
962 ; This is the variant we use for real CD-ROMs:
963 ; LBA, 2K sectors, some special error handling.
966 mov si,dapa
; Load up the DAPA
971 push bp ; Sectors left
972 cmp bp,[MaxTransferCD
]
974 mov bp,[MaxTransferCD
]
979 mov ah,42h ; Extended Read
983 movzx eax,word [si+2] ; Sectors we read
984 add [si+8],eax ; Advance sector pointer
985 sub bp,ax ; Sectors left
986 shl ax,SECTOR_SHIFT
-4 ; 2048-byte sectors -> segment
987 add [si+6],ax ; Advance buffer pointer
990 mov eax,[si+8] ; Next sector
994 xint13: mov byte [RetryCount
],retry_count
998 add sp,byte 8*4 ; Clean up stack
1001 mov [DiskError
],ah ; Save error code
1003 mov [DiskSys
],ax ; Save system call number
1004 dec byte [RetryCount
]
1008 mov ah,[dapa
+2] ; Sector transfer count
1009 cmp al,2 ; Only 2 attempts left
1011 mov ah,1 ; Drop transfer size to 1
1014 cmp al,retry_count
-2
1015 ja .again
; First time, just try again
1016 shr ah,1 ; Otherwise, try to reduce
1017 adc ah,0 ; the max transfer size, but not to 0
1019 mov [MaxTransferCD
],ah
1025 .
real_error: mov si,diskerr_msg
1038 ; Fall through to kaboom
1041 ; kaboom: write a message and bail out. Wait for a user keypress,
1042 ; then do a hard reboot.
1047 RESET_STACK_AND_SEGS
AX
1052 mov word [BIOS_magic
],0 ; Cold reboot
1053 jmp 0F000h:0FFF0h
; Reset vector address
1055 ; -----------------------------------------------------------------------------
1056 ; Common modules needed in the first sector
1057 ; -----------------------------------------------------------------------------
1059 %include "writehex.inc" ; Hexadecimal output
1061 ; -----------------------------------------------------------------------------
1062 ; Data that needs to be in the first sector
1063 ; -----------------------------------------------------------------------------
1065 global syslinux_banner
, copyright_str
1066 syslinux_banner
db CR
, LF
, MY_NAME
, ' ', VERSION_STR
, ' ', DATE_STR
, ' ', 0
1067 copyright_str
db ' Copyright (C) 1994-'
1069 db ' H. Peter Anvin et al', CR
, LF
, 0
1070 isolinux_str
db 'isolinux: ', 0
1071 %ifdef DEBUG_MESSAGES
1072 startup_msg: db 'Starting up, DL = ', 0
1073 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
1074 secsize_msg: db 'Sector size ', 0
1075 offset_msg: db 'Main image LBA = ', 0
1076 verify_msg: db 'Image checksum verified.', CR
, LF
, 0
1077 allread_msg
db 'Main image read, jumping to main code...', CR
, LF
, 0
1079 noinfotable_msg
db 'No boot info table, assuming single session disk...', CR
, LF
, 0
1080 noinfoinspec_msg
db 'Spec packet missing LBA information, trying to wing it...', CR
, LF
, 0
1081 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR
, LF
, 0
1082 maybe_msg: db 'Found something at drive = ', 0
1083 alright_msg: db 'Looks reasonable, continuing...', CR
, LF
, 0
1084 nospec_msg
db 'Extremely broken BIOS detected, last attempt with drive = ', 0
1085 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR
, LF
1086 trysbm_msg
db 'See http://syslinux.zytor.com/sbm for more information.', CR
, LF
, 0
1087 diskerr_msg: db 'Disk error ', 0
1088 oncall_str: db ', AX = ',0
1089 ondrive_str: db ', drive ', 0
1090 checkerr_msg: db 'Image checksum error, sorry...', CR
, LF
, 0
1092 err_bootfailed
db CR
, LF
, 'Boot failed: press a key to retry...'
1093 bailmsg
equ err_bootfailed
1097 bios_cdrom_str
db 'ETCD', 0
1098 %ifndef DEBUG_MESSAGES
1099 bios_cbios_str
db 'CHDD', 0
1100 bios_ebios_str
db 'EHDD' ,0
1105 bios_cdrom: dw getlinsec_cdrom
, bios_cdrom_str
1106 %ifndef DEBUG_MESSAGES
1107 bios_cbios: dw getlinsec_cbios
, bios_cbios_str
1108 bios_ebios: dw getlinsec_ebios
, bios_ebios_str
1111 ; Maximum transfer size
1112 MaxTransfer
dw 127 ; Hard disk modes
1113 MaxTransferCD
dw 32 ; CD mode
1115 rl_checkpt
equ $
; Must be <= 800h
1117 ; This pads to the end of sector 0 and errors out on
1119 times
2048-($
-$$
) db 0
1121 ; ----------------------------------------------------------------------------
1122 ; End of code and data that have to be in the first sector
1123 ; ----------------------------------------------------------------------------
1134 ; Common initialization code
1138 ; Tell the user we got this far...
1139 %ifndef DEBUG_MESSAGES
; Gets messy with debugging on
1140 mov si,copyright_str
1145 ; Now we're all set to start with our *real* business. First load the
1146 ; configuration file (if any) and parse it.
1148 ; In previous versions I avoided using 32-bit registers because of a
1149 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
1150 ; random. I figure, though, that if there are any of those still left
1151 ; they probably won't be trying to install Linux on them...
1153 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
1154 ; to take'm out. In fact, we may want to put them back if we're going
1155 ; to boot ELKS at some point.
1159 ; Now, we need to sniff out the actual filesystem data structures.
1160 ; mkisofs gave us a pointer to the primary volume descriptor
1161 ; (which will be at 16 only for a single-session disk!); from the PVD
1162 ; we should be able to find the rest of what we need to know.
1167 mov dl,[DriveNumber
]
1168 cmp word [BIOSType
],bios_cdrom
1169 sete dh ; 1 for cdrom, 0 for hybrid mode
1171 movzx ebp,word [MaxTransferCD
]
1174 movzx ebp,word [MaxTransfer
]
1179 mov di,[bsSecPerTrack
]
1184 jmp kaboom
; load_env32() should never return. If
1185 ; it does, then kaboom!
1197 %ifdef DEBUG_TRACERS
1199 ; debug hack to print a character with minimal code impact
1201 debug_tracer: pushad
1204 mov bx,[bp+9*4] ; Get return address
1205 mov al,[cs:bx] ; Get data byte
1206 inc word [bp+9*4] ; Return to after data byte
1211 %endif
; DEBUG_TRACERS
1215 ThisKbdTo resd
1 ; Temporary holder for KbdTimeout
1216 ThisTotalTo resd
1 ; Temporary holder for TotalTimeout
1217 KernelExtPtr resw
1 ; During search, final null pointer
1218 FuncFlag resb
1 ; Escape sequences received from keyboard
1219 KernelType resb
1 ; Kernel type, from vkernel, if known
1221 KernelName resb FILENAME_MAX
; Mangled name for kernel
1223 global IPAppends
, numIPAppends
1227 IPAppends
dw IPOption
1228 numIPAppends
equ ($
-IPAppends
)/2
1236 ; COMBOOT-loading code
1238 %include "comboot.inc"
1239 %include "com32.inc"
1242 ; Boot sector loading code
1246 ; Abort loading code
1250 ; Hardware cleanup common code
1253 %include "localboot.inc"
1255 ; -----------------------------------------------------------------------------
1257 ; -----------------------------------------------------------------------------
1259 %include "common.inc" ; Universal modules
1261 ; -----------------------------------------------------------------------------
1262 ; Begin data section
1263 ; -----------------------------------------------------------------------------
1266 err_disk_image
db 'Cannot load disk image (invalid file)?', CR
, LF
, 0