diff options
author | hpa <hpa> | 2005-01-06 22:34:06 +0000 |
---|---|---|
committer | hpa <hpa> | 2005-01-06 22:34:06 +0000 |
commit | a966e54c41674cfb72340fd436bdf85988c14dd7 (patch) | |
tree | 93d244d27e6c2f9a6bca7b2432ba66c841be57fb | |
parent | fb7489b14bc413a373e4138157a34e2683a1aa26 (diff) | |
download | syslinux-elf-a966e54c41674cfb72340fd436bdf85988c14dd7.tar.gz syslinux-elf-a966e54c41674cfb72340fd436bdf85988c14dd7.tar.xz syslinux-elf-a966e54c41674cfb72340fd436bdf85988c14dd7.zip |
Commit 3.10 changes to mainline. In particular, support multi-file
initrd, and the shuffle and boot API.
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | bcopy32.inc | 86 | ||||
-rw-r--r-- | bootsect.inc | 36 | ||||
-rw-r--r-- | com32.inc | 1 | ||||
-rw-r--r-- | comboot.doc | 66 | ||||
-rw-r--r-- | comboot.inc | 91 | ||||
-rw-r--r-- | ext2_fs.inc | 6 | ||||
-rw-r--r-- | kernel.inc | 2 | ||||
-rw-r--r-- | loadhigh.inc | 5 | ||||
-rw-r--r-- | memdisk/setup.c | 3 | ||||
-rw-r--r-- | parseconfig.inc | 2 | ||||
-rw-r--r-- | runkernel.inc | 215 | ||||
-rw-r--r-- | version | 2 |
14 files changed, 384 insertions, 146 deletions
@@ -1,7 +1,7 @@ ## $Id$ ## ----------------------------------------------------------------------- ## -## Copyright 1998-2004 H. Peter Anvin - All Rights Reserved +## Copyright 1998-2005 H. Peter Anvin - All Rights Reserved ## ## 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 @@ -50,7 +50,7 @@ VERSION = $(shell cat version) # directories. # CSRC = syslxmod.c gethostip.c -NASMSRC = ldlinux.asm copybs.asm pxelinux.asm mbr.asm isolinux.asm +NASMSRC = $(wildcard *.asm) SOURCES = $(CSRC) *.h $(NASMSRC) *.inc # _bin.c files required by both BTARGET and ITARGET installers @@ -2,7 +2,16 @@ Starting with 1.47, changes marked with SYSLINUX/PXELINUX/ISOLINUX apply to that specific program only; other changes apply to all of them. -Changes in 3.03: +Changes in 3.10: + * New API function "shuffle and boot"; allows COM32 modules to + load or construct (almost) arbitrarily complex objects, + e.g. a kernel and its initrd/initramfs in pieces, and have + the API core reorganize memory for booting. + * The initrd= option now supports multiple filenames separated + by commas. This is mostly useful for initramfs, which can + be composed of multiple separate cpio or cpio.gz archives. + (Note: all files except the last one are zero-padded to a 4K + page boundary. This should not affect initramfs.) * EXTLINUX: Fix API function 000Ah (get derivative-specific info). * libcom32/ethersel: Support PCI Config Mechanism #2 on diff --git a/bcopy32.inc b/bcopy32.inc index 7d049b73..9eb782e2 100644 --- a/bcopy32.inc +++ b/bcopy32.inc @@ -1,7 +1,7 @@ ;; $Id$ ;; ----------------------------------------------------------------------- ;; -;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved +;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved ;; ;; 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 @@ -56,7 +56,7 @@ bcopy_gdt_size: equ $-bcopy_gdt ; ; bcopy: -; 32-bit copy +; 32-bit copy, overlap safe ; ; Inputs: ; ESI - source pointer @@ -70,13 +70,12 @@ bcopy_gdt_size: equ $-bcopy_gdt ; ECX - zero ; bcopy: push eax + push esi + push edi + push ecx pushf ; Saves, among others, the IF flag - push gs - push fs push ds push es - mov [cs:SavedSSSP],sp - mov [cs:SavedSSSP+2],ss cli call enable_a20 @@ -91,21 +90,45 @@ bcopy: push eax mov es,ax mov ds,ax - mov al,18h ; "Real-mode-like" data segment - mov ss,ax - mov fs,ax - mov gs,ax + ; Don't mess with ss, fs, and gs. They are never changed + ; and should be able to make it back out of protected mode. + ; This works because (and only because) we don't take + ; interrupt in protected mode. + cmp esi,edi ; If source > destination, we might + ja .reverse ; have to copy backwards + +.forward: mov al,cl ; Save low bits + and al,3 shr ecx,2 ; Convert to dwords a32 rep movsd ; Do our business ; At this point ecx == 0 mov cl,al ; Copy any fractional dword - and cl,3 a32 rep movsb + jmp .exit + +.reverse: + std ; Reverse copy + lea esi,[esi+ecx-1] ; Point to final byte + lea edi,[edi+ecx-1] + mov eax,ecx + and ecx,3 + shr eax,2 + a32 rep movsb + + ; Change ESI/EDI to point to the last dword, instead + ; of the last byte. + sub esi,3 + sub edi,3 + mov ecx,eax + a32 rep movsd - mov al,18h ; "Real-mode-like" data segment + cld + +.exit: + mov ax,18h ; "Real-mode-like" data segment mov es,ax mov ds,ax @@ -115,15 +138,17 @@ bcopy: push eax jmp 0:.in_rm .in_rm: ; Back in real mode - lss sp,[cs:SavedSSSP] pop es pop ds - pop fs - pop gs call disable_a20 popf ; Re-enables interrupts pop eax + pop edi + pop esi + add edi,eax + add esi,eax + pop eax ret ; @@ -372,8 +397,9 @@ try_wbinvd: ; ; bcopy_over_self: ; -; This routine is used to copy large blocks of code on top of -; conventional memory (to 0:7c00). We therefore have to move +; This routine is used to shuffle memory around, followed by +; invoking an entry point somewhere in low memory. This routine +; can clobber any memory above 7C00h, we therefore have to move ; necessary code into the trackbuf area before doing the copy, ; and do adjustments to anything except BSS area references. ; @@ -381,25 +407,37 @@ try_wbinvd: ; references in the ".earlybss" segment. ; ; After performing the copy, this routine resets the stack and -; jumps to 0:7c00. +; jumps to the specified entrypoint. ; ; IMPORTANT: This routine does not canonicalize the stack or the ; SS register. That is the responsibility of the caller. ; ; Inputs: -; ESI, EDI, ECX - same as bcopy +; DS:BX -> Pointer to list of (dst, src, len) pairs +; AX -> Number of list entries +; [CS:EntryPoint] -> CS:IP to jump to ; On stack - initial state (fd, ad, ds, es, fs, gs) ; -bcopy_over_self: +shuffle_and_boot: + and ax,ax + jz .done +.loop: + mov edi,[bx] + mov esi,[bx+4] + mov ecx,[bx+8] call bcopy - + add bx,12 + dec ax + jnz .loop + +.done: pop gs pop fs pop es pop ds popad popfd - jmp 0:7c00h + jmp far [cs:EntryPoint] align 2 A20List dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast @@ -414,9 +452,7 @@ __bcopy_size equ $-__bcopy_start section .earlybss alignb 2 +EntryPoint resd 1 ; CS:IP for shuffle_and_boot SavedSSSP resd 1 ; Saved real mode SS:SP A20Test resw 1 ; Counter for testing status of A20 A20Tries resb 1 ; Times until giving up on A20 - - - diff --git a/bootsect.inc b/bootsect.inc index f901cf5e..67ce6762 100644 --- a/bootsect.inc +++ b/bootsect.inc @@ -1,7 +1,7 @@ ;; $Id$ ;; ----------------------------------------------------------------------- ;; -;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved +;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved ;; ;; 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 @@ -39,12 +39,18 @@ load_bootsec: shl eax,16 xchg dx,ax ; Now EAX = file length mov edi, 100000h + mov [trackbuf+4],edi ; Copy from this address push edi ; Save load address + xor dx,dx ; No padding call load_high call crlf sub edi,100000h - push edi ; Save length + mov [trackbuf+8],edi ; Save length + + mov eax,7C00h ; Entry point + mov [trackbuf],eax ; Copy to this address + mov [EntryPoint],eax ; Jump to this address when done %if IS_SYSLINUX || IS_MDSLINUX movzx ecx,byte [CopySuper] @@ -81,15 +87,24 @@ load_bootsec: %endif xor bx,bx +; +; replace_bootstrap for the special case where we have exactly one +; descriptor, and it's the first entry in the trackbuf +; + +replace_bootstrap_one: + push word trackbuf ; Address of descriptor list + push word 1 ; Length of descriptor list + ; Fall through + ; ; Entrypoint for "shut down and replace bootstrap" -- also invoked by -; the COMBOOT API. This routine expects two dword on the stack: -; linear address and length. Additionally, the values of ESI and EDX -; are passed on to the new bootstrap; the value of BX becomes the new -; DS. +; the COMBOOT API. This routine expects two words on the stack: +; address of the copy list (versus DS) and count. Additionally, +; the values of ESI and EDX are passed on to the new bootstrap; +; the value of BX becomes the new DS. ; replace_bootstrap: - ; ; Prepare for shutting down ; @@ -120,16 +135,15 @@ replace_bootstrap: mov [es:di+12],esi mov [es:di+6],bx - pop ecx ; Byte count to copy - pop esi ; Copy from... + pop cx ; Copy list count + pop bx ; Copy from... cli mov ax,es mov ss,ax movzx esp,di - mov edi,7C00h ; Copy to... - jmp bcopy_over_self + jmp shuffle_and_boot %if IS_SYSLINUX || IS_MDSLINUX ; Nothing @@ -64,6 +64,7 @@ is_com32_image: mov edi,pm_entry ; Load address pop eax ; File length pop si ; File handle + xor dx,dx ; No padding call load_high call crlf diff --git a/comboot.doc b/comboot.doc index b717d0b7..b8de94ea 100644 --- a/comboot.doc +++ b/comboot.doc @@ -423,10 +423,10 @@ AX=000Ah [2.00] Get Derivative-Specific Information AX=000Bh [2.00] Get Serial Console Configuration Input: AX 000Bh - Output: DX Serial port I/O base (e.g. 3F8h = COM1...) - CX Baud rate divisor (1 = 115200 bps, 2 = 57600 bps...) - BX Flow control configuration bits (see syslinux.doc) - -> Bit 15 is set if the video console is disabled + Output: DX serial port I/O base (e.g. 3F8h = COM1...) + CX baud rate divisor (1 = 115200 bps, 2 = 57600 bps...) + BX flow control configuration bits (see syslinux.doc) + -> bit 15 is set if the video console is disabled If no serial port is configured, DX will be set to 0 and the other registers are undefined. @@ -447,7 +447,7 @@ AX=000Ch [2.00] Perform final cleanup For COM32 images, the boot loader will continue to provide interrupt and BIOS call thunking services as long its memory - areas (0x1000-0xffff, 0x100000-0x100fff) are not overwritten. + areas (0x0800-0xffff, 0x100000-0x100fff) are not overwritten. MAKE SURE TO DISABLE INTERRUPTS, AND INSTALL NEW GDT AND IDTS BEFORE OVERWRITING THESE MEMORY AREAS. @@ -499,10 +499,10 @@ AX=000Eh [2.11] Get configuration file name AX=000Fh [3.00] Get IPAPPEND strings [PXELINUX] Input: AX 000Fh - Output: CX Number of strings (currently 2) - ES:BX Pointer to an array of NEAR pointers in + Output: CX number of strings (currently 2) + ES:BX pointer to an array of NEAR pointers in the same segment, one for each of the above - strings. + strings Returns the same strings that the "ipappend" option would have added to the command line, one for each bit of the "ipappend" @@ -511,7 +511,7 @@ AX=000Fh [3.00] Get IPAPPEND strings [PXELINUX] AX=0010h [3.00] Resolve hostname [PXELINUX] - Input: ES:BX Pointer to null-terminated hostname + Input: ES:BX pointer to null-terminated hostname Output: EAX IP address of hostname (zero if not found) Queries the DNS server(s) for a specific hostname. If the @@ -527,3 +527,51 @@ AX=0010h [3.00] Resolve hostname [PXELINUX] all uses of IP addresses in PXE are also in network byte order. +AX=0011h [3.10] Maximum number of shuffle descriptors + Input: AX 0011h + Output: CX maximum number of descriptors + + This routine reports the maximum number of shuffle descriptors + permitted in a call to function 0012h. + + Typical values are 682 and 1365. + + +AX=0012h [3.10] Cleanup, shuffle and boot + Input: AX 0012h + DX derivative-specific flags (see previous function) + ES:DI shuffle descriptor list (must be in low memory) + CX number of shuffle descriptors + EBX(!) initial value of EDX after bootstrap + ESI initial value of ESI after bootstrap + DS initial value of DS after bootstrap + EBP CS:IP of routine to jump to + Output: Does not return + (if CX is too large the routine returns with CF=1) + + This routine performs final cleanup, then performs a sequence + of copies, and jumps to a specified real mode entry point. + This is a more general version of function 000Dh, which can + also be used to load other types of programs. + + The copies must not touch memory below address 7C00h. + + ES:DI points to a list of CX descriptors each of the form: + + Offset Size Meaning + 0 dword destination address + 4 dword source address + 8 dword length in bytes + + The copies are overlap-safe, like memmove(). + + Normal boot sectors expect DL to contain the drive number, + and, for hard drives (DL >= 80h) DS:SI to contain a pointer to + the 16-byte partition table entry. The memory between + 600h-7FFh is available to put the partition table entry in. + + For PXELINUX, if the PXE stack is not unloaded, all registers + (except DS, ESI and EDX) and the stack will be set up as they + were set up by the PXE ROM. + + diff --git a/comboot.inc b/comboot.inc index ae418b6f..83b57f46 100644 --- a/comboot.inc +++ b/comboot.inc @@ -188,7 +188,7 @@ comboot_int21: cli loopne .again ; The last function in the list is the ; "no such function" function - + clc call ax ; Call the invoked function comboot_resume: setc P_FLAGSL ; Propagate CF->error @@ -281,14 +281,13 @@ comboot_checkver: ; 30 = check DOS version mov P_EBX,'SL' << 16 mov P_ECX,'IN' << 16 mov P_EDX,'UX' << 16 - clc ret comboot_getchar: cmp byte [APIKeyFlag],00h jne .queued call getchar ; If not queued get input - and al,al ; Function key? + and al,al ; Function key? (CF <- 0) jnz .done mov [APIKeyWait],ah ; High part of key inc byte [APIKeyFlag] ; Set flag @@ -322,7 +321,7 @@ comboot_int22: xor ax,ax ; Function 0 -> unimplemented .ok: xchg ax,bx - add bx,bx + add bx,bx ; CF <- 0 call [bx+int22_table] jmp comboot_resume ; On return @@ -546,12 +545,17 @@ comapi_cleanup: ; comapi_chainboot: call comapi_cleanup + mov eax,P_EDI + mov [trackbuf+4],eax ; Copy from + mov eax,P_ECX + mov [trackbuf+8],eax ; Total bytes + mov eax,7C00h + mov [trackbuf],eax ; Copy to + mov [EntryPoint],eax ; CS:IP entry point mov esi,P_ESI mov edx,P_EBX mov bx,P_DS - push P_EDI - push P_ECX - jmp replace_bootstrap + jmp replace_bootstrap_one ; @@ -604,6 +608,43 @@ comapi_dnsresolv equ comapi_err dw %2 %endmacro + +; +; INT 22h AX=0011h Maximum number of shuffle descriptors +; +comapi_maxshuffle: + mov P_CX,(2*trackbufsize)/12 + ret + +; +; INT 22h AX=0012h Cleanup, shuffle and boot +; +comapi_shuffle: + call comapi_cleanup + mov cx,P_CX + cmp cx,(2*trackbufsize)/12 + ja .error + + push cx ; On stack: descriptor count + + lea cx,[ecx+ecx*2] ; CX *= 3 + + mov fs,P_ES + mov si,P_DI + mov di,trackbuf + push di ; On stack: descriptor list address + fs rep movsd ; Copy the list + + mov eax,P_EBP + mov [EntryPoint],eax ; CS:IP entry point + mov esi,P_ESI + mov edx,P_EBX + mov bx,P_DS + jmp replace_bootstrap +.error: + stc + ret + int21_table: int21 00h, comboot_return int21 01h, comboot_getkey @@ -619,23 +660,25 @@ int21_count equ ($-int21_table)/3 align 2, db 0 int22_table: - dw comapi_err ; 0000 unimplemented syscall - dw comapi_get_version ; 0001 get SYSLINUX version - dw comapi_writestr ; 0002 write string - dw comapi_run ; 0003 run specified command - dw comapi_run_default ; 0004 run default command - dw comapi_textmode ; 0005 force text mode - dw comapi_open ; 0006 open file - dw comapi_read ; 0007 read file - dw comapi_close ; 0008 close file - dw comapi_pxecall ; 0009 call PXE stack - dw comapi_derinfo ; 000A derivative-specific info - dw comapi_serialcfg ; 000B get serial port config - dw comapi_cleanup ; 000C perform final cleanup - dw comapi_chainboot ; 000D clean up then bootstrap - dw comapi_configfile ; 000E get name of config file - dw comapi_ipappend ; 000F get ipappend strings - dw comapi_dnsresolv ; 0010 resolve hostname + dw comapi_err ; 0000 unimplemented syscall + dw comapi_get_version ; 0001 get SYSLINUX version + dw comapi_writestr ; 0002 write string + dw comapi_run ; 0003 run specified command + dw comapi_run_default ; 0004 run default command + dw comapi_textmode ; 0005 force text mode + dw comapi_open ; 0006 open file + dw comapi_read ; 0007 read file + dw comapi_close ; 0008 close file + dw comapi_pxecall ; 0009 call PXE stack + dw comapi_derinfo ; 000A derivative-specific info + dw comapi_serialcfg ; 000B get serial port config + dw comapi_cleanup ; 000C perform final cleanup + dw comapi_chainboot ; 000D clean up then bootstrap + dw comapi_configfile ; 000E get name of config file + dw comapi_ipappend ; 000F get ipappend strings + dw comapi_dnsresolv ; 0010 resolve hostname + dw comapi_maxshuffle ; 0011 maximum shuffle descriptors + dw comapi_shuffle ; 0012 cleanup, shuffle and boot int22_count equ ($-int22_table)/2 APIKeyWait db 0 diff --git a/ext2_fs.inc b/ext2_fs.inc index 4cedd122..c4c8bf71 100644 --- a/ext2_fs.inc +++ b/ext2_fs.inc @@ -90,9 +90,11 @@ s_padding1 resw 1 s_reserved resd 204 ; Padding to the end of the block endstruc +%ifndef DEPEND %if ext2_super_block_size != 1024 %error "ext2_super_block definition bogus" %endif +%endif ; ; Structure definition for the ext2 inode @@ -121,9 +123,11 @@ i_pad1 resw 1 l_i_reserved2 resd 2 endstruc +%ifndef DEPEND %if ext2_inode_size != 128 %error "ext2_inode definition bogus" %endif +%endif ; ; Structure definition for ext2 block group descriptor @@ -139,9 +143,11 @@ bg_pad resw 1 bg_reserved resd 3 endstruc +%ifndef DEPEND %if ext2_group_desc_size != 32 %error "ext2_group_desc definition bogus" %endif +%endif %define ext2_group_desc_lg2size 5 @@ -51,8 +51,6 @@ su_movesize resw 1 ; 0212 su_code32start resd 1 ; 0214 Start of code loaded high su_ramdiskat resd 1 ; 0218 Start of initial ramdisk su_ramdisklen equ $ ; Length of initial ramdisk -su_ramdisklen1 resw 1 ; 021C -su_ramdisklen2 resw 1 ; 021E su_bsklugeoffs resw 1 ; 0220 su_bsklugeseg resw 1 ; 0222 su_heapend resw 1 ; 0224 diff --git a/loadhigh.inc b/loadhigh.inc index 0bad64f0..0eef6858 100644 --- a/loadhigh.inc +++ b/loadhigh.inc @@ -27,11 +27,12 @@ ; 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. +; 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 +; DX = zero-padding mask (e.g. 0003h for pad to dword) ; ; Outputs: SI = file handle/cluster pointer ; EDI = first untouched address (not including padding) @@ -70,7 +71,7 @@ load_high: push ecx ; <B> Byte count this round push edi ; <C> Target buffer .fix_slop: - test cl,3 + test cx,dx jz .noslop ; The last dword fractional - pad with zeroes ; Zero-padding is critical for multi-file initramfs. diff --git a/memdisk/setup.c b/memdisk/setup.c index 24ce060b..0832a266 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -317,7 +317,8 @@ void unzip_if_needed(uint32_t *where_p, uint32_t *size_p) } if ( !okmem ) { - puts("Not enough memory to decompress image\n"); + printf("Not enough memory to decompress image (need 0x%08x bytes)\n", + gzdatasize); die(); } diff --git a/parseconfig.inc b/parseconfig.inc index 1db13a1e..cad86b3a 100644 --- a/parseconfig.inc +++ b/parseconfig.inc @@ -353,8 +353,6 @@ OntimeoutLen dw 0 ; Bytes in ontimeout command OnerrorLen dw 0 ; Bytes in onerror command KbdTimeOut dw 0 ; Keyboard timeout (if any) CmdLinePtr dw cmd_line_here ; Command line advancing pointer -initrd_flag equ $ -initrd_ptr dw 0 ; Initial ramdisk pointer/flag ForcePrompt dw 0 ; Force prompt AllowImplicit dw 1 ; Allow implicit kernels AllowOptions dw 1 ; User-specified options allowed diff --git a/runkernel.inc b/runkernel.inc index 7a71350c..bc31f9e1 100644 --- a/runkernel.inc +++ b/runkernel.inc @@ -1,7 +1,7 @@ ;; $Id$ ;; ----------------------------------------------------------------------- ;; -;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved +;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved ;; ;; 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 @@ -126,7 +126,8 @@ construct_cmdline: ; the first option was BOOT_IMAGE=, but that is no longer certain. ; mov si,cmd_line_here - mov byte [initrd_flag],0 + xor ax,ax + mov [InitRDPtr],ax ; No initrd= option (yet) push es ; Set DS <- real_mode_seg pop ds get_next_opt: lodsb @@ -156,15 +157,16 @@ get_next_opt: lodsb mov di,initrd_cmd mov cx,initrd_cmd_len repe cmpsb - jne not_initrd - - mov di,InitRD - push si ; mangle_dir mangles si - call mangle_name ; Mangle ramdisk name - pop si - cmp byte [es:InitRD+NULLOFFSET],NULLFILE ; Null filename? - seta byte [es:initrd_flag] ; Set flag if not -not_initrd: pop es ; Restore ES -> real_mode_seg + jne .not_initrd + + cmp al,' ' + jbe .noramdisk + mov [cs:InitRDPtr],si + jmp .not_initrd +.noramdisk: + xor ax,ax + mov [cs:InitRDPtr],ax +.not_initrd: pop es ; Restore ES -> real_mode_seg skip_this_opt: lodsb ; Load from command line cmp al,' ' ja skip_this_opt @@ -225,6 +227,9 @@ new_kernel: mov byte [es:su_loader],my_id ; Show some ID movzx ax,byte [es:bs_setupsecs] ; Variable # of setup sectors mov [SetupSecs],ax + xor eax,eax + mov [es:su_ramdisklen],eax ; No initrd loaded yet + ; ; About to load the kernel. This is a modern kernel, so use the boot flags ; we were provided. @@ -272,9 +277,11 @@ read_kernel: sub eax,8000h ; Amount of kernel not yet loaded jbe high_load_done ; Zero left (tiny kernel) + xor dx,dx ; No padding needed call load_high ; Copy the file high_load_done: + mov [KernelEnd],edi mov ax,real_mode_seg ; Set to real mode seg mov es,ax @@ -287,49 +294,9 @@ high_load_done: ; if we tried to load initrd using an old kernel ; load_initrd: - test byte [initrd_flag],1 + cmp word [InitRDPtr],0 jz nk_noinitrd - push es ; ES->real_mode_seg - push ds - pop es ; We need ES==DS - mov si,InitRD - mov di,InitRDCName - call unmangle_name ; Create human-readable name - sub di,InitRDCName - mov [InitRDCNameLen],di - mov di,InitRD - call searchdir ; Look for it in directory - pop es - jz initrd_notthere - mov [es:su_ramdisklen1],ax ; Ram disk length - mov [es:su_ramdisklen2],dx - mov edx,[HighMemSize] ; 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 - 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 - call loadinitrd ; Load initial ramdisk - jmp short initrd_end - -initrd_notthere: - mov si,err_noinitrd - call cwritestr - mov si,InitRDCName - call cwritestr - mov si,crlf_msg - jmp abort_load - -no_high_mem: mov si,err_nohighmem ; Error routine - jmp abort_load - -initrd_end: + call parse_load_initrd nk_noinitrd: ; ; Abandon hope, ye that enter here! We do no longer permit aborts. @@ -496,8 +463,8 @@ kill_motor: ; initrd, and are always loaded low. ; old_kernel: - test byte [initrd_flag],1 ; Old kernel can't have initrd - jz load_old_kernel + cmp word [InitRDPtr],0 ; Old kernel can't have initrd + je load_old_kernel mov si,err_oldkernel jmp abort_load load_old_kernel: @@ -506,19 +473,118 @@ load_old_kernel: jmp read_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_load_initrd: + push es + push ds + mov ax,real_mode_seg + mov ds,ax + push cs + pop es ; DS == real_mode_seg, ES == CS + + 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 + +.find_start: + dec si + cmp si,[cs:InitRDPtr] + je .got_start + cmp byte [si],',' + jne .find_start + + ; It's a comma byte + inc si + +.got_start: + push si + mov di,InitRD ; Target buffer for mangled name + call mangle_name + call loadinitrd + pop si + + pop ax + pop di + mov [di],al ; Restore ending byte + + cmp si,[cs:InitRDPtr] + ja .get_chunk + + pop ds + pop es + ret + +; ; 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 +; Input: InitRD - set to the mangled name of the initrd ; - section .text loadinitrd: - push es ; Save ES on entry + push ds + push es + mov ax,cs ; CS == DS == ES + mov ds,ax + mov es,ax + mov si,InitRD + mov di,InitRDCName + call unmangle_name ; Create human-readable name + sub di,InitRDCName + mov [InitRDCNameLen],di + mov di,InitRD + call searchdir ; Look for it in directory + jz .notthere + + mov cx,dx + shl ecx,16 + mov cx,ax ; ECX <- ram disk length + mov ax,real_mode_seg - mov es,ax - mov edi,[es:su_ramdiskat] ; initrd load address + mov es,ax + + push ecx ; Bytes to load + cmp dword [es:su_ramdisklen],0 + je .nopadding ; Don't pad the last initrd + add ecx,4095 + and cx,0F000h +.nopadding: + add [es:su_ramdisklen],ecx + mov edx,[HighMemSize] ; 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 + + mov [es:su_ramdiskat],edx ; Load address + mov [RamdiskMax],edx ; Next initrd loaded here + + mov edi,edx ; initrd load address push si mov si,crlfloading_msg ; Write "Loading " call cwritestr @@ -528,11 +594,26 @@ loadinitrd: call cwritestr pop si - mov eax,[es:su_ramdisklen] + pop eax ; Bytes to load + mov dx,0FFFh ; Pad to page call load_high ; Load the file - call crlf - pop es ; Restore original ES + pop es + pop ds + jmp crlf ; Print carriage return and return + +.notthere: + mov si,err_noinitrd + call cwritestr + mov si,InitRDCName + call cwritestr + mov si,crlf_msg + jmp abort_load + +no_high_mem: ; Error routine + mov si,err_nohighmem + jmp abort_load + ret section .data @@ -544,6 +625,8 @@ boot_image_len equ $-boot_image 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 CmdLineLen resw 1 ; Length of command line including null SetupSecs resw 1 ; Number of setup sectors +InitRDPtr resw 1 ; Pointer to initrd= option in command line LoadFlags resb 1 ; Loadflags from kernel @@ -1 +1 @@ -3.03 +3.10 |