Browse Source

[image] Simplify image management commands and internal API

Remove the name, cmdline, and action parameters from imgdownload() and
imgdownload_string().  These functions now simply download and return
an image.

Add the function imgacquire(), which will interpret a "name or URI
string" parameter and return either an existing image or a newly
downloaded image.

Use imgacquire() to merge similar image-management commands that
currently differ only by whether they take the name of an existing
image or the URI of a new image to download.  For example, "chain" and
"imgexec" can now be merged.

Extend imgstat and imgfree commands to take an optional list of
images.

Remove the arbitrary restriction on the length of image names.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
1c127a6962

+ 7
- 2
src/arch/i386/core/runtime.c View File

189
 	       initrd_phys, ( initrd_phys + initrd_len ) );
189
 	       initrd_phys, ( initrd_phys + initrd_len ) );
190
 
190
 
191
 	/* Allocate image */
191
 	/* Allocate image */
192
-	image = alloc_image();
192
+	image = alloc_image ( NULL );
193
 	if ( ! image ) {
193
 	if ( ! image ) {
194
 		DBGC ( colour, "RUNTIME could not allocate image for "
194
 		DBGC ( colour, "RUNTIME could not allocate image for "
195
 		       "initrd\n" );
195
 		       "initrd\n" );
196
 		rc = -ENOMEM;
196
 		rc = -ENOMEM;
197
 		goto err_alloc_image;
197
 		goto err_alloc_image;
198
 	}
198
 	}
199
-	image_set_name ( image, "<INITRD>" );
199
+	if ( ( rc = image_set_name ( image, "<INITRD>" ) ) != 0 ) {
200
+		DBGC ( colour, "RUNTIME could not set image name: %s\n",
201
+		       strerror ( rc ) );
202
+		goto err_set_name;
203
+	}
200
 
204
 
201
 	/* Allocate and copy initrd content */
205
 	/* Allocate and copy initrd content */
202
 	image->data = umalloc ( initrd_len );
206
 	image->data = umalloc ( initrd_len );
227
 
231
 
228
  err_register_image:
232
  err_register_image:
229
  err_umalloc:
233
  err_umalloc:
234
+ err_set_name:
230
 	image_put ( image );
235
 	image_put ( image );
231
  err_alloc_image:
236
  err_alloc_image:
232
 	return rc;
237
 	return rc;

+ 12
- 5
src/arch/i386/interface/syslinux/comboot_call.c View File

166
  * Fetch kernel and optional initrd
166
  * Fetch kernel and optional initrd
167
  */
167
  */
168
 static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
168
 static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
169
+	struct image *kernel;
170
+	struct image *initrd;
169
 	char *initrd_file;
171
 	char *initrd_file;
170
 	int rc;
172
 	int rc;
171
 
173
 
184
 		DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
186
 		DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
185
 
187
 
186
 		/* Fetch initrd */
188
 		/* Fetch initrd */
187
-		if ( ( rc = imgdownload_string ( initrd_file, NULL, NULL,
188
-						 NULL ) ) != 0 ) {
189
+		if ( ( rc = imgdownload_string ( initrd_file, &initrd ) ) != 0){
189
 			DBG ( "COMBOOT: could not fetch initrd: %s\n",
190
 			DBG ( "COMBOOT: could not fetch initrd: %s\n",
190
 			      strerror ( rc ) );
191
 			      strerror ( rc ) );
191
 			return rc;
192
 			return rc;
198
 
199
 
199
 	DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
200
 	DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
200
 
201
 
201
-	/* Allocate and fetch kernel */
202
-	if ( ( rc = imgdownload_string ( kernel_file, NULL, cmdline,
203
-					 image_replace ) ) != 0 ) {
202
+	/* Fetch kernel */
203
+	if ( ( rc = imgdownload_string ( kernel_file, &kernel ) ) != 0 ) {
204
 		DBG ( "COMBOOT: could not fetch kernel: %s\n",
204
 		DBG ( "COMBOOT: could not fetch kernel: %s\n",
205
 		      strerror ( rc ) );
205
 		      strerror ( rc ) );
206
 		return rc;
206
 		return rc;
207
 	}
207
 	}
208
 
208
 
209
+	/* Replace comboot image with kernel */
210
+	if ( ( rc = image_replace ( kernel ) ) != 0 ) {
211
+		DBG ( "COMBOOT: could not replace with kernel: %s\n",
212
+		      strerror ( rc ) );
213
+		return rc;
214
+	}
215
+
209
 	return 0;
216
 	return 0;
210
 }
217
 }
211
 
218
 

+ 42
- 19
src/core/image.c View File

