[tcpip] Allow supported address families to be detected at runtime
[ipxe.git] / src / hci / commands / image_cmd.c
1 /*
2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <getopt.h>
31 #include <ipxe/image.h>
32 #include <ipxe/command.h>
33 #include <ipxe/parseopt.h>
34 #include <ipxe/shell.h>
35 #include <usr/imgmgmt.h>
36
37 /** @file
38 *
39 * Image management commands
40 *
41 */
42
43 /** "img{single}" options */
44 struct imgsingle_options {
45 /** Image name */
46 char *name;
47 /** Download timeout */
48 unsigned long timeout;
49 /** Replace image */
50 int replace;
51 /** Free image after execution */
52 int autofree;
53 };
54
55 /** "img{single}" option list */
56 static union {
57 /* "imgexec" takes all three options */
58 struct option_descriptor imgexec[4];
59 /* Other "img{single}" commands take only --name, --timeout,
60 * and --autofree
61 */
62 struct option_descriptor imgsingle[3];
63 } opts = {
64 .imgexec = {
65 OPTION_DESC ( "name", 'n', required_argument,
66 struct imgsingle_options, name, parse_string ),
67 OPTION_DESC ( "timeout", 't', required_argument,
68 struct imgsingle_options, timeout, parse_timeout),
69 OPTION_DESC ( "autofree", 'a', no_argument,
70 struct imgsingle_options, autofree, parse_flag ),
71 OPTION_DESC ( "replace", 'r', no_argument,
72 struct imgsingle_options, replace, parse_flag ),
73 },
74 };
75
76 /** An "img{single}" family command descriptor */
77 struct imgsingle_descriptor {
78 /** Command descriptor */
79 struct command_descriptor *cmd;
80 /** Function to use to acquire the image */
81 int ( * acquire ) ( const char *name, unsigned long timeout,
82 struct image **image );
83 /** Pre-action to take upon image, or NULL */
84 void ( * preaction ) ( struct image *image );
85 /** Action to take upon image, or NULL */
86 int ( * action ) ( struct image *image,
87 struct imgsingle_options *opts );
88 /** Verb to describe action */
89 const char *verb;
90 };
91
92 /**
93 * The "img{single}" family of commands
94 *
95 * @v argc Argument count
96 * @v argv Argument list
97 * @v desc "img{single}" command descriptor
98 * @v action_name Action name (for error messages)
99 * @v action Action to take upon image
100 * @ret rc Return status code
101 */
102 static int imgsingle_exec ( int argc, char **argv,
103 struct imgsingle_descriptor *desc ) {
104 struct imgsingle_options opts;
105 char *name_uri = NULL;
106 char *cmdline = NULL;
107 struct image *image;
108 int rc;
109
110 /* Parse options */
111 if ( ( rc = parse_options ( argc, argv, desc->cmd, &opts ) ) != 0 )
112 goto err_parse_options;
113
114 /* Parse name/URI string and command line, if present */
115 if ( optind < argc ) {
116 name_uri = argv[optind];
117 if ( argv[ optind + 1 ] != NULL ) {
118 cmdline = concat_args ( &argv[ optind + 1 ] );
119 if ( ! cmdline ) {
120 rc = -ENOMEM;
121 goto err_parse_cmdline;
122 }
123 }
124 }
125
126 /* Acquire the image */
127 if ( name_uri ) {
128 if ( ( rc = desc->acquire ( name_uri, opts.timeout,
129 &image ) ) != 0 )
130 goto err_acquire;
131 } else {
132 image = image_find_selected();
133 if ( ! image ) {
134 printf ( "No image selected\n" );
135 goto err_acquire;
136 }
137 }
138
139 /* Carry out command pre-action, if applicable */
140 if ( desc->preaction )
141 desc->preaction ( image );
142
143 /* Set the image name, if applicable */
144 if ( opts.name ) {
145 if ( ( rc = image_set_name ( image, opts.name ) ) != 0 ) {
146 printf ( "Could not name image: %s\n",
147 strerror ( rc ) );
148 goto err_set_name;
149 }
150 }
151
152 /* Set the command-line arguments, if applicable */
153 if ( cmdline ) {
154 if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 ) {
155 printf ( "Could not set arguments: %s\n",
156 strerror ( rc ) );
157 goto err_set_cmdline;
158 }
159 }
160
161 /* Set the auto-unregister flag, if applicable */
162 if ( opts.autofree )
163 image->flags |= IMAGE_AUTO_UNREGISTER;
164
165 /* Carry out command action, if applicable */
166 if ( desc->action ) {
167 if ( ( rc = desc->action ( image, &opts ) ) != 0 ) {
168 printf ( "Could not %s: %s\n",
169 desc->verb, strerror ( rc ) );
170 goto err_action;
171 }
172 }
173
174 /* Success */
175 rc = 0;
176
177 err_action:
178 err_set_cmdline:
179 err_set_name:
180 err_acquire:
181 free ( cmdline );
182 err_parse_cmdline:
183 err_parse_options:
184 return rc;
185 }
186
187 /** "imgfetch" command descriptor */
188 static struct command_descriptor imgfetch_cmd =
189 COMMAND_DESC ( struct imgsingle_options, opts.imgsingle,
190 1, MAX_ARGUMENTS, "<uri> [<arguments>...]" );
191
192 /** "imgfetch" family command descriptor */
193 struct imgsingle_descriptor imgfetch_desc = {
194 .cmd = &imgfetch_cmd,
195 .acquire = imgdownload_string,
196 };
197
198 /**
199 * The "imgfetch" command
200 *
201 * @v argc Argument count
202 * @v argv Argument list
203 * @ret rc Return status code
204 */
205 static int imgfetch_exec ( int argc, char **argv ) {
206 return imgsingle_exec ( argc, argv, &imgfetch_desc );
207 }
208
209 /**
210 * "imgselect" command action
211 *
212 * @v image Image
213 * @v opts Options
214 * @ret rc Return status code
215 */
216 static int imgselect ( struct image *image,
217 struct imgsingle_options *opts __unused ) {
218 return image_select ( image );
219 }
220
221 /** "imgselect" command descriptor */
222 static struct command_descriptor imgselect_cmd =
223 COMMAND_DESC ( struct imgsingle_options, opts.imgsingle,
224 1, MAX_ARGUMENTS, "<uri|image> [<arguments>...]" );
225
226 /** "imgselect" family command descriptor */
227 struct imgsingle_descriptor imgselect_desc = {
228 .cmd = &imgselect_cmd,
229 .acquire = imgacquire,
230 .action = imgselect,
231 .verb = "select",
232 };
233
234 /**
235 * The "imgselect" command
236 *
237 * @v argc Argument count
238 * @v argv Argument list
239 * @ret rc Return status code
240 */
241 static int imgselect_exec ( int argc, char **argv ) {
242 return imgsingle_exec ( argc, argv, &imgselect_desc );
243 }
244
245 /** "imgexec" command descriptor */
246 static struct command_descriptor imgexec_cmd =
247 COMMAND_DESC ( struct imgsingle_options, opts.imgexec,
248 0, MAX_ARGUMENTS, "[<uri|image> [<arguments>...]]" );
249
250 /**
251 * "imgexec" command action
252 *
253 * @v image Image
254 * @v opts Options
255 * @ret rc Return status code
256 */
257 static int imgexec ( struct image *image, struct imgsingle_options *opts ) {
258 int rc;
259
260 /* Perform replacement or execution as applicable */
261 if ( opts->replace ) {
262
263 /* Try to replace image */
264 if ( ( rc = image_replace ( image ) ) != 0 )
265 return rc;
266
267 /* Stop script and tail-recurse into replacement image */
268 shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
269
270 } else {
271
272 /* Try to execute image */
273 if ( ( rc = image_exec ( image ) ) != 0 )
274 return rc;
275 }
276
277 return 0;
278 }
279
280 /** "imgexec" family command descriptor */
281 struct imgsingle_descriptor imgexec_desc = {
282 .cmd = &imgexec_cmd,
283 .acquire = imgacquire,
284 .action = imgexec,
285 .verb = "boot",
286 };
287
288 /**
289 * The "imgexec" command
290 *
291 * @v argc Argument count
292 * @v argv Argument list
293 * @ret rc Return status code
294 */
295 static int imgexec_exec ( int argc, char **argv) {
296 return imgsingle_exec ( argc, argv, &imgexec_desc );
297 }
298
299 /** "imgargs" command descriptor */
300 static struct command_descriptor imgargs_cmd =
301 COMMAND_DESC ( struct imgsingle_options, opts.imgsingle,
302 1, MAX_ARGUMENTS, "<uri|image> [<arguments>...]" );
303
304 /** "imgargs" family command descriptor */
305 struct imgsingle_descriptor imgargs_desc = {
306 .cmd = &imgargs_cmd,
307 .acquire = imgacquire,
308 .preaction = image_clear_cmdline,
309 };
310
311 /**
312 * The "imgargs" command body
313 *
314 * @v argc Argument count
315 * @v argv Argument list
316 * @ret rc Return status code
317 */
318 static int imgargs_exec ( int argc, char **argv ) {
319 return imgsingle_exec ( argc, argv, &imgargs_desc );
320 }
321
322 /** "img{multi}" options */
323 struct imgmulti_options {};
324
325 /** "img{multi}" option list */
326 static struct option_descriptor imgmulti_opts[] = {};
327
328 /** "img{multi}" command descriptor */
329 static struct command_descriptor imgmulti_cmd =
330 COMMAND_DESC ( struct imgmulti_options, imgmulti_opts, 0, MAX_ARGUMENTS,
331 "[<image>...]" );
332
333 /**
334 * The "img{multi}" family of commands
335 *
336 * @v argc Argument count
337 * @v argv Argument list
338 * @v payload Function to execute on each image
339 * @ret rc Return status code
340 */
341 static int imgmulti_exec ( int argc, char **argv,
342 void ( * payload ) ( struct image *image ) ) {
343 struct imgmulti_options opts;
344 struct image *image;
345 struct image *tmp;
346 int i;
347 int rc;
348
349 /* Parse options */
350 if ( ( rc = parse_options ( argc, argv, &imgmulti_cmd, &opts ) ) != 0 )
351 return rc;
352
353 /* If no images are explicitly specified, process all images */
354 if ( optind == argc ) {
355 for_each_image_safe ( image, tmp )
356 payload ( image );
357 return 0;
358 }
359
360 /* Otherwise, process specified images */
361 for ( i = optind ; i < argc ; i++ ) {
362 image = find_image ( argv[i] );
363 if ( ! image ) {
364 printf ( "\"%s\": no such image\n", argv[i] );
365 return -ENOENT;
366 }
367 payload ( image );
368 }
369
370 return 0;
371 }
372
373 /**
374 * The "imgstat" command
375 *
376 * @v argc Argument count
377 * @v argv Argument list
378 * @ret rc Return status code
379 */
380 static int imgstat_exec ( int argc, char **argv ) {
381 return imgmulti_exec ( argc, argv, imgstat );
382 }
383
384 /**
385 * The "imgfree" command
386 *
387 * @v argc Argument count
388 * @v argv Argument list
389 * @ret rc Return status code
390 */
391 static int imgfree_exec ( int argc, char **argv ) {
392 return imgmulti_exec ( argc, argv, unregister_image );
393 }
394
395 /** Image management commands */
396 struct command image_commands[] __command = {
397 {
398 .name = "imgfetch",
399 .exec = imgfetch_exec,
400 },
401 {
402 .name = "module",
403 .exec = imgfetch_exec, /* synonym for "imgfetch" */
404 },
405 {
406 .name = "initrd",
407 .exec = imgfetch_exec, /* synonym for "imgfetch" */
408 },
409 {
410 .name = "kernel",
411 .exec = imgselect_exec, /* synonym for "imgselect" */
412 },
413 {
414 .name = "chain",
415 .exec = imgexec_exec, /* synonym for "imgexec" */
416 },
417 {
418 .name = "imgselect",
419 .exec = imgselect_exec,
420 },
421 {
422 .name = "imgload",
423 .exec = imgselect_exec, /* synonym for "imgselect" */
424 },
425 {
426 .name = "imgargs",
427 .exec = imgargs_exec,
428 },
429 {
430 .name = "imgexec",
431 .exec = imgexec_exec,
432 },
433 {
434 .name = "boot", /* synonym for "imgexec" */
435 .exec = imgexec_exec,
436 },
437 {
438 .name = "imgstat",
439 .exec = imgstat_exec,
440 },
441 {
442 .name = "imgfree",
443 .exec = imgfree_exec,
444 },
445 };