|  | @@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 26 | 26 |  #include <ipxe/image.h>
 | 
		
	
		
			
			| 27 | 27 |  #include <ipxe/command.h>
 | 
		
	
		
			
			| 28 | 28 |  #include <ipxe/parseopt.h>
 | 
		
	
		
			
			|  | 29 | +#include <ipxe/shell.h>
 | 
		
	
		
			
			| 29 | 30 |  #include <usr/imgmgmt.h>
 | 
		
	
		
			
			| 30 | 31 |  
 | 
		
	
		
			
			| 31 | 32 |  /** @file
 | 
		
	
	
		
			
			|  | @@ -38,6 +39,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 38 | 39 |  struct imgsingle_options {
 | 
		
	
		
			
			| 39 | 40 |  	/** Image name */
 | 
		
	
		
			
			| 40 | 41 |  	const char *name;
 | 
		
	
		
			
			|  | 42 | +	/** Replace image */
 | 
		
	
		
			
			|  | 43 | +	int replace;
 | 
		
	
		
			
			| 41 | 44 |  	/** Free image after execution */
 | 
		
	
		
			
			| 42 | 45 |  	int autofree;
 | 
		
	
		
			
			| 43 | 46 |  };
 | 
		
	
	
		
			
			|  | @@ -46,6 +49,8 @@ struct imgsingle_options {
 | 
		
	
		
			
			| 46 | 49 |  static struct option_descriptor imgsingle_opts[] = {
 | 
		
	
		
			
			| 47 | 50 |  	OPTION_DESC ( "name", 'n', required_argument,
 | 
		
	
		
			
			| 48 | 51 |  		      struct imgsingle_options, name, parse_string ),
 | 
		
	
		
			
			|  | 52 | +	OPTION_DESC ( "replace", 'r', no_argument,
 | 
		
	
		
			
			|  | 53 | +		      struct imgsingle_options, replace, parse_flag ),
 | 
		
	
		
			
			| 49 | 54 |  	OPTION_DESC ( "autofree", 'a', no_argument,
 | 
		
	
		
			
			| 50 | 55 |  		      struct imgsingle_options, autofree, parse_flag ),
 | 
		
	
		
			
			| 51 | 56 |  };
 | 
		
	
	
		
			
			|  | @@ -66,7 +71,8 @@ struct imgsingle_descriptor {
 | 
		
	
		
			
			| 66 | 71 |  	/** Pre-action to take upon image, or NULL */
 | 
		
	
		
			
			| 67 | 72 |  	void ( * preaction ) ( struct image *image );
 | 
		
	
		
			
			| 68 | 73 |  	/** Action to take upon image, or NULL */
 | 
		
	
		
			
			| 69 |  | -	int ( * action ) ( struct image *image );
 | 
		
	
		
			
			|  | 74 | +	int ( * action ) ( struct image *image,
 | 
		
	
		
			
			|  | 75 | +			   struct imgsingle_options *opts );
 | 
		
	
		
			
			| 70 | 76 |  	/** Verb to describe action */
 | 
		
	
		
			
			| 71 | 77 |  	const char *verb;
 | 
		
	
		
			
			| 72 | 78 |  };
 | 
		
	
	
		
			
			|  | @@ -145,7 +151,7 @@ static int imgsingle_exec ( int argc, char **argv,
 | 
		
	
		
			
			| 145 | 151 |  
 | 
		
	
		
			
			| 146 | 152 |  	/* Carry out command action, if applicable */
 | 
		
	
		
			
			| 147 | 153 |  	if ( desc->action ) {
 | 
		
	
		
			
			| 148 |  | -		if ( ( rc = desc->action ( image ) ) != 0 ) {
 | 
		
	
		
			
			|  | 154 | +		if ( ( rc = desc->action ( image, &opts ) ) != 0 ) {
 | 
		
	
		
			
			| 149 | 155 |  			printf ( "Could not %s: %s\n",
 | 
		
	
		
			
			| 150 | 156 |  				 desc->verb, strerror ( rc ) );
 | 
		
	
		
			
			| 151 | 157 |  			goto err_action;
 | 
		
	
	
		
			
			|  | @@ -188,11 +194,23 @@ static int imgfetch_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			| 188 | 194 |  	return imgsingle_exec ( argc, argv, &imgfetch_desc );
 | 
		
	
		
			
			| 189 | 195 |  }
 | 
		
	
		
			
			| 190 | 196 |  
 | 
		
	
		
			
			|  | 197 | +/**
 | 
		
	
		
			
			|  | 198 | + * "imgselect" command action
 | 
		
	
		
			
			|  | 199 | + *
 | 
		
	
		
			
			|  | 200 | + * @v image		Image
 | 
		
	
		
			
			|  | 201 | + * @v opts		Options
 | 
		
	
		
			
			|  | 202 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 203 | + */
 | 
		
	
		
			
			|  | 204 | +static int imgselect ( struct image *image,
 | 
		
	
		
			
			|  | 205 | +		       struct imgsingle_options *opts __unused ) {
 | 
		
	
		
			
			|  | 206 | +	return image_select ( image );
 | 
		
	
		
			
			|  | 207 | +}
 | 
		
	
		
			
			|  | 208 | +
 | 
		
	
		
			
			| 191 | 209 |  /** "imgselect" family command descriptor */
 | 
		
	
		
			
			| 192 | 210 |  struct imgsingle_descriptor imgselect_desc = {
 | 
		
	
		
			
			| 193 | 211 |  	.cmd = &imgsingle_cmd,
 | 
		
	
		
			
			| 194 | 212 |  	.acquire = imgacquire,
 | 
		
	
		
			
			| 195 |  | -	.action = image_select,
 | 
		
	
		
			
			|  | 213 | +	.action = imgselect,
 | 
		
	
		
			
			| 196 | 214 |  	.verb = "select",
 | 
		
	
		
			
			| 197 | 215 |  };
 | 
		
	
		
			
			| 198 | 216 |  
 | 
		
	
	
		
			
			|  | @@ -211,13 +229,44 @@ static int imgselect_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			| 211 | 229 |  static struct command_descriptor imgexec_cmd =
 | 
		
	
		
			
			| 212 | 230 |  	COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
 | 
		
	
		
			
			| 213 | 231 |  		       0, MAX_ARGUMENTS,
 | 
		
	
		
			
			| 214 |  | -		       "[--autofree] [<uri|image> [<arguments>...]]" );
 | 
		
	
		
			
			|  | 232 | +		       "[--autofree] [--replace] "
 | 
		
	
		
			
			|  | 233 | +		       "[<uri|image> [<arguments>...]]" );
 | 
		
	
		
			
			|  | 234 | +
 | 
		
	
		
			
			|  | 235 | +/**
 | 
		
	
		
			
			|  | 236 | + * "imgexec" command action
 | 
		
	
		
			
			|  | 237 | + *
 | 
		
	
		
			
			|  | 238 | + * @v image		Image
 | 
		
	
		
			
			|  | 239 | + * @v opts		Options
 | 
		
	
		
			
			|  | 240 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 241 | + */
 | 
		
	
		
			
			|  | 242 | +static int imgexec ( struct image *image, struct imgsingle_options *opts ) {
 | 
		
	
		
			
			|  | 243 | +	int rc;
 | 
		
	
		
			
			|  | 244 | +
 | 
		
	
		
			
			|  | 245 | +	/* Perform replacement or execution as applicable */
 | 
		
	
		
			
			|  | 246 | +	if ( opts->replace ) {
 | 
		
	
		
			
			|  | 247 | +
 | 
		
	
		
			
			|  | 248 | +		/* Try to replace image */
 | 
		
	
		
			
			|  | 249 | +		if ( ( rc = image_replace ( image ) ) != 0 )
 | 
		
	
		
			
			|  | 250 | +			return rc;
 | 
		
	
		
			
			|  | 251 | +
 | 
		
	
		
			
			|  | 252 | +		/* Stop script and tail-recurse into replacement image */
 | 
		
	
		
			
			|  | 253 | +		shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
 | 
		
	
		
			
			|  | 254 | +
 | 
		
	
		
			
			|  | 255 | +	} else {
 | 
		
	
		
			
			|  | 256 | +
 | 
		
	
		
			
			|  | 257 | +		/* Try to execute image */
 | 
		
	
		
			
			|  | 258 | +		if ( ( rc = image_exec ( image ) ) != 0 )
 | 
		
	
		
			
			|  | 259 | +			return rc;
 | 
		
	
		
			
			|  | 260 | +	}
 | 
		
	
		
			
			|  | 261 | +
 | 
		
	
		
			
			|  | 262 | +	return 0;
 | 
		
	
		
			
			|  | 263 | +}
 | 
		
	
		
			
			| 215 | 264 |  
 | 
		
	
		
			
			| 216 | 265 |  /** "imgexec" family command descriptor */
 | 
		
	
		
			
			| 217 | 266 |  struct imgsingle_descriptor imgexec_desc = {
 | 
		
	
		
			
			| 218 | 267 |  	.cmd = &imgexec_cmd,
 | 
		
	
		
			
			| 219 | 268 |  	.acquire = imgacquire,
 | 
		
	
		
			
			| 220 |  | -	.action = image_exec,
 | 
		
	
		
			
			|  | 269 | +	.action = imgexec,
 | 
		
	
		
			
			| 221 | 270 |  	.verb = "boot",
 | 
		
	
		
			
			| 222 | 271 |  };
 | 
		
	
		
			
			| 223 | 272 |  
 |