summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2005-08-18 20:47:15 +0000
committerhpa <hpa>2005-08-18 20:47:15 +0000
commit47db0904ca61ad48b406053ab3817dfa8f7ee6e4 (patch)
tree41efa1d1b1f283c097b53a4e1a6a28b5f4c4be1a
parentaf0ab3b74f3c489d6ae2730fe5c367e1ae6fb24d (diff)
downloadsyslinux-47db0904ca61ad48b406053ab3817dfa8f7ee6e4.tar.gz
Merge updates to syslinux into extlinux
-rw-r--r--extlinux.asm268
1 files changed, 145 insertions, 123 deletions
diff --git a/extlinux.asm b/extlinux.asm
index 999d4021..73c9f3f0 100644
--- a/extlinux.asm
+++ b/extlinux.asm
@@ -35,7 +35,7 @@ FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size
NULLFILE equ 0 ; Null character == empty filename
NULLOFFSET equ 0 ; Position in which to look
-retry_count equ 6 ; How patient are we with the disk?
+retry_count equ 16 ; How patient are we with the disk?
%assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top
LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with
@@ -301,7 +301,6 @@ not_harddisk:
;
sti
-
;
; Do we have EBIOS (EDD)?
;
@@ -318,7 +317,7 @@ eddcheck:
;
; We have EDD support...
;
- mov byte [getlinsec.jmp+1],getlinsec_ebios-(getlinsec.jmp+2)
+ mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
.noedd:
;
@@ -331,64 +330,13 @@ eddcheck:
call getonesec
; Some modicum of integrity checking
- cmp dword [ldlinux_magic],LDLINUX_MAGIC
- jne kaboom
- cmp dword [ldlinux_magic+4],HEXDATE
+ cmp dword [ldlinux_magic+4],LDLINUX_MAGIC^HEXDATE
jne kaboom
; Go for it...
jmp ldlinux_ent
;
-; kaboom: write a message and bail out.
-;
-kaboom:
- xor si,si
- mov ss,si
- mov sp,StackBuf-4 ; Reset stack
- mov ds,si ; Reset data segment
- pop dword [fdctab] ; Restore FDC table
-.patch: mov si,bailmsg
- call writestr ; Returns with AL = 0
- cbw ; AH <- 0
- int 16h ; Wait for keypress
- int 19h ; And try once more to boot...
-.norge: jmp short .norge ; If int 19h returned; this is the end
-
-;
-;
-; writestr: write a null-terminated string to the console
-; This assumes we're on page 0. This is only used for early
-; messages, so it should be OK.
-;
-writestr:
-.loop: lodsb
- and al,al
- jz .return
- mov ah,0Eh ; Write to screen as TTY
- mov bx,0007h ; Attribute
- int 10h
- jmp short .loop
-.return: ret
-
-;
-; xint13: wrapper for int 13h which will retry 6 times and then die,
-; AND save all registers except BP
-;
-xint13:
-.again:
- mov bp,retry_count
-.loop: pushad
- int 13h
- popad
- jnc writestr.return
- dec bp
- jnz .loop
-.disk_error:
- jmp strict near kaboom ; Patched
-
-
-;
; getonesec: get one disk sector
;
getonesec:
@@ -413,7 +361,9 @@ getonesec:
;
getlinsec:
add eax,[bsHidden] ; Add partition offset
-.jmp: jmp strict short getlinsec_cbios ; This is patched
+ xor edx,edx ; Zero-extend LBA (eventually allow 64 bits)
+
+.jmp: jmp strict short getlinsec_cbios
;
; getlinsec_ebios:
@@ -421,30 +371,66 @@ getlinsec:
; getlinsec implementation for EBIOS (EDD)
;
getlinsec_ebios:
- mov si,dapa ; Load up the DAPA
- mov [si+4],bx
- mov [si+6],es
- mov [si+8],eax
.loop:
push bp ; Sectors left
+.retry2:
call maxtrans ; Enforce maximum transfer size
-.bp_ok:
- mov [si+2],bp
+ movzx edi,bp ; Sectors we are about to read
+ mov cx,retry_count
+.retry:
+
+ ; Form DAPA on stack
+ push edx
+ push eax
+ push es
+ push bx
+ push di
+ push word 16
+ mov si,sp
+ pushad
mov dl,[DriveNumber]
+ push ds
+ push ss
+ pop ds ; DS <- SS
mov ah,42h ; Extended Read
- call xint13
- pop bp
- movzx eax,word [si+2] ; Sectors we read
- add [si+8],eax ; Advance sector pointer
- sub bp,ax ; Sectors left
- shl ax,9 ; 512-byte sectors
- add [si+4],ax ; Advance buffer pointer
+ int 13h
+ pop ds
+ popad
+ lea sp,[si+16] ; Remove DAPA
+ jc .error
+ pop bp
+ add eax,edi ; Advance sector pointer
+ sub bp,di ; Sectors left
+ shl di,SECTOR_SHIFT ; 512-byte sectors
+ add bx,di ; Advance buffer pointer
and bp,bp
jnz .loop
- mov eax,[si+8] ; Next sector
- mov bx,[si+4] ; Buffer pointer
+
ret
+.error:
+ ; Some systems seem to get "stuck" in an error state when
+ ; using EBIOS. Doesn't happen when using CBIOS, which is
+ ; good, since some other systems get timeout failures
+ ; waiting for the floppy disk to spin up.
+
+ pushad ; Try resetting the device
+ xor ax,ax
+ mov dl,[DriveNumber]
+ int 13h
+ popad
+ loop .retry ; CX-- and jump if not zero
+
+ ;shr word [MaxTransfer],1 ; Reduce the transfer size
+ ;jnz .retry2
+
+ ; Total failure. Try falling back to CBIOS.
+ mov byte [getlinsec.jmp+1],(getlinsec_cbios-(getlinsec.jmp+2))
+ ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer
+
+ pop bp
+ ; ... fall through ...
+
;
; getlinsec_cbios:
;
@@ -452,6 +438,7 @@ getlinsec_ebios:
;
getlinsec_cbios:
.loop:
+ push edx
push eax
push bp
push bx
@@ -462,13 +449,17 @@ getlinsec_cbios:
; Dividing by sectors to get (track,sector): we may have
; up to 2^18 tracks, so we need to use 32-bit arithmetric.
;
- xor edx,edx ; Zero-extend LBA to 64 bits
div esi
xor cx,cx
xchg cx,dx ; CX <- sector index (0-based)
; EDX <- 0
; eax = track #
div edi ; Convert track to head/cyl
+
+ ; We should test this, but it doesn't fit...
+ ; cmp eax,1023
+ ; ja .error
+
;
; Now we have AX = cyl, DX = head, CX = sector (0-based),
; BP = sectors to transfer, SI = bsSecPerTrack,
@@ -494,18 +485,61 @@ getlinsec_cbios:
mov dl,[DriveNumber]
xchg ax,bp ; Sector to transfer count
mov ah,02h ; Read sectors
- call xint13
- movzx ecx,al
- shl ax,9 ; Convert sectors in AL to bytes in AX
+ mov bp,retry_count
+.retry:
+ pushad
+ int 13h
+ popad
+ jc .error
+.resume:
+ movzx ecx,al ; ECX <- sectors transferred
+ shl ax,SECTOR_SHIFT ; Convert sectors in AL to bytes in AX
pop bx
add bx,ax
pop bp
pop eax
+ pop edx
add eax,ecx
sub bp,cx
jnz .loop
ret
+.error:
+ dec bp
+ jnz .retry
+
+ xchg ax,bp ; Sectors transferred <- 0
+ shr word [MaxTransfer],1
+ jnz .resume
+ ; Fall through to disk_error
+
+;
+; kaboom: write a message and bail out.
+;
+disk_error:
+kaboom:
+ xor si,si
+ mov ss,si
+ mov sp,StackBuf-4 ; Reset stack
+ mov ds,si ; Reset data segment
+ pop dword [fdctab] ; Restore FDC table
+.patch: ; When we have full code, intercept here
+ mov si,bailmsg
+
+ ; Write error message, this assumes screen page 0
+.loop: lodsb
+ and al,al
+ jz .done
+ mov ah,0Eh ; Write to screen as TTY
+ mov bx,0007h ; Attribute
+ int 10h
+ jmp short .loop
+.done:
+ cbw ; AH <- 0
+ int 16h ; Wait for keypress
+ int 19h ; And try once more to boot...
+.norge: jmp short .norge ; If int 19h returned; this is the end
+
;
; Truncate BP to MaxTransfer
;
@@ -518,31 +552,11 @@ maxtrans:
;
; Error message on failure
;
-bailmsg: db 'Boot failed', 0Dh, 0Ah, 0
-
-;
-; EBIOS disk address packet
-;
- align 4, db 0
-dapa:
- dw 16 ; Packet size
-.count: dw 0 ; Block count
-.off: dw 0 ; Offset of buffer
-.seg: dw 0 ; Segment of buffer
-.lba: dd 0 ; LBA (LSW)
- dd 0 ; LBA (MSW)
-
-
-%if 1
-bs_checkpt_off equ ($-$$)
-%ifndef DEPEND
-%if bs_checkpt_off > 1F8h
-%error "Boot sector overflow"
-%endif
-%endif
+bailmsg: db 'Boot error', 0Dh, 0Ah, 0
+ ; This fails if the boot sector overflows
zb 1F8h-($-$$)
-%endif
+
FirstSector dd 0xDEADBEEF ; Location of sector 1
MaxTransfer dw 0x007F ; Max transfer size
bootsignature dw 0AA55h
@@ -563,7 +577,7 @@ syslinux_banner db 0Dh, 0Ah
align 8, db 0
ldlinux_magic dd LDLINUX_MAGIC
- dd HEXDATE
+ dd LDLINUX_MAGIC^HEXDATE
;
; This area is patched by the installer. It is found by looking for
@@ -597,9 +611,15 @@ ldlinux_ent:
call writestr
;
-; Patch disk error handling
+; Tell the user if we're using EBIOS or CBIOS
;
- mov word [xint13.disk_error+1],do_disk_error-(xint13.disk_error+3)
+print_bios:
+ mov si,cbios_name
+ cmp byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
+ jne .cbios
+ mov si,ebios_name
+.cbios:
+ call writestr
;
; Now we read the rest of LDLINUX.SYS. Don't bother loading the first
@@ -622,9 +642,9 @@ load_rest:
dec cx
jz .chunk_ready
inc edx ; Next linear sector
- cmp [esi],edx ; Does it match
+ cmp [si],edx ; Does it match
jnz .chunk_ready ; If not, this is it
- add esi,4 ; If so, add sector to chunk
+ add si,4 ; If so, add sector to chunk
jmp short .make_chunk
.chunk_ready:
@@ -665,6 +685,22 @@ verify_checksum:
; -----------------------------------------------------------------------------
;
+;
+; writestr: write a null-terminated string to the console
+; This assumes we're on page 0. This is only used for early
+; messages, so it should be OK.
+;
+writestr:
+.loop: lodsb
+ and al,al
+ jz .return
+ mov ah,0Eh ; Write to screen as TTY
+ mov bx,0007h ; Attribute
+ int 10h
+ jmp short .loop
+.return: ret
+
+
; getlinsecsr: save registers, call getlinsec, restore registers
;
getlinsecsr: pushad
@@ -673,29 +709,15 @@ getlinsecsr: pushad
ret
;
-; This routine captures disk errors, and tries to decide if it is
-; time to reduce the transfer size.
+; Checksum error message
;
-do_disk_error:
- cmp ah,42h
- je .ebios
- shr al,1 ; Try reducing the transfer size
- mov [MaxTransfer],al
- jz kaboom ; If we can't, we're dead...
- jmp xint13 ; Try again
-.ebios:
- push ax
- mov ax,[si+2]
- shr ax,1
- mov [MaxTransfer],ax
- mov [si+2],ax
- pop ax
- jmp xint13
+checksumerr_msg db ' Load error - ', 0 ; Boot failed appended
;
-; Checksum error message
+; BIOS type string
;
-checksumerr_msg db 'Load error - ', 0 ; Boot failed appended
+cbios_name db 'CBIOS', 0
+ebios_name db 'EBIOS', 0
;
; Debug routine
@@ -710,7 +732,7 @@ safedumpregs:
rl_checkpt equ $ ; Must be <= 8000h
rl_checkpt_off equ ($-$$)
-%if 0 ; ndef DEPEND
+%ifndef DEPEND
%if rl_checkpt_off > 400h
%error "Sector 1 overflow"
%endif