image_cmd.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <stdint.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <errno.h>
00025 #include <libgen.h>
00026 #include <getopt.h>
00027 #include <gpxe/image.h>
00028 #include <gpxe/command.h>
00029 #include <usr/imgmgmt.h>
00030 
00031 /** @file
00032  *
00033  * Image management commands
00034  *
00035  */
00036 
00037 enum image_action {
00038         IMG_FETCH = 0,
00039         IMG_LOAD,
00040         IMG_EXEC,
00041 };
00042 
00043 /**
00044  * Fill in image command line
00045  *
00046  * @v image             Image
00047  * @v nargs             Argument count
00048  * @v args              Argument list
00049  * @ret rc              Return status code
00050  */
00051 static int imgfill_cmdline ( struct image *image, unsigned int nargs, 
00052                              char **args ) {
00053         size_t len;
00054         unsigned int i;
00055 
00056         /* Determine total length of command line */
00057         len = 1; /* NUL */
00058         for ( i = 0 ; i < nargs ; i++ )
00059                 len += ( 1 /* possible space */ + strlen ( args[i] ) );
00060 
00061         {
00062                 char buf[len];
00063                 char *ptr = buf;
00064 
00065                 /* Assemble command line */
00066                 buf[0] = '\0';
00067                 for ( i = 0 ; i < nargs ; i++ ) {
00068                         ptr += sprintf ( ptr, "%s%s", ( i ? " " : "" ),
00069                                          args[i] );
00070                 }
00071                 assert ( ptr < ( buf + len ) );
00072 
00073                 return image_set_cmdline ( image, buf );
00074         }
00075 }
00076 
00077 /**
00078  * "imgfetch"/"module"/"kernel" command syntax message
00079  *
00080  * @v argv              Argument list
00081  */
00082 static void imgfetch_core_syntax ( char **argv, enum image_action action ) {
00083         static const char *actions[] = {
00084                 [IMG_FETCH]     = "Fetch",
00085                 [IMG_LOAD]      = "Fetch and load",
00086                 [IMG_EXEC]      = "Fetch and execute",
00087         };
00088 
00089         printf ( "Usage:\n"
00090                  "  %s [-n|--name <name>] filename [arguments...]\n"
00091                  "\n"
00092                  "%s executable/loadable image\n",
00093                  argv[0], actions[action] );
00094 }
00095 
00096 /**
00097  * The "imgfetch"/"module"/"kernel" command body
00098  *
00099  * @v image_type        Image type to assign (or NULL)
00100  * @v load              Image will be automatically loaded after fetching
00101  * @v argc              Argument count
00102  * @v argv              Argument list
00103  * @ret rc              Return status code
00104  */
00105 static int imgfetch_core_exec ( struct image_type *image_type,
00106                                 enum image_action action,
00107                                 int argc, char **argv ) {
00108         static struct option longopts[] = {
00109                 { "help", 0, NULL, 'h' },
00110                 { "name", required_argument, NULL, 'n' },
00111                 { NULL, 0, NULL, 0 },
00112         };
00113         struct image *image;
00114         const char *name = NULL;
00115         char *filename;
00116         int ( * image_register ) ( struct image *image );
00117         int c;
00118         int rc;
00119 
00120         /* Parse options */
00121         while ( ( c = getopt_long ( argc, argv, "hn:",
00122                                     longopts, NULL ) ) >= 0 ) {
00123                 switch ( c ) {
00124                 case 'n':
00125                         /* Set image name */
00126                         name = optarg;
00127                         break;
00128                 case 'h':
00129                         /* Display help text */
00130                 default:
00131                         /* Unrecognised/invalid option */
00132                         imgfetch_core_syntax ( argv, action );
00133                         return -EINVAL;
00134                 }
00135         }
00136 
00137         /* Need at least a filename remaining after the options */
00138         if ( optind == argc ) {
00139                 imgfetch_core_syntax ( argv, action );
00140                 return -EINVAL;
00141         }
00142         filename = argv[optind++];
00143         if ( ! name )
00144                 name = basename ( filename );
00145 
00146         /* Allocate image */
00147         image = alloc_image();
00148         if ( ! image ) {
00149                 printf ( "%s\n", strerror ( -ENOMEM ) );
00150                 return -ENOMEM;
00151         }
00152 
00153         /* Fill in image name */
00154         if ( name ) {
00155                 if ( ( rc = image_set_name ( image, name ) ) != 0 )
00156                         return rc;
00157         }
00158 
00159         /* Set image type (if specified) */
00160         image->type = image_type;
00161 
00162         /* Fill in command line */
00163         if ( ( rc = imgfill_cmdline ( image, ( argc - optind ),
00164                                       &argv[optind] ) ) != 0 )
00165                 return rc;
00166 
00167         /* Fetch the image */
00168         switch ( action ) {
00169         case IMG_FETCH:
00170                 image_register = register_image;
00171                 break;
00172         case IMG_LOAD:
00173                 image_register = register_and_autoload_image;
00174                 break;
00175         case IMG_EXEC:
00176                 image_register = register_and_autoexec_image;
00177                 break;
00178         default:
00179                 assert ( 0 );
00180                 return -EINVAL;
00181         }
00182         if ( ( rc = imgfetch ( image, filename, image_register ) ) != 0 ) {
00183                 printf ( "Could not fetch %s: %s\n",
00184                          filename, strerror ( rc ) );
00185                 image_put ( image );
00186                 return rc;
00187         }
00188 
00189         image_put ( image );
00190         return 0;
00191 }
00192 
00193 /**
00194  * The "imgfetch"/"module" command
00195  *
00196  * @v argc              Argument count
00197  * @v argv              Argument list
00198  * @ret rc              Exit code
00199  */
00200 static int imgfetch_exec ( int argc, char **argv ) {
00201         int rc;
00202 
00203         if ( ( rc = imgfetch_core_exec ( NULL, IMG_FETCH,
00204                                          argc, argv ) ) != 0 )
00205                 return rc;
00206 
00207         return 0;
00208 }
00209 
00210 /**
00211  * The "kernel" command
00212  *
00213  * @v argc              Argument count
00214  * @v argv              Argument list
00215  * @ret rc              Exit code
00216  */
00217 static int kernel_exec ( int argc, char **argv ) {
00218         int rc;
00219 
00220         if ( ( rc = imgfetch_core_exec ( NULL, IMG_LOAD, argc, argv ) ) != 0 )
00221                 return rc;
00222 
00223         return 0;
00224 }
00225 
00226 /**
00227  * The "chain" command
00228  *
00229  * @v argc              Argument count
00230  * @v argv              Argument list
00231  * @ret rc              Exit code
00232  */
00233 static int chain_exec ( int argc, char **argv) {
00234         int rc;
00235 
00236         if ( ( rc = imgfetch_core_exec ( NULL, IMG_EXEC, argc, argv ) ) != 0 )
00237                 return rc;
00238 
00239         return 0;
00240 }
00241 
00242 /**
00243  * "imgload" command syntax message
00244  *
00245  * @v argv              Argument list
00246  */
00247 static void imgload_syntax ( char **argv ) {
00248         printf ( "Usage:\n"
00249                  "  %s <image name>\n"
00250                  "\n"
00251                  "Load executable/loadable image\n",
00252                  argv[0] );
00253 }
00254 
00255 /**
00256  * The "imgload" command
00257  *
00258  * @v argc              Argument count
00259  * @v argv              Argument list
00260  * @ret rc              Exit code
00261  */
00262 static int imgload_exec ( int argc, char **argv ) {
00263         static struct option longopts[] = {
00264                 { "help", 0, NULL, 'h' },
00265                 { NULL, 0, NULL, 0 },
00266         };
00267         struct image *image;
00268         const char *name;
00269         int c;
00270         int rc;
00271 
00272         /* Parse options */
00273         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
00274                 switch ( c ) {
00275                 case 'h':
00276                         /* Display help text */
00277                 default:
00278                         /* Unrecognised/invalid option */
00279                         imgload_syntax ( argv );
00280                         return 1;
00281                 }
00282         }
00283 
00284         /* Need exactly one image name remaining after the options */
00285         if ( optind != ( argc - 1 ) ) {
00286                 imgload_syntax ( argv );
00287                 return 1;
00288         }
00289         name = argv[optind];
00290 
00291         /* Load all specified images */
00292         image = find_image ( name );
00293         if ( ! image ) {
00294                 printf ( "No such image: %s\n", name );
00295                 return 1;
00296         }
00297         if ( ( rc = imgload ( image ) ) != 0 ) {
00298                 printf ( "Could not load %s: %s\n", name, strerror ( rc ) );
00299                 return rc;
00300         }
00301 
00302         return 0;
00303 }
00304 
00305 /**
00306  * "imgargs" command syntax message
00307  *
00308  * @v argv              Argument list
00309  */
00310 static void imgargs_syntax ( char **argv ) {
00311         printf ( "Usage:\n"
00312                  "  %s <image name> [<arguments>...]\n"
00313                  "\n"
00314                  "Set arguments for executable/loadable image\n",
00315                  argv[0] );
00316 }
00317 
00318 /**
00319  * The "imgargs" command body
00320  *
00321  * @v argc              Argument count
00322  * @v argv              Argument list
00323  * @ret rc              Exit code
00324  */
00325 static int imgargs_exec ( int argc, char **argv ) {
00326         static struct option longopts[] = {
00327                 { "help", 0, NULL, 'h' },
00328                 { NULL, 0, NULL, 0 },
00329         };
00330         struct image *image;
00331         const char *name;
00332         int c;
00333         int rc;
00334 
00335         /* Parse options */
00336         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
00337                 switch ( c ) {
00338                 case 'h':
00339                         /* Display help text */
00340                 default:
00341                         /* Unrecognised/invalid option */
00342                         imgargs_syntax ( argv );
00343                         return 1;
00344                 }
00345         }
00346 
00347         /* Need at least an image name remaining after the options */
00348         if ( optind == argc ) {
00349                 imgargs_syntax ( argv );
00350                 return 1;
00351         }
00352         name = argv[optind++];
00353 
00354         /* Fill in command line */
00355         image = find_image ( name );
00356         if ( ! image ) {
00357                 printf ( "No such image: %s\n", name );
00358                 return 1;
00359         }
00360         if ( ( rc = imgfill_cmdline ( image, ( argc - optind ),
00361                                       &argv[optind] ) ) != 0 )
00362                 return rc;
00363 
00364 
00365         return 0;
00366 }
00367 
00368 /**
00369  * "imgexec" command syntax message
00370  *
00371  * @v argv              Argument list
00372  */
00373 static void imgexec_syntax ( char **argv ) {
00374         printf ( "Usage:\n"
00375                  "  %s <image name>\n"
00376                  "\n"
00377                  "Execute executable/loadable image\n",
00378                  argv[0] );
00379 }
00380 
00381 /**
00382  * The "imgexec" command
00383  *
00384  * @v argc              Argument count
00385  * @v argv              Argument list
00386  * @ret rc              Exit code
00387  */
00388 static int imgexec_exec ( int argc, char **argv ) {
00389         static struct option longopts[] = {
00390                 { "help", 0, NULL, 'h' },
00391                 { NULL, 0, NULL, 0 },
00392         };
00393         struct image *image;
00394         const char *name = NULL;
00395         int c;
00396         int rc;
00397 
00398         /* Parse options */
00399         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
00400                 switch ( c ) {
00401                 case 'h':
00402                         /* Display help text */
00403                 default:
00404                         /* Unrecognised/invalid option */
00405                         imgexec_syntax ( argv );
00406                         return 1;
00407                 }
00408         }
00409 
00410         /* Need no more than one image name */
00411         if ( optind != argc )
00412                 name = argv[optind++];
00413         if ( optind != argc ) {
00414                 imgexec_syntax ( argv );
00415                 return 1;
00416         }
00417         
00418         /* Execute specified image */
00419         if ( name ) {
00420                 image = find_image ( name );
00421                 if ( ! image ) {
00422                         printf ( "No such image: %s\n", name );
00423                         return 1;
00424                 }
00425         } else {
00426                 image = imgautoselect();
00427                 if ( ! image ) {
00428                         printf ( "No (unique) loaded image\n" );
00429                         return 1;
00430                 }
00431         }
00432 
00433         if ( ( rc = imgexec ( image ) ) != 0 ) {
00434                 printf ( "Could not execute %s: %s\n",
00435                          image->name, strerror ( rc ) );
00436                 return 1;
00437         }
00438 
00439         return 0;
00440 }
00441 
00442 /**
00443  * "imgstat" command syntax message
00444  *
00445  * @v argv              Argument list
00446  */
00447 static void imgstat_syntax ( char **argv ) {
00448         printf ( "Usage:\n"
00449                  "  %s\n"
00450                  "\n"
00451                  "List executable/loadable images\n",
00452                  argv[0] );
00453 }
00454 
00455 /**
00456  * The "imgstat" command
00457  *
00458  * @v argc              Argument count
00459  * @v argv              Argument list
00460  * @ret rc              Exit code
00461  */
00462 static int imgstat_exec ( int argc, char **argv ) {
00463         static struct option longopts[] = {
00464                 { "help", 0, NULL, 'h' },
00465                 { NULL, 0, NULL, 0 },
00466         };
00467         struct image *image;
00468         int c;
00469 
00470         /* Parse options */
00471         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
00472                 switch ( c ) {
00473                 case 'h':
00474                         /* Display help text */
00475                 default:
00476                         /* Unrecognised/invalid option */
00477                         imgstat_syntax ( argv );
00478                         return 1;
00479                 }
00480         }
00481 
00482         /* No arguments */
00483         if ( optind != argc ) {
00484                 imgstat_syntax ( argv );
00485                 return 1;
00486         }
00487 
00488         /* Show status of all images */
00489         for_each_image ( image ) {
00490                 imgstat ( image );
00491         }
00492         return 0;
00493 }
00494 
00495 /**
00496  * "imgstat" command syntax message
00497  *
00498  * @v argv              Argument list
00499  */
00500 static void imgfree_syntax ( char **argv ) {
00501         printf ( "Usage:\n"
00502                  "  %s [<image name>]\n"
00503                  "\n"
00504                  "Free one or all executable/loadable images\n",
00505                  argv[0] );
00506 }
00507 
00508 /**
00509  * The "imgfree" command
00510  *
00511  * @v argc              Argument count
00512  * @v argv              Argument list
00513  * @ret rc              Exit code
00514  */
00515 static int imgfree_exec ( int argc, char **argv ) {
00516         static struct option longopts[] = {
00517                 { "help", 0, NULL, 'h' },
00518                 { NULL, 0, NULL, 0 },
00519         };
00520         struct image *image;
00521         struct image *tmp;
00522         const char *name = NULL;
00523         int c;
00524 
00525         /* Parse options */
00526         while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
00527                 switch ( c ) {
00528                 case 'h':
00529                         /* Display help text */
00530                 default:
00531                         /* Unrecognised/invalid option */
00532                         imgfree_syntax ( argv );
00533                         return 1;
00534                 }
00535         }
00536 
00537         /* Need no more than one image name */
00538         if ( optind != argc )
00539                 name = argv[optind++];
00540         if ( optind != argc ) {
00541                 imgfree_syntax ( argv );
00542                 return 1;
00543         }
00544 
00545         if ( name ) {
00546                 /* Free specified image (may leak) */
00547                 image = find_image ( name );
00548                 if ( ! image ) {
00549                         printf ( "No such image: %s\n", name );
00550                         return 1;
00551                 }
00552                 imgfree ( image );
00553         } else {
00554                 /* Free all images */
00555                 list_for_each_entry_safe ( image, tmp, &images, list ) {
00556                         imgfree ( image );
00557                 }
00558         }
00559         return 0;
00560 }
00561 
00562 /** Image management commands */
00563 struct command image_commands[] __command = {
00564         {
00565                 .name = "imgfetch",
00566                 .exec = imgfetch_exec,
00567         },
00568         {
00569                 .name = "module",
00570                 .exec = imgfetch_exec, /* synonym for "imgfetch" */
00571         },
00572         {
00573                 .name = "initrd",
00574                 .exec = imgfetch_exec, /* synonym for "imgfetch" */
00575         },
00576         {
00577                 .name = "kernel",
00578                 .exec = kernel_exec,
00579         },
00580         {
00581                 .name = "chain",
00582                 .exec = chain_exec,
00583         },
00584         {
00585                 .name = "imgload",
00586                 .exec = imgload_exec,
00587         },
00588         {
00589                 .name = "imgargs",
00590                 .exec = imgargs_exec,
00591         },
00592         {
00593                 .name = "imgexec",
00594                 .exec = imgexec_exec,
00595         },
00596         {
00597                 .name = "boot", /* synonym for "imgexec" */
00598                 .exec = imgexec_exec,
00599         },
00600         {
00601                 .name = "imgstat",
00602                 .exec = imgstat_exec,
00603         },
00604         {
00605                 .name = "imgfree",
00606                 .exec = imgfree_exec,
00607         },
00608 };

Generated on Tue Apr 6 20:01:06 2010 for gPXE by  doxygen 1.5.7.1