diff options
author | hpa <hpa> | 2001-12-23 01:02:30 +0000 |
---|---|---|
committer | hpa <hpa> | 2001-12-23 01:02:30 +0000 |
commit | a0208c5997d850e3c8a6369f1bad8914114e4077 (patch) | |
tree | cec68e2621c00950f879b369aa4f16396155efc8 /isolinux.asm | |
parent | 61c13e1f40d68cac439a2a78061a61b71502012c (diff) | |
download | syslinux-a0208c5997d850e3c8a6369f1bad8914114e4077.tar.gz |
Code restructuring: common subroutine to load a file into high memory
Diffstat (limited to 'isolinux.asm')
-rw-r--r-- | isolinux.asm | 213 |
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 |