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