syslinux/gpxe/src/hci/commands/image_cmd.c
<<
>>
Prefs
   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};
 609
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.