]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[prefix] Allow iPXE's own command line to be executed as a script
authorMichael Brown <mcb30@ipxe.org>
Mon, 7 Mar 2011 22:02:07 +0000 (22:02 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 7 Mar 2011 22:28:31 +0000 (22:28 +0000)
Some prefixes (e.g. .lkrn) allow a command line to be passed in to
iPXE.  At present, this command line is ignored.

If a command line is provided, treat it as an embedded script (without
an explicit "#!ipxe" magic marker).  This allows for patterns of
invocation such as

  title  iPXE
  kernel /boot/ipxe.lkrn dhcp && \
         sanboot iscsi:10.0.4.1::::iqn.2010-04.org.ipxe.dolphin:storage

Here GRUB is instructed to load ipxe.lkrn with an embedded script
equivalent to

  #!ipxe
  dhcp
  sanboot iscsi:10.0.4.1::::iqn.2010-04.org.ipxe.dolphin:storage

This can be used to effectively vary the embedded script without
having to rebuild ipxe.lkrn.

Originally-implemented-by: Dave Hansen <dave@sr71.net>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/core/cmdline.c [new file with mode: 0644]
src/arch/i386/prefix/lkrnprefix.S
src/image/embedded.c
src/image/script.c
src/include/ipxe/init.h
src/include/ipxe/script.h [new file with mode: 0644]

diff --git a/src/arch/i386/core/cmdline.c b/src/arch/i386/core/cmdline.c
new file mode 100644 (file)
index 0000000..fa5adb8
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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 *tmp;
+       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 ( ( tmp = strstr ( cmdline, "BOOT_IMAGE=" ) ) != NULL ) {
+               DBGC ( image, "CMDLINE stripping \"%s\"\n", tmp );
+               *tmp = '\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,
+};
index 008c79efd7da4345f5ff2dc334d0731234187ea1..f87ef85a9d5b59cd7a9af75306f4d28d5227e0a7 100644 (file)
@@ -193,6 +193,9 @@ run_ipxe:
        movw    %ax, %ss
        movw    $0x7c00, %sp
 
+       /* Retrieve command-line pointer */
+       movl    %es:cmd_line_ptr, %edx
+
        /* Install iPXE */
        call    install
 
@@ -206,6 +209,13 @@ run_ipxe:
        lret
        .section ".text16", "awx", @progbits
 1:
+       /* Set up %ds for access to .data16 */
+       movw    %bx, %ds
+
+       /* Store command-line pointer */
+       movl    %edx, cmdline_phys
+
+       /* Run iPXE */
        pushl   $main
        pushw   %cs
        call    prot_call
index 2ddccfed4ac6935abf816a7aa4f93e68fe0f6d24..6358378fb4f06b61599d3243d938fc552614183d 100644 (file)
@@ -86,6 +86,6 @@ static void embedded_init ( void ) {
 }
 
 /** Embedded image initialisation function */
-struct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = {
+struct init_fn embedded_init_fn __init_fn ( INIT_LATE ) = {
        .initialise = embedded_init,
 };
index b819693d3f066d9e663fd70ddb7abe9406e7b3b9..572eac7180badfcaef43822d412d1d5ac5f7c1c4 100644 (file)
@@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/image.h>
 #include <ipxe/shell.h>
 #include <usr/prompt.h>
+#include <ipxe/script.h>
 
 /** Currently running script
  *
index 954cda45374bb17b6e5c067f89f950bf2b4c2c76..19c5925bfe5f994e4ef1615911ae5dbf29c67e18 100644 (file)
@@ -29,6 +29,7 @@ struct init_fn {
 #define INIT_SERIAL    02      /**< Serial driver initialisation */
 #define        INIT_CONSOLE    03      /**< Console initialisation */
 #define INIT_NORMAL    04      /**< Normal initialisation */
+#define INIT_LATE      05      /**< Late initialisation */
 
 /** @} */
 
diff --git a/src/include/ipxe/script.h b/src/include/ipxe/script.h
new file mode 100644 (file)
index 0000000..33420da
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _IPXE_SCRIPT_H
+#define _IPXE_SCRIPT_H
+
+/** @file
+ *
+ * iPXE scripts
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/image.h>
+
+extern struct image_type script_image_type __image_type ( PROBE_NORMAL );
+
+#endif /* _IPXE_SCRIPT_H */