diff options
Diffstat (limited to 'ldlinux.asm')
-rw-r--r-- | ldlinux.asm | 207 |
1 files changed, 88 insertions, 119 deletions
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: |