66
 static void free_image ( struct refcnt *refcnt ) {
66
 static void free_image ( struct refcnt *refcnt ) {
67
 	struct image *image = container_of ( refcnt, struct image, refcnt );
67
 	struct image *image = container_of ( refcnt, struct image, refcnt );
68
 
68
 
69
+	free ( image->name );
69
 	free ( image->cmdline );
70
 	free ( image->cmdline );
70
 	uri_put ( image->uri );
71
 	uri_put ( image->uri );
71
 	ufree ( image->data );
72
 	ufree ( image->data );
77
 /**
78
 /**
78
  * Allocate executable image
79
  * Allocate executable image
79
  *
80
  *
81
+ * @v uri		URI, or NULL
80
  * @ret image		Executable image
82
  * @ret image		Executable image
81
  */
83
  */
82
-struct image * alloc_image ( void ) {
84
+struct image * alloc_image ( struct uri *uri ) {
85
+	const char *name;
83
 	struct image *image;
86
 	struct image *image;
87
+	int rc;
84
 
88
 
89
+	/* Allocate image */
85
 	image = zalloc ( sizeof ( *image ) );
90
 	image = zalloc ( sizeof ( *image ) );
86
-	if ( image ) {
87
-		ref_init ( &image->refcnt, free_image );
91
+	if ( ! image )
92
+		goto err_alloc;
93
+
94
+	/* Initialise image */
95
+	ref_init ( &image->refcnt, free_image );
96
+	if ( uri ) {
97
+		image->uri = uri_get ( uri );
98
+		name = basename ( ( char * ) uri->path );
99
+		if ( ( rc = image_set_name ( image, name ) ) != 0 )
100
+			goto err_set_name;
88
 	}
101
 	}
102
+
89
 	return image;
103
 	return image;
104
+
105
+ err_set_name:
106
+	image_put ( image );
107
+ err_alloc:
108
+	return NULL;
90
 }
109
 }
91
 
110
 
92
 /**
111
 /**
93
- * Set image URI
112
+ * Set image name
94
  *
113
  *
95
  * @v image		Image
114
  * @v image		Image
96
- * @v URI		New image URI
97
- *
98
- * If no name is set, the name will be updated to the base name of the
99
- * URI path (if any).
115
+ * @v name		New image name
116
+ * @ret rc		Return status code
100
  */
117
  */
101
-void image_set_uri ( struct image *image, struct uri *uri ) {
102
-	const char *path = uri->path;
118
+int image_set_name ( struct image *image, const char *name ) {
119
+	char *name_copy;
103
 
120
 
104
-	/* Replace URI reference */
105
-	uri_put ( image->uri );
106
-	image->uri = uri_get ( uri );
121
+	/* Duplicate name */
122
+	name_copy = strdup ( name );
123
+	if ( ! name_copy )
124
+		return -ENOMEM;
125
+
126
+	/* Replace existing name */
127
+	free ( image->name );
128
+	image->name = name_copy;
107
 
129
 
108
-	/* Set name if none already specified */
109
-	if ( path && ( ! image->name[0] ) )
110
-		image_set_name ( image, basename ( ( char * ) path ) );
130
+	return 0;
111
 }
131
 }
112
 
132
 
113
 /**
133
 /**
137
  */
157
  */
138
 int register_image ( struct image *image ) {
158
 int register_image ( struct image *image ) {
139
 	static unsigned int imgindex = 0;
159
 	static unsigned int imgindex = 0;
160
+	char name[8]; /* "imgXXXX" */
161
+	int rc;
140
 
162
 
141
 	/* Create image name if it doesn't already have one */
163
 	/* Create image name if it doesn't already have one */
142
-	if ( ! image->name[0] ) {
143
-		snprintf ( image->name, sizeof ( image->name ), "img%d",
144
-			   imgindex++ );
164
+	if ( ! image->name ) {
165
+		snprintf ( name, sizeof ( name ), "img%d", imgindex++ );
166
+		if ( ( rc = image_set_name ( image, name ) ) != 0 )
167
+			return rc;
145
 	}
168
 	}
146
 
169
 
147
 	/* Avoid ending up with multiple "selected" images on
170
 	/* Avoid ending up with multiple "selected" images on

+ 0
- 22
src/core/parseopt.c View File

114
 	return 0;
114
 	return 0;
115
 }
115
 }
116
 
116
 
117
-/**
118
- * Parse image name
119
- *
120
- * @v text		Text
121
- * @ret image		Image
122
- * @ret rc		Return status code
123
- */
124
-int parse_image ( const char *text, struct image **image ) {
125
-
126
-	/* Sanity check */
127
-	assert ( text != NULL );
128
-
129
-	/* Find network device */
130
-	*image = find_image ( text );
131
-	if ( ! *image ) {
132
-		printf ( "\"%s\": no such image\n", text );
133
-		return -ENOENT;
134
-	}
135
-
136
-	return 0;
137
-}
138
-
139
 /**
117
 /**
140
  * Parse flag
118
  * Parse flag
141
  *
119
  *

+ 3
- 2
src/hci/commands/digest_cmd.c View File

28
 #include <ipxe/crypto.h>
28
 #include <ipxe/crypto.h>
29
 #include <ipxe/md5.h>
29
 #include <ipxe/md5.h>
30
 #include <ipxe/sha1.h>
30
 #include <ipxe/sha1.h>
31
+#include <usr/imgmgmt.h>
31
 
32
 
32
 /** @file
33
 /** @file
33
  *
34
  *
74
 
75
 
75
 	for ( i = optind ; i < argc ; i++ ) {
76
 	for ( i = optind ; i < argc ; i++ ) {
76
 
77
 
77
-		/* find image */
78
-		if ( ( rc = parse_image ( argv[i], &image ) ) != 0 )
78
+		/* Acquire image */
79
+		if ( ( rc = imgacquire ( argv[i], &image ) ) != 0 )
79
 			continue;
80
 			continue;
80
 		offset = 0;
81
 		offset = 0;
81
 		len = image->len;
82
 		len = image->len;

+ 170
- 223
src/hci/commands/image_cmd.c View File

34
  *
34
  *
35
  */
35
  */
36
 
36
 
37
-/** "imgfetch" options */
38
-struct imgfetch_options {
37
+/** "img{single}" options */
38
+struct imgsingle_options {
39
 	/** Image name */
39
 	/** Image name */
40
 	const char *name;
40
 	const char *name;
41
 };
41
 };
42
 
42
 
43
-/** "imgfetch" option list */
44
-static struct option_descriptor imgfetch_opts[] = {
43
+/** "img{single}" option list */
44
+static struct option_descriptor imgsingle_opts[] = {
45
 	OPTION_DESC ( "name", 'n', required_argument,
45
 	OPTION_DESC ( "name", 'n', required_argument,
46
-		      struct imgfetch_options, name, parse_string ),
46
+		      struct imgsingle_options, name, parse_string ),
47
 };
47
 };
48
 
48
 
49
-/** "imgfetch" command descriptor */
50
-static struct command_descriptor imgfetch_cmd =
51
-	COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
52
-		       "[--name <name>] <uri> [<arguments>...]" );
49
+/** "img{single}" command descriptor */
50
+static struct command_descriptor imgsingle_cmd =
51
+	COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
52
+		       1, MAX_ARGUMENTS,
53
+		       "[--name <name>] <uri|image> [<arguments>...]" );
54
+
55
+/** An "img{single}" family command descriptor */
56
+struct imgsingle_descriptor {
57
+	/** Command descriptor */
58
+	struct command_descriptor *cmd;
59
+	/** Function to use to acquire the image */
60
+	int ( * acquire ) ( const char *name, struct image **image );
61
+	/** Pre-action to take upon image, or NULL */
62
+	void ( * preaction ) ( struct image *image );
63
+	/** Action to take upon image, or NULL */
64
+	int ( * action ) ( struct image *image );
65
+	/** Verb to describe action */
66
+	const char *verb;
67
+};
53
 
68
 
54
 /**
69
 /**
55
- * The "imgfetch" and friends command body
70
+ * The "img{single}" family of commands
56
  *
71
  *
57
  * @v argc		Argument count
72
  * @v argc		Argument count
58
  * @v argv		Argument list
73
  * @v argv		Argument list
59
- * @v cmd		Command descriptor
74
+ * @v desc		"img{single}" command descriptor
60
  * @v action_name	Action name (for error messages)
75
  * @v action_name	Action name (for error messages)
61
- * @v action		Action to take upon a successful download
76
+ * @v action		Action to take upon image
62
  * @ret rc		Return status code
77
  * @ret rc		Return status code
63
  */
78
  */
64
-static int imgfetch_core_exec ( int argc, char **argv,
65
-				const char *action_name,
66
-				int ( * action ) ( struct image *image ) ) {
67
-	struct imgfetch_options opts;
68
-	char *uri_string;
79
+static int imgsingle_exec ( int argc, char **argv,
80
+			    struct imgsingle_descriptor *desc ) {
81
+	struct imgsingle_options opts;
82
+	char *name_uri = NULL;
69
 	char *cmdline = NULL;
83
 	char *cmdline = NULL;
84
+	struct image *image;
70
 	int rc;
85
 	int rc;
71
 
86
 
72
 	/* Parse options */
87
 	/* Parse options */
73
-	if ( ( rc = parse_options ( argc, argv, &imgfetch_cmd, &opts ) ) != 0 )
88
+	if ( ( rc = parse_options ( argc, argv, desc->cmd, &opts ) ) != 0 )
74
 		goto err_parse_options;
89
 		goto err_parse_options;
75
 
90
 
76
-	/* Parse URI string */
77
-	uri_string = argv[optind];
91
+	/* Parse name/URI string and command line, if present */
92
+	if ( optind < argc ) {
93
+		name_uri = argv[optind];
94
+		if ( argv[ optind + 1 ] != NULL ) {
95
+			cmdline = concat_args ( &argv[ optind + 1 ] );
96
+			if ( ! cmdline ) {
97
+				rc = -ENOMEM;
98
+				goto err_parse_cmdline;
99
+			}
100
+		}
101
+	}
78
 
102
 
79
-	/* Parse command line */
80
-	if ( argv[ optind + 1 ] != NULL ) {
81
-		cmdline = concat_args ( &argv[ optind + 1 ] );
82
-		if ( ! cmdline ) {
83
-			rc = -ENOMEM;
84
-			goto err_cmdline;
103
+	/* Acquire the image */
104
+	if ( name_uri ) {
105
+		if ( ( rc = desc->acquire ( name_uri, &image ) ) != 0 )
106
+			goto err_acquire;
107
+	} else {
108
+		image = image_find_selected();
109
+		if ( ! image ) {
110
+			printf ( "No image selected\n" );
111
+			goto err_acquire;
85
 		}
112
 		}
86
 	}
113
 	}
87
 
114
 
88
-	/* Fetch the image */
89
-	if ( ( rc = imgdownload_string ( uri_string, opts.name, cmdline,
90
-					 action ) ) != 0 ) {
91
-		printf ( "Could not %s %s: %s\n",
92
-			 action_name, uri_string, strerror ( rc ) );
93
-		goto err_imgdownload;
115
+	/* Carry out command pre-action, if applicable */
116
+	if ( desc->preaction )
117
+		desc->preaction ( image );
118
+
119
+	/* Set the image name, if applicable */
120
+	if ( opts.name ) {
121
+		if ( ( rc = image_set_name ( image, opts.name ) ) != 0 ) {
122
+			printf ( "Could not name image: %s\n",
123
+				 strerror ( rc ) );
124
+			goto err_set_name;
125
+		}
94
 	}
126
 	}
95
 
127
 
96
-	/* Free command line */
97
-	free ( cmdline );
128
+	/* Set the command-line arguments, if applicable */
129
+	if ( cmdline ) {
130
+		if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 ) {
131
+			printf ( "Could not set arguments: %s\n",
132
+				 strerror ( rc ) );
133
+			goto err_set_cmdline;
134
+		}
135
+	}
98
 
136
 
99
-	return 0;
137
+	/* Carry out command action, if applicable */
138
+	if ( desc->action ) {
139
+		if ( ( rc = desc->action ( image ) ) != 0 ) {
140
+			printf ( "Could not %s: %s\n",
141
+				 desc->verb, strerror ( rc ) );
142
+			goto err_action;
143
+		}
144
+	}
100
 
145
 
101
- err_imgdownload:
146
+	/* Success */
147
+	rc = 0;
148
+
149
+ err_action:
150
+ err_set_cmdline:
151
+ err_set_name:
152
+ err_acquire:
102
 	free ( cmdline );
153
 	free ( cmdline );
103
- err_cmdline:
154
+ err_parse_cmdline:
104
  err_parse_options:
155
  err_parse_options:
105
 	return rc;
156
 	return rc;
106
 }
157
 }
107
 
158
 
108
-/**
109
- * The "imgfetch"/"module" command
110
- *
111
- * @v argc		Argument count
112
- * @v argv		Argument list
113
- * @ret rc		Return status code
114
- */
115
-static int imgfetch_exec ( int argc, char **argv ) {
159
+/** "imgfetch" command descriptor */
160
+static struct command_descriptor imgfetch_cmd =
161
+	COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
162
+		       1, MAX_ARGUMENTS,
163
+		       "[--name <name>] <uri> [<arguments>...]" );
116
 
164
 
117
-	return imgfetch_core_exec ( argc, argv, "fetch", NULL );
118
-}
165
+/** "imgfetch" family command descriptor */
166
+struct imgsingle_descriptor imgfetch_desc = {
167
+	.cmd = &imgfetch_cmd,
168
+	.acquire = imgdownload_string,
169
+};
119
 
