summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--isolinux.asm58
2 files changed, 54 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 15c26602..52075d0b 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,8 @@ Changes in 1.75:
to guess the maximum transfer size. I am *hoping* this will
cut down on the number of systems for which -s is required
to work at any acceptable speed.
+ * ISOLINUX: Add a few more workarounds for various broken El
+ Torito BIOSes.
Changes in 1.74:
* SYSLINUX: fix bug that would cause valid kernel images to be
diff --git a/isolinux.asm b/isolinux.asm
index 807f707d..1b57a944 100644
--- a/isolinux.asm
+++ b/isolinux.asm
@@ -33,6 +33,7 @@ my_id equ isolinux_id
FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
FILENAME_MAX equ (1 << FILENAME_MAX_LG2)
NULLFILE equ 0 ; Zero byte == null file name
+retry_count equ 6 ; How patient are we wirh the BIOS?
%assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
MAX_OPEN equ (1 << MAX_OPEN_LG2)
@@ -173,6 +174,7 @@ PktTimeout resw 1 ; Timeout for current packet
KernelExtPtr resw 1 ; During search, final null pointer
LocalBootType resw 1 ; Local boot return code
ImageSectors resw 1 ; isolinux.bin size, sectors
+DiskSys resw 1 ; Last INT 13h call
TextAttrBX equ $
TextAttribute resb 1 ; Text attribute for message file
TextPage resb 1 ; Active display page
@@ -434,6 +436,23 @@ spec_query_failed:
cmp dl, 80h
jnb .test_loop
+ ; No spec packet anywhere. Some particularly pathetic
+ ; BIOSes apparently don't even implement function
+ ; 4B01h, so we can't query a spec packet no matter
+ ; what. If we got a drive number in DL, then try to
+ ; use it, and if it works, then well...
+ mov dl,[DriveNo]
+ cmp dl,81h ; Should be 81-FF at least
+ jb fatal_error ; If not, it's hopeless
+
+ ; Write a warning to indicate we're on *very* thin ice now
+ mov si,nospec_msg
+ call writemsg
+ mov al,dl
+ call writehex2
+ call crlf
+ jmp .found_drive ; Pray that this works...
+
fatal_error:
mov si,nothing_msg
call writemsg
@@ -498,9 +517,9 @@ getlinsec:
mov [si+8],eax
.loop:
push bp ; Sectors left
- cmp bp,byte 32
+ cmp bp,[MaxTransfer]
jbe .bp_ok
- mov bp,32
+ mov bp,[MaxTransfer]
.bp_ok:
mov [si+2],bp
push si
@@ -520,21 +539,45 @@ getlinsec:
ret
; INT 13h with retry
-xint13: mov byte [RetryCount], 6
+xint13: mov byte [RetryCount],retry_count
.try: pushad
int 13h
jc .error
add sp,byte 8*4 ; Clean up stack
ret
-.error: mov [DiskError],ah ; Save error code
+.error:
+ mov [DiskError],ah ; Save error code
popad
+ mov [DiskSys],ax ; Save system call number
dec byte [RetryCount]
- jnz .try
+ jz .real_error
+ push ax
+ mov al,[RetryCount]
+ mov ah,[dapa+2] ; Sector transfer count
+ cmp al,2 ; Only 2 attempts left
+ ja .nodanger
+ mov ah,1 ; Drop transfer size to 1
+ jmp short .setsize
+.nodanger:
+ cmp al,retry_count-2
+ ja .again ; First time, just try again
+ shr ah,1 ; Otherwise, try to reduce
+ adc ah,0 ; the max transfer size, but not to 0
+.setsize:
+ mov [MaxTransfer],ah
+ mov [dapa+2],ah
+.again:
+ pop ax
+ jmp .try
.real_error: mov si,diskerr_msg
call writemsg
mov al,[DiskError]
call writehex2
+ mov si,oncall_str
+ call writestr
+ mov ax,[DiskSys]
+ call writehex4
mov si,ondrive_str
call writestr
mov al,dl
@@ -590,8 +633,10 @@ allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
maybe_msg: db 'Found something at drive = ', 0
alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
+nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
nosecsize_msg: db 'Failed to get sector size, assuming 0800', CR, LF, 0
diskerr_msg: db 'Disk error ', 0
+oncall_str: db ', AX = ',0
ondrive_str: db ', drive ', 0
nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF, 0
checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
@@ -667,7 +712,8 @@ dapa: dw 16 ; Packet size
dd 0 ; LBA (MSW)
alignb 4, db 0
-Stack dw _start, 0 ; SS:SP for stack reset
+Stack dw _start, 0 ; SS:SP for stack reset
+MaxTransfer dw 32 ; Max sectors per transfer
rl_checkpt equ $ ; Must be <= 800h