]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[prefix] Allow an initrd to be passed to iPXE
authorMichael Brown <mcb30@ipxe.org>
Sat, 12 Nov 2011 00:34:55 +0000 (00:34 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sat, 12 Nov 2011 00:34:55 +0000 (00:34 +0000)
Allow an initrd (such as an embedded script) to be passed to iPXE when
loaded as a .lkrn (or .iso) image.  This allows an embedded script to
be varied without recompiling iPXE.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/core/cmdline.c [deleted file]
src/arch/i386/core/runtime.c [new file with mode: 0644]
src/arch/i386/include/bits/errfile.h
src/arch/i386/prefix/lkrnprefix.S

diff --git a/src/arch/i386/core/cmdline.c b/src/arch/i386/core/cmdline.c
deleted file mode 100644 (file)
index 595fdad..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * 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 the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-/** @file
- *
- * Command line passed to iPXE
- *
- */
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <ipxe/init.h>
-#include <ipxe/image.h>
-#include <ipxe/script.h>
-#include <realmode.h>
-
-/** Command line physical address
- *
- * This can be set by the prefix.
- */
-uint32_t __bss16 ( cmdline_phys );
-#define cmdline_phys __use_data16 ( cmdline_phys )
-
-/** Internal copy of the command line */
-static char *cmdline_copy;
-
-/** Free command line image */
-static void cmdline_image_free ( struct refcnt *refcnt ) {
-       struct image *image = container_of ( refcnt, struct image, refcnt );
-
-       DBGC ( image, "CMDLINE freeing command line\n" );
-       free ( cmdline_copy );
-}
-
-/** Embedded script representing the command line */
-static struct image cmdline_image = {
-       .refcnt = REF_INIT ( cmdline_image_free ),
-       .name = "<CMDLINE>",
-       .type = &script_image_type,
-};
-
-/**
- * Initialise command line
- *
- */
-static void cmdline_init ( void ) {
-       struct image *image = &cmdline_image;
-       userptr_t cmdline_user;
-       char *cmdline;
-       char *boot_image;
-       char *boot_image_end;
-       size_t len;
-
-       /* Do nothing if no command line was specified */
-       if ( ! cmdline_phys ) {
-               DBGC ( image, "CMDLINE found no command line\n" );
-               return;
-       }
-       cmdline_user = phys_to_user ( cmdline_phys );
-       len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
-
-       /* Allocate and copy command line */
-       cmdline_copy = malloc ( len );
-       if ( ! cmdline_copy ) {
-               DBGC ( image, "CMDLINE could not allocate %zd bytes\n", len );
-               /* No way to indicate failure */
-               return;
-       }
-       cmdline = cmdline_copy;
-       copy_from_user ( cmdline, cmdline_user, 0, len );
-       DBGC ( image, "CMDLINE found \"%s\"\n", cmdline );
-
-       /* Check for unwanted cruft in the command line */
-       while ( isspace ( *cmdline ) )
-               cmdline++;
-       if ( ( boot_image = strstr ( cmdline, "BOOT_IMAGE=" ) ) != NULL ) {
-               boot_image_end = strchr ( boot_image, ' ' );
-               if ( boot_image_end ) {
-                       *boot_image_end = '\0';
-                       DBGC ( image, "CMDLINE stripping \"%s\"\n",
-                              boot_image );
-                       strcpy ( boot_image, ( boot_image_end + 1 ) );
-               } else {
-                       DBGC ( image, "CMDLINE stripping \"%s\"\n",
-                              boot_image );
-                       *boot_image = '\0';
-               }
-       }
-       DBGC ( image, "CMDLINE using \"%s\"\n", cmdline );
-
-       /* Prepare and register image */
-       cmdline_image.data = virt_to_user ( cmdline );
-       cmdline_image.len = strlen ( cmdline );
-       if ( cmdline_image.len )
-               register_image ( &cmdline_image );
-
-       /* Drop our reference to the image */
-       image_put ( &cmdline_image );
-}
-
-/** Command line initialisation function */
-struct init_fn cmdline_init_fn __init_fn ( INIT_NORMAL ) = {
-       .initialise = cmdline_init,
-};
diff --git a/src/arch/i386/core/runtime.c b/src/arch/i386/core/runtime.c
new file mode 100644 (file)
index 0000000..09ba625
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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 the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Command line and initrd passed to iPXE at runtime
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <ipxe/init.h>
+#include <ipxe/image.h>
+#include <ipxe/script.h>
+#include <ipxe/umalloc.h>
+#include <realmode.h>
+
+/** Command line physical address
+ *
+ * This can be set by the prefix.
+ */
+uint32_t __bss16 ( cmdline_phys );
+#define cmdline_phys __use_data16 ( cmdline_phys )
+
+/** initrd physical address
+ *
+ * This can be set by the prefix.
+ */
+uint32_t __bss16 ( initrd_phys );
+#define initrd_phys __use_data16 ( initrd_phys )
+
+/** initrd length
+ *
+ * This can be set by the prefix.
+ */
+uint32_t __bss16 ( initrd_len );
+#define initrd_len __use_data16 ( initrd_len )
+
+/** Internal copy of the command line */
+static char *cmdline_copy;
+
+/** Free command line image */
+static void cmdline_image_free ( struct refcnt *refcnt ) {
+       struct image *image = container_of ( refcnt, struct image, refcnt );
+
+       DBGC ( image, "RUNTIME freeing command line\n" );
+       free ( cmdline_copy );
+}
+
+/** Embedded script representing the command line */
+static struct image cmdline_image = {
+       .refcnt = REF_INIT ( cmdline_image_free ),
+       .name = "<CMDLINE>",
+       .type = &script_image_type,
+};
+
+/** Colour for debug messages */
+#define colour &cmdline_image
+
+/**
+ * Strip unwanted cruft from command line
+ *
+ * @v cmdline          Command line
+ * @v cruft            Initial substring of cruft to strip
+ */
+static void cmdline_strip ( char *cmdline, const char *cruft ) {
+       char *strip;
+       char *strip_end;
+
+       /* Find unwanted cruft, if present */
+       if ( ! ( strip = strstr ( cmdline, cruft ) ) )
+               return;
+
+       /* Strip unwanted cruft */
+       strip_end = strchr ( strip, ' ' );
+       if ( strip_end ) {
+               *strip_end = '\0';
+               DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
+               strcpy ( strip, ( strip_end + 1 ) );
+       } else {
+               DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
+               *strip = '\0';
+       }
+}
+
+/**
+ * Initialise command line
+ *
+ * @ret rc             Return status code
+ */
+static int cmdline_init ( void ) {
+       userptr_t cmdline_user;
+       char *cmdline;
+       size_t len;
+       int rc;
+
+       /* Do nothing if no command line was specified */
+       if ( ! cmdline_phys ) {
+               DBGC ( colour, "RUNTIME found no command line\n" );
+               return 0;
+       }
+       cmdline_user = phys_to_user ( cmdline_phys );
+       len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
+
+       /* Allocate and copy command line */
+       cmdline_copy = malloc ( len );
+       if ( ! cmdline_copy ) {
+               DBGC ( colour, "RUNTIME could not allocate %zd bytes for "
+                      "command line\n", len );
+               rc = -ENOMEM;
+               goto err_alloc_cmdline_copy;
+       }
+       cmdline = cmdline_copy;
+       copy_from_user ( cmdline, cmdline_user, 0, len );
+       DBGC ( colour, "RUNTIME found command line \"%s\"\n", cmdline );
+
+       /* Strip unwanted cruft from the command line */
+       cmdline_strip ( cmdline, "BOOT_IMAGE=" );
+       cmdline_strip ( cmdline, "initrd=" );
+       while ( isspace ( *cmdline ) )
+               cmdline++;
+       DBGC ( colour, "RUNTIME using command line \"%s\"\n", cmdline );
+
+       /* Prepare and register image */
+       cmdline_image.data = virt_to_user ( cmdline );
+       cmdline_image.len = strlen ( cmdline );
+       if ( cmdline_image.len ) {
+               if ( ( rc = register_image ( &cmdline_image ) ) != 0 ) {
+                       DBGC ( colour, "RUNTIME could not register command "
+                              "line: %s\n", strerror ( rc ) );
+                       goto err_register_image;
+               }
+       }
+
+       /* Drop our reference to the image */
+       image_put ( &cmdline_image );
+
+       return 0;
+
+ err_register_image:
+       image_put ( &cmdline_image );
+ err_alloc_cmdline_copy:
+       return rc;
+}
+
+/**
+ * Initialise initrd
+ *
+ * @ret rc             Return status code
+ */
+static int initrd_init ( void ) {
+       struct image *image;
+       int rc;
+
+       /* Do nothing if no initrd was specified */
+       if ( ! initrd_phys ) {
+               DBGC ( colour, "RUNTIME found no initrd\n" );
+               return 0;
+       }
+       if ( ! initrd_len ) {
+               DBGC ( colour, "RUNTIME found empty initrd\n" );
+               return 0;
+       }
+       DBGC ( colour, "RUNTIME found initrd at [%x,%x)\n",
+              initrd_phys, ( initrd_phys + initrd_len ) );
+
+       /* Allocate image */
+       image = alloc_image();
+       if ( ! image ) {
+               DBGC ( colour, "RUNTIME could not allocate image for "
+                      "initrd\n" );
+               goto err_alloc_image;
+       }
+       image_set_name ( image, "<INITRD>" );
+
+       /* Allocate and copy initrd content */
+       image->data = umalloc ( initrd_len );
+       if ( ! image->data ) {
+               DBGC ( colour, "RUNTIME could not allocate %zd bytes for "
+                      "initrd\n", initrd_len );
+               goto err_umalloc;
+       }
+       image->len = initrd_len;
+       memcpy_user ( image->data, 0, phys_to_user ( initrd_phys ), 0,
+                     initrd_len );
+
+       /* Register image */
+       if ( ( rc = register_image ( image ) ) != 0 ) {
+               DBGC ( colour, "RUNTIME could not register initrd: %s\n",
+                      strerror ( rc ) );
+               goto err_register_image;
+       }
+
+       /* Drop our reference to the image */
+       image_put ( image );
+
+       return 0;
+
+ err_register_image:
+ err_umalloc:
+       image_put ( image );
+ err_alloc_image:
+       return rc;
+}
+
+/**
+ * Initialise command line and initrd
+ *
+ */
+static void runtime_init ( void ) {
+       int rc;
+
+       /* Initialise command line */
+       if ( ( rc = cmdline_init() ) != 0 ) {
+               /* No way to report failure */
+               return;
+       }
+
+       /* Initialise initrd */
+       if ( ( rc = initrd_init() ) != 0 ) {
+               /* No way to report failure */
+               return;
+       }
+}
+
+/** Command line and initrd initialisation function */
+struct init_fn runtime_init_fn __init_fn ( INIT_NORMAL ) = {
+       .initialise = runtime_init,
+};
index 32b8a085bb1a2aaeae9349610591dac447af6b0c..93f34f8d27566afcb844731718ac675755ce7b75 100644 (file)
@@ -15,6 +15,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_biosint                ( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 )
 #define ERRFILE_int13          ( ERRFILE_ARCH | ERRFILE_CORE | 0x00050000 )
 #define ERRFILE_pxeparent      ( ERRFILE_ARCH | ERRFILE_CORE | 0x00060000 )
+#define ERRFILE_runtime                ( ERRFILE_ARCH | ERRFILE_CORE | 0x00070000 )
 
 #define ERRFILE_bootsector     ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
 #define ERRFILE_bzimage               ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
index 338ffa3d424e9321b0200d497f5084f1dce47e70..bc1f8bfb7c24e0b305be6e29ab4e05f38f331f63 100644 (file)
@@ -196,8 +196,15 @@ run_ipxe:
        /* Retrieve command-line pointer */
        movl    %es:cmd_line_ptr, %edx
 
+       /* Retrieve initrd pointer and size */
+       movl    %es:ramdisk_image, %ebp
+       movl    %es:ramdisk_size, %ecx
+
        /* Install iPXE */
-       call    install
+       call    alloc_basemem
+       xorl    %esi, %esi
+       xorl    %edi, %edi
+       call    install_prealloc
 
        /* Set up real-mode stack */
        movw    %bx, %ss
@@ -215,6 +222,10 @@ run_ipxe:
        /* Store command-line pointer */
        movl    %edx, cmdline_phys
 
+       /* Store initrd pointer and size */
+       movl    %ebp, initrd_phys
+       movl    %ecx, initrd_len
+
        /* Run iPXE */
        pushl   $main
        pushw   %cs