170
 
120
 /**
171
 /**
121
- * The "kernel" command
172
+ * The "imgfetch" command
122
  *
173
  *
123
  * @v argc		Argument count
174
  * @v argc		Argument count
124
  * @v argv		Argument list
175
  * @v argv		Argument list
125
  * @ret rc		Return status code
176
  * @ret rc		Return status code
126
  */
177
  */
127
-static int kernel_exec ( int argc, char **argv ) {
128
-
129
-	return imgfetch_core_exec ( argc, argv, "select", image_select );
178
+static int imgfetch_exec ( int argc, char **argv ) {
179
+	return imgsingle_exec ( argc, argv, &imgfetch_desc );
130
 }
180
 }
131
 
181
 
182
+/** "imgselect" family command descriptor */
183
+struct imgsingle_descriptor imgselect_desc = {
184
+	.cmd = &imgsingle_cmd,
185
+	.acquire = imgacquire,
186
+	.action = image_select,
187
+	.verb = "select",
188
+};
189
+
132
 /**
190
 /**
133
- * The "chain" command
191
+ * The "imgselect" command
134
  *
192
  *
135
  * @v argc		Argument count
193
  * @v argc		Argument count
136
  * @v argv		Argument list
194
  * @v argv		Argument list
137
  * @ret rc		Return status code
195
  * @ret rc		Return status code
138
  */
196
  */
139
-static int chain_exec ( int argc, char **argv) {
140
-
141
-	return imgfetch_core_exec ( argc, argv, "boot", image_exec );
197
+static int imgselect_exec ( int argc, char **argv ) {
198
+	return imgsingle_exec ( argc, argv, &imgselect_desc );
142
 }
199
 }
143
 
200
 
144
-/** "imgselect" options */
145
-struct imgselect_options {};
146
-
147
-/** "imgselect" option list */
148
-static struct option_descriptor imgselect_opts[] = {};
149
-
150
-/** "imgselect" command descriptor */
151
-static struct command_descriptor imgselect_cmd =
152
-	COMMAND_DESC ( struct imgselect_options, imgselect_opts, 1, 1,
153
-		       "<image>" );
201
+/** "imgexec" command descriptor */
202
+static struct command_descriptor imgexec_cmd =
203
+	COMMAND_DESC ( struct imgsingle_options, imgsingle_opts,
204
+		       0, MAX_ARGUMENTS,
205
+		       "[--name <name>] [<uri|image> [<arguments>...]]" );
206
+
207
+/** "imgexec" family command descriptor */
208
+struct imgsingle_descriptor imgexec_desc = {
209
+	.cmd = &imgexec_cmd,
210
+	.acquire = imgacquire,
211
+	.action = image_exec,
212
+	.verb = "boot",
213
+};
154
 
214
 
155
 /**
215
 /**
156
- * The "imgselect" command
216
+ * The "imgexec" command
157
  *
217
  *
158
  * @v argc		Argument count
218
  * @v argc		Argument count
159
  * @v argv		Argument list
219
  * @v argv		Argument list
160
  * @ret rc		Return status code
220
  * @ret rc		Return status code
161
  */
221
  */
162
-static int imgselect_exec ( int argc, char **argv ) {
163
-	struct imgselect_options opts;
164
-	struct image *image;
165
-	int rc;
166
-
167
-	/* Parse options */
168
-	if ( ( rc = parse_options ( argc, argv, &imgselect_cmd, &opts ) ) != 0 )
169
-		return rc;
170
-
171
-	/* Parse image name */
172
-	if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
173
-		return rc;
174
-
175
-	/* Load image */
176
-	if ( ( rc = imgselect ( image ) ) != 0 ) {
177
-		printf ( "Could not select %s: %s\n",
178
-			 image->name, strerror ( rc ) );
179
-		return rc;
180
-	}
181
-
182
-	return 0;
222
+static int imgexec_exec ( int argc, char **argv) {
223
+	return imgsingle_exec ( argc, argv, &imgexec_desc );
183
 }
224
 }
184
 
225
 
185
-/** "imgargs" options */
186
-struct imgargs_options {};
187
-
188
-/** "imgargs" option list */
189
-static struct option_descriptor imgargs_opts[] = {};
190
-
191
-/** "imgargs" command descriptor */
192
-static struct command_descriptor imgargs_cmd =
193
-	COMMAND_DESC ( struct imgargs_options, imgargs_opts, 1, MAX_ARGUMENTS,
194
-		       "<image> [<arguments>...]" );
226
+/** "imgargs" family command descriptor */
227
+struct imgsingle_descriptor imgargs_desc = {
228
+	.cmd = &imgsingle_cmd,
229
+	.acquire = imgacquire,
230
+	.preaction = image_clear_cmdline,
231
+};
195
 
232
 
196
 /**
233
 /**
197
  * The "imgargs" command body
234
  * The "imgargs" command body
201
  * @ret rc		Return status code
238
  * @ret rc		Return status code
202
  */
239
  */
203
 static int imgargs_exec ( int argc, char **argv ) {
240
 static int imgargs_exec ( int argc, char **argv ) {
204
-	struct imgargs_options opts;
205
-	struct image *image;
206
-	char *cmdline = NULL;
207
-	int rc;
208
-
209
-	/* Parse options */
210
-	if ( ( rc = parse_options ( argc, argv, &imgargs_cmd, &opts ) ) != 0 )
211
-		goto err_parse_options;
212
-
213
-	/* Parse image name */
214
-	if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
215
-		goto err_parse_image;
216
-
217
-	/* Parse command line */
218
-	if ( argv[ optind + 1 ] != NULL ) {
219
-		cmdline = concat_args ( &argv[ optind + 1 ] );
220
-		if ( ! cmdline ) {
221
-			rc = -ENOMEM;
222
-			goto err_cmdline;
223
-		}
224
-	}
225
-
226
-	/* Set command line */
227
-	if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 )
228
-		goto err_set_cmdline;
229
-
230
-	/* Free command line */
231
-	free ( cmdline );
232
-
233
-	return 0;
234
-
235
- err_set_cmdline:
236
-	free ( cmdline );
237
- err_cmdline:
238
- err_parse_image:
239
- err_parse_options:
240
-	return rc;
241
+	return imgsingle_exec ( argc, argv, &imgargs_desc );
241
 }
242
 }
242
 
243
 
243
-/** "imgexec" options */
244
-struct imgexec_options {};
244
+/** "img{multi}" options */
245
+struct imgmulti_options {};
245
 
246
 
246
-/** "imgexec" option list */
247
-static struct option_descriptor imgexec_opts[] = {};
247
+/** "img{multi}" option list */
248
+static struct option_descriptor imgmulti_opts[] = {};
248
 
249
 
249
-/** "imgexec" command descriptor */
250
-static struct command_descriptor imgexec_cmd =
251
-	COMMAND_DESC ( struct imgexec_options, imgexec_opts, 0, 1,
252
-		       "[<image>]" );
250
+/** "img{multi}" command descriptor */
251
+static struct command_descriptor imgmulti_cmd =
252
+	COMMAND_DESC ( struct imgmulti_options, imgmulti_opts, 0, MAX_ARGUMENTS,
253
+		       "[<image>...]" );
253
 
254
 
254
 /**
255
 /**
255
- * The "imgexec" command
256
+ * The "img{multi}" family of commands
256
  *
257
  *
257
  * @v argc		Argument count
258
  * @v argc		Argument count
258
  * @v argv		Argument list
259
  * @v argv		Argument list
260
+ * @v payload		Function to execute on each image
259
  * @ret rc		Return status code
261
  * @ret rc		Return status code
260
  */
262
  */
261
-static int imgexec_exec ( int argc, char **argv ) {
262
-	struct imgexec_options opts;
263
+static int imgmulti_exec ( int argc, char **argv,
264
+			   void ( * payload ) ( struct image *image ) ) {
265
+	struct imgmulti_options opts;
263
 	struct image *image;
266
 	struct image *image;
267
+	struct image *tmp;
268
+	int i;
264
 	int rc;
269
 	int rc;
265
 
270
 
266
 	/* Parse options */
271
 	/* Parse options */
267
-	if ( ( rc = parse_options ( argc, argv, &imgexec_cmd, &opts ) ) != 0 )
272
+	if ( ( rc = parse_options ( argc, argv, &imgmulti_cmd, &opts ) ) != 0 )
268
 		return rc;
273
 		return rc;
269
 
274
 
270
-	/* Parse image name */
271
-	if ( optind < argc ) {
272
-		if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
273
-			return rc;
274
-	} else {
275
-		image = imgautoselect();
276
-		if ( ! image ) {
277
-			rc = -ENOTTY;
278
-			printf ( "No image selected: %s\n", strerror ( rc ) );
279
-			return rc;
280
-		}
275
+	/* If no images are explicitly specified, process all images */
276
+	if ( optind == argc ) {
277
+		for_each_image_safe ( image, tmp )
278
+			payload ( image );
279
+		return 0;
281
 	}
280
 	}
282
 
281
 
283
-	/* Execute image */
284
-	if ( ( rc = imgexec ( image ) ) != 0 ) {
285
-		printf ( "Could not execute %s: %s\n",
286
-			 image->name, strerror ( rc ) );
287
-		return rc;
282
+	/* Otherwise, process specified images */
283
+	for ( i = optind ; i < argc ; i++ ) {
284
+		image = find_image ( argv[i] );
285
+		if ( ! image ) {
286
+			printf ( "\"%s\": no such image\n", argv[i] );
287
+			return -ENOENT;
288
+		}
289
+		payload ( image );
288
 	}
290
 	}
289
 
291
 
290
 	return 0;
292
 	return 0;
291
 }
293
 }
292
 
294
 
293
-/** "imgstat" options */
294
-struct imgstat_options {};
295
-
296
-/** "imgstat" option list */
297
-static struct option_descriptor imgstat_opts[] = {};
298
-
299
-/** "imgstat" command descriptor */
300
-static struct command_descriptor imgstat_cmd =
301
-	COMMAND_DESC ( struct imgstat_options, imgstat_opts, 0, 0, "" );
302
-
303
 /**
295
 /**
304
  * The "imgstat" command
296
  * The "imgstat" command
305
  *
297
  *
308
  * @ret rc		Return status code
300
  * @ret rc		Return status code
309
  */
301
  */
310
 static int imgstat_exec ( int argc, char **argv ) {
302
 static int imgstat_exec ( int argc, char **argv ) {
311
-	struct imgstat_options opts;
312
-	struct image *image;
313
-	int rc;
314
-
315
-	/* Parse options */
316
-	if ( ( rc = parse_options ( argc, argv, &imgstat_cmd, &opts ) ) != 0 )
317
-		return rc;
318
-
319
-	/* Show status of all images */
320
-	for_each_image ( image ) {
321
-		imgstat ( image );
322
-	}
323
-
324
-	return 0;
303
+	return imgmulti_exec ( argc, argv, imgstat );
325
 }
304
 }
326
 
305
 
327
-/** "imgfree" options */
328
-struct imgfree_options {};
329
-
330
-/** "imgfree" option list */
331
-static struct option_descriptor imgfree_opts[] = {};
332
-
333
-/** "imgfree" command descriptor */
334
-static struct command_descriptor imgfree_cmd =
335
-	COMMAND_DESC ( struct imgfree_options, imgfree_opts, 0, 1,
336
-		       "[<image>]" );
337
-
338
 /**
306
 /**
339
  * The "imgfree" command
307
  * The "imgfree" command
340
  *
308
  *
343
  * @ret rc		Return status code
311
  * @ret rc		Return status code
344
  */
312
  */
345
 static int imgfree_exec ( int argc, char **argv ) {
313
 static int imgfree_exec ( int argc, char **argv ) {
346
-	struct imgfree_options opts;
347
-	struct image *image;
348
-	struct image *tmp;
349
-	int rc;
350
-
351
-	/* Parse options */
352
-	if ( ( rc = parse_options ( argc, argv, &imgfree_cmd, &opts ) ) != 0 )
353
-		return rc;
354
-
355
-	if ( optind < argc ) {
356
-		/* Free specified image */
357
-		if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
358
-			return rc;
359
-		imgfree ( image );
360
-	} else {
361
-		/* Free all images */
362
-		list_for_each_entry_safe ( image, tmp, &images, list ) {
363
-			imgfree ( image );
364
-		}
365
-	}
366
-
367
-	return 0;
314
+	return imgmulti_exec ( argc, argv, unregister_image );
368
 }
315
 }
369
 
316
 
370
 /** Image management commands */
317
 /** Image management commands */
383
 	},
330
 	},
384
 	{
331
 	{
385
 		.name = "kernel",
332
 		.name = "kernel",
386
-		.exec = kernel_exec,
333
+		.exec = imgselect_exec, /* synonym for "imgselect" */
387
 	},
334
 	},
388
 	{
335
 	{
389
 		.name = "chain",
336
 		.name = "chain",
390
-		.exec = chain_exec,
337
+		.exec = imgexec_exec, /* synonym for "imgexec" */
391
 	},
338
 	},
392
 	{
339
 	{
393
 		.name = "imgselect",
340
 		.name = "imgselect",
394
 		.exec = imgselect_exec,
341
 		.exec = imgselect_exec,
395
 	},
342
 	},
396
 	{
343
 	{
397
-		.name = "imgload", /* synonym for "imgselect" */
398
-		.exec = imgselect_exec,
344
+		.name = "imgload",
345
+		.exec = imgselect_exec, /* synonym for "imgselect" */
399
 	},
346
 	},
400
 	{
347
 	{
401
 		.name = "imgargs",
348
 		.name = "imgargs",

+ 10
- 9
src/include/ipxe/image.h View File

29
 	/** URI of image */
29
 	/** URI of image */
30
 	struct uri *uri;
30
 	struct uri *uri;
31
 	/** Name */
31
 	/** Name */
32
-	char name[16];
32
+	char *name;
33
 	/** Flags */
33
 	/** Flags */
34
 	unsigned int flags;
34
 	unsigned int flags;
35
 
35
 
122
 #define for_each_image( image ) \
122
 #define for_each_image( image ) \
123
 	list_for_each_entry ( (image), &images, list )
123
 	list_for_each_entry ( (image), &images, list )
124
 
124
 
125
+/** Iterate over all registered images, safe against deletion */
126
+#define for_each_image_safe( image, tmp ) \
127
+	list_for_each_entry_safe ( (image), (tmp), &images, list )
128
+
125
 /**
129
 /**
126
  * Test for existence of images
130
  * Test for existence of images
127
  *
131
  *
140
 	return list_first_entry ( &images, struct image, list );
144
 	return list_first_entry ( &images, struct image, list );
141
 }
145
 }
142
 
146
 
143
-extern struct image * alloc_image ( void );
144
-extern void image_set_uri ( struct image *image, struct uri *uri );
147
+extern struct image * alloc_image ( struct uri *uri );
148
+extern int image_set_name ( struct image *image, const char *name );
145
 extern int image_set_cmdline ( struct image *image, const char *cmdline );
149
 extern int image_set_cmdline ( struct image *image, const char *cmdline );
146
 extern int register_image ( struct image *image );
150
 extern int register_image ( struct image *image );
147
 extern void unregister_image ( struct image *image );
151
 extern void unregister_image ( struct image *image );
174
 }
178
 }
175
 
179
 
176
 /**
180
 /**
177
- * Set image name
181
+ * Clear image command line
178
  *
182
  *
179
  * @v image		Image
183
  * @v image		Image
180
- * @v name		New image name
181
- * @ret rc		Return status code
182
  */
184
  */
183
-static inline int image_set_name ( struct image *image, const char *name ) {
184
-	strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) );
185
-	return 0;
185
+static inline void image_clear_cmdline ( struct image *image ) {
186
+	image_set_cmdline ( image, NULL );
186
 }
187
 }
187
 
188
 
188
 /**
189
 /**

+ 0
- 2
src/include/ipxe/parseopt.h View File

13
 #include <stddef.h>
13
 #include <stddef.h>
14
 
14
 
15
 struct net_device;
15
 struct net_device;
16
-struct image;
17
 
16
 
18
 /** A command-line option descriptor */
17
 /** A command-line option descriptor */
19
 struct option_descriptor {
18
 struct option_descriptor {
117
 extern int parse_string ( const char *text, const char **value );
116
 extern int parse_string ( const char *text, const char **value );
118
 extern int parse_integer ( const char *text, unsigned int *value );
117
 extern int parse_integer ( const char *text, unsigned int *value );
119
 extern int parse_netdev ( const char *text, struct net_device **netdev );
118
 extern int parse_netdev ( const char *text, struct net_device **netdev );
120
-extern int parse_image ( const char *text, struct image **image );
121
 extern int parse_flag ( const char *text __unused, int *flag );
119
 extern int parse_flag ( const char *text __unused, int *flag );
122
 extern void print_usage ( struct command_descriptor *cmd, char **argv );
120
 extern void print_usage ( struct command_descriptor *cmd, char **argv );
123
 extern int reparse_options ( int argc, char **argv,
121
 extern int reparse_options ( int argc, char **argv,

+ 3
- 35
src/include/usr/imgmgmt.h View File

11
 
11
 
12
 #include <ipxe/image.h>
12
 #include <ipxe/image.h>
13
 
13
 
14
-extern int imgdownload ( struct uri *uri, const char *name, const char *cmdline,
15
-			 int ( * action ) ( struct image *image ) );
16
-extern int imgdownload_string ( const char *uri_string, const char *name,
17
-				const char *cmdline,
18
-				int ( * action ) ( struct image *image ) );
14
+extern int imgdownload ( struct uri *uri, struct image **image );
15
+extern int imgdownload_string ( const char *uri_string, struct image **image );
16
+extern int imgacquire ( const char *name, struct image **image );
19
 extern void imgstat ( struct image *image );
17
 extern void imgstat ( struct image *image );
20
-extern void imgfree ( struct image *image );
21
-
22
-/**
23
- * Select an image for execution
24
- *
25
- * @v image		Image
26
- * @ret rc		Return status code
27
- */
28
-static inline int imgselect ( struct image *image ) {
29
-	return image_select ( image );
30
-}
31
-
32
-/**
33
- * Find the previously-selected image
34
- *
35
- * @ret image		Image, or NULL
36
- */
37
-static inline struct image * imgautoselect ( void ) {
38
-	return image_find_selected();
39
-}
40
-
41
-/**
42
- * Execute an image
43
- *
44
- * @v image		Image
45
- * @ret rc		Return status code
46
- */
47
-static inline int imgexec ( struct image *image ) {
48
-	return image_exec ( image );
49
-}
50
 
18
 
51
 #endif /* _USR_IMGMGMT_H */
19
 #endif /* _USR_IMGMGMT_H */

+ 1
- 5
src/tests/test.c View File

149
 	.exec = test_image_exec,
149
 	.exec = test_image_exec,
150
 };
150
 };
151
 
151
 
152
-static void test_image_free ( struct refcnt *refcnt __unused ) {
153
-	/* Do nothing */
154
-}
155
-
156
 static struct image test_image = {
152
 static struct image test_image = {
157
-	.refcnt = REF_INIT ( test_image_free ),
153
+	.refcnt = REF_INIT ( ref_no_free ),
158
 	.name = "<TESTS>",
154
 	.name = "<TESTS>",
159
 	.type = &test_image_type,
155
 	.type = &test_image_type,
160
 };
156
 };

+ 6
- 3
src/usr/autoboot.c View File

131
  */
131
  */
132
 int uriboot ( struct uri *filename, struct uri *root_path, int drive,
132
 int uriboot ( struct uri *filename, struct uri *root_path, int drive,
133
 	      unsigned int flags ) {
133
 	      unsigned int flags ) {
134
+	struct image *image;
134
 	int rc;
135
 	int rc;
135
 
136
 
136
 	/* Hook SAN device, if applicable */
137
 	/* Hook SAN device, if applicable */
157
 
158
 
158
 	/* Attempt filename boot if applicable */
159
 	/* Attempt filename boot if applicable */
159
 	if ( filename ) {
160
 	if ( filename ) {
160
-		if ( ( rc = imgdownload ( filename, NULL, NULL,
161
-					  image_exec ) ) != 0 ) {
162
-			printf ( "\nCould not chain image: %s\n",
161
+		if ( ( rc = imgdownload ( filename, &image ) ) != 0 )
162
+			goto err_download;
163
+		if ( ( rc = image_exec ( image ) ) != 0 ) {
164
+			printf ( "Could not boot image: %s\n",
163
 				 strerror ( rc ) );
165
 				 strerror ( rc ) );
164
 			/* Fall through to (possibly) attempt a SAN boot
166
 			/* Fall through to (possibly) attempt a SAN boot
165
 			 * as a fallback.  If no SAN boot is attempted,
167
 			 * as a fallback.  If no SAN boot is attempted,
190
 		}
192
 		}
191
 	}
193
 	}
192
 
194
 
195
+ err_download:
193
  err_san_describe:
196
  err_san_describe:
194
 	/* Unhook SAN device, if applicable */
197
 	/* Unhook SAN device, if applicable */
195
 	if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_UNHOOK ) ) {
198
 	if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_UNHOOK ) ) {

+ 36
- 43
src/usr/imgmgmt.c View File

36
  */
36
  */
37
 
37
 
38
 /**
38
 /**
39
- * Download an image
39
+ * Download a new image
40
  *
40
  *
41
  * @v uri		URI
41
  * @v uri		URI
42
- * @v name		Image name, or NULL to use default
43
- * @v cmdline		Command line, or NULL for no command line
44
- * @v action		Action to take upon a successful download, or NULL
42
+ * @v image		Image to fill in
45
  * @ret rc		Return status code
43
  * @ret rc		Return status code
46
  */
44
  */
47
-int imgdownload ( struct uri *uri, const char *name, const char *cmdline,
48
-		  int ( * action ) ( struct image *image ) ) {
49
-	struct image *image;
45
+int imgdownload ( struct uri *uri, struct image **image ) {
50
 	size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 );
46
 	size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 );
51
 	char uri_string_redacted[len];
47
 	char uri_string_redacted[len];
52
 	const char *password;
48
 	const char *password;
53
 	int rc;
49
 	int rc;
54
 
50
 
55
 	/* Allocate image */
51
 	/* Allocate image */
56
-	image = alloc_image();
57
-	if ( ! image ) {
52
+	*image = alloc_image ( uri );
53
+	if ( ! *image ) {
58
 		rc = -ENOMEM;
54
 		rc = -ENOMEM;
59
 		goto err_alloc_image;
55
 		goto err_alloc_image;
60
 	}
56
 	}
61
 
57
 
62
-	/* Set image name */
63
-	if ( name )
64
-		image_set_name ( image, name );
65
-
66
-	/* Set image URI */
67
-	image_set_uri ( image, uri );
68
-
69
-	/* Set image command line */
70
-	image_set_cmdline ( image, cmdline );
71
-
72
 	/* Redact password portion of URI, if necessary */
58
 	/* Redact password portion of URI, if necessary */
73
 	password = uri->password;
59
 	password = uri->password;
74
 	if ( password )
60
 	if ( password )
78
 	uri->password = password;
64
 	uri->password = password;
79
 
65
 
80
 	/* Create downloader */
66
 	/* Create downloader */
81
-	if ( ( rc = create_downloader ( &monojob, image, LOCATION_URI,
67
+	if ( ( rc = create_downloader ( &monojob, *image, LOCATION_URI,
82
 					uri ) ) != 0 ) {
68
 					uri ) ) != 0 ) {
69
+		printf ( "Could not start download: %s\n", strerror ( rc ) );
83
 		goto err_create_downloader;
70
 		goto err_create_downloader;
84
 	}
71
 	}
85
 
72
 
88
 		goto err_monojob_wait;
75
 		goto err_monojob_wait;
89
 
76
 
90
 	/* Register image */
77
 	/* Register image */
91
-	if ( ( rc = register_image ( image ) ) != 0 )
78
+	if ( ( rc = register_image ( *image ) ) != 0 ) {
79
+		printf ( "Could not register image: %s\n", strerror ( rc ) );
92
 		goto err_register_image;
80
 		goto err_register_image;
81
+	}
93
 
82
 
94
 	/* Drop local reference to image.  Image is guaranteed to
83
 	/* Drop local reference to image.  Image is guaranteed to
95
 	 * remain in scope since it is registered.
84
 	 * remain in scope since it is registered.
96
 	 */
85
 	 */
97
-	image_put ( image );
86
+	image_put ( *image );
98
 
87
 
99
-	/* Carry out specified post-download action, if applicable */
100
-	return ( action ? action ( image ) : 0 );
88
+	return 0;
101
 
89
 
102
  err_register_image:
90
  err_register_image:
103
  err_monojob_wait:
91
  err_monojob_wait:
104
  err_create_downloader:
92
  err_create_downloader:
105
-	image_put ( image );
93
+	image_put ( *image );
106
  err_alloc_image:
94
  err_alloc_image:
107
 	return rc;
95
 	return rc;
108
 }
96
 }
109
 
97
 
110
 /**
98
 /**
111
- * Download an image
99
+ * Download a new image
112
  *
100
  *
113
- * @v uri_string	URI as a string (e.g. "http://www.nowhere.com/vmlinuz")
114
- * @v name		Image name, or NULL to use default
115
- * @v cmdline		Command line, or NULL for no command line
116
- * @v action		Action to take upon a successful download
101
+ * @v uri_string	URI string
102
+ * @v image		Image to fill in
117
  * @ret rc		Return status code
103
  * @ret rc		Return status code
118
  */
104
  */
119
-int imgdownload_string ( const char *uri_string, const char *name,
120
-			 const char *cmdline,
121
-			 int ( * action ) ( struct image *image ) ) {
105
+int imgdownload_string ( const char *uri_string, struct image **image ) {
122
 	struct uri *uri;
106
 	struct uri *uri;
123
 	int rc;
107
 	int rc;
124
 
108
 
125
 	if ( ! ( uri = parse_uri ( uri_string ) ) )
109
 	if ( ! ( uri = parse_uri ( uri_string ) ) )
126
 		return -ENOMEM;
110
 		return -ENOMEM;
127
 
111
 
128
-	rc = imgdownload ( uri, name, cmdline, action );
112
+	rc = imgdownload ( uri, image );
129
 
113
 
130
 	uri_put ( uri );
114
 	uri_put ( uri );
131
 	return rc;
115
 	return rc;
132
 }
116
 }
133
 
117
 
118
+/**
119
+ * Acquire an image
120
+ *
121
+ * @v name_uri		Name or URI string
122
+ * @v image		Image to fill in
123
+ * @ret rc		Return status code
124
+ */
125
+int imgacquire ( const char *name_uri, struct image **image ) {
126
+
127
+	/* If we already have an image with the specified name, use it */
128
+	*image = find_image ( name_uri );
129
+	if ( *image )
130
+		return 0;
131
+
132
+	/* Otherwise, download a new image */
133
+	return imgdownload_string ( name_uri, image );
134
+}
135
+
134
 /**
136
 /**
135
  * Display status of an image
137
  * Display status of an image
136
  *
138
  *
148
 		printf ( " \"%s\"", image->cmdline );
150
 		printf ( " \"%s\"", image->cmdline );
149
 	printf ( "\n" );
151
 	printf ( "\n" );
150
 }
152
 }
151
-
152
-/**
153
- * Free an image
154
- *
155
- * @v image		Executable/loadable image
156
- */
157
-void imgfree ( struct image *image ) {
158
-	unregister_image ( image );
159
-}

Loading…
Cancel
Save