[gPXE-devel] [PATCH v3][lkrn] add ramdisk support
Wu Fengguang
fengguang.wu at intel.com
Wed Jun 2 23:06:33 EDT 2010
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 <fengguang.wu at intel.com>
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 <fengguang.wu at intel.com>
---
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)
More information about the gPXE-devel
mailing list