summaryrefslogtreecommitdiff
path: root/isolinux.asm
diff options
context:
space:
mode:
authorhpa <hpa>2001-12-23 01:02:30 +0000
committerhpa <hpa>2001-12-23 01:02:30 +0000
commita0208c5997d850e3c8a6369f1bad8914114e4077 (patch)
treecec68e2621c00950f879b369aa4f16396155efc8 /isolinux.asm
parent61c13e1f40d68cac439a2a78061a61b71502012c (diff)
downloadsyslinux-a0208c5997d850e3c8a6369f1bad8914114e4077.tar.gz
Code restructuring: common subroutine to load a file into high memory
Diffstat (limited to 'isolinux.asm')
-rw-r--r--isolinux.asm213
1 files changed, 122 insertions, 91 deletions
diff --git a/isolinux.asm b/isolinux.asm
index 903e6fe7..e5d867d3 100644
--- a/isolinux.asm
+++ b/isolinux.asm
@@ -306,7 +306,6 @@ 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
@@ -315,7 +314,6 @@ 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
@@ -2005,53 +2003,35 @@ read_kernel:
movzx esi,word [SetupSecs] ; Setup sectors
inc esi ; plus 1 boot sector
shl esi,9 ; Convert to bytes
- mov ecx,108000h ; 108000h = 1M + 32K
- sub ecx,esi ; Adjust pointer to 2nd block
- mov [HiLoadAddr],ecx
- sub ecx,100000h ; Turn into a counter
+ mov ecx,8000h ; 32K
+ sub ecx,esi ; Number of bytes to copy
+ push ecx
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
- push word xfer_buf_seg ; Transfer buffer segment
- pop es
-high_load_loop:
+ ; On exit EDI -> where to load the rest
+
mov si,dot_msg ; Progress report
call cwritestr
call abort_check
- 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
+
+ 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
+
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
@@ -2072,18 +2052,8 @@ 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
@@ -2094,7 +2064,7 @@ memsize_ok:
inc edx
sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk
xor dx,dx ; Round down to 64K boundary
- mov [InitRDat],edx ; Load address
+ mov [es:su_ramdiskat],edx ; Load address
call loadinitrd ; Load initial ramdisk
jmp short initrd_end
@@ -2131,8 +2101,7 @@ 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
@@ -2164,8 +2133,10 @@ 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
;
@@ -2173,8 +2144,6 @@ 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]
@@ -2200,6 +2169,8 @@ 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
@@ -2207,13 +2178,14 @@ 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)
@@ -2262,10 +2234,10 @@ kill_motor:
%endif
;
; Set up segment registers and the Linux real-mode stack
-; Note: bx == the real mode segment
+; Note: es == the real mode segment
;
cli
- ; es is already == real mode segment
+ mov bx,es
mov ds,bx
mov fs,bx
mov gs,bx
@@ -2577,7 +2549,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 == ss == 0.
+; and then exit. IMPORTANT: This code assumes cs == 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
@@ -2608,7 +2580,7 @@ bcopy: push eax
cli
call enable_a20
- o32 lgdt [bcopy_gdt]
+ o32 lgdt [cs:bcopy_gdt]
mov eax,cr0
or al,1
mov cr0,eax ; Enter protected mode
@@ -2886,53 +2858,111 @@ 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 si,[initrd_ptr]
- mov edi,[InitRDat] ; initrd load address
- mov [es:su_ramdiskat],edi ; Offset for ram disk
+ mov edi,[es:su_ramdiskat] ; initrd load address
push si
- mov si,loading_msg
- call cwritestr
+ mov si,crlfloading_msg ; Write "Loading "
+ call cwritestr
mov si,InitRDCName ; Write ramdisk name
call cwritestr
mov si,dotdot_msg ; Write dots
call cwritestr
-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
+ pop si
+
+ mov eax,[es:su_ramdisklen]
+ call load_high ; Load the file
+
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:
@@ -4471,6 +4501,7 @@ 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