Shao, On Thu, Jun 03, 2010 at 02:02:17AM +0800, Miller, Shao wrote: > Fengguang, > > Is there a need to hide the initrd? If gPXE relocates to underneath it, > malloc() and umalloc() should allocate below the initrd's base, should > they not?
umalloc finds the largest free e820 region and allocates memory from it. So if you don't hide the ramdisk image, it might be overwritten by umalloc? > H. Peter, > > Could you please confirm whose responsibility it is to mark the initrd > in the E820 map, if anyone's? I couldn't find it in > linux/Documentation/i386/boot.txt, but a glance at Syslinux' linux.c32 > suggested that it gets marked. The bootloader marks the initrd location in ramdisk_image/ramdisk_size, so it should be gPXE's responsibility to not overwrite the region before using it? Stefan, sorry that I still found it necessary to put lkrn dependant code into libprefix.S (after decompressing .data16 and before calling relocate). Is it possible to #ifdef the code block? Sorry it's not obvious to me how to do it the neat way. Thanks, Fengguang --- Subject: [lkrn] add ramdisk support From: Wu Fengguang <[email protected]> Date: Thu May 20 06:49:43 CST 2010 Allow passing ramdisk script to gpxe. We can already _statically_ embed scripts into gpxe.lkrn, however this will be much more convenient for end user. Usage: /boot/grub/grub.cfg: menuentry "gPXE" { echo Loading gPXE ... linux16 /boot/gpxe.lkrn initrd16 /boot/bee.gpxe } /boot/bee.gpxe: #!gpxe dhcp net0 kernel http://somewhere/~wfg/cgi-bin/gpxe.cgi?mac=${mac} boot The ramdisk memory is hidden to avoid it being overwritten. Signed-off-by: Wu Fengguang <[email protected]> --- src/arch/i386/core/relocate.c | 23 ++++++++++ src/arch/i386/firmware/pcbios/e820mangler.S | 4 + src/arch/i386/firmware/pcbios/hidemem.c | 12 +++++ src/arch/i386/image/lkrn.c | 41 ++++++++++++++++++ src/arch/i386/prefix/libprefix.S | 5 ++ src/arch/i386/prefix/lkrnprefix.S | 2 src/include/gpxe/hidemem.h | 1 src/include/gpxe/image.h | 9 +++ 8 files changed, 97 insertions(+) --- gpxe.orig/src/arch/i386/prefix/lkrnprefix.S 2010-06-02 23:49:51.000000000 +0800 +++ gpxe/src/arch/i386/prefix/lkrnprefix.S 2010-06-03 10:38:23.000000000 +0800 @@ -134,8 +134,10 @@ setup_move_size: .word 0 code32_start: .long 0 +.globl ramdisk_image ramdisk_image: .long 0 +.globl ramdisk_size ramdisk_size: .long 0 bootsect_kludge: --- gpxe.orig/src/include/gpxe/image.h 2010-06-02 23:49:51.000000000 +0800 +++ gpxe/src/include/gpxe/image.h 2010-06-02 23:50:25.000000000 +0800 @@ -191,4 +191,13 @@ static inline int image_set_name ( struc return 0; } +extern char preloaded_ramdisk[128]; +extern char *userimage_addr; +extern unsigned long userimage_size; + +extern unsigned long __data16 ( lkrn_ramdisk ); +extern unsigned long __data16 ( lkrn_ramdisk_size ); +#define lkrn_ramdisk __use_data16 ( lkrn_ramdisk ) +#define lkrn_ramdisk_size __use_data16 ( lkrn_ramdisk_size ) + #endif /* _GPXE_IMAGE_H */ --- gpxe.orig/src/arch/i386/core/relocate.c 2010-06-02 23:49:51.000000000 +0800 +++ gpxe/src/arch/i386/core/relocate.c 2010-06-03 00:12:14.000000000 +0800 @@ -1,6 +1,8 @@ #include <gpxe/io.h> #include <registers.h> #include <gpxe/memmap.h> +#include <gpxe/image.h> +#include <gpxe/hidemem.h> /* * Originally by Eric Biederman @@ -58,6 +60,9 @@ __asmcall void relocate ( struct i386_al "...need %lx bytes for %d-byte alignment\n", start, end, padded_size, max_align ); + if ( lkrn_ramdisk && lkrn_ramdisk_size ) + hide_ramdisk( lkrn_ramdisk, lkrn_ramdisk + lkrn_ramdisk_size ); + /* Walk through the memory map and find the highest address * below 4GB that etherboot will fit into. Ensure etherboot * lies entirely within a range with A20=0. This means that @@ -88,6 +93,24 @@ __asmcall void relocate ( struct i386_al r_end = region->end; } + /* hide_ramdisk() takes effect in future. + * For now 'substract' it manually. If it cuts one region into + * two, take the larger one. + */ + if ( r_end > lkrn_ramdisk && + r_start < lkrn_ramdisk + lkrn_ramdisk_size ) { + + long s1 = lkrn_ramdisk - r_start; + long s2 = r_end - ( lkrn_ramdisk + lkrn_ramdisk_size ); + + if ( r_end - r_start < lkrn_ramdisk_size ) + continue; + if ( s1 < s2 ) + r_start = lkrn_ramdisk; + else + r_end = lkrn_ramdisk + lkrn_ramdisk_size; + } + /* Shrink the range down to use only even megabytes * (i.e. A20=0). */ --- gpxe.orig/src/arch/i386/firmware/pcbios/e820mangler.S 2010-06-02 23:49:51.000000000 +0800 +++ gpxe/src/arch/i386/firmware/pcbios/e820mangler.S 2010-06-02 23:50:25.000000000 +0800 @@ -66,6 +66,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) .globl hidemem_base .globl hidemem_umalloc .globl hidemem_textdata + .globl hidemem_ramdisk memory_windows: base_memory_window: .long 0x00000000, 0x00000000 /* Start of memory */ @@ -78,6 +79,9 @@ hidemem_umalloc: .long 0xffffffff, 0xfff hidemem_textdata: .long 0xffffffff, 0xffffffff /* Changes at runtime */ .long 0xffffffff, 0xffffffff /* Changes at runtime */ +hidemem_ramdisk: .long 0xffffffff, 0xffffffff /* Changes at runtime */ + .long 0xffffffff, 0xffffffff /* Changes at runtime */ + .long 0xffffffff, 0xffffffff /* End of memory */ memory_windows_end: --- gpxe.orig/src/include/gpxe/hidemem.h 2010-06-02 23:49:51.000000000 +0800 +++ gpxe/src/include/gpxe/hidemem.h 2010-06-02 23:50:25.000000000 +0800 @@ -13,5 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> extern void hide_umalloc ( physaddr_t start, physaddr_t end ); +extern void hide_ramdisk ( physaddr_t start, physaddr_t end ); #endif /* _GPXE_HIDEMEM_H */ --- gpxe.orig/src/arch/i386/firmware/pcbios/hidemem.c 2010-06-02 23:49:51.000000000 +0800 +++ gpxe/src/arch/i386/firmware/pcbios/hidemem.c 2010-06-02 23:50:25.000000000 +0800 @@ -60,6 +60,10 @@ extern struct hidden_region __data16 ( h extern struct hidden_region __data16 ( hidemem_textdata ); #define hidemem_textdata __use_data16 ( hidemem_textdata ) +/** Hidden ramdisk memory */ +extern struct hidden_region __data16 ( hidemem_ramdisk ); +#define hidemem_ramdisk __use_data16 ( hidemem_ramdisk ) + /** Assembly routine in e820mangler.S */ extern void int15(); @@ -126,6 +130,14 @@ void hide_textdata ( void ) { } /** + * Hide linux ramdisk + * + */ +void hide_ramdisk ( physaddr_t start, physaddr_t end ) { + hide_region ( &hidemem_ramdisk, start, end ); +} + +/** * Hide Etherboot * * Installs an INT 15 handler to edit Etherboot out of the memory map --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gpxe/src/arch/i386/image/lkrn.c 2010-06-03 00:46:09.000000000 +0800 @@ -0,0 +1,41 @@ +/** @file + * + * lkrn ramdisk image + * + * lkrn ramdisk is preloaded by GRUB/PXELinux with their "initrd" command. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <gpxe/image.h> +#include <gpxe/uaccess.h> +#include <gpxe/init.h> + +unsigned long __data16 ( lkrn_ramdisk ) = 0; +unsigned long __data16 ( lkrn_ramdisk_size ) = 0; + +static void lkrn_ramdisk_init ( void ) { + + struct image *initrd; + + if ( ! lkrn_ramdisk ) + return; + if ( ! lkrn_ramdisk_size ) + return; + + DBG ( "Found ramdisk at %lx size %ld\n", + lkrn_ramdisk, lkrn_ramdisk_size ); + + initrd = alloc_image(); + if ( ! initrd ) + return; + + initrd->data = phys_to_user( lkrn_ramdisk ); + initrd->len = lkrn_ramdisk_size; + + register_and_autoload_image ( initrd ); +} + +struct init_fn lkrn_ramdisk_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = lkrn_ramdisk_init, +}; --- gpxe.orig/src/arch/i386/prefix/libprefix.S 2010-06-03 10:38:34.000000000 +0800 +++ gpxe/src/arch/i386/prefix/libprefix.S 2010-06-03 10:40:58.000000000 +0800 @@ -704,6 +704,11 @@ install_prealloc: /* Set up %ds for access to .data16 */ movw %bx, %ds + movl %es:ramdisk_image, %ecx + movl %ecx, lkrn_ramdisk + movl %es:ramdisk_size, %ecx + movl %ecx, lkrn_ramdisk_size + #ifdef KEEP_IT_REAL /* Initialise libkir */ movw %ax, (init_libkir_vector+2) _______________________________________________ gPXE-devel mailing list [email protected] http://etherboot.org/mailman/listinfo/gpxe-devel
