mirror of https://github.com/ipxe/ipxe.git
[image] Add "--replace" option
Expose image tail-recursion to iPXE scripts via the "--replace" option. This functions similarly to exec() under Unix: the currently-executing script is replaced with the new image (as opposed to running the new image as a subroutine). Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/598/head
parent
d3c660b671
commit
5d3c368efb
|
@ -327,6 +327,14 @@ int image_exec ( struct image *image ) {
|
||||||
if ( image->flags & IMAGE_AUTO_UNREGISTER )
|
if ( image->flags & IMAGE_AUTO_UNREGISTER )
|
||||||
unregister_image ( image );
|
unregister_image ( image );
|
||||||
|
|
||||||
|
/* Debug message for tail-recursion. Placed here because the
|
||||||
|
* image_put() may end up freeing the image.
|
||||||
|
*/
|
||||||
|
if ( replacement ) {
|
||||||
|
DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n",
|
||||||
|
image->name, replacement->name );
|
||||||
|
}
|
||||||
|
|
||||||
/* Drop temporary reference to the original image */
|
/* Drop temporary reference to the original image */
|
||||||
image_put ( image );
|
image_put ( image );
|
||||||
|
|
||||||
|
@ -338,12 +346,8 @@ int image_exec ( struct image *image ) {
|
||||||
uri_put ( old_cwuri );
|
uri_put ( old_cwuri );
|
||||||
|
|
||||||
/* Tail-recurse into replacement image, if one exists */
|
/* Tail-recurse into replacement image, if one exists */
|
||||||
if ( replacement ) {
|
if ( replacement )
|
||||||
DBGC ( image, "IMAGE <freed> replacing self with IMAGE %s\n",
|
return image_exec ( replacement );
|
||||||
replacement->name );
|
|
||||||
if ( ( rc = image_exec ( replacement ) ) != 0 )
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
#include <ipxe/image.h>
|
#include <ipxe/image.h>
|
||||||
#include <ipxe/command.h>
|
#include <ipxe/command.h>
|
||||||
#include <ipxe/parseopt.h>
|
#include <ipxe/parseopt.h>
|
||||||
|
#include <ipxe/shell.h>
|
||||||
#include <usr/imgmgmt.h>
|
#include <usr/imgmgmt.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
@ -38,6 +39,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
struct imgsingle_options {
|
struct imgsingle_options {
|
||||||
/** Image name */
|
/** Image name */
|
||||||
const char *name;
|
const char *name;
|
||||||
|
/** Replace image */
|
||||||
|
int replace;
|
||||||
/** Free image after execution */
|
/** Free image after execution */
|
||||||
int autofree;
|
int autofree;
|
||||||
};
|
};
|
||||||
|
@ -46,6 +49,8 @@ struct imgsingle_options {
|
||||||
static struct option_descriptor imgsingle_opts[] = {
|
static struct option_descriptor imgsingle_opts[] = {
|
||||||
OPTION_DESC ( "name", 'n', required_argument,
|
OPTION_DESC ( "name", 'n', required_argument,
|
||||||
struct imgsingle_options, name, parse_string ),
|
struct imgsingle_options, name, parse_string ),
|
||||||
|
OPTION_DESC ( "replace", 'r', no_argument,
|
||||||
|
struct imgsingle_options, replace, parse_flag ),
|
||||||
OPTION_DESC ( "autofree", 'a', no_argument,
|
OPTION_DESC ( "autofree", 'a', no_argument,
|
||||||
struct imgsingle_options, autofree, parse_flag ),
|
struct imgsingle_options, autofree, parse_flag ),
|
||||||
};
|
};
|
||||||
|
@ -66,7 +71,8 @@ struct imgsingle_descriptor {
|
||||||
/** Pre-action to take upon image, or NULL */
|
/** Pre-action to take upon image, or NULL */
|
||||||
void ( * preaction ) ( struct image *image );
|
void ( * preaction ) ( struct image *image );
|
||||||
/** Action to take upon image, or NULL */
|
/** Action to take upon image, or NULL */
|
||||||
int ( * action ) ( struct image *image );
|
int ( * action ) ( struct image *image,
|
||||||
|
struct imgsingle_options *opts );
|
||||||
/** Verb to describe action */
|
/** Verb to describe action */
|
||||||
const char *verb;
|
const char *verb;
|
||||||
};
|
};
|
||||||
|
@ -145,7 +151,7 @@ static int imgsingle_exec ( int argc, char **argv,
|
||||||
|
|
||||||
/* Carry out command action, if applicable */
|
/* Carry out command action, if applicable */
|
||||||
if ( desc->action ) {
|
if ( desc->action ) {
|
||||||
if ( ( rc = desc->action ( image ) ) != 0 ) {
|
if ( ( rc = desc->action ( image, &opts ) ) != 0 ) {
|
||||||
printf ( "Could not %s: %s\n",
|
printf ( "Could not %s: %s\n",
|
||||||
desc->verb, strerror ( rc ) );
|
desc->verb, strerror ( rc ) );
|
||||||
goto err_action;
|
goto err_action;
|
||||||
|
@ -188,11 +194,23 @@ static int imgfetch_exec ( int argc, char **argv ) {
|
||||||
return imgsingle_exec ( argc, argv, &imgfetch_desc );
|
return imgsingle_exec ( argc, argv, &imgfetch_desc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "imgselect" command action
|
||||||
|
*
|
||||||
|
* @v image Image
|
||||||
|
* @v opts Options
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int imgselect ( struct image *image,
|
||||||
|
struct imgsingle_options *opts __unused ) {
|
||||||
|
return image_select ( image );
|
||||||
|
}
|
||||||
|
|
||||||
/** "imgselect" family command descriptor */
|
/** "imgselect" family command descriptor */
|
||||||
struct imgsingle_descriptor imgselect_desc = {
|
struct imgsingle_descriptor imgselect_desc = {
|
||||||
.cmd = &imgsingle_cmd,
|
.cmd = &imgsingle_cmd,
|
||||||
.acquire = imgacquire,
|
.acquire = imgacquire,
|
||||||
.action = image_select,
|
.action = imgselect,
|
||||||
.verb = "select",
|
.verb = "select",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -211,13 +229,44 @@ static int imgselect_exec ( int argc, char **argv ) {
|
||||||
static struct command_descriptor imgexec_cmd =
|
static struct command_descriptor imgexec_cmd =
|
||||||
COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
|
COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
|
||||||
0, MAX_ARGUMENTS,
|
0, MAX_ARGUMENTS,
|
||||||
"[--autofree] [<uri|image> [<arguments>...]]" );
|
"[--autofree] [--replace] "
|
||||||
|
"[<uri|image> [<arguments>...]]" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "imgexec" command action
|
||||||
|
*
|
||||||
|
* @v image Image
|
||||||
|
* @v opts Options
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int imgexec ( struct image *image, struct imgsingle_options *opts ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Perform replacement or execution as applicable */
|
||||||
|
if ( opts->replace ) {
|
||||||
|
|
||||||
|
/* Try to replace image */
|
||||||
|
if ( ( rc = image_replace ( image ) ) != 0 )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Stop script and tail-recurse into replacement image */
|
||||||
|
shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Try to execute image */
|
||||||
|
if ( ( rc = image_exec ( image ) ) != 0 )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** "imgexec" family command descriptor */
|
/** "imgexec" family command descriptor */
|
||||||
struct imgsingle_descriptor imgexec_desc = {
|
struct imgsingle_descriptor imgexec_desc = {
|
||||||
.cmd = &imgexec_cmd,
|
.cmd = &imgexec_cmd,
|
||||||
.acquire = imgacquire,
|
.acquire = imgacquire,
|
||||||
.action = image_exec,
|
.action = imgexec,
|
||||||
.verb = "boot",
|
.verb = "boot",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue