Browse Source

[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>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
5d3c368efb
2 changed files with 64 additions and 11 deletions
  1. 10
    6
      src/core/image.c
  2. 54
    5
      src/hci/commands/image_cmd.c

+ 10
- 6
src/core/image.c View File

@@ -327,6 +327,14 @@ int image_exec ( struct image *image ) {
327 327
 	if ( image->flags & IMAGE_AUTO_UNREGISTER )
328 328
 		unregister_image ( image );
329 329
 
330
+	/* Debug message for tail-recursion.  Placed here because the
331
+	 * image_put() may end up freeing the image.
332
+	 */
333
+	if ( replacement ) {
334
+		DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n",
335
+		       image->name, replacement->name );
336
+	}
337
+
330 338
 	/* Drop temporary reference to the original image */
331 339
 	image_put ( image );
332 340
 
@@ -338,12 +346,8 @@ int image_exec ( struct image *image ) {
338 346
 	uri_put ( old_cwuri );
339 347
 
340 348
 	/* Tail-recurse into replacement image, if one exists */
341
-	if ( replacement ) {
342
-		DBGC ( image, "IMAGE <freed> replacing self with IMAGE %s\n",
343
-		       replacement->name );
344
-		if ( ( rc = image_exec ( replacement ) ) != 0 )
345
-			return rc;
346
-	}
349
+	if ( replacement )
350
+		return image_exec ( replacement );
347 351
 
348 352
 	return rc;
349 353
 }

+ 54
- 5
src/hci/commands/image_cmd.c View File

@@ -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
 

Loading…
Cancel
Save