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