mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-22 17:41:55 +00:00
[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>
This commit is contained in:
parent
d3c660b671
commit
5d3c368efb
@ -327,6 +327,14 @@ int image_exec ( struct image *image ) {
|
||||
if ( image->flags & IMAGE_AUTO_UNREGISTER )
|
||||
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 */
|
||||
image_put ( image );
|
||||
|
||||
@ -338,12 +346,8 @@ int image_exec ( struct image *image ) {
|
||||
uri_put ( old_cwuri );
|
||||
|
||||
/* Tail-recurse into replacement image, if one exists */
|
||||
if ( replacement ) {
|
||||
DBGC ( image, "IMAGE <freed> replacing self with IMAGE %s\n",
|
||||
replacement->name );
|
||||
if ( ( rc = image_exec ( replacement ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
if ( replacement )
|
||||
return image_exec ( replacement );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/shell.h>
|
||||
#include <usr/imgmgmt.h>
|
||||
|
||||
/** @file
|
||||
@ -38,6 +39,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
struct imgsingle_options {
|
||||
/** Image name */
|
||||
const char *name;
|
||||
/** Replace image */
|
||||
int replace;
|
||||
/** Free image after execution */
|
||||
int autofree;
|
||||
};
|
||||
@ -46,6 +49,8 @@ struct imgsingle_options {
|
||||
static struct option_descriptor imgsingle_opts[] = {
|
||||
OPTION_DESC ( "name", 'n', required_argument,
|
||||
struct imgsingle_options, name, parse_string ),
|
||||
OPTION_DESC ( "replace", 'r', no_argument,
|
||||
struct imgsingle_options, replace, parse_flag ),
|
||||
OPTION_DESC ( "autofree", 'a', no_argument,
|
||||
struct imgsingle_options, autofree, parse_flag ),
|
||||
};
|
||||
@ -66,7 +71,8 @@ struct imgsingle_descriptor {
|
||||
/** Pre-action to take upon image, or NULL */
|
||||
void ( * preaction ) ( struct image *image );
|
||||
/** 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 */
|
||||
const char *verb;
|
||||
};
|
||||
@ -145,7 +151,7 @@ static int imgsingle_exec ( int argc, char **argv,
|
||||
|
||||
/* Carry out command action, if applicable */
|
||||
if ( desc->action ) {
|
||||
if ( ( rc = desc->action ( image ) ) != 0 ) {
|
||||
if ( ( rc = desc->action ( image, &opts ) ) != 0 ) {
|
||||
printf ( "Could not %s: %s\n",
|
||||
desc->verb, strerror ( rc ) );
|
||||
goto err_action;
|
||||
@ -188,11 +194,23 @@ static int imgfetch_exec ( int argc, char **argv ) {
|
||||
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 */
|
||||
struct imgsingle_descriptor imgselect_desc = {
|
||||
.cmd = &imgsingle_cmd,
|
||||
.acquire = imgacquire,
|
||||
.action = image_select,
|
||||
.action = imgselect,
|
||||
.verb = "select",
|
||||
};
|
||||
|
||||
@ -211,13 +229,44 @@ static int imgselect_exec ( int argc, char **argv ) {
|
||||
static struct command_descriptor imgexec_cmd =
|
||||
COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
|
||||
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 */
|
||||
struct imgsingle_descriptor imgexec_desc = {
|
||||
.cmd = &imgexec_cmd,
|
||||
.acquire = imgacquire,
|
||||
.action = image_exec,
|
||||
.action = imgexec,
|
||||
.verb = "boot",
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user