summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2002-01-16 01:58:11 +0000
committerhpa <hpa>2002-01-16 01:58:11 +0000
commit2775964e0d571f00e645e99abb446162cac53a0d (patch)
tree8002f0ceb8bb9146e983a5549884852b3e70f328
parenta10218c3be8fc6bbe9b253dcda7dc39af8f8bcc5 (diff)
downloadsyslinux-1.67-pre1.tar.gz
Handle bug in the alignment of the initrd.syslinux-1.67-pre1
-rw-r--r--NEWS2
-rw-r--r--isolinux.asm218
-rw-r--r--ldlinux.asm207
-rw-r--r--pxelinux.asm218
4 files changed, 277 insertions, 368 deletions
diff --git a/NEWS b/NEWS
index 71a6c024..0a16a697 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,7 @@ Starting with 1.47, changes marked with SYSLINUX/PXELINUX/ISOLINUX
apply to that specific program only; other changes apply to both.
Changes in 1.67:
- * Major code restructuring.
+ * Handle bug in the location of initrd.
Changes in 1.66:
* MEMDISK: Make compile with newer versions of gcc.
diff --git a/isolinux.asm b/isolinux.asm
index e9803c09..0d624f3d 100644
--- a/isolinux.asm
+++ b/isolinux.asm
@@ -9,7 +9,7 @@
; available. It is based on the SYSLINUX boot loader for MS-DOS
; floppies.
;
-; Copyright (C) 1994-2002 H. Peter Anvin
+; Copyright (C) 1994-2001 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
@@ -58,7 +58,7 @@ SECTORSIZE equ (1 << SECTORSIZE_LG2)
;
%define version_str VERSION ; Must be 4 characters long!
%define date DATE_STR ; Defined from the Makefile
-%define year '2002'
+%define year '2001'
;
; Debgging stuff
;
@@ -306,6 +306,7 @@ MNameBuf resb FILENAME_MAX
InitRD resb FILENAME_MAX
PartInfo resb 16 ; Partition table entry
E820Buf resd 5 ; INT 15:E820 data buffer
+InitRDat resd 1 ; Load address (linear) for initrd
HiLoadAddr resd 1 ; Address pointer for high load loop
HighMemSize resd 1 ; End of memory pointer (bytes)
RamdiskMax resd 1 ; Highest address for a ramdisk
@@ -314,6 +315,7 @@ RootDir resb dir_t_size ; Root directory
CurDir resb dir_t_size ; Current directory
SavedSSSP resd 1 ; Our SS:SP while running a COMBOOT image
KernelClust resd 1 ; Kernel size in clusters
+InitRDClust resd 1 ; Ramdisk size in clusters
InitStack resd 1 ; Initial stack pointer (SS:SP)
FirstSecSum resd 1 ; Checksum of bytes 64-2048
ImageDwords resd 1 ; isolinux.bin size, dwords
@@ -2003,35 +2005,53 @@ read_kernel:
movzx esi,word [SetupSecs] ; Setup sectors
inc esi ; plus 1 boot sector
shl esi,9 ; Convert to bytes
- mov ecx,8000h ; 32K
- sub ecx,esi ; Number of bytes to copy
- push ecx
+ mov ecx,108000h ; 108000h = 1M + 32K
+ sub ecx,esi ; Adjust pointer to 2nd block
+ mov [HiLoadAddr],ecx
+ sub ecx,100000h ; Turn into a counter
shr ecx,2 ; Convert to dwords
add esi,(real_mode_seg << 4) ; Pointer to source
mov edi,100000h ; Copy to address 100000h
call bcopy ; Transfer to high memory
- ; On exit EDI -> where to load the rest
-
+ push word xfer_buf_seg ; Transfer buffer segment
+ pop es
+high_load_loop:
mov si,dot_msg ; Progress report
call cwritestr
call abort_check
-
- pop ecx ; Number of bytes in the initial portion
- pop si ; Restore file handle/cluster pointer
- mov eax,[KernelSize]
- sub eax,ecx ; Amount of kernel left over
- jbe high_load_done ; Zero left (tiny kernel)
-
- call load_high ; Copy the file
-
+ mov ecx,[KernelClust]
+ and ecx,ecx
+ jz high_load_done ; Zero left (tiny kernel?)
+ cmp ecx,[ClustPerMoby]
+ jna high_last_moby
+ mov ecx,[ClustPerMoby]
+high_last_moby:
+ sub [KernelClust],ecx
+ xor bx,bx ; Load at offset 0
+ pop si ; Restore cluster pointer
+ call getfssec
+ push si ; Save cluster pointer
+ pushf ; Save EOF
+ xor bx,bx
+ mov esi,(xfer_buf_seg << 4)
+ mov edi,[HiLoadAddr] ; Destination address
+ mov ecx,4000h ; Cheating - transfer 64K
+ call bcopy ; Transfer to high memory
+ mov [HiLoadAddr],edi ; Point to next target area
+ popf ; Restore EOF
+ jc high_load_done ; If EOF we are done
+ cmp dword [KernelClust],byte 0 ; Are we done?
+ jne high_load_loop ; Apparently not
high_load_done:
+ pop si ; No longer needed
mov ax,real_mode_seg ; Set to real mode seg
mov es,ax
mov si,dot_msg
call cwritestr
+ call crlf
;
; Now see if we have an initial RAMdisk; if so, do requisite computation
; We know we have a new kernel; the old_kernel code already will have objected
@@ -2052,8 +2072,18 @@ load_initrd:
call searchdir ; Look for it in directory
pop es
jz initrd_notthere
+ mov [initrd_ptr],si ; Save cluster pointer
mov [es:su_ramdisklen1],ax ; Ram disk length
mov [es:su_ramdisklen2],dx
+ movzx eax,ax
+ shl edx,16
+ or eax,edx
+ xor edx,edx
+ div dword [ClustSize]
+ ; Round up...
+ add edx,byte -1 ; Sets CF if EDX >= 1
+ adc eax,byte 0 ; Add 1 to EAX if CF set
+ mov [InitRDClust],eax ; Ramdisk clusters
mov edx,[HighMemSize] ; End of memory
dec edx
mov eax,[RamdiskMax] ; Highest address allowed by kernel
@@ -2062,9 +2092,10 @@ load_initrd:
mov edx,eax ; Adjust to fit inside limit
memsize_ok:
inc edx
+ xor dx,dx ; Round down to 64K boundary
sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk
xor dx,dx ; Round down to 64K boundary
- mov [es:su_ramdiskat],edx ; Load address
+ mov [InitRDat],edx ; Load address
call loadinitrd ; Load initial ramdisk
jmp short initrd_end
@@ -2101,7 +2132,8 @@ nk_noinitrd:
; and the real mode stuff to 90000h. We assume that all bzImage kernels are
; capable of starting their setup from a different address.
;
-
+ mov bx,real_mode_seg ; Real mode segment
+ mov fs,bx ; FS -> real_mode_seg
;
; Copy command line. Unfortunately, the kernel boot protocol requires
; the command line to exist in the 9xxxxh range even if the rest of the
@@ -2133,10 +2165,8 @@ need_high_cmdline:
shr cx,2 ; Convert to dwords
fs rep movsd
- push fs
- pop es
-
test byte [LoadFlags],LOAD_HIGH
+ ; Note bx -> real_mode_seg still
jnz in_proper_place ; If high load, we're done
;
@@ -2144,6 +2174,8 @@ need_high_cmdline:
;
; Copy real_mode stuff up to 90000h
;
+ mov ax,real_mode_seg
+ mov fs,ax
mov ax,9000h
mov es,ax
mov cx,[SetupSecs]
@@ -2169,8 +2201,6 @@ need_high_cmdline:
xor eax,eax
rep stosd ; Clear region
;
-; Copy the kernel down to the "low" location
-;
mov ecx,[KernelSize]
add ecx,3 ; Round upwards
shr ecx,2 ; Bytes -> dwords
@@ -2178,14 +2208,13 @@ need_high_cmdline:
mov edi,10000h
call bcopy
+ mov bx,9000h ; Real mode segment
+
;
; Now everything is where it needs to be...
;
-; When we get here, es points to the final segment, either
-; 9000h or real_mode_seg
-;
in_proper_place:
-
+ mov es,bx ; Real mode segment
;
; If the default root device is set to FLOPPY (0000h), change to
; /dev/fd0 (0200h)
@@ -2234,10 +2263,10 @@ kill_motor:
%endif
;
; Set up segment registers and the Linux real-mode stack
-; Note: es == the real mode segment
+; Note: bx == the real mode segment
;
cli
- mov bx,es
+ ; es is already == real mode segment
mov ds,bx
mov fs,bx
mov gs,bx
@@ -2549,7 +2578,7 @@ local_boot:
; 32-bit bcopy routine for real mode
;
; We enter protected mode, set up a flat 32-bit environment, run rep movsd
-; and then exit. IMPORTANT: This code assumes cs == 0.
+; and then exit. IMPORTANT: This code assumes cs == ss == 0.
;
; This code is probably excessively anal-retentive in its handling of
; segments, but this stuff is painful enough as it is without having to rely
@@ -2580,7 +2609,7 @@ bcopy: push eax
cli
call enable_a20
- o32 lgdt [cs:bcopy_gdt]
+ o32 lgdt [bcopy_gdt]
mov eax,cr0
or al,1
mov cr0,eax ; Enter protected mode
@@ -2858,111 +2887,53 @@ try_wbinvd:
;
; Load RAM disk into high memory
;
-; Need to be set:
-; su_ramdiskat - Where in memory to load
-; su_ramdisklen - Size of file
-; SI - initrd filehandle/cluster pointer
-;
loadinitrd:
push es ; Save ES on entry
- mov ax,real_mode_seg
+ mov ax,real_mode_seg
mov es,ax
- mov edi,[es:su_ramdiskat] ; initrd load address
+ mov si,[initrd_ptr]
+ mov edi,[InitRDat] ; initrd load address
+ mov [es:su_ramdiskat],edi ; Offset for ram disk
push si
- mov si,crlfloading_msg ; Write "Loading "
- call cwritestr
+ mov si,loading_msg
+ call cwritestr
mov si,InitRDCName ; Write ramdisk name
call cwritestr
mov si,dotdot_msg ; Write dots
call cwritestr
- pop si
-
- mov eax,[es:su_ramdisklen]
- call load_high ; Load the file
-
+rd_load_loop:
+ mov si,dot_msg ; Progress report
+ call cwritestr
+ pop si ; Restore cluster pointer
+ call abort_check
+ mov ecx,[InitRDClust]
+ cmp ecx,[ClustPerMoby]
+ jna rd_last_moby
+ mov ecx,[ClustPerMoby]
+rd_last_moby:
+ sub [InitRDClust],ecx
+ xor bx,bx ; Load at offset 0
+ push word xfer_buf_seg ; Bounce buffer segment
+ pop es
+ push cx
+ call getfssec
+ pop cx
+ push si ; Save cluster pointer
+ mov esi,(xfer_buf_seg << 4)
+ mov edi,[InitRDat]
+ mov ecx,4000h ; Copy 64K
+ call bcopy ; Does not change flags!!
+ jc rd_load_done ; EOF?
+ add dword [InitRDat],10000h ; Point to next 64K
+ cmp dword [InitRDClust],byte 0 ; Are we done?
+ jne rd_load_loop ; Apparently not
+rd_load_done:
+ pop si ; Clean up the stack
call crlf
- mov si,loading_msg ; Write new "Loading " for
- call cwritestr ; the benefit of the kernel
pop es ; Restore original ES
ret
;
-; load_high: loads (the remainder of) a file into high memory.
-; This routine prints dots for each 64K transferred, and
-; calls abort_check periodically.
-;
-; The xfer_buf_seg is used as a bounce buffer.
-;
-; The input address (EDI) should be dword aligned, and the final
-; dword written is padded with zeroes if necessary.
-;
-; Inputs: SI = file handle/cluster pointer
-; EDI = target address in high memory
-; EAX = size of remaining file in bytes
-;
-; Outputs: SI = file handle/cluster pointer
-; EDI = first untouched address (not including padding)
-;
-load_high:
- push es
-
- mov bx,xfer_buf_seg
- mov es,bx
-
-.read_loop:
- push si
- mov si,dot_msg
- call cwritestr
- pop si
- call abort_check
-
- push eax ; Total chunk to transfer
- cmp eax,(1 << 16) ; Max 64K in one transfer
- jna .size_ok
- mov eax,(1 << 16)
-.size_ok:
- cdq ; EDX <- 0
- push eax ; Bytes transferred this chunk
- div dword [ClustSize] ; Convert to clusters
- ; Round up...
- add edx,byte -1 ; Sets CF if EDX >= 1
- adc eax,byte 0 ; Add 1 to EAX if CF set
-
- ; Now (e)ax contains the number of clusters to get
- push edi
- mov cx,ax
- xor bx,bx ; ES:0
- call getfssec ; Load the data into xfer_buf_seg
- pop edi
- pop ecx ; Byte count this round
- push ecx
- push edi
-.fix_slop:
- test cl,3
- jz .noslop
- ; The last dword fractional - pad with zeroes
- ; Zero-padding is critical for multi-file initramfs.
- mov bx,cx
- mov byte [es:bx],0
- inc ecx
- jmp short .fix_slop
-.noslop:
- shr ecx,2 ; Convert to dwords
- push esi
- mov esi,(xfer_buf_seg << 4) ; Source address
- call bcopy ; Copy to high memory
- pop esi
- pop edi
- pop ecx
- pop eax
- add edi,ecx
- sub eax,ecx
- jnz .read_loop ; More to read...
-
- pop es
- ret
-
-;
; abort_check: let the user abort with <ESC> or <Ctrl-C>
;
abort_check:
@@ -4501,7 +4472,6 @@ localboot_msg db 'Booting from local disk...', CR, LF, 0
cmdline_msg db 'Command line: ', CR, LF, 0
ready_msg db ' ready.', CR, LF, 0
trying_msg db 'Trying to load: ', 0
-crlfloading_msg db CR, LF ; Fall through
loading_msg db 'Loading ', 0
dotdot_msg db '.'
dot_msg db '.', 0
diff --git a/ldlinux.asm b/ldlinux.asm
index 62e8537e..f120d889 100644
--- a/ldlinux.asm
+++ b/ldlinux.asm
@@ -16,7 +16,7 @@
; then the first sector (cluster, really, but we can only assume 1 sector)
; of LDLINUX.SYS at 7E00h and finally the remainder of LDLINUX.SYS at 8000h.
;
-; Copyright (C) 1994-2002 H. Peter Anvin
+; Copyright (C) 1994-2001 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
@@ -40,7 +40,7 @@ BAUD_DIVISOR equ 115200 ; Serial port parameter
;
%define version_str VERSION ; Must be 4 characters long!
%define date DATE_STR ; Defined from the Makefile
-%define year '2002'
+%define year '2001'
;
; Debgging stuff
;
@@ -270,6 +270,7 @@ NumBufEnd resb 1 ; Last byte in NumBuf
alignb 4
PartInfo resb 16 ; Partition table entry
E820Buf resd 5 ; INT 15:E820 data buffer
+InitRDat resd 1 ; Load address (linear) for initrd
HiLoadAddr resd 1 ; Address pointer for high load loop
HighMemSize resd 1 ; End of memory pointer (bytes)
RamdiskMax resd 1 ; Highest address for a ramdisk
@@ -298,6 +299,7 @@ BufSafeSec resw 1 ; = how many sectors?
BufSafeBytes resw 1 ; = how many bytes?
EndOfGetCBuf resw 1 ; = getcbuf+BufSafeBytes
KernelClust resw 1 ; Kernel size in clusters
+InitRDClust resw 1 ; Ramdisk size in clusters
ClustPerMoby resw 1 ; Clusters per 64K
FClust resw 1 ; Number of clusters in open/getc file
FNextClust resw 1 ; Pointer to next cluster in d:o
@@ -2050,8 +2052,15 @@ new_kernel:
call searchdir ; Look for it in directory
pop es
jz initrd_notthere
+ mov [initrd_ptr],si ; Save cluster pointer
mov [es:su_ramdisklen1],ax ; Ram disk length
mov [es:su_ramdisklen2],dx
+ div word [ClustSize]
+ and dx,dx ; Round up
+ setnz dl
+ movzx dx,dl
+ add ax,dx
+ mov [InitRDClust],ax ; Ramdisk clusters
mov edx,[HighMemSize] ; End of memory
dec edx
mov eax,[RamdiskMax] ; Highest address allowed by kernel
@@ -2060,9 +2069,10 @@ new_kernel:
mov edx,eax ; Adjust to fit inside limit
memsize_ok:
inc edx
+ xor dx,dx ; Round down to 64K boundary
sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk
xor dx,dx ; Round down to 64K boundary
- mov [es:su_ramdiskat],edx ; Load address
+ mov [InitRDat],edx ; Load address
call loadinitrd ; Load initial ramdisk
jmp short initrd_end
@@ -2105,31 +2115,48 @@ read_kernel:
movzx esi,word [SetupSecs] ; Setup sectors
inc esi ; plus 1 boot sector
shl esi,9 ; Convert to bytes
- mov ecx,8000h ; 32K
- sub ecx,esi ; Number of bytes to copy
- push ecx
+ mov ecx,108000h ; 108000h = 1M + 32K
+ sub ecx,esi ; Adjust pointer to 2nd block
+ mov [HiLoadAddr],ecx
+ sub ecx,100000h ; Turn into a counter
shr ecx,2 ; Convert to dwords
add esi,(real_mode_seg << 4) ; Pointer to source
mov edi,100000h ; Copy to address 100000h
call bcopy ; Transfer to high memory
- ; On exit EDI -> where to load the rest
-
+ push word xfer_buf_seg ; Transfer buffer segment
+ pop es
+high_load_loop:
mov si,dot_msg ; Progress report
call cwritestr
call abort_check
-
- pop ecx ; Number of bytes in the initial portion
- pop si ; Restore file handle/cluster pointer
- mov eax,[KernelSize]
- sub eax,ecx ; Amount of kernel left over
- jbe high_load_done ; Zero left (tiny kernel)
-
- call load_high ; Copy the file
-
+ mov cx,[KernelClust]
+ and cx,cx
+ jz high_load_done ; Zero left (tiny kernel?)
+ cmp cx,[ClustPerMoby]
+ jna high_last_moby
+ mov cx,[ClustPerMoby]
+high_last_moby:
+ sub [KernelClust],cx
+ xor bx,bx ; Load at offset 0
+ pop si ; Restore cluster pointer
+ call getfssec
+ push si ; Save cluster pointer
+ pushf ; Save EOF
+ xor bx,bx
+ mov esi,(xfer_buf_seg << 4)
+ mov edi,[HiLoadAddr] ; Destination address
+ mov ecx,4000h ; Cheating - transfer 64K
+ call bcopy ; Transfer to high memory
+ mov [HiLoadAddr],edi ; Point to next target area
+ popf ; Restore EOF
+ jc high_load_done ; If EOF we are done
+ cmp word [KernelClust],byte 0 ; Are we done?
+ jne high_load_loop ; Apparently not
high_load_done:
+ pop si ; No longer needed
mov ax,real_mode_seg ; Set to real mode seg
- mov fs,ax ; FS -> real_mode_seg
+ mov es,ax
mov si,dot_msg
call cwritestr
@@ -2147,7 +2174,8 @@ high_load_done:
; and the real mode stuff to 90000h. We assume that all bzImage kernels are
; capable of starting their setup from a different address.
;
-
+ mov bx,real_mode_seg ; Real mode segment
+ mov fs,bx ; FS -> real_mode_seg
;
; Copy command line. Unfortunately, the kernel boot protocol requires
; the command line to exist in the 9xxxxh range even if the rest of the
@@ -2179,10 +2207,8 @@ need_high_cmdline:
shr cx,2 ; Convert to dwords
fs rep movsd
- push fs
- pop es
-
test byte [LoadFlags],LOAD_HIGH
+ ; Note bx -> real_mode_seg still
jnz in_proper_place ; If high load, we're done
;
@@ -2190,6 +2216,8 @@ need_high_cmdline:
;
; Copy real_mode stuff up to 90000h
;
+ mov ax,real_mode_seg
+ mov fs,ax
mov ax,9000h
mov es,ax
mov cx,[SetupSecs]
@@ -2215,8 +2243,6 @@ need_high_cmdline:
xor eax,eax
rep stosd ; Clear region
;
-; Copy the kernel down to the "low" location
-;
mov ecx,[KernelSize]
add ecx,3 ; Round upwards
shr ecx,2 ; Bytes -> dwords
@@ -2224,14 +2250,13 @@ need_high_cmdline:
mov edi,10000h
call bcopy
+ mov bx,9000h ; Real mode segment
+
;
; Now everything is where it needs to be...
;
-; When we get here, es points to the final segment, either
-; 9000h or real_mode_seg
-;
in_proper_place:
-
+ mov es,bx ; Real mode segment
;
; If the default root device is set to FLOPPY (0000h), change to
; /dev/fd0 (0200h)
@@ -2280,10 +2305,10 @@ kill_motor:
%endif
;
; Set up segment registers and the Linux real-mode stack
-; Note: es == the real mode segment
+; Note: bx == the real mode segment
;
cli
- mov bx,es
+ ; es is already == real mode segment
mov ds,bx
mov fs,bx
mov gs,bx
@@ -2503,7 +2528,7 @@ bcopy: push eax
cli
call enable_a20
- o32 lgdt [cs:bcopy_gdt]
+ o32 lgdt [bcopy_gdt]
mov eax,cr0
or al,1
mov cr0,eax ; Enter protected mode
@@ -2781,26 +2806,46 @@ try_wbinvd:
;
; Load RAM disk into high memory
;
-; Need to be set:
-; su_ramdiskat - Where in memory to load
-; su_ramdisklen - Size of file
-; SI - initrd filehandle/cluster pointer
-;
loadinitrd:
push es ; Save ES on entry
- mov ax,real_mode_seg
+ mov ax,real_mode_seg
mov es,ax
- mov edi,[es:su_ramdiskat] ; initrd load address
+ mov si,[initrd_ptr]
+ mov edi,[InitRDat] ; initrd load address
+ mov [es:su_ramdiskat],edi ; Offset for ram disk
push si
mov si,InitRDCName ; Write ramdisk name
call cwritestr
mov si,dotdot_msg ; Write dots
call cwritestr
- pop si
-
- mov eax,[es:su_ramdisklen]
- call load_high ; Load the file
-
+rd_load_loop:
+ mov si,dot_msg ; Progress report
+ call cwritestr
+ pop si ; Restore cluster pointer
+ call abort_check
+ mov cx,[InitRDClust]
+ cmp cx,[ClustPerMoby]
+ jna rd_last_moby
+ mov cx,[ClustPerMoby]
+rd_last_moby:
+ sub [InitRDClust],cx
+ xor bx,bx ; Load at offset 0
+ push word xfer_buf_seg ; Bounce buffer segment
+ pop es
+ push cx
+ call getfssec
+ pop cx
+ push si ; Save cluster pointer
+ mov esi,(xfer_buf_seg << 4)
+ mov edi,[InitRDat]
+ mov ecx,4000h ; Copy 64K
+ call bcopy ; Does not change flags!!
+ jc rd_load_done ; EOF?
+ add dword [InitRDat],10000h ; Point to next 64K
+ cmp word [InitRDClust],byte 0 ; Are we done?
+ jne rd_load_loop ; Apparently not
+rd_load_done:
+ pop si ; Clean up the stack
call crlf
mov si,loading_msg ; Write new "Loading " for
call cwritestr ; the benefit of the kernel
@@ -2808,82 +2853,6 @@ loadinitrd:
ret
;
-; load_high: loads (the remainder of) a file into high memory.
-; This routine prints dots for each 64K transferred, and
-; calls abort_check periodically.
-;
-; The xfer_buf_seg is used as a bounce buffer.
-;
-; The input address (EDI) should be dword aligned, and the final
-; dword written is padded with zeroes if necessary.
-;
-; Inputs: SI = file handle/cluster pointer
-; EDI = target address in high memory
-; EAX = size of remaining file in bytes
-;
-; Outputs: SI = file handle/cluster pointer
-; EDI = first untouched address (not including padding)
-;
-load_high:
- push es
-
- mov bx,xfer_buf_seg
- mov es,bx
-
-.read_loop:
- push si
- mov si,dot_msg
- call cwritestr
- pop si
- call abort_check
-
- push eax ; Total chunk to transfer
- cmp eax,(1 << 16) ; Max 64K in one transfer
- jna .size_ok
- mov eax,(1 << 16)
-.size_ok:
- cdq ; EDX <- 0
- push eax ; Bytes transferred this chunk
- div dword [ClustSize] ; Convert to clusters
- ; Round up...
- add edx,byte -1 ; Sets CF if EDX >= 1
- adc eax,byte 0 ; Add 1 to EAX if CF set
-
- ; Now (e)ax contains the number of clusters to get
- push edi
- mov cx,ax
- xor bx,bx ; ES:0
- call getfssec ; Load the data into xfer_buf_seg
- pop edi
- pop ecx ; Byte count this round
- push ecx
- push edi
-.fix_slop:
- test cl,3
- jz .noslop
- ; The last dword fractional - pad with zeroes
- ; Zero-padding is critical for multi-file initramfs.
- mov bx,cx
- mov byte [es:bx],0
- inc ecx
- jmp short .fix_slop
-.noslop:
- shr ecx,2 ; Convert to dwords
- push esi
- mov esi,(xfer_buf_seg << 4) ; Source address
- call bcopy ; Copy to high memory
- pop edi
- pop esi
- pop ecx
- pop eax
- add edi,ecx
- sub eax,ecx
- jnz .read_loop ; More to read...
-
- pop es
- ret
-
-;
; abort_check: let the user abort with <ESC> or <Ctrl-C>
;
abort_check:
diff --git a/pxelinux.asm b/pxelinux.asm
index 72c0fc2a..077e618b 100644
--- a/pxelinux.asm
+++ b/pxelinux.asm
@@ -8,7 +8,7 @@
; network booting API. It is based on the SYSLINUX boot loader for
; MS-DOS floppies.
;
-; Copyright (C) 1994-2002 H. Peter Anvin
+; Copyright (C) 1994-2001 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
@@ -64,7 +64,7 @@ TFTP_OACK equ htons(6) ; OACK packet
;
%define version_str VERSION ; Must be 4 characters long!
%define date DATE_STR ; Defined from the Makefile
-%define year '2002'
+%define year '2001'
;
; Debgging stuff
;
@@ -343,6 +343,7 @@ MNameBuf resb FILENAME_MAX
InitRD resb FILENAME_MAX
PartInfo resb 16 ; Partition table entry
E820Buf resd 5 ; INT 15:E820 data buffer
+InitRDat resd 1 ; Load address (linear) for initrd
HiLoadAddr resd 1 ; Address pointer for high load loop
HighMemSize resd 1 ; End of memory pointer (bytes)
RamdiskMax resd 1 ; Highest address for a ramdisk
@@ -352,6 +353,7 @@ PXEEntry resd 1 ; !PXE API entry point
SavedSSSP resd 1 ; Our SS:SP while running a COMBOOT image
RebootTime resd 1 ; Reboot timeout, if set by option
KernelClust resd 1 ; Kernel size in clusters
+InitRDClust resd 1 ; Ramdisk size in clusters
FBytes equ $ ; Used by open/getc
FBytes1 resw 1
FBytes2 resw 1
@@ -1882,35 +1884,53 @@ read_kernel:
movzx esi,word [SetupSecs] ; Setup sectors
inc esi ; plus 1 boot sector
shl esi,9 ; Convert to bytes
- mov ecx,8000h ; 32K
- sub ecx,esi ; Number of bytes to copy
- push ecx
+ mov ecx,108000h ; 108000h = 1M + 32K
+ sub ecx,esi ; Adjust pointer to 2nd block
+ mov [HiLoadAddr],ecx
+ sub ecx,100000h ; Turn into a counter
shr ecx,2 ; Convert to dwords
add esi,(real_mode_seg << 4) ; Pointer to source
mov edi,100000h ; Copy to address 100000h
call bcopy ; Transfer to high memory
- ; On exit EDI -> where to load the rest
-
+ push word xfer_buf_seg ; Transfer buffer segment
+ pop es
+high_load_loop:
mov si,dot_msg ; Progress report
call cwritestr
call abort_check
-
- pop ecx ; Number of bytes in the initial portion
- pop si ; Restore file handle/cluster pointer
- mov eax,[KernelSize]
- sub eax,ecx ; Amount of kernel left over
- jbe high_load_done ; Zero left (tiny kernel)
-
- call load_high ; Copy the file
-
+ mov ecx,[KernelClust]
+ and ecx,ecx
+ jz high_load_done ; Zero left (tiny kernel?)
+ cmp ecx,[ClustPerMoby]
+ jna high_last_moby
+ mov ecx,[ClustPerMoby]
+high_last_moby:
+ sub [KernelClust],ecx
+ xor bx,bx ; Load at offset 0
+ pop si ; Restore cluster pointer
+ call getfssec
+ push si ; Save cluster pointer
+ pushf ; Save EOF
+ xor bx,bx
+ mov esi,(xfer_buf_seg << 4)
+ mov edi,[HiLoadAddr] ; Destination address
+ mov ecx,4000h ; Cheating - transfer 64K
+ call bcopy ; Transfer to high memory
+ mov [HiLoadAddr],edi ; Point to next target area
+ popf ; Restore EOF
+ jc high_load_done ; If EOF we are done
+ cmp dword [KernelClust],byte 0 ; Are we done?
+ jne high_load_loop ; Apparently not
high_load_done:
+ pop si ; No longer needed
mov ax,real_mode_seg ; Set to real mode seg
mov es,ax
mov si,dot_msg
call cwritestr
+ call crlf
;
; Now see if we have an initial RAMdisk; if so, do requisite computation
; We know we have a new kernel; the old_kernel code already will have objected
@@ -1931,8 +1951,18 @@ load_initrd:
call searchdir ; Look for it in directory
pop es
jz initrd_notthere
+ mov [initrd_ptr],si ; Save cluster pointer
mov [es:su_ramdisklen1],ax ; Ram disk length
mov [es:su_ramdisklen2],dx
+ movzx eax,ax
+ shl edx,16
+ or eax,edx
+ xor edx,edx
+ div dword [ClustSize]
+ ; Round up...
+ add edx,byte -1 ; Sets CF if EDX >= 1
+ adc eax,byte 0 ; Add 1 to EAX if CF set
+ mov [InitRDClust],eax ; Ramdisk clusters
mov edx,[HighMemSize] ; End of memory
dec edx
mov eax,[RamdiskMax] ; Highest address allowed by kernel
@@ -1941,9 +1971,10 @@ load_initrd:
mov edx,eax ; Adjust to fit inside limit
memsize_ok:
inc edx
+ xor dx,dx ; Round down to 64K boundary
sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk
xor dx,dx ; Round down to 64K boundary
- mov [es:su_ramdiskat],edx ; Load address
+ mov [InitRDat],edx ; Load address
call loadinitrd ; Load initial ramdisk
jmp short initrd_end
@@ -1983,7 +2014,8 @@ nk_noinitrd:
; and the real mode stuff to 90000h. We assume that all bzImage kernels are
; capable of starting their setup from a different address.
;
-
+ mov bx,real_mode_seg ; Real mode segment
+ mov fs,bx ; FS -> real_mode_seg
;
; Copy command line. Unfortunately, the kernel boot protocol requires
; the command line to exist in the 9xxxxh range even if the rest of the
@@ -2015,10 +2047,8 @@ need_high_cmdline:
shr cx,2 ; Convert to dwords
fs rep movsd
- push fs
- pop es
-
test byte [LoadFlags],LOAD_HIGH
+ ; Note bx -> real_mode_seg still
jnz in_proper_place ; If high load, we're done
;
@@ -2026,6 +2056,8 @@ need_high_cmdline:
;
; Copy real_mode stuff up to 90000h
;
+ mov ax,real_mode_seg
+ mov fs,ax
mov ax,9000h
mov es,ax
mov cx,[SetupSecs]
@@ -2051,8 +2083,6 @@ need_high_cmdline:
xor eax,eax
rep stosd ; Clear region
;
-; Copy the kernel down to the "low" location
-;
mov ecx,[KernelSize]
add ecx,3 ; Round upwards
shr ecx,2 ; Bytes -> dwords
@@ -2060,14 +2090,13 @@ need_high_cmdline:
mov edi,10000h
call bcopy
+ mov bx,9000h ; Real mode segment
+
;
; Now everything is where it needs to be...
;
-; When we get here, es points to the final segment, either
-; 9000h or real_mode_seg
-;
in_proper_place:
-
+ mov es,bx ; Real mode segment
;
; If the default root device is set to FLOPPY (0000h), change to
; /dev/fd0 (0200h)
@@ -2116,10 +2145,10 @@ kill_motor:
%endif
;
; Set up segment registers and the Linux real-mode stack
-; Note: es == the real mode segment
+; Note: bx == the real mode segment
;
cli
- mov bx,es
+ ; es is already == real mode segment
mov ds,bx
mov fs,bx
mov gs,bx
@@ -2281,7 +2310,7 @@ local_boot:
; 32-bit bcopy routine for real mode
;
; We enter protected mode, set up a flat 32-bit environment, run rep movsd
-; and then exit. IMPORTANT: This code assumes cs == 0.
+; and then exit. IMPORTANT: This code assumes cs == ss == 0.
;
; This code is probably excessively anal-retentive in its handling of
; segments, but this stuff is painful enough as it is without having to rely
@@ -2312,7 +2341,7 @@ bcopy: push eax
cli
call enable_a20
- o32 lgdt [cs:bcopy_gdt]
+ o32 lgdt [bcopy_gdt]
mov eax,cr0
or al,1
mov cr0,eax ; Enter protected mode
@@ -2590,111 +2619,53 @@ try_wbinvd:
;
; Load RAM disk into high memory
;
-; Need to be set:
-; su_ramdiskat - Where in memory to load
-; su_ramdisklen - Size of file
-; SI - initrd filehandle/cluster pointer
-;
loadinitrd:
push es ; Save ES on entry
- mov ax,real_mode_seg
+ mov ax,real_mode_seg
mov es,ax
- mov edi,[es:su_ramdiskat] ; initrd load address
+ mov si,[initrd_ptr]
+ mov edi,[InitRDat] ; initrd load address
+ mov [es:su_ramdiskat],edi ; Offset for ram disk
push si
- mov si,crlfloading_msg ; Write "Loading "
- call cwritestr
+ mov si,loading_msg
+ call cwritestr
mov si,InitRDCName ; Write ramdisk name
call cwritestr
mov si,dotdot_msg ; Write dots
call cwritestr
- pop si
-
- mov eax,[es:su_ramdisklen]
- call load_high ; Load the file
-
+rd_load_loop:
+ mov si,dot_msg ; Progress report
+ call cwritestr
+ pop si ; Restore cluster pointer
+ call abort_check
+ mov ecx,[InitRDClust]
+ cmp ecx,[ClustPerMoby]
+ jna rd_last_moby
+ mov ecx,[ClustPerMoby]
+rd_last_moby:
+ sub [InitRDClust],ecx
+ xor bx,bx ; Load at offset 0
+ push word xfer_buf_seg ; Bounce buffer segment
+ pop es
+ push cx
+ call getfssec
+ pop cx
+ push si ; Save cluster pointer
+ mov esi,(xfer_buf_seg << 4)
+ mov edi,[InitRDat]
+ mov ecx,4000h ; Copy 64K
+ call bcopy ; Does not change flags!!
+ jc rd_load_done ; EOF?
+ add dword [InitRDat],10000h ; Point to next 64K
+ cmp dword [InitRDClust],byte 0 ; Are we done?
+ jne rd_load_loop ; Apparently not
+rd_load_done:
+ pop si ; Clean up the stack
call crlf
- mov si,loading_msg ; Write new "Loading " for
- call cwritestr ; the benefit of the kernel
pop es ; Restore original ES
ret
;
-; load_high: loads (the remainder of) a file into high memory.
-; This routine prints dots for each 64K transferred, and
-; calls abort_check periodically.
-;
-; The xfer_buf_seg is used as a bounce buffer.
-;
-; The input address (EDI) should be dword aligned, and the final
-; dword written is padded with zeroes if necessary.
-;
-; Inputs: SI = file handle/cluster pointer
-; EDI = target address in high memory
-; EAX = size of remaining file in bytes
-;
-; Outputs: SI = file handle/cluster pointer
-; EDI = first untouched address (not including padding)
-;
-load_high:
- push es
-
- mov bx,xfer_buf_seg
- mov es,bx
-
-.read_loop:
- push si
- mov si,dot_msg
- call cwritestr
- pop si
- call abort_check
-
- push eax ; Total chunk to transfer
- cmp eax,(1 << 16) ; Max 64K in one transfer
- jna .size_ok
- mov eax,(1 << 16)
-.size_ok:
- cdq ; EDX <- 0
- push eax ; Bytes transferred this chunk
- div dword [ClustSize] ; Convert to clusters
- ; Round up...
- add edx,byte -1 ; Sets CF if EDX >= 1
- adc eax,byte 0 ; Add 1 to EAX if CF set
-
- ; Now (e)ax contains the number of clusters to get
- push edi
- mov cx,ax
- xor bx,bx ; ES:0
- call getfssec ; Load the data into xfer_buf_seg
- pop edi
- pop ecx ; Byte count this round
- push ecx
- push edi
-.fix_slop:
- test cl,3
- jz .noslop
- ; The last dword fractional - pad with zeroes
- ; Zero-padding is critical for multi-file initramfs.
- mov bx,cx
- mov byte [es:bx],0
- inc ecx
- jmp short .fix_slop
-.noslop:
- shr ecx,2 ; Convert to dwords
- push esi
- mov esi,(xfer_buf_seg << 4) ; Source address
- call bcopy ; Copy to high memory
- pop esi
- pop edi
- pop ecx
- pop eax
- add edi,ecx
- sub eax,ecx
- jnz .read_loop ; More to read...
-
- pop es
- ret
-
-;
; abort_check: let the user abort with <ESC> or <Ctrl-C>
;
abort_check:
@@ -4928,7 +4899,6 @@ localboot_msg db 'Booting from local disk...', CR, LF, 0
cmdline_msg db 'Command line: ', CR, LF, 0
ready_msg db ' ready.', CR, LF, 0
trying_msg db 'Trying to load: ', 0
-crlfloading_msg db CR, LF ; Fall through
loading_msg db 'Loading ', 0
dotdot_msg db '.'
dot_msg db '.', 0