source: bootcd/isolinux/syslinux-6.03/gpxe/src/hci/commands/image_cmd.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

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