Skip to content

Commit

Permalink
[prefix] Allow an initrd to be passed to iPXE
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mcb30 committed Nov 12, 2011
1 parent 2422647 commit 27fdb95
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 124 deletions.
123 changes: 0 additions & 123 deletions src/arch/i386/core/cmdline.c

This file was deleted.

249 changes: 249 additions & 0 deletions src/arch/i386/core/runtime.c
@@ -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,
};
1 change: 1 addition & 0 deletions src/arch/i386/include/bits/errfile.h
Expand Up @@ -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 )
Expand Down

0 comments on commit 27fdb95

Please sign in to comment.