Revamp runkernel.inc for "lengthless" operation
authorH. Peter Anvin <hpa@zytor.com>
Wed, 27 Feb 2008 01:18:59 +0000 (17:18 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 27 Feb 2008 01:18:59 +0000 (17:18 -0800)
Revamp runkernel.inc to be able to operate without a priori known
length.

kernel.inc
loadhigh.inc
pxelinux.asm
runkernel.inc
ui.inc

index ecf6698..0da0363 100644 (file)
@@ -56,10 +56,10 @@ su_heapend  resw 1                  ; 0224
 su_pad1                resw 1                  ; 0226
 su_cmd_line_ptr        resd 1                  ; 0228
 su_ramdisk_max resd 1                  ; 022C
-               resb (0e000h-12)-($-$$) ; Were bootsect.S puts it...
-linux_stack    equ $                   ; DFF4
+               resb (0f800h-12)-($-$$)
+linux_stack    equ $                   ; F7F4
 linux_fdctab   resb 12
-cmd_line_here  equ $                   ; E000 Should be out of the way
+cmd_line_here  equ $                   ; F800 Should be out of the way
                endstruc
 
 ;
@@ -72,6 +72,7 @@ CMD_MAGIC     equ 0A33Fh              ; Command line magic
 ; heap.
 ;
 old_cmd_line_here equ 9800h
+old_max_cmd_len   equ 2047
 old_linux_fdctab  equ old_cmd_line_here-12
 old_linux_stack   equ old_linux_fdctab
 
index b2e87f2..6304148 100644 (file)
 ;
 ;              The xfer_buf_seg is used as a bounce buffer.
 ;
+;              Assumes CS == DS.
+;
 ;              The input address (EDI) should be dword aligned, and the final
 ;              stretch 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
+;              EAX = maximum number of bytes to load
 ;              DX  = zero-padding mask (e.g. 0003h for pad to dword)
 ;              BX  = subroutine to call at the top of each loop
 ;                     (to print status and check for abort)
+;              MyHighMemSize = maximum load address
 ;
 ; Outputs:     SI  = file handle/cluster pointer
-;              EDI = first untouched address (not including padding)
+;              EBX = first untouched address (not including padding)
+;              EDI = first untouched address (including padding)
+;              CF  = reached EOF
 ;
 load_high:
                push es                         ; <AAA> ES
 
                mov cx,xfer_buf_seg
                mov es,cx
+               mov [PauseBird],bx
 
 .read_loop:
                and si,si                       ; If SI == 0 then we have end of file
                jz .eof
-               call bx
-               push bx                         ; <AA> Pausebird function
+               call [PauseBird]
 
                push eax                        ; <A> Total bytes to transfer
                cmp eax,(1 << 16)               ; Max 64K in one transfer
@@ -65,38 +70,51 @@ load_high:
                xor bx,bx                       ; ES:0
                call getfssec                   ; Load the data into xfer_buf_seg
                pop edi                         ; <C> Target buffer
-               pop ecx                         ; <B> Byte count this round
-               push ecx                        ; <B> Byte count this round
-               push edi                        ; <C> Target buffer
+               pushf                           ; <C> EOF status
+               lea ebx,[edi+ecx]               ; End of data
 .fix_slop:
                test cx,dx
                jz .noslop
                ; The last dword fractional - pad with zeroes
                ; Zero-padding is critical for multi-file initramfs.
                mov byte [es:ecx],0
-               inc ecx
+               inc cx
                jmp short .fix_slop
 .noslop:
+               lea eax,[edi+ecx]
+               cmp eax,[MyHighMemSize]
+               ja .overflow
+
                push esi                        ; <D> File handle/cluster pointer
                mov esi,(xfer_buf_seg << 4)     ; Source address
                call bcopy                      ; Copy to high memory
                pop esi                         ; <D> File handle/cluster pointer
-               pop edi                         ; <C> Target buffer
+               popf                            ; <C> EOF status
                pop ecx                         ; <B> Byte count this round
                pop eax                         ; <A> Total bytes to transfer
-               add edi,ecx
+               jc .eof
                sub eax,ecx
-               pop bx                          ; <AA> Pausebird function
-               jnz .read_loop                  ; More to read...
-
-
+               jnz .read_loop                  ; More to read... (if ZF=1 then CF=0)
 .eof:
                pop es                          ; <AAA> ES
                ret
 
+.overflow:     mov si,err_nohighmem
+               jmp abort_load
+
 dot_pause:
                push ax
                mov al,'.'
                call writechr
                pop ax
                jmp abort_check                 ; Handles the return
+
+               section .data
+err_nohighmem   db CR, LF
+               db 'Not enough memory to load specified image.', CR, LF, 0
+
+               section .bss
+               alignb 2
+PauseBird      resw 1
+
+               section .text
index 1a43a0c..041e146 100644 (file)
@@ -1603,6 +1603,7 @@ PXEEntry  equ pxe_thunk.jump+1
 ;  On exit:
 ;      SI      -> TFTP socket pointer (or 0 on EOF)
 ;      CF = 1  -> Hit EOF
+;      ECX     -> number of bytes actually read
 ;
 getfssec:      push si
                push fs
@@ -1613,6 +1614,7 @@ getfssec: push si
 
                movzx ecx,cx
                shl ecx,TFTP_BLOCKSIZE_LG2      ; Convert to bytes
+               push ecx                        ; Initial positioning
                jz .hit_eof                     ; Nothing to do?
 
 .need_more:
@@ -1635,26 +1637,29 @@ getfssec:       push si
                sub ecx,eax
                jnz .need_more
 
-
 .hit_eof:
+               pop eax                         ; Initial request amount
+               xchg eax,ecx
+               sub ecx,eax                     ; ... minus anything not gotten
                pop fs
                pop si
 
                ; Is there anything left of this?
                mov eax,[si+tftp_filesize]
                sub eax,[si+tftp_filepos]
-               jnz .bytes_left ; CF <- 0
+               jnz .bytes_left
 
                cmp [si+tftp_bytesleft],ax
-               jnz .bytes_left ; CF <- 0
+               jnz .bytes_left
 
                ; The socket is closed and the buffer drained
                ; Close socket structure and re-init for next user
                call free_socket
                stc
+               ret
 .bytes_left:
+               clc
                ret
-
 ;
 ; No data in buffer, check to see if we can get a packet...
 ;
@@ -1761,7 +1766,8 @@ get_packet:
                call ack_packet
                jmp .send_ok                    ; Reset timeout
 
-.right_packet: ; It's the packet we want.  We're also EOF if the size < blocksize
+.right_packet: ; It's the packet we want.  We're also EOF if the
+               ; size < blocksize
 
                pop cx                          ; <D> Don't need the retry count anymore
 
index 1a25a91..5cabbef 100644 (file)
 ; obsolete.
 ;
 is_linux_kernel:
-               cmp eax,1024                    ; Bootsect + 1 setup sect
-               jb kernel_corrupt
-kernel_sane:   push ax
-               push dx
-               push si
+               push si                         ; <A> file pointer
                mov si,loading_msg
                 call cwritestr
+                mov si,KernelCName             ; Print kernel name part of
+                call cwritestr                  ; "Loading" message
+
+
 ;
 ; Now start transferring the kernel
 ;
                push word real_mode_seg
                pop es
 
-               mov [KernelSize],eax
-               add eax,SECTOR_SIZE-1
-               shr eax,SECTOR_SHIFT
-                mov [KernelSects],eax          ; Total sectors in kernel
-
-;
-; Now, if we transfer these straight, we'll hit 64K boundaries.         Hence we
-; have to see if we're loading more than 64K, and if so, load it step by
-; step.
-;
-
 ;
 ; Start by loading the bootsector/setup code, to see if we need to
 ; do something funky.  It should fit in the first 32K (loading 64K won't
 ; work since we might have funny stuff up near the end of memory).
-; If we have larger than 32K clusters, yes, we're hosed.
-;
-               call abort_check                ; Check for abort key
-               mov ecx,8000h >> SECTOR_SHIFT   ; Half a moby (32K)
-               cmp ecx,[KernelSects]
-               jna .normalkernel
-               mov ecx,[KernelSects]
-.normalkernel:
-               sub [KernelSects],ecx
+;
+               call dot_pause                  ; Check for abort key
+               mov cx,8000h >> SECTOR_SHIFT    ; Half a moby (32K)
                xor bx,bx
-                pop si                          ; Cluster pointer on stack
+                pop si                          ; <A> file pointer
                call getfssec
+               cmp cx,1024
+               jb kernel_corrupt
                 cmp word [es:bs_bootsign],0AA55h
                jne kernel_corrupt              ; Boot sec signature missing
 
 ;
-; Save the cluster pointer for later...
-;
-               push si
-
-;
-; Initialize our end of memory pointer
+; Save the file pointer for later...
 ;
-               mov eax,[HighMemRsvd]
-               xor ax,ax                       ; Align to a 64K boundary
-               mov [MyHighMemSize],eax
+               push si                         ; <A> file pointer
 
 ;
 ; Construct the command line (append options have already been copied)
@@ -150,7 +128,7 @@ get_next_opt:   lodsb
                or byte [cs:KeepPXE],1
 .notkeep:
 %endif
-                push es                         ; Save ES -> real_mode_seg
+                push es                         ; <B> ES -> real_mode_seg
                 push cs
                 pop es                          ; Set ES <- normal DS
                 mov di,initrd_cmd
@@ -165,7 +143,7 @@ get_next_opt:   lodsb
 .noramdisk:
                xor ax,ax
                mov [cs:InitRDPtr],ax
-.not_initrd:   pop es                          ; Restore ES -> real_mode_seg
+.not_initrd:   pop es                          ; <B> ES -> real_mode_seg
 skip_this_opt:  lodsb                           ; Load from command line
                 cmp al,' '
                 ja skip_this_opt
@@ -237,6 +215,16 @@ new_kernel:
 ;
                 mov al,[es:su_loadflags]
                mov [LoadFlags],al
+
+               ; Cap the ramdisk memory range if appropriate
+               mov eax,[RamdiskMax]
+               cmp eax,[MyHighMemSize]
+               ja .ok
+               mov [MyHighMemSize],eax
+.ok:
+
+any_kernel:
+
 ;
 ; Load the kernel.  We always load it at 100000h even if we're supposed to
 ; load it "low"; for a "low" load we copy it down to low memory right before
@@ -248,46 +236,33 @@ read_kernel:
                jnz .sects_ok
                mov al,4                        ; 0 = 4 setup sectors
 .sects_ok:
+               inc ax                          ; Including the boot sector
                mov [SetupSecs],ax
 
-                mov si,KernelCName             ; Print kernel name part of
-                call cwritestr                  ; "Loading" message
-                mov si,dotdot_msg              ; Print dots
-                call cwritestr
+               call dot_pause
 
-                mov eax,[MyHighMemSize]
-               sub eax,100000h                 ; Load address
-               cmp eax,[KernelSize]
-               jb no_high_mem          ; Not enough high memory
 ;
 ; Move the stuff beyond the setup code to high memory at 100000h
 ;
                movzx esi,word [SetupSecs]      ; Setup sectors
-               inc si                          ; plus 1 boot sector
                 shl si,9                       ; Convert to bytes
                 mov ecx,8000h                  ; 32K
                sub ecx,esi                     ; Number of bytes to copy
-               push ecx
                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
+               pop si                          ; <A> File pointer
+               and si,si                       ; EOF already?
+               jz high_load_done
 
-                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,8000h                   ; Amount of kernel not yet loaded
-               jbe high_load_done              ; Zero left (tiny kernel)
+               ; On exit EDI -> where to load the rest
 
-               xor dx,dx                       ; No padding needed
-               mov bx,dot_pause                ; Print dots...
-               call load_high                  ; Copy the file
+               mov bx,dot_pause
+               or eax,-1                       ; Load the whole file
+               mov dx,3                        ; Pad to dword
+               call load_high
 
 high_load_done:
                mov [KernelEnd],edi
@@ -296,6 +271,19 @@ high_load_done:
 
                 mov si,dot_msg
                 call cwritestr
+;
+; Some older kernels (1.2 era) would have more than 4 setup sectors, but
+; would not rely on the boot protocol to manage that.  These kernels fail
+; if they see protected-mode kernel data after the setup sectors, so
+; clear that memory.
+;
+               mov di,[SetupSecs]
+               shl di,9
+               xor eax,eax
+               mov cx,cmd_line_here
+               sub cx,di
+               shr cx,2
+               rep stosd
 
 ;
 ; Now see if we have an initial RAMdisk; if so, do requisite computation
@@ -303,10 +291,12 @@ high_load_done:
 ; if we tried to load initrd using an old kernel
 ;
 load_initrd:
-                cmp word [InitRDPtr],0
-                jz nk_noinitrd
+               xor eax,eax
+                cmp [InitRDPtr],ax
+                jz .noinitrd
                call parse_load_initrd
-nk_noinitrd:
+.noinitrd:
+
 ;
 ; Abandon hope, ye that enter here!  We do no longer permit aborts.
 ;
@@ -315,8 +305,6 @@ nk_noinitrd:
                mov si,ready_msg
                call cwritestr
 
-               call vgaclearmode               ; We can't trust ourselves after this
-
                UNLOAD_PREP                     ; Module-specific hook
 
 ;
@@ -329,24 +317,34 @@ nk_noinitrd:
                mov fs,ax
 
 ;
+; If the default root device is set to FLOPPY (0000h), change to
+; /dev/fd0 (0200h)
+;
+               cmp word [es:bs_rootdev],byte 0
+               jne root_not_floppy
+               mov word [es:bs_rootdev],0200h
+root_not_floppy:
+
+;
 ; Copy command line.  Unfortunately, the old kernel boot protocol requires
 ; the command line to exist in the 9xxxxh range even if the rest of the
 ; setup doesn't.
 ;
 setup_command_line:
-               cli                             ; In case of hooked interrupts
                mov dx,[KernelVersion]
                test byte [LoadFlags],LOAD_HIGH
-               jz need_high_cmdline
+               jz .need_high_cmdline
                cmp dx,0202h                    ; Support new cmdline protocol?
-               jb need_high_cmdline
+               jb .need_high_cmdline
                ; New cmdline protocol
                ; Store 32-bit (flat) pointer to command line
                ; This is the "high" location, since we have bzImage
                mov dword [fs:su_cmd_line_ptr],(real_mode_seg << 4)+cmd_line_here
-               jmp in_proper_place
+               mov word [HeapEnd],linux_stack
+               mov word [fs:su_heapend],linux_stack-512
+               jmp .setup_done
 
-need_high_cmdline:
+.need_high_cmdline:
 ;
 ; Copy command line down to fit in high conventional memory
 ; -- this happens if we have a zImage kernel or the protocol
@@ -368,7 +366,7 @@ need_high_cmdline:
                ; because we have a zImage, so we anticipate the move
                ; to 90000h already...
                mov dword [fs:su_cmd_line_ptr],0x90000+old_cmd_line_here
-               mov ax,4095                     ; 2.02+ allow a higher limit
+               mov ax,old_max_cmd_len          ; 2.02+ allow a higher limit
 .adjusted:
 
                mov cx,[CmdLineLen]
@@ -378,112 +376,112 @@ need_high_cmdline:
 .len_ok:
                fs rep movsb
                stosb                           ; Final null, note AL=0 already
+               mov [CmdLineEnd],di
                cmp dx,0200h
                jb .nomovesize
                mov [es:su_movesize],di         ; Tell the kernel what to move
 .nomovesize:
+.setup_done:
 
-               test byte [LoadFlags],LOAD_HIGH
-               jnz in_proper_place             ; If high load, we're done
-
-;
-; Loading low; we can't assume it's safe to run in place.
-;
-; Copy real_mode stuff up to 90000h
-;
-               mov ax,9000h
-               mov es,ax
-               mov cx,di                       ; == su_movesize (from above)
-               add cx,3                        ; Round up
-               shr cx,2                        ; Convert to dwords
-               xor si,si
-               xor di,di
-               fs rep movsd                    ; Copy setup + boot sector
-;
-; Some kernels in the 1.2 ballpark but pre-bzImage have more than 4
-; setup sectors, but the boot protocol had not yet been defined.  They
-; rely on a signature to figure out if they need to copy stuff from
-; the "protected mode" kernel area.  Unfortunately, we used that area
-; as a transfer buffer, so it's going to find the signature there.
-; Hence, zero the low 32K beyond the setup area.
-;
-               mov di,[SetupSecs]
-               inc di                          ; Setup + boot sector
-               mov cx,32768/512                ; Sectors/32K
-               sub cx,di                       ; Remaining sectors
-               shl di,9                        ; Sectors -> bytes
-               shl cx,7                        ; Sectors -> dwords
-               xor eax,eax
-               rep stosd                       ; Clear region
-;
-; Copy the kernel down to the "low" location (the kernel will then
-; move itself again, sigh.)
-;
-               mov ecx,[KernelSize]
-               mov esi,100000h
-               mov edi,10000h
-               call bcopy
-
-;
-; Now everything is where it needs to be...
 ;
-; When we get here, es points to the final segment, either
-; 9000h or real_mode_seg
+; Time to start setting up move descriptors
 ;
-in_proper_place:
+setup_move:
+               mov di,trackbuf
+               xor cx,cx                       ; Number of descriptors
 
-;
-; If the default root device is set to FLOPPY (0000h), change to
-; /dev/fd0 (0200h)
-;
-               cmp word [es:bs_rootdev],byte 0
-               jne root_not_floppy
-               mov word [es:bs_rootdev],0200h
-root_not_floppy:
+               mov bx,es                       ; real_mode_seg
+               mov fs,bx
+               push ds                         ; We need DS == ES == CS here
+               pop es
 
-;
-; Copy the disk table to high memory, then re-initialize the floppy
-; controller
-;
-%if IS_SYSLINUX || IS_MDSLINUX
-               lgs si,[cs:fdctab]
-               mov di,[cs:HeapEnd]
-               mov cx,6
-               gs rep movsw
-               mov [cs:fdctab],word linux_fdctab ; Save new floppy tab pos
-               mov [cs:fdctab+2],es
+               test byte [LoadFlags],LOAD_HIGH
+               jnz .loading_high
+
+; Loading low: move real_mode stuff to 90000h, then move the kernel down
+               mov eax,90000h
+               stosd
+               mov eax,real_mode_seg << 4
+               stosd
+               movzx eax,word [CmdLineEnd]
+               stosd
+               inc cx
+
+               mov eax,10000h                  ; Target address of low kernel
+               stosd
+               mov eax,100000h                 ; Where currently loaded
+               stosd
+               neg eax
+               add eax,[KernelEnd]
+               stosd
+               inc cx
+
+               mov bx,9000h                    ; Revised real mode segment
+
+.loading_high:
+
+               cmp word [InitRDPtr],0          ; Did we have an initrd?
+               je .no_initrd
+
+               mov eax,[fs:su_ramdiskat]
+               stosd
+               mov eax,[InitRDStart]
+               stosd
+               mov eax,[fs:su_ramdisklen]
+               stosd
+               inc cx
+
+.no_initrd:
+               push cx                         ; Length of descriptor list
+               push word trackbuf
+
+%ifdef DEBUG_TRACERS
+               pushad
+               mov si,trackbuf
+.foo:
+               lodsd
+               call writehex8
+               mov al,'.'
+               call writechr
+               lodsd
+               call writehex8
+               mov al,'.'
+               call writechr
+               lodsd
+               call writehex8
+               call crlf
+               loop .foo
+               popad
 %endif
 
-               call cleanup_hardware
-;
-; If we're debugging, wait for a keypress so we can read any debug messages
-;
-%ifdef debug
-                xor ax,ax
-                int 16h
-%endif
+               mov dword [EntryPoint],run_linux_kernel
+               ; BX points to the final real mode segment, and will be loaded
+               ; into DS.
+               jmp replace_bootstrap
+
+
+run_linux_kernel:
 ;
 ; Set up segment registers and the Linux real-mode stack
-; Note: es == the real mode segment
+; Note: ds == the real mode segment
 ;
-
                cli
-               mov bx,es
-               mov ds,bx
-               mov fs,bx
-               mov gs,bx
-               mov ss,bx
+               mov ax,ds
+               mov ss,ax
                mov sp,strict word linux_stack
                ; Point HeapEnd to the immediate of the instruction above
 HeapEnd                equ $-2                 ; Self-modifying code!  Fun!
+               mov es,ax
+               mov fs,ax
+               mov gs,ax
 
 ;
 ; We're done... now RUN THAT KERNEL!!!!
 ; Setup segment == real mode segment + 020h; we need to jump to offset
 ; zero in the real mode segment.
 ;
-               add bx,020h
-               push bx
+               add ax,020h
+               push ax
                push word 0h
                retf
 
@@ -500,14 +498,16 @@ old_kernel:
 .load:
                mov byte [LoadFlags],al         ; Always low
                mov word [KernelVersion],ax     ; Version 0.00
-               jmp read_kernel
+               jmp any_kernel
 
 ;
 ; parse_load_initrd
 ;
-; Parse an initrd= option and load the initrds.  Note that we load
-; from the high end of memory first, so we parse this option from
-; left to right.
+; Parse an initrd= option and load the initrds.  This sets
+; InitRDStart and InitRDEnd with dword padding between; we then
+; do a global memory shuffle to move it to the end of memory.
+;
+; On entry, EDI points to where to start loading.
 ;
 parse_load_initrd:
                push es
@@ -517,47 +517,50 @@ parse_load_initrd:
                push cs
                pop es                  ; DS == real_mode_seg, ES == CS
 
+               mov [cs:InitRDStart],edi
+               mov [cs:InitRDEnd],edi
+
                mov si,[cs:InitRDPtr]
-.find_end:
-               lodsb
-               cmp al,' '
-               ja .find_end
-               ; Now SI points to one character beyond the
-               ; byte that ended this option.
 
 .get_chunk:
-               dec si
-
-               ; DS:SI points to a termination byte
-
-               xor ax,ax
-               xchg al,[si]            ; Zero-terminate
-               push si                 ; Save ending byte address
-               push ax                 ; Save ending byte
+               ; DS:SI points to the start of a name
 
-.find_start:
-               dec si
-               cmp si,[cs:InitRDPtr]
-               je .got_start
-               cmp byte [si],','
-               jne .find_start
+               mov bx,si
+.find_end:
+               lodsb
+               cmp al,','
+               je .got_end
+               cmp al,' '
+               jbe .got_end
+               jmp .find_end
 
-               ; It's a comma byte
-               inc si
+.got_end:
+               push ax                 ; Terminating character
+               push si                 ; Next filename (if any)
+               mov byte [si-1],0       ; Zero-terminate
+               mov si,bx               ; Current filename
 
-.got_start:
-               push si
+               push di
                mov di,InitRD           ; Target buffer for mangled name
                call mangle_name
+               pop di
                call loadinitrd
-               pop si
 
+               pop si
                pop ax
-               pop di
-               mov [di],al             ; Restore ending byte
+               mov [si-1],al           ; Restore ending byte
+
+               cmp al,','
+               je .get_chunk
 
-               cmp si,[cs:InitRDPtr]
-               ja .get_chunk
+               ; Compute the initrd target location
+               mov edx,[cs:InitRDEnd]
+               sub edx,[cs:InitRDStart]
+               mov [su_ramdisklen],edx
+               mov eax,[cs:MyHighMemSize]
+               sub eax,edx
+               and ax,0F000h           ; Round to a page boundary
+               mov [su_ramdiskat],eax
 
                pop ds
                pop es
@@ -567,6 +570,9 @@ parse_load_initrd:
 ; Load RAM disk into high memory
 ;
 ; Input:       InitRD          - set to the mangled name of the initrd
+;              EDI             - location to load
+; Output:      EDI             - location for next initrd
+;              InitRDEnd       - updated
 ;
 loadinitrd:
                push ds
@@ -574,6 +580,7 @@ loadinitrd:
                mov ax,cs                       ; CS == DS == ES
                mov ds,ax
                mov es,ax
+               push edi
                 mov si,InitRD
                 mov di,InitRDCName
                 call unmangle_name              ; Create human-readable name
@@ -581,42 +588,8 @@ loadinitrd:
                 mov [InitRDCNameLen],di
                 mov di,InitRD
                 call searchdir                  ; Look for it in directory
+               pop edi
                jz .notthere
-               mov ecx,eax                     ; ECX <- ram disk length
-
-               mov ax,real_mode_seg
-               mov es,ax
-
-               push ecx                        ; Bytes to load
-               mov edx,[MyHighMemSize]         ; End of memory
-               dec edx
-               mov eax,[RamdiskMax]            ; Highest address allowed by kernel
-               cmp edx,eax
-               jna .memsize_ok
-               mov edx,eax                     ; Adjust to fit inside limit
-.memsize_ok:
-               inc edx
-                and dx,0F000h                  ; Round down to 4K boundary
-               sub edx,ecx                     ; Subtract size of ramdisk
-                and dx,0F000h                  ; Round down to 4K boundary
-               cmp edx,[KernelEnd]             ; Are we hitting the kernel image?
-               jb no_high_mem
-
-               cmp dword [es:su_ramdisklen],0
-               je .highest
-               ; The total length has to include the padding between
-               ; different ramdisk files, so consider "the length" the
-               ; total amount we're about to adjust the base pointer.
-               mov ecx,[es:su_ramdiskat]
-               sub ecx,edx
-.highest:
-               add [es:su_ramdisklen],ecx
-
-                mov [es:su_ramdiskat],edx      ; Load address
-                mov edi,edx                    ; initrd load address
-
-               dec edx                         ; Note: RamdiskMax is addr-1
-               mov [RamdiskMax],edx            ; Next initrd loaded here
 
                push si
                mov si,crlfloading_msg          ; Write "Loading "
@@ -627,10 +600,10 @@ loadinitrd:
                 call cwritestr
                pop si
 
-               pop eax                         ; Bytes to load
-               mov dx,0FFFh                    ; Pad to page
-               mov bx,dot_pause                ; Print dots...
-               call load_high                  ; Load the file
+               mov dx,3
+               mov bx,dot_pause
+               call load_high
+               mov [InitRDEnd],ebx
 
                pop es
                pop ds
@@ -659,7 +632,6 @@ ready_msg   db 'ready.', CR, LF, 0
 err_oldkernel   db 'Cannot load a ramdisk with an old kernel image.'
                 db CR, LF, 0
 err_noinitrd    db CR, LF, 'Could not find ramdisk image: ', 0
-err_nohighmem   db 'Not enough memory to load specified kernel.', CR, LF, 0
 
 boot_image      db 'BOOT_IMAGE='
 boot_image_len  equ $-boot_image
@@ -671,8 +643,11 @@ RamdiskMax resd 1                  ; Highest address for ramdisk
 KernelSize     resd 1                  ; Size of kernel in bytes
 KernelSects    resd 1                  ; Size of kernel in sectors
 KernelEnd      resd 1                  ; Ending address of the kernel image
+InitRDStart    resd 1                  ; Start of initrd (pre-relocation)
+InitRDEnd      resd 1                  ; End of initrd (pre-relocation)
 CmdLineLen     resw 1                  ; Length of command line including null
-SetupSecs      resw 1                  ; Number of setup sectors
+CmdLineEnd     resw 1                  ; End of the command line in real_mode_seg
+SetupSecs      resw 1                  ; Number of setup sectors (+bootsect)
 InitRDPtr      resw 1                  ; Pointer to initrd= option in command line
 KernelVersion  resw 1                  ; Kernel protocol version
 LoadFlags      resb 1                  ; Loadflags from kernel
diff --git a/ui.inc b/ui.inc
index 7d86f00..0677733 100644 (file)
--- a/ui.inc
+++ b/ui.inc
@@ -537,11 +537,17 @@ kernel_good_saved:
 
 kernel_good:
                pushad
+
                mov si,KernelName
                mov di,KernelCName
                call unmangle_name
                sub di,KernelCName
                mov [KernelCNameLen],di
+
+               ; Default memory limit, can be overridden by image loaders
+               mov eax,[HighMemRsvd]
+               mov [MyHighMemSize],eax
+
                popad
 
                push di