2d35ebcb2328ca7b6f597c87b60ab06d0bf4a87b
[people/adir/gpxe.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., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <errno.h>
23 #include <libgen.h>
24 #include <getopt.h>
25 #include <gpxe/image.h>
26 #include <gpxe/command.h>
27 #include <gpxe/initrd.h>
28 #include <usr/imgmgmt.h>
29
30 /** @file
31  *
32  * Image management commands
33  *
34  */
35
36 /**
37  * Print image description
38  *
39  */
40
41 /**
42  * Fill in image command line
43  *
44  * @v image             Image
45  * @v nargs             Argument count
46  * @v args              Argument list
47  */
48 void imgfill_cmdline ( struct image *image, unsigned int nargs, char **args ) {
49         size_t used = 0;
50
51         image->cmdline[0] = '\0';
52         while ( ( used < sizeof ( image->cmdline ) ) && nargs-- ) {
53                 used += snprintf ( &image->cmdline[used],
54                                    ( sizeof ( image->cmdline ) - used ),
55                                    "%s%s", ( used ? " " : "" ), *(args++) );
56         }
57 }
58
59 /**
60  * "imgfetch"/"module"/"kernel" command syntax message
61  *
62  * @v argv              Argument list
63  */
64 static void imgfetch_core_syntax ( char **argv, int load ) {
65         printf ( "Usage:\n"
66                  "  %s [-n|--name <name>] filename [arguments...]\n"
67                  "\n"
68                  "%s executable/loadable image\n",
69                  argv[0], ( load ? "Fetch and load" : "Fetch" ) );
70 }
71
72 /**
73  * The "imgfetch"/"module"/"kernel" command body
74  *
75  * @v image_type        Image type to assign (or NULL)
76  * @v load              Image will be automatically loaded after fetching
77  * @v argc              Argument count
78  * @v argv              Argument list
79  * @ret rc              Return status code
80  */
81 static int imgfetch_core_exec ( struct image_type *image_type, int load,
82                                 int argc, char **argv ) {
83         static struct option longopts[] = {
84                 { "help", 0, NULL, 'h' },
85                 { "name", required_argument, NULL, 'n' },
86                 { NULL, 0, NULL, 0 },
87         };
88         struct image *image;
89         const char *name = NULL;
90         char *filename;
91         int c;
92         int rc;
93
94         /* Parse options */
95         while ( ( c = getopt_long ( argc, argv, "hn:",
96                                     longopts, NULL ) ) >= 0 ) {
97                 switch ( c ) {
98                 case 'n':
99                         /* Set image name */
100                         name = optarg;
101                         break;
102                 case 'h':
103                         /* Display help text */
104                 default:
105                         /* Unrecognised/invalid option */
106                         imgfetch_core_syntax ( argv, load );
107                         return -EINVAL;
108                 }
109         }
110
111         /* Need at least a filename remaining after the options */
112         if ( optind == argc ) {
113                 imgfetch_core_syntax ( argv, load );
114                 return -EINVAL;
115         }
116         filename = argv[optind++];
117         if ( ! name )
118                 name = basename ( filename );
119
120         /* Allocate image */
121         image = alloc_image();
122         if ( ! image ) {
123                 printf ( "%s\n", strerror ( -ENOMEM ) );
124                 return -ENOMEM;
125         }
126
127         /* Fill in image name */
128         if ( name )
129                 strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) );
130
131         /* Set image type (if specified) */
132         image->type = image_type;
133
134         /* Fill in command line */
135         imgfill_cmdline ( image, ( argc - optind ), &argv[optind] );
136
137         /* Fetch the image */
138         if ( ( rc = imgfetch ( image, filename, load ) ) != 0 ) {
139                 printf ( "Could not fetch %s: %s\n", name, strerror ( rc ) );
140                 image_put ( image );
141                 return rc;
142         }
143
144         image_put ( image );
145         return 0;
146 }
147
148 /**
149  * The "imgfetch"/"module" command
150  *
151  * @v argc              Argument count
152  * @v argv              Argument list
153  * @ret rc              Exit code
154  */
155 static int imgfetch_exec ( int argc, char **argv ) {
156         int rc;
157
158         if ( ( rc = imgfetch_core_exec ( NULL, 0, argc, argv ) ) != 0 )
159                 return rc;
160
161         return 0;
162 }
163
164 /**
165  * The "kernel" command
166  *
167  * @v argc              Argument count
168  * @v argv              Argument list
169  * @ret rc              Exit code
170  */
171 static int kernel_exec ( int argc, char **argv ) {
172         int rc;
173
174         if ( ( rc = imgfetch_core_exec ( NULL, 1, argc, argv ) ) != 0 )
175                 return rc;
176
177         return 0;
178 }
179
180 /**
181  * The "initrd" command
182  *
183  * @v argc              Argument count
184  * @v argv              Argument list
185  * @ret rc              Exit code
186  */
187 static int initrd_exec ( int argc, char **argv ) {
188         int rc;
189
190         if ( ( rc = imgfetch_core_exec ( &initrd_image_type, 0,
191                                          argc, argv ) ) != 0 )
192                 return rc;
193
194         return 0;
195 }
196
197 /**
198  * "imgload" command syntax message
199  *
200  * @v argv              Argument list
201  */
202 static void imgload_syntax ( char **argv ) {
203         printf ( "Usage:\n"
204                  "  %s <image name>\n"
205                  "\n"
206                  "Load executable/loadable image\n",
207                  argv[0] );
208 }
209
210 /**
211  * The "imgload" command
212  *
213  * @v argc              Argument count
214  * @v argv              Argument list
215  * @ret rc              Exit code
216  */
217 static int imgload_exec ( int argc, char **argv ) {
218         static struct option longopts[] = {
219                 { "help", 0, NULL, 'h' },
220                 { NULL, 0, NULL, 0 },
221         };
222         struct image *image;
223         const char *name;
224         int c;
225         int rc;
226
227         /* Parse options */
228         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
229                 switch ( c ) {
230                 case 'h':
231                         /* Display help text */
232                 default:
233                         /* Unrecognised/invalid option */
234                         imgload_syntax ( argv );
235                         return 1;
236                 }
237         }
238
239         /* Need exactly one image name remaining after the options */
240         if ( optind != ( argc - 1 ) ) {
241                 imgload_syntax ( argv );
242                 return 1;
243         }
244         name = argv[optind];
245
246         /* Load all specified images */
247         image = find_image ( name );
248         if ( ! image ) {
249                 printf ( "No such image: %s\n", name );
250                 return 1;
251         }
252         if ( ( rc = imgload ( image ) ) != 0 ) {
253                 printf ( "Could not load %s: %s\n", name, strerror ( rc ) );
254                 return rc;
255         }
256
257         return 0;
258 }
259
260 /**
261  * "imgargs" command syntax message
262  *
263  * @v argv              Argument list
264  */
265 static void imgargs_syntax ( char **argv ) {
266         printf ( "Usage:\n"
267                  "  %s <image name> [<arguments>...]\n"
268                  "\n"
269                  "Set arguments for executable/loadable image\n",
270                  argv[0] );
271 }
272
273 /**
274  * The "imgargs" command body
275  *
276  * @v argc              Argument count
277  * @v argv              Argument list
278  * @ret rc              Exit code
279  */
280 static int imgargs_exec ( int argc, char **argv ) {
281         static struct option longopts[] = {
282                 { "help", 0, NULL, 'h' },
283                 { NULL, 0, NULL, 0 },
284         };
285         struct image *image;
286         const char *name;
287         int c;
288
289         /* Parse options */
290         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
291                 switch ( c ) {
292                 case 'h':
293                         /* Display help text */
294                 default:
295                         /* Unrecognised/invalid option */
296                         imgargs_syntax ( argv );
297                         return 1;
298                 }
299         }
300
301         /* Need at least an image name remaining after the options */
302         if ( optind == argc ) {
303                 imgargs_syntax ( argv );
304                 return 1;
305         }
306         name = argv[optind++];
307
308         /* Fill in command line */
309         image = find_image ( name );
310         if ( ! image ) {
311                 printf ( "No such image: %s\n", name );
312                 return 1;
313         }
314         imgfill_cmdline ( image, ( argc - optind ), &argv[optind] );
315
316         return 0;
317 }
318
319 /**
320  * "imgexec" command syntax message
321  *
322  * @v argv              Argument list
323  */
324 static void imgexec_syntax ( char **argv ) {
325         printf ( "Usage:\n"
326                  "  %s <image name>\n"
327                  "\n"
328                  "Execute executable/loadable image\n",
329                  argv[0] );
330 }
331
332 /**
333  * The "imgexec" command
334  *
335  * @v argc              Argument count
336  * @v argv              Argument list
337  * @ret rc              Exit code
338  */
339 static int imgexec_exec ( int argc, char **argv ) {
340         static struct option longopts[] = {
341                 { "help", 0, NULL, 'h' },
342                 { NULL, 0, NULL, 0 },
343         };
344         struct image *image;
345         const char *name = NULL;
346         int c;
347         int rc;
348
349         /* Parse options */
350         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
351                 switch ( c ) {
352                 case 'h':
353                         /* Display help text */
354                 default:
355                         /* Unrecognised/invalid option */
356                         imgexec_syntax ( argv );
357                         return 1;
358                 }
359         }
360
361         /* Need no more than one image name */
362         if ( optind != argc )
363                 name = argv[optind++];
364         if ( optind != argc ) {
365                 imgexec_syntax ( argv );
366                 return 1;
367         }
368         
369         /* Execute specified image */
370         if ( name ) {
371                 image = find_image ( name );
372                 if ( ! image ) {
373                         printf ( "No such image: %s\n", name );
374                         return 1;
375                 }
376         } else {
377                 image = imgautoselect();
378                 if ( ! image ) {
379                         printf ( "No loaded images\n" );
380                         return 1;
381                 }
382         }
383
384         if ( ( rc = imgexec ( image ) ) != 0 ) {
385                 printf ( "Could not execute %s: %s\n",
386                          image->name, strerror ( rc ) );
387                 return 1;
388         }
389
390         return 0;
391 }
392
393 /**
394  * "imgstat" command syntax message
395  *
396  * @v argv              Argument list
397  */
398 static void imgstat_syntax ( char **argv ) {
399         printf ( "Usage:\n"
400                  "  %s\n"
401                  "\n"
402                  "List executable/loadable images\n",
403                  argv[0] );
404 }
405
406 /**
407  * The "imgstat" command
408  *
409  * @v argc              Argument count
410  * @v argv              Argument list
411  * @ret rc              Exit code
412  */
413 static int imgstat_exec ( int argc, char **argv ) {
414         static struct option longopts[] = {
415                 { "help", 0, NULL, 'h' },
416                 { NULL, 0, NULL, 0 },
417         };
418         struct image *image;
419         int c;
420
421         /* Parse options */
422         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
423                 switch ( c ) {
424                 case 'h':
425                         /* Display help text */
426                 default:
427                         /* Unrecognised/invalid option */
428                         imgstat_syntax ( argv );
429                         return 1;
430                 }
431         }
432
433         /* No arguments */
434         if ( optind != argc ) {
435                 imgstat_syntax ( argv );
436                 return 1;
437         }
438
439         /* Show status of all images */
440         for_each_image ( image ) {
441                 imgstat ( image );
442         }
443         return 0;
444 }
445
446 /**
447  * "imgstat" command syntax message
448  *
449  * @v argv              Argument list
450  */
451 static void imgfree_syntax ( char **argv ) {
452         printf ( "Usage:\n"
453                  "  %s\n"
454                  "\n"
455                  "Free all executable/loadable images\n",
456                  argv[0] );
457 }
458
459 /**
460  * The "imgfree" command
461  *
462  * @v argc              Argument count
463  * @v argv              Argument list
464  * @ret rc              Exit code
465  */
466 static int imgfree_exec ( int argc, char **argv ) {
467         static struct option longopts[] = {
468                 { "help", 0, NULL, 'h' },
469                 { NULL, 0, NULL, 0 },
470         };
471         struct image *image;
472         struct image *tmp;
473         int c;
474
475         /* Parse options */
476         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
477                 switch ( c ) {
478                 case 'h':
479                         /* Display help text */
480                 default:
481                         /* Unrecognised/invalid option */
482                         imgfree_syntax ( argv );
483                         return 1;
484                 }
485         }
486
487         /* No arguments */
488         if ( optind != argc ) {
489                 imgfree_syntax ( argv );
490                 return 1;
491         }
492
493         /* Free all images */
494         list_for_each_entry_safe ( image, tmp, &images, list ) {
495                 imgfree ( image );
496         }
497         return 0;
498 }
499
500 /** Image management commands */
501 struct command image_commands[] __command = {
502         {
503                 .name = "imgfetch",
504                 .exec = imgfetch_exec,
505         },
506         {
507                 .name = "module",
508                 .exec = imgfetch_exec, /* synonym for "imgfetch" */
509         },
510         {
511                 .name = "kernel",
512                 .exec = kernel_exec,
513         },
514         {
515                 .name = "initrd",
516                 .exec = initrd_exec,
517         },
518         {
519                 .name = "imgload",
520                 .exec = imgload_exec,
521         },
522         {
523                 .name = "imgargs",
524                 .exec = imgargs_exec,
525         },
526         {
527                 .name = "imgexec",
528                 .exec = imgexec_exec,
529         },
530         {
531                 .name = "boot", /* synonym for "imgexec" */
532                 .exec = imgexec_exec,
533         },
534         {
535                 .name = "imgstat",
536                 .exec = imgstat_exec,
537         },
538         {
539                 .name = "imgfree",
540                 .exec = imgfree_exec,
541         },
542 };