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