summaryrefslogtreecommitdiff
path: root/ldlinux.asm
diff options
context:
space:
mode:
Diffstat (limited to 'ldlinux.asm')
-rw-r--r--ldlinux.asm227
1 files changed, 120 insertions, 107 deletions
diff --git a/ldlinux.asm b/ldlinux.asm
index a8048119..02521e91 100644
--- a/ldlinux.asm
+++ b/ldlinux.asm
@@ -311,7 +311,6 @@ not_harddisk:
;
sti
-
;
; Do we have EBIOS (EDD)?
;
@@ -328,7 +327,8 @@ eddcheck:
;
; We have EDD support...
;
- mov byte [getlinsec.jmp+1],getlinsec_ebios-(getlinsec.jmp+2)
+ ; 0xEB = short jump
+ mov word [getlinsec_cbios],((getlinsec_ebios-(getlinsec_cbios+2)) << 8) + 0xeb
.noedd:
;
@@ -341,48 +341,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.
-;
-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: 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
-
-;
; getonesec: get one disk sector
;
getonesec:
@@ -407,69 +372,9 @@ getonesec:
;
getlinsec:
add eax,[bsHidden] ; Add partition offset
-.jmp: jmp strict short getlinsec_cbios ; This is patched
-
-;
-; getlinsec_ebios:
-;
-; getlinsec implementation for EBIOS (EDD)
-;
-getlinsec_ebios:
-.loop:
- push bp ; Sectors left
- call maxtrans ; Enforce maximum transfer size
- movzx ecx,bp ; Sectors we are about to read
- mov bp,retry_count
-.retry:
-
- ; Form DAPA on stack
- push dword 0
- push eax
- push es
- push cx
- push bp
- push word 16
- mov si,sp
- mov dl,[DriveNumber]
- mov ah,42h ; Extended Read
- push ds
- push ss
- pop ds ; DS <- SS
- pushad
- int 13h
- popad
- pop ds
- lea sp,[si+16] ; Remove DAPA
- pop bp
- jc .error
-
- add eax,ecx ; Advance sector pointer
- sub bp,cx ; Sectors left
- shl cx,SECTOR_SHIFT ; 512-byte sectors
- add bx,cx ; Advance buffer pointer
- and bp,bp
- jnz .loop
-
- 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
- int 13h
- popad
- dec bp
- jnz .retry
-
- shr word [MaxTransfer],1 ; Reduce the transfer size
- jnz .loop
-
- jmp disk_error
+ xor edx,edx ; Zero-extend LBA (eventually allow 64 bits)
+ ; Fall through. In the case of EBIOS, we patch over the first instruction.
;
; getlinsec_cbios:
;
@@ -477,6 +382,7 @@ getlinsec_ebios:
;
getlinsec_cbios:
.loop:
+ push edx
push eax
push bp
push bx
@@ -487,13 +393,14 @@ 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
@@ -529,12 +436,13 @@ getlinsec_cbios:
popad
jc .error
.resume:
- movzx ecx,al
- shl ax,9 ; Convert sectors in AL to bytes in AX
+ 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
@@ -546,11 +454,99 @@ getlinsec_cbios:
xor ax,ax ; Sectors transferred <- 0
shr word [MaxTransfer],1
- jnz .resume
-
+ jnz .error
jmp disk_error
;
+; getlinsec_ebios:
+;
+; getlinsec implementation for EBIOS (EDD)
+;
+getlinsec_ebios:
+.loop:
+ push bp ; Sectors left
+.retry2:
+ call maxtrans ; Enforce maximum transfer size
+ 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
+ mov dl,[DriveNumber]
+ mov ah,42h ; Extended Read
+ push ds
+ push ss
+ pop ds ; DS <- SS
+ pushad
+ int 13h
+ popad
+ pop ds
+ 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
+
+ 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
+ int 13h
+ popad
+ loop .retry ; CX-- and jump if not zero
+
+ shr word [MaxTransfer],1 ; Reduce the transfer size
+ jnz .retry2
+
+ ; Fall back to CBIOS here?
+
+ ; 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
;
maxtrans:
@@ -559,10 +555,11 @@ maxtrans:
mov bp,[MaxTransfer]
.ok: ret
+
;
; Error message on failure
;
-bailmsg: db 'ERR', 0Dh, 0Ah, 0
+bailmsg: db 'Boot failed', 0Dh, 0Ah, 0
%if 1
bs_checkpt_off equ ($-$$)
@@ -598,7 +595,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
@@ -694,6 +691,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