[gPXE-devel] [PATCH v2][lkrn] add ramdisk support

Wu Fengguang fengguang.wu at intel.com
Wed Jun 2 12:36:20 EDT 2010


Stefen,

This updated patch addresses all of your review comments.
(except that I still need to auto load the _script_ image)

It needs more tests as well as early reviews :)

Thanks,
Fengguang
---
Allow passing ramdisk script to gpxe. We can already _statically_ embed
scripts into gpxe.lkrn, however it's 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=${net0/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/lkrnprefix.S           |    5 ++
 src/include/gpxe/hidemem.h                  |    1 
 src/include/gpxe/image.h                    |    9 +++
 7 files changed, 95 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-02 23:50:25.000000000 +0800
@@ -198,6 +198,11 @@ run_gpxe:
 	movw	%bx, %ss
 	movw	$_estack16, %sp
 
+	movl	ramdisk_image, %ecx
+	movl	%ecx, %ss:lkrn_ramdisk
+	movl	ramdisk_size, %ecx
+	movl	%ecx, %ss:lkrn_ramdisk_size
+
 	/* Jump to .text16 segment */
 	pushw	%ax
 	pushw	$1f
--- 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:27:53.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,
+};


More information about the gPXE-devel mailing list