aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFeng Tang <feng.tang@intel.com>2010-07-14 15:55:25 +0800
committerFeng Tang <feng.tang@intel.com>2010-07-20 11:10:05 +0800
commit2e91ec5f155f04aee878ed70a04fb5b15e40da3b (patch)
tree205b2d002e4a1e933fc7fbaa1f05aa3d8ed6d75b
parent29f87cf47dd49d5bb715722329c45260a571214c (diff)
downloadsyslinux-2e91ec5f155f04aee878ed70a04fb5b15e40da3b.tar.gz
syslinux-2e91ec5f155f04aee878ed70a04fb5b15e40da3b.tar.xz
syslinux-2e91ec5f155f04aee878ed70a04fb5b15e40da3b.zip
elflink: a lot of core/fs merge
As: modified: core/Makefile modified: core/adv.inc modified: core/call16.c modified: core/callback.inc modified: core/comboot.inc modified: core/diskstart.inc deleted: core/extlinux.asm modified: core/include/core.h modified: core/isolinux.asm modified: core/ldlinux.asm modified: core/pmapi.c modified: core/timer.inc modified: elf_gen_dep.sh
-rw-r--r--core/Makefile7
-rw-r--r--core/adv.inc42
-rw-r--r--core/call16.c18
-rw-r--r--core/callback.inc13
-rw-r--r--core/comboot.inc14
-rw-r--r--core/diskstart.inc599
-rw-r--r--core/extlinux.asm38
-rw-r--r--core/include/core.h6
-rw-r--r--core/isolinux.asm32
-rw-r--r--core/ldlinux.asm4
-rw-r--r--core/pmapi.c8
-rw-r--r--core/timer.inc15
-rwxr-xr-xelf_gen_dep.sh2
13 files changed, 458 insertions, 340 deletions
diff --git a/core/Makefile b/core/Makefile
index 8c675c26..54848f28 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -33,7 +33,6 @@ CODEPAGE = cp865
# The targets to build in this directory...
BTARGET = kwdhash.gen \
- extlinux.bin extlinux.bss extlinux.sys \
ldlinux.bss ldlinux.sys ldlinux.bin \
isolinux.bin isolinux-debug.bin pxelinux.0
@@ -110,12 +109,6 @@ ldlinux.bss: ldlinux.bin
ldlinux.sys: ldlinux.bin
dd if=$< of=$@ bs=512 skip=1
-extlinux.bss: extlinux.bin
- dd if=$< of=$@ bs=512 count=1
-
-extlinux.sys: extlinux.bin
- dd if=$< of=$@ bs=512 skip=1
-
codepage.cp: ../codepage/$(CODEPAGE).cp
cp -f $< $@
diff --git a/core/adv.inc b/core/adv.inc
index 67252619..0b45a6c7 100644
--- a/core/adv.inc
+++ b/core/adv.inc
@@ -71,18 +71,12 @@ adv_init:
cmp word [ADVSectors],2 ; Not present?
jb adv_verify
- ;
- ; Update pointers to default ADVs...
- ;
- mov bx,[DataSectors]
- shl bx,2
- mov ecx,[bsHidden]
- mov eax,[bx+SectorPtrs-4]; First ADV sector
- mov edx,[bx+SectorPtrs] ; Second ADV sector
- add eax,ecx
- add edx,ecx
- mov [ADVSec0],eax
- mov [ADVSec1],edx
+ mov eax,[Hidden]
+ mov edx,[Hidden+4]
+ add [ADVSec0],eax
+ adc [ADVSec0+4],edx
+ add [ADVSec1],eax
+ adc [ADVSec1+4],edx
mov al,[DriveNumber]
mov [ADVDrive],al
jmp adv_read
@@ -300,23 +294,26 @@ adv_cleanup:
; Returns CF=1 if the ADV cannot be written.
;
adv_write:
- cmp dword [ADVSec0],0
+ push eax
+ mov eax,[ADVSec0]
+ or eax,[ADVSec0+4]
je .bad
- cmp dword [ADVSec1],0
+ mov eax,[ADVSec1]
+ or eax,[ADVSec1+4]
je .bad
cmp byte [ADVDrive],-1
je .bad
- push ax
call adv_cleanup
mov ah,3 ; Write
call adv_read_write
- pop ax
clc
+ pop eax
ret
.bad: ; No location for ADV set
stc
+ pop eax
ret
;
@@ -358,10 +355,12 @@ adv_read_write:
.noedd:
mov eax,[ADVSec0]
+ mov edx,[ADVSec0+4]
mov bx,adv0
call .doone
mov eax,[ADVSec1]
+ mov edx,[ADVSec1+4]
mov bx,adv1
call .doone
@@ -369,7 +368,6 @@ adv_read_write:
ret
.doone:
- xor edx,edx ; Zero-extend LBA
push si
jmp si
@@ -409,6 +407,9 @@ adv_read_write:
push eax
push bp
+ and edx,edx ; > 2 TiB not possible
+ jnz .cb_overflow
+
mov dl,[ADVDrive]
and dl,dl
; Floppies: can't trust INT 13h 08h, we better know
@@ -445,6 +446,7 @@ adv_read_write:
; 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
div esi
xor cx,cx
xchg cx,dx ; CX <- sector index (0-based)
@@ -495,9 +497,9 @@ adv_read_write:
jmp .cb_done
section .data16
- alignz 4
-ADVSec0 dd 0 ; Not specified
-ADVSec1 dd 0 ; Not specified
+ alignz 8
+ADVSec0 dq 0 ; Not specified
+ADVSec1 dq 0 ; Not specified
ADVDrive db -1 ; No ADV defined
ADVCHSInfo db -1 ; We have CHS info for this drive
diff --git a/core/call16.c b/core/call16.c
index 86d70461..095f814f 100644
--- a/core/call16.c
+++ b/core/call16.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,11 +17,25 @@
*/
#include <stddef.h>
+#include <stdio.h>
#include "core.h"
const com32sys_t zero_regs; /* Common all-zero register set */
+static inline uint32_t eflags(void)
+{
+ uint32_t v;
+
+ asm volatile("pushfl ; popl %0" : "=rm" (v));
+ return v;
+}
+
void call16(void (*func)(void), const com32sys_t *ireg, com32sys_t *oreg)
{
- core_farcall((size_t)func, ireg, oreg);
+ com32sys_t xreg = *ireg;
+
+ /* Enable interrupts if and only if they are enabled in the caller */
+ xreg.eflags.l = (xreg.eflags.l & ~EFLAGS_IF) | (eflags() & EFLAGS_IF);
+
+ core_farcall((size_t)func, &xreg, oreg);
}
diff --git a/core/callback.inc b/core/callback.inc
index a33b5825..d98d8008 100644
--- a/core/callback.inc
+++ b/core/callback.inc
@@ -74,7 +74,7 @@ core_syscall:
mov eax,.rm_return ; Return seg:offs
stosd ; Save in stack frame
mov eax,[edi-12] ; Return flags
- and eax,0x200cd7 ; Mask (potentially) unsafe flags
+ and eax,0x200ed7 ; Mask (potentially) unsafe flags
mov [edi-12],eax ; Primary flags entry
stosw ; Return flags
@@ -84,13 +84,15 @@ core_syscall:
bits 16
section .text16
.rm:
+ mov ax,sp
+ add ax,9*4+4*2
+ mov [CallbackSP],ax
pop gs
pop fs
pop es
pop ds
popad
popfd
- mov [cs:CallbackSP],sp
retf ; Invoke routine
.rm_return:
@@ -138,6 +140,7 @@ core_syscall:
;
; Cfarcall invocation. We copy the stack frame to the real-mode stack,
; followed by the return CS:IP and the CS:IP of the target function.
+; The value of IF is copied from the calling routine.
;
global core_cfarcall
core_cfarcall:
@@ -156,11 +159,14 @@ core_cfarcall:
mov [word CallbackSP],di
sub edi,ecx ; Allocate space for stack frame
and edi,~3 ; Round
- sub edi,4*2 ; Return pointer, return value
+ sub edi,4*3 ; Return pointer, return value, EFLAGS
mov [word RealModeSSSP],di
shl ebx,4
add edi,ebx ; Create linear address
+ mov eax,[esp+5*4] ; EFLAGS from entry
+ and eax,0x202 ; IF only
+ stosd
mov eax,[esp+7*4] ; CS:IP
stosd ; Save to stack frame
mov eax,.rm_return ; Return seg:off
@@ -179,6 +185,7 @@ core_cfarcall:
bits 16
section .text16
.rm:
+ popfd
retf
.rm_return:
mov sp,[cs:CallbackSP]
diff --git a/core/comboot.inc b/core/comboot.inc
index 0c9956a0..59db7ec1 100644
--- a/core/comboot.inc
+++ b/core/comboot.inc
@@ -1,7 +1,7 @@
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -593,6 +593,8 @@ comapi_derinfo:
mov P_DL,al
mov P_FS,cs
mov P_SI,OrigESDI
+ mov P_GS,cs
+ mov P_DI,Hidden
%if IS_SYSLINUX || IS_EXTLINUX
mov P_ES,cs
mov P_BX,PartInfo
@@ -751,11 +753,11 @@ comapi_runkernel:
; It's not just possible, but quite likely, that ES:BX
; points into real_mode_seg or xfer_buf_seg, so we
; need to exercise some special care here... use
- ; vk_append for temporary storage.
+ ; VKernelBuf for temporary storage.
push ds
mov ds,P_ES
mov si,P_BX
- mov di,vk_append
+ mov di,VKernelBuf
call strcpy
pop ds
@@ -784,7 +786,7 @@ comapi_runkernel:
push es
mov dx,real_mode_seg
mov es,dx
- mov si,vk_append
+ mov si,VKernelBuf
mov di,cmd_line_here
call strcpy
mov word [es:di-1],' ' ; Simulate APPEND: space plus null
@@ -837,10 +839,10 @@ comapi_userfont:
;
%if IS_SYSLINUX || IS_ISOLINUX || IS_EXTLINUX
comapi_readdisk:
- mov esi,P_ESI ; Enforce ESI == EDI == 0, these
- or esi,P_EDI ; are reserved for future expansion
+ cmp P_EDI,0 ; Reserved for future expansion
jnz .err
mov eax,P_EDX
+ mov edx,P_ESI
mov es,P_ES
mov bx,P_BX
mov bp,P_CX ; WE CANNOT use P_* after touching bp!
diff --git a/core/diskstart.inc b/core/diskstart.inc
index 4084ff78..c61a615f 100644
--- a/core/diskstart.inc
+++ b/core/diskstart.inc
@@ -17,24 +17,25 @@
; Common early-bootstrap code for harddisk-based Syslinux derivatives.
;
- ; Expanded superblock
- section .earlybss
- alignb 8
-SuperInfo resq 16 ; The first 16 bytes expanded 8 times
-DriveNumber resb 1
-
section .init
;
; Some of the things that have to be saved very early are saved
; "close" to the initial stack pointer offset, in order to
; reduce the code size...
;
-StackBuf equ STACK_TOP-44-32 ; Start the stack here (grow down - 4K)
-PartInfo equ StackBuf ; Saved partition table entry
-FloppyTable equ PartInfo+16 ; Floppy info table (must follow PartInfo)
-OrigFDCTabPtr equ StackBuf-8 ; The 2nd high dword on the stack
-OrigESDI equ StackBuf-4 ; The high dword on the stack
-StackHome equ OrigFDCTabPtr ; The start of the canonical stack
+
+StackBuf equ STACK_TOP-44-92 ; Start the stack here (grow down - 4K)
+PartInfo equ StackBuf
+.mbr equ PartInfo
+.gptlen equ PartInfo+16
+.gpt equ PartInfo+20
+FloppyTable equ PartInfo+76
+; Total size of PartInfo + FloppyTable == 76+16 = 92 bytes
+Hidden equ StackBuf-20 ; Partition offset
+OrigFDCTabPtr equ StackBuf-12 ; The 2nd high dword on the stack
+OrigESDI equ StackBuf-8 ; The high dword on the stack
+DriveNumber equ StackBuf-4 ; Drive number
+StackHome equ Hidden ; The start of the canonical stack
;
; Primary entry point. Tempting as though it may be, we can't put the
@@ -98,6 +99,7 @@ superblock_max equ $-superblock
global SecPerClust
SecPerClust equ bxSecPerClust
+
;
; Note we don't check the constraints above now; we did that at install
; time (we hope!)
@@ -108,20 +110,24 @@ start:
;
; Set up the stack
;
- xor ax,ax
- mov ss,ax
- mov sp,StackBuf ; Just below BSS
+ xor cx,cx
+ mov ss,cx
+ mov sp,StackBuf-2 ; Just below BSS (-2 for alignment)
+ push dx ; Save drive number (in DL)
push es ; Save initial ES:DI -> $PnP pointer
push di
- mov es,ax
+ mov es,cx
+
;
-; DS:SI may contain a partition table entry. Preserve it for us.
+; DS:SI may contain a partition table entry and possibly a GPT entry.
+; Preserve it for us. This saves 56 bytes of the GPT entry, which is
+; currently the maximum we care about. Total is 76 bytes.
;
- mov cx,8 ; Save partition info
+ mov cl,(16+4+56)/2 ; Save partition info
mov di,PartInfo
- rep movsw
+ rep movsw ; This puts CX back to zero
- mov ds,ax ; Now we can initialize DS...
+ mov ds,cx ; Now we can initialize DS...
;
; Now sautee the BIOS floppy info block to that it will support decent-
@@ -138,12 +144,12 @@ start:
; Save the old fdctab even if hard disk so the stack layout
; is the same. The instructions above do not change the flags
- mov [DriveNumber],dl ; Save drive number in DL
and dl,dl ; If floppy disk (00-7F), assume no
; partition table
js harddisk
floppy:
+ xor ax,ax
mov cl,6 ; 12 bytes (CX == 0)
; es:di -> FloppyTable already
; This should be safe to do now, interrupts are off...
@@ -151,26 +157,49 @@ floppy:
mov [bx+2],ax ; Segment 0
fs rep movsw ; Faster to move words
mov cl,[bsSecPerTrack] ; Patch the sector count
- mov [di-8],cl
- ; AX == 0 here
- int 13h ; Some BIOSes need this
+ mov [di-76+8],cl
+
+ push ax ; Partition offset == 0
+ push ax
+ push ax
+ push ax
+ int 13h ; Some BIOSes need this
jmp short not_harddisk
;
; The drive number and possibly partition information was passed to us
; by the BIOS or previous boot loader (MBR). Current "best practice" is to
; trust that rather than what the superblock contains.
;
-; Would it be better to zero out bsHidden if we don't have a partition table?
-;
; Note: di points to beyond the end of PartInfo
;
harddisk:
- test byte [di-16],7Fh ; Sanity check: "active flag" should
- jnz no_partition ; be 00 or 80
- mov eax,[di-8] ; Partition offset (dword)
- mov [bsHidden],eax
-no_partition:
+ test byte [di-76],7Fh ; Sanity check: "active flag" should
+ jnz .no_partition ; be 00 or 80
+ cmp [di-76+4],cl ; Sanity check: partition type != 0
+ je .no_partition
+ cmp eax,'!GPT' ; !GPT signature?
+ jne .mbr
+ cmp byte [di-76+4],0EDh ; Synthetic GPT partition entry?
+ jne .mbr
+.gpt: ; GPT-style partition info
+ push dword [di-76+20+36]
+ push dword [di-76+20+32]
+ jmp .gotoffs
+.mbr: ; MBR-style partition info
+ push cx ; Upper half partition offset == 0
+ push cx
+ push dword [di-76+8] ; Partition offset (dword)
+ jmp .gotoffs
+.no_partition:
+;
+; No partition table given... assume that the Hidden field in the boot sector
+; tells the truth (in particular, is zero if this is an unpartitioned disk.)
+;
+ push cx
+ push cx
+ push dword [bsHidden]
+.gotoffs:
;
; Get disk drive parameters (don't trust the superblock.) Don't do this for
; floppy drives -- INT 13:08 on floppy drives will (may?) return info about
@@ -211,7 +240,7 @@ eddcheck:
;
; We have EDD support...
;
- mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
+ mov byte [getonesec.jmp+1],(getonesec_ebios-(getonesec.jmp+2))
.noedd:
;
@@ -219,7 +248,10 @@ eddcheck:
; with parsing the superblock and root directory; it doesn't fit
; together with EBIOS support, unfortunately.
;
- mov eax,[FirstSector] ; Sector start
+ mov eax,strict dword 0xdeadbeef
+Sect1Ptr0 equ $-4
+ mov edx,strict dword 0xfeedface
+Sect1Ptr1 equ $-4
mov bx,ldlinux_sys ; Where to load it
call getonesec
@@ -228,79 +260,46 @@ eddcheck:
jne kaboom
; Go for it...
- jmp ldlinux_ent
+ jmp 0:ldlinux_ent
-;
-; getonesec: get one disk sector
-;
-getonesec:
- mov bp,1 ; One sector
- ; Fall through
;
-; getlinsec: load a sequence of BP floppy sector given by the linear sector
-; number in EAX into the buffer at ES:BX. We try to optimize
-; by loading up to a whole track at a time, but the user
-; is responsible for not crossing a 64K boundary.
-; (Yes, BP is weird for a count, but it was available...)
+; getonesec: load a single disk linear sector EDX:EAX into the buffer
+; at ES:BX.
;
-; On return, BX points to the first byte after the transferred
-; block.
-;
-; This routine assumes CS == DS, and trashes most registers.
+; This routine assumes CS == DS == SS, and trashes most registers.
;
; Stylistic note: use "xchg" instead of "mov" when the source is a register
; that is dead from that point; this saves space. However, please keep
; the order to dst,src to keep things sane.
;
- global getlinsec
-getlinsec:
- add eax,[bsHidden] ; Add partition offset
- xor edx,edx ; Zero-extend LBA (eventually allow 64 bits)
-
-.jmp: jmp strict short getlinsec_cbios
+getonesec:
+ add eax,[Hidden] ; Add partition offset
+ adc edx,[Hidden+4]
+ mov cx,retry_count
+.jmp: jmp strict short getonesec_cbios
;
-; getlinsec_ebios:
+; getonesec_ebios:
;
-; getlinsec implementation for EBIOS (EDD)
+; getonesec 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
+getonesec_ebios:
.retry:
-
; Form DAPA on stack
push edx
push eax
push es
push bx
- push di
+ push word 1
push word 16
mov si,sp
pushad
- mov dl,[DriveNumber]
- push ds
- push ss
- pop ds ; DS <- SS
mov ah,42h ; Extended Read
- int 13h
- pop ds
+ call xint13
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
-
ret
.error:
@@ -311,32 +310,21 @@ getlinsec_ebios:
pushad ; Try resetting the device
xor ax,ax
- mov dl,[DriveNumber]
- int 13h
+ call xint13
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 ...
+ mov byte [getonesec.jmp+1],(getonesec_cbios-(getonesec.jmp+2))
;
-; getlinsec_cbios:
+; getonesec_cbios:
;
; getlinsec implementation for legacy CBIOS
;
-getlinsec_cbios:
-.loop:
- push edx
- push eax
- push bp
- push bx
+getonesec_cbios:
+.retry:
+ pushad
movzx esi,word [bsSecPerTrack]
movzx edi,word [bsHeads]
@@ -351,25 +339,13 @@ getlinsec_cbios:
; eax = track #
div edi ; Convert track to head/cyl
- ; We should test this, but it doesn't fit...
- ; cmp eax,1023
- ; ja .error
+ cmp eax,1023 ; Outside the CHS range?
+ ja kaboom
;
; Now we have AX = cyl, DX = head, CX = sector (0-based),
- ; BP = sectors to transfer, SI = bsSecPerTrack,
- ; ES:BX = data target
+ ; SI = bsSecPerTrack, ES:BX = data target
;
-
- call maxtrans ; Enforce maximum transfer size
-
- ; Must not cross track boundaries, so BP <= SI-CX
- sub si,cx
- cmp bp,si
- jna .bp_ok
- mov bp,si
-.bp_ok:
-
shl ah,6 ; Because IBM was STOOPID
; and thought 8 bits were enough
; then thought 10 bits were enough...
@@ -377,35 +353,14 @@ getlinsec_cbios:
or cl,ah
mov ch,al
mov dh,dl
- mov dl,[DriveNumber]
- xchg ax,bp ; Sector to transfer count
- mov ah,02h ; Read sectors
- mov bp,retry_count
-.retry:
- pushad
- int 13h
+ mov ax,0201h ; Read one sector
+ call xint13
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
+ loop .retry
; Fall through to disk_error
;
@@ -421,47 +376,51 @@ kaboom:
pop dword [fdctab] ; Restore FDC table
.patch: ; When we have full code, intercept here
mov si,bailmsg
+ call writestr_early
- ; Write error message, this assumes screen page 0
+ xor ax,ax
+.again: int 16h ; Wait for keypress
+ ; NB: replaced by int 18h if
+ ; chosen at install time..
+ int 19h ; And try once more to boot...
+.norge: hlt ; If int 19h returned; this is the end
+ jmp short .norge
+
+;
+;
+; writestr_early: 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_early:
+ pushad
.loop: lodsb
and al,al
- jz .done
+ jz .return
mov ah,0Eh ; Write to screen as TTY
mov bx,0007h ; Attribute
int 10h
jmp short .loop
-.done:
- cbw ; AH <- 0
-.again: int 16h ; Wait for keypress
- ; NB: replaced by int 18h if
- ; chosen at install time..
- int 19h ; And try once more to boot...
-.norge: jmp short .norge ; If int 19h returned; this is the end
+.return: popad
+ ret
;
-; Truncate BP to MaxTransfer
+; INT 13h wrapper function
;
-maxtrans:
- cmp bp,[MaxTransfer]
- jna .ok
- mov bp,[MaxTransfer]
-.ok: ret
+xint13:
+ mov dl,[DriveNumber]
+ int 13h
+ ret
;
; Error message on failure
;
bailmsg: db 'Boot error', 0Dh, 0Ah, 0
- ; This fails if the boot sector overflows
- zb 1F8h-($-$$)
+ ; This fails if the boot sector overflowsg
+ zb 1FEh-($-$$)
-FirstSector dd 0xDEADBEEF ; Location of sector 1
-MaxTransfer dw 0x007F ; Max transfer size
-
-; This field will be filled in 0xAA55 by the installer, but we abuse it
-; to house a pointer to the INT 16h instruction at
-; kaboom.again, which gets patched to INT 18h in RAID mode.
-bootsignature dw kaboom.again-bootsec
+bootsignature dw 0xAA55
;
; ===========================================================================
@@ -493,24 +452,41 @@ ADVSectors dw 0 ; Additional sectors for ADVs
LDLDwords dd 0 ; Total dwords starting at ldlinux_sys,
CheckSum dd 0 ; Checksum starting at ldlinux_sys
; value = LDLINUX_MAGIC - [sum of dwords]
+MaxTransfer dw 127 ; Max sectors to transfer
+EPAPtr dw EPA - LDLINUX_SYS ; Pointer to the extended patch area
+
+;
+; Extended patch area -- this is in .data16 so it doesn't occupy space in
+; the first sector. Use this structure for anything that isn't used by
+; the first sector itself.
+;
+ section .data16
+ alignz 2
+EPA:
+ADVSecPtr dw ADVSec0 - LDLINUX_SYS
CurrentDirPtr dw CurrentDirName-LDLINUX_SYS ; Current directory name string
CurrentDirLen dw CURRENTDIR_MAX
SubvolPtr dw SubvolName-LDLINUX_SYS
SubvolLen dw SUBVOL_MAX
SecPtrOffset dw SectorPtrs-LDLINUX_SYS
-SecPtrCnt dw (SectorPtrsEnd - SectorPtrs) >> 2
+SecPtrCnt dw (SectorPtrsEnd - SectorPtrs)/10
+
+;
+; Boot sector patch pointers
+;
+Sect1Ptr0Ptr dw Sect1Ptr0 - bootsec ; Pointers to Sector 1 location
+Sect1Ptr1Ptr dw Sect1Ptr1 - bootsec
+RAIDPatchPtr dw kaboom.again - bootsec ; Patch to INT 18h in RAID mode
;
-; Installer pokes the base directory here. This is in .data16 so it
-; isn't actually located in the first sector.
+; Base directory name and subvolume, if applicable.
;
%define HAVE_CURRENTDIRNAME
- section .data16
global CurrentDirName, SubvolName
CurrentDirName times CURRENTDIR_MAX db 0
SubvolName times SUBVOL_MAX db 0
- section .init
+ section .init
ldlinux_ent:
;
; Note that some BIOSes are buggy and run the boot sector at 07C0:0000
@@ -519,8 +495,6 @@ ldlinux_ent:
; value in CS, but we don't want to deal with that anymore from now
; on.
;
- jmp 0:.next
-.next:
sti ; In case of broken INT 13h BIOSes
;
@@ -530,13 +504,26 @@ ldlinux_ent:
call writestr_early
;
+; Checksum data thus far
+;
+ mov si,ldlinux_sys
+ mov cx,SECTOR_SIZE >> 2
+ mov edx,-LDLINUX_MAGIC
+.checksum:
+ lodsd
+ add edx,eax
+ loop .checksum
+ mov [CheckSum],edx ; Save intermediate result
+
+;
; Tell the user if we're using EBIOS or CBIOS
;
print_bios:
mov si,cbios_name
- cmp byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
+ cmp byte [getonesec.jmp+1],(getonesec_ebios-(getonesec.jmp+2))
jne .cbios
mov si,ebios_name
+ mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
.cbios:
mov [BIOSName],si
call writestr_early
@@ -547,8 +534,7 @@ BIOSName resw 1
section .init
;
-; Now we read the rest of LDLINUX.SYS. Don't bother loading the first
-; sector again, though.
+; Now we read the rest of LDLINUX.SYS.
;
load_rest:
lea esi,[SectorPtrs]
@@ -558,37 +544,19 @@ load_rest:
.get_chunk:
jcxz .done
- xor ebp,ebp
- mov di,bx ; Low 64K of target address
- lodsd ; First sector of this chunk
-
- mov edx,eax
-
-.make_chunk:
- inc bp
- dec cx
- jz .chunk_ready
- cmp ebx,esi ; Pointer we don't have yet?
- jae .chunk_ready
- inc edx ; Next linear sector
- cmp [si],edx ; Does it match
- jnz .chunk_ready ; If not, this is it
- add si,4 ; If so, add sector to chunk
- add di,SECTOR_SIZE ; Check for 64K segment wrap
- jnz .make_chunk
-
-.chunk_ready:
+ mov eax,[si]
+ mov edx,[si+4]
+ movzx ebp,word [si+8]
+ sub cx,bp
push ebx
- push es
shr ebx,4 ; Convert to a segment
mov es,bx
xor bx,bx
- xor edx,edx ; Zero-extend LBA
- call getlinsecsr
- pop es
+ call getlinsec
pop ebx
shl ebp,SECTOR_SHIFT
add ebx,ebp
+ add si,10
jmp .get_chunk
.done:
@@ -599,10 +567,10 @@ load_rest:
; by the time we get to the end it should all cancel out.
;
verify_checksum:
- mov si,ldlinux_sys
+ mov si,ldlinux_sys + SECTOR_SIZE
mov ecx,[LDLDwords]
- mov eax,-LDLINUX_MAGIC
- push ds
+ sub ecx,SECTOR_SIZE >> 2
+ mov eax,[CheckSum]
.checksum:
add eax,[si]
add si,4
@@ -614,12 +582,7 @@ verify_checksum:
.nowrap:
dec ecx
jnz .checksum
- pop ds
- push eax
- mov si,cbios_name
- call writestr_early
- pop eax
and eax,eax ; Should be zero
jz all_read ; We're cool, go for it!
@@ -635,37 +598,181 @@ verify_checksum:
; Subroutines that have to be in the first sector
; -----------------------------------------------------------------------------
+
+
;
+; getlinsec: load a sequence of BP floppy sector given by the linear sector
+; number in EAX into the buffer at ES:BX. We try to optimize
+; by loading up to a whole track at a time, but the user
+; is responsible for not crossing a 64K boundary.
+; (Yes, BP is weird for a count, but it was available...)
;
-; writestr_early: 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.
+; On return, BX points to the first byte after the transferred
+; block.
;
-writestr_early:
+; This routine assumes CS == DS.
+;
+ global getlinsec
+getlinsec:
pushad
-.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: popad
- ret
+ add eax,[Hidden] ; Add partition offset
+ adc edx,[Hidden+4]
+.jmp: jmp strict short getlinsec_cbios
+;
+; 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
+ pushad
+ mov ah,42h ; Extended Read
+ push ds
+ push ss
+ pop ds
+ call xint13
+ pop ds
+ popad
+ lea sp,[si+16] ; Remove DAPA
+ jc .error
+ pop bp
+ add eax,edi ; Advance sector pointer
+ adc edx,0
+ sub bp,di ; Sectors left
+ shl di,SECTOR_SHIFT ; 512-byte sectors
+ add bx,di ; Advance buffer pointer
+ and bp,bp
+ jnz .loop
+
+ popad
+ 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 ...
;
-; getlinsecsr: save registers, call getlinsec, restore registers
-; Save/restore the flags, too, especially IF.
+; getlinsec_cbios:
+;
+; getlinsec implementation for legacy CBIOS
;
-getlinsecsr:
- pushfd
+getlinsec_cbios:
+.loop:
+ push edx
+ push eax
+ push bp
+ push bx
+
+ movzx esi,word [bsSecPerTrack]
+ movzx edi,word [bsHeads]
+ ;
+ ; Dividing by sectors to get (track,sector): we may have
+ ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
+ ;
+ div esi
+ xor cx,cx
+ xchg cx,dx ; CX <- sector index (0-based)
+ ; EDX <- 0
+ ; eax = track #
+ div edi ; Convert track to head/cyl
+
+ cmp eax,1023 ; Outside the CHS range?
+ ja kaboom
+
+ ;
+ ; Now we have AX = cyl, DX = head, CX = sector (0-based),
+ ; BP = sectors to transfer, SI = bsSecPerTrack,
+ ; ES:BX = data target
+ ;
+
+ call maxtrans ; Enforce maximum transfer size
+
+ ; Must not cross track boundaries, so BP <= SI-CX
+ sub si,cx
+ cmp bp,si
+ jna .bp_ok
+ mov bp,si
+.bp_ok:
+
+ shl ah,6 ; Because IBM was STOOPID
+ ; and thought 8 bits were enough
+ ; then thought 10 bits were enough...
+ inc cx ; Sector numbers are 1-based, sigh
+ or cl,ah
+ mov ch,al
+ mov dh,dl
+ xchg ax,bp ; Sector to transfer count
+ mov ah,02h ; Read sectors
+ mov bp,retry_count
+.retry:
pushad
- call getlinsec
+ call xint13
+ 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
popad
- popfd
ret
+.error:
+ dec bp
+ jnz .retry
+
+ xchg ax,bp ; Sectors transferred <- 0
+ shr word [MaxTransfer],1
+ jnz .resume
+ jmp kaboom
+
+maxtrans:
+ cmp bp,[MaxTransfer]
+ jna .ok
+ mov bp,[MaxTransfer]
+.ok: ret
+
;
; Checksum error message
;
@@ -691,16 +798,22 @@ rl_checkpt equ $ ; Must be <= 8000h
rl_checkpt_off equ ($-$$)
%ifndef DEPEND
-%if rl_checkpt_off > 3FCh ; Need one pointer in here
-%error "Sector 1 overflow"
-%endif
+ %if rl_checkpt_off > 3F6h ; Need one extent
+ %assign rl_checkpt_overflow rl_checkpt_off - 3F6h
+ %error Sector 1 overflow by rl_checkpt_overflow bytes
+ %endif
%endif
-; Sector pointers
- alignz 4
+;
+; Extent pointers... each extent contains an 8-byte LBA and an 2-byte
+; sector count. In most cases, we will only ever need a handful of
+; extents, but we have to assume a maximally fragmented system where each
+; extent contains only one sector.
+;
+ alignz 2
MaxInitDataSize equ 96 << 10
MaxLMA equ TEXT_START+SECTOR_SIZE+MaxInitDataSize
-SectorPtrs times MaxInitDataSize >> SECTOR_SHIFT dd 0
+SectorPtrs zb 10*(MaxInitDataSize >> SECTOR_SHIFT)
SectorPtrsEnd equ $
; ----------------------------------------------------------------------------
@@ -708,18 +821,19 @@ SectorPtrsEnd equ $
; ----------------------------------------------------------------------------
section .text16
-test_string db 'test', 0 ; temp add by feng
-
all_read:
+ ; We enter here with both DS and ES scrambled...
+ xor ax,ax
+ mov ds,ax
+ mov es,ax
;
; Let the user (and programmer!) know we got this far. This used to be
; in Sector 1, but makes a lot more sense here.
;
- ;mov si,copyright_str
- ;call writestr_early
-
- mov si,test_string
+ mov si,copyright_str
call writestr_early
+
+
;
; Insane hack to expand the DOS superblock to dwords
;
@@ -746,21 +860,16 @@ expand_super:
mov eax,ROOT_FS_OPS
movzx dx,byte [DriveNumber]
; DH = 0: we are boot from disk not CDROM
- mov ecx,[bsHidden]
- ; Reserved for upper 32 bits of partition offset...
- ; mov ebx,[bsHidden+4]
- xor ebx,ebx
+ mov ecx,[Hidden]
+ mov ebx,[Hidden+4]
mov si,[bsHeads]
mov di,[bsSecPerTrack]
movzx ebp,word [MaxTransfer]
-
- ;mov si,ebios_name
- ;call writestr_early
-
pm_call fs_init
-
- ;mov si,ebios_name
- ;call writestr_early
-
pm_call load_env32
popad
+
+ section .bss16
+SuperInfo resq 16 ; The first 16 bytes expanded 8 times
+
+ section .text16
diff --git a/core/extlinux.asm b/core/extlinux.asm
deleted file mode 100644
index 95385765..00000000
--- a/core/extlinux.asm
+++ /dev/null
@@ -1,38 +0,0 @@
-; -*- fundamental -*- (asm-mode sucks)
-; ****************************************************************************
-;
-; extlinux.asm
-;
-; A program to boot Linux kernels off an ext2/ext3 filesystem.
-;
-; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;
-; This program is free software; you can redistribute it and/or modify
-; it under the terms of the GNU General Public License as published by
-; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-; Boston MA 02111-1307, USA; either version 2 of the License, or
-; (at your option) any later version; incorporated herein by reference.
-;
-; ****************************************************************************
-
-%define IS_EXTLINUX 1
-%include "head.inc"
-
-;
-; Some semi-configurable constants... change on your own risk.
-;
-my_id equ extlinux_id
-
- section .rodata
- alignz 4
-ROOT_FS_OPS:
- extern vfat_fs_ops
- dd vfat_fs_ops
- extern ext2_fs_ops
- dd ext2_fs_ops
- extern btrfs_fs_ops
- dd btrfs_fs_ops
- dd 0
-
-%include "diskfs.inc"
diff --git a/core/include/core.h b/core/include/core.h
index 3de2b4de..799c337d 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -64,10 +64,14 @@ __noreturn _kaboom(void);
/*
* Basic timer function...
*/
-extern volatile uint32_t __jiffies;
+extern volatile uint32_t __jiffies, __ms_timer;
static inline uint32_t jiffies(void)
{
return __jiffies;
}
+static inline uint32_t ms_timer(void)
+{
+ return __ms_timer;
+}
#endif /* CORE_H */
diff --git a/core/isolinux.asm b/core/isolinux.asm
index 80607679..1ef68d8c 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -101,7 +101,7 @@ ISOFlags resb 1 ; Flags for ISO directory search
RetryCount resb 1 ; Used for disk access retries
alignb 8
-bsHidden resq 1 ; Used in hybrid mode
+Hidden resq 1 ; Used in hybrid mode
bsSecPerTrack resw 1 ; Used in hybrid mode
bsHeads resw 1 ; Used in hybrid mode
@@ -242,9 +242,6 @@ _start_hybrid:
pop eax
pop ebx
.nooffset:
- mov [cs:bsHidden],eax
- mov [cs:bsHidden+4],ebx
-
mov si,bios_cbios
jcxz _start_common
mov si,bios_ebios
@@ -253,21 +250,26 @@ _start_hybrid:
_start1:
mov si,bios_cdrom
+ xor eax,eax
+ xor ebx,ebx
_start_common:
mov [cs:InitStack],sp ; Save initial stack pointer
mov [cs:InitStack+2],ss
- xor ax,ax
- mov ss,ax
+ xor cx,cx
+ mov ss,cx
mov sp,StackBuf ; Set up stack
push es ; Save initial ES:DI -> $PnP pointer
push di
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
+ mov ds,cx
+ mov es,cx
+ mov fs,cx
+ mov gs,cx
sti
cld
+ mov [Hidden],eax
+ mov [Hidden+4],ebx
+
mov [BIOSType],si
mov eax,[si]
mov [GetlinsecPtr],eax
@@ -779,8 +781,8 @@ getlinsec_ebios:
xor edx,edx
shld edx,eax,2
shl eax,2 ; Convert to HDD sectors
- add eax,[bsHidden]
- adc edx,[bsHidden+4]
+ add eax,[Hidden]
+ adc edx,[Hidden+4]
shl bp,2
.loop:
@@ -852,7 +854,7 @@ getlinsec_ebios:
getlinsec_cbios:
xor edx,edx
shl eax,2 ; Convert to HDD sectors
- add eax,[bsHidden]
+ add eax,[Hidden]
shl bp,2
.loop:
@@ -1165,8 +1167,8 @@ init_fs:
.hybrid:
movzx ebp,word [MaxTransfer]
.common:
- mov ecx,[bsHidden]
- mov ebx,[bsHidden+4]
+ mov ecx,[Hidden]
+ mov ebx,[Hidden+4]
mov si,[bsHeads]
mov di,[bsSecPerTrack]
pm_call fs_init
diff --git a/core/ldlinux.asm b/core/ldlinux.asm
index 23540ea5..f62f55b2 100644
--- a/core/ldlinux.asm
+++ b/core/ldlinux.asm
@@ -35,6 +35,10 @@ my_id equ syslinux_id
ROOT_FS_OPS:
extern vfat_fs_ops
dd vfat_fs_ops
+ extern ext2_fs_ops
+ dd ext2_fs_ops
+ extern btrfs_fs_ops
+ dd btrfs_fs_ops
dd 0
%include "diskfs.inc"
diff --git a/core/pmapi.c b/core/pmapi.c
index 3313ceaf..4b1ccbb1 100644
--- a/core/pmapi.c
+++ b/core/pmapi.c
@@ -19,6 +19,8 @@
const struct com32_pmapi pm_api_vector =
{
+ .__pmapi_size = sizeof(struct com32_pmapi),
+
.lmalloc = pmapi_lmalloc, /* Allocate low memory */
.lfree = free, /* Free low memory */
@@ -32,4 +34,10 @@ const struct com32_pmapi pm_api_vector =
.idle = __idle,
.reset_idle = reset_idle,
+
+ .chdir = chdir,
+ .getcwd = getcwd,
+
+ .jiffies = &__jiffies,
+ .ms_timer = &__ms_timer,
};
diff --git a/core/timer.inc b/core/timer.inc
index 728812b1..b01ff917 100644
--- a/core/timer.inc
+++ b/core/timer.inc
@@ -19,6 +19,9 @@
;; about the BIOS_timer variable wrapping around at "midnight" and other
;; weird things.
;;
+;; This also maintains a timer variable calibrated in milliseconds
+;; (wraparound time = 49.7 days!)
+;;
section .text16
@@ -35,12 +38,20 @@ timer_cleanup:
mov [BIOS_timer_hook],eax
ret
+;
+; The specified frequency is 14.31818 MHz/12/65536; this turns out
+; to be a period of 54.92542 ms, or 0x36.ece8(187c) hexadecimal.
+;
timer_irq:
inc dword [cs:__jiffies]
+ add word [cs:__ms_timer_adj],0xece8
+ adc dword [cs:__ms_timer],0x36
jmp 0:0
BIOS_timer_next equ $-4
section .data16
alignz 4
- global __jiffies
-__jiffies dd 0 ; The actual timer variable
+ global __jiffies, __ms_timer
+__jiffies dd 0 ; Clock tick timer
+__ms_timer dd 0 ; Millisecond timer
+__ms_timer_adj dw 0 ; Millisecond timer correction factor
diff --git a/elf_gen_dep.sh b/elf_gen_dep.sh
index 654f96d5..306034a1 100755
--- a/elf_gen_dep.sh
+++ b/elf_gen_dep.sh
@@ -4,7 +4,7 @@
# Round 1: get all the loacl and external symbols
#######################################################
-for i in com32/elflink/modules/*.c32 core/extlinux.elf core/isolinux.elf core/pxelinux.elf
+for i in com32/elflink/modules/*.c32 core/isolinux.elf core/pxelinux.elf
do
# module=$(echo $i | sed "s/^\(.*\).o$/\1/")