diff options
Diffstat (limited to 'contrib/syslinux-4.02/gpxe/src/hci/commands/image_cmd.c')
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/hci/commands/image_cmd.c | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/gpxe/src/hci/commands/image_cmd.c b/contrib/syslinux-4.02/gpxe/src/hci/commands/image_cmd.c new file mode 100644 index 0000000..33994b5 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/hci/commands/image_cmd.c @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <libgen.h> +#include <getopt.h> +#include <gpxe/image.h> +#include <gpxe/command.h> +#include <usr/imgmgmt.h> + +/** @file + * + * Image management commands + * + */ + +enum image_action { + IMG_FETCH = 0, + IMG_LOAD, + IMG_EXEC, +}; + +/** + * Fill in image command line + * + * @v image Image + * @v nargs Argument count + * @v args Argument list + * @ret rc Return status code + */ +static int imgfill_cmdline ( struct image *image, unsigned int nargs, + char **args ) { + size_t len; + unsigned int i; + + /* Determine total length of command line */ + len = 1; /* NUL */ + for ( i = 0 ; i < nargs ; i++ ) + len += ( 1 /* possible space */ + strlen ( args[i] ) ); + + { + char buf[len]; + char *ptr = buf; + + /* Assemble command line */ + buf[0] = '\0'; + for ( i = 0 ; i < nargs ; i++ ) { + ptr += sprintf ( ptr, "%s%s", ( i ? " " : "" ), + args[i] ); + } + assert ( ptr < ( buf + len ) ); + + return image_set_cmdline ( image, buf ); + } +} + +/** + * "imgfetch"/"module"/"kernel" command syntax message + * + * @v argv Argument list + */ +static void imgfetch_core_syntax ( char **argv, enum image_action action ) { + static const char *actions[] = { + [IMG_FETCH] = "Fetch", + [IMG_LOAD] = "Fetch and load", + [IMG_EXEC] = "Fetch and execute", + }; + + printf ( "Usage:\n" + " %s [-n|--name <name>] filename [arguments...]\n" + "\n" + "%s executable/loadable image\n", + argv[0], actions[action] ); +} + +/** + * The "imgfetch"/"module"/"kernel" command body + * + * @v image_type Image type to assign (or NULL) + * @v load Image will be automatically loaded after fetching + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int imgfetch_core_exec ( struct image_type *image_type, + enum image_action action, + int argc, char **argv ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { "name", required_argument, NULL, 'n' }, + { NULL, 0, NULL, 0 }, + }; + struct image *image; + const char *name = NULL; + char *filename; + int ( * image_register ) ( struct image *image ); + int c; + int rc; + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, "hn:", + longopts, NULL ) ) >= 0 ) { + switch ( c ) { + case 'n': + /* Set image name */ + name = optarg; + break; + case 'h': + /* Display help text */ + default: + /* Unrecognised/invalid option */ + imgfetch_core_syntax ( argv, action ); + return -EINVAL; + } + } + + /* Need at least a filename remaining after the options */ + if ( optind == argc ) { + imgfetch_core_syntax ( argv, action ); + return -EINVAL; + } + filename = argv[optind++]; + if ( ! name ) + name = basename ( filename ); + + /* Allocate image */ + image = alloc_image(); + if ( ! image ) { + printf ( "%s\n", strerror ( -ENOMEM ) ); + return -ENOMEM; + } + + /* Fill in image name */ + if ( name ) { + if ( ( rc = image_set_name ( image, name ) ) != 0 ) + return rc; + } + + /* Set image type (if specified) */ + image->type = image_type; + + /* Fill in command line */ + if ( ( rc = imgfill_cmdline ( image, ( argc - optind ), + &argv[optind] ) ) != 0 ) + return rc; + + /* Fetch the image */ + switch ( action ) { + case IMG_FETCH: + image_register = register_image; + break; + case IMG_LOAD: + image_register = register_and_autoload_image; + break; + case IMG_EXEC: + image_register = register_and_autoexec_image; + break; + default: + assert ( 0 ); + return -EINVAL; + } + if ( ( rc = imgfetch ( image, filename, image_register ) ) != 0 ) { + printf ( "Could not fetch %s: %s\n", + filename, strerror ( rc ) ); + image_put ( image ); + return rc; + } + + image_put ( image ); + return 0; +} + +/** + * The "imgfetch"/"module" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int imgfetch_exec ( int argc, char **argv ) { + int rc; + + if ( ( rc = imgfetch_core_exec ( NULL, IMG_FETCH, + argc, argv ) ) != 0 ) + return rc; + + return 0; +} + +/** + * The "kernel" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int kernel_exec ( int argc, char **argv ) { + int rc; + + if ( ( rc = imgfetch_core_exec ( NULL, IMG_LOAD, argc, argv ) ) != 0 ) + return rc; + + return 0; +} + +/** + * The "chain" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int chain_exec ( int argc, char **argv) { + int rc; + + if ( ( rc = imgfetch_core_exec ( NULL, IMG_EXEC, argc, argv ) ) != 0 ) + return rc; + + return 0; +} + +/** + * "imgload" command syntax message + * + * @v argv Argument list + */ +static void imgload_syntax ( char **argv ) { + printf ( "Usage:\n" + " %s <image name>\n" + "\n" + "Load executable/loadable image\n", + argv[0] ); +} + +/** + * The "imgload" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int imgload_exec ( int argc, char **argv ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 }, + }; + struct image *image; + const char *name; + int c; + int rc; + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){ + switch ( c ) { + case 'h': + /* Display help text */ + default: + /* Unrecognised/invalid option */ + imgload_syntax ( argv ); + return 1; + } + } + + /* Need exactly one image name remaining after the options */ + if ( optind != ( argc - 1 ) ) { + imgload_syntax ( argv ); + return 1; + } + name = argv[optind]; + + /* Load all specified images */ + image = find_image ( name ); + if ( ! image ) { + printf ( "No such image: %s\n", name ); + return 1; + } + if ( ( rc = imgload ( image ) ) != 0 ) { + printf ( "Could not load %s: %s\n", name, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * "imgargs" command syntax message + * + * @v argv Argument list + */ +static void imgargs_syntax ( char **argv ) { + printf ( "Usage:\n" + " %s <image name> [<arguments>...]\n" + "\n" + "Set arguments for executable/loadable image\n", + argv[0] ); +} + +/** + * The "imgargs" command body + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int imgargs_exec ( int argc, char **argv ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 }, + }; + struct image *image; + const char *name; + int c; + int rc; + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){ + switch ( c ) { + case 'h': + /* Display help text */ + default: + /* Unrecognised/invalid option */ + imgargs_syntax ( argv ); + return 1; + } + } + + /* Need at least an image name remaining after the options */ + if ( optind == argc ) { + imgargs_syntax ( argv ); + return 1; + } + name = argv[optind++]; + + /* Fill in command line */ + image = find_image ( name ); + if ( ! image ) { + printf ( "No such image: %s\n", name ); + return 1; + } + if ( ( rc = imgfill_cmdline ( image, ( argc - optind ), + &argv[optind] ) ) != 0 ) + return rc; + + + return 0; +} + +/** + * "imgexec" command syntax message + * + * @v argv Argument list + */ +static void imgexec_syntax ( char **argv ) { + printf ( "Usage:\n" + " %s <image name>\n" + "\n" + "Execute executable/loadable image\n", + argv[0] ); +} + +/** + * The "imgexec" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int imgexec_exec ( int argc, char **argv ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 }, + }; + struct image *image; + const char *name = NULL; + int c; + int rc; + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){ + switch ( c ) { + case 'h': + /* Display help text */ + default: + /* Unrecognised/invalid option */ + imgexec_syntax ( argv ); + return 1; + } + } + + /* Need no more than one image name */ + if ( optind != argc ) + name = argv[optind++]; + if ( optind != argc ) { + imgexec_syntax ( argv ); + return 1; + } + + /* Execute specified image */ + if ( name ) { + image = find_image ( name ); + if ( ! image ) { + printf ( "No such image: %s\n", name ); + return 1; + } + } else { + image = imgautoselect(); + if ( ! image ) { + printf ( "No (unique) loaded image\n" ); + return 1; + } + } + + if ( ( rc = imgexec ( image ) ) != 0 ) { + printf ( "Could not execute %s: %s\n", + image->name, strerror ( rc ) ); + return 1; + } + + return 0; +} + +/** + * "imgstat" command syntax message + * + * @v argv Argument list + */ +static void imgstat_syntax ( char **argv ) { + printf ( "Usage:\n" + " %s\n" + "\n" + "List executable/loadable images\n", + argv[0] ); +} + +/** + * The "imgstat" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int imgstat_exec ( int argc, char **argv ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 }, + }; + struct image *image; + int c; + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){ + switch ( c ) { + case 'h': + /* Display help text */ + default: + /* Unrecognised/invalid option */ + imgstat_syntax ( argv ); + return 1; + } + } + + /* No arguments */ + if ( optind != argc ) { + imgstat_syntax ( argv ); + return 1; + } + + /* Show status of all images */ + for_each_image ( image ) { + imgstat ( image ); + } + return 0; +} + +/** + * "imgstat" command syntax message + * + * @v argv Argument list + */ +static void imgfree_syntax ( char **argv ) { + printf ( "Usage:\n" + " %s [<image name>]\n" + "\n" + "Free one or all executable/loadable images\n", + argv[0] ); +} + +/** + * The "imgfree" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int imgfree_exec ( int argc, char **argv ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 }, + }; + struct image *image; + struct image *tmp; + const char *name = NULL; + int c; + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){ + switch ( c ) { + case 'h': + /* Display help text */ + default: + /* Unrecognised/invalid option */ + imgfree_syntax ( argv ); + return 1; + } + } + + /* Need no more than one image name */ + if ( optind != argc ) + name = argv[optind++]; + if ( optind != argc ) { + imgfree_syntax ( argv ); + return 1; + } + + if ( name ) { + /* Free specified image (may leak) */ + image = find_image ( name ); + if ( ! image ) { + printf ( "No such image: %s\n", name ); + return 1; + } + imgfree ( image ); + } else { + /* Free all images */ + list_for_each_entry_safe ( image, tmp, &images, list ) { + imgfree ( image ); + } + } + return 0; +} + +/** Image management commands */ +struct command image_commands[] __command = { + { + .name = "imgfetch", + .exec = imgfetch_exec, + }, + { + .name = "module", + .exec = imgfetch_exec, /* synonym for "imgfetch" */ + }, + { + .name = "initrd", + .exec = imgfetch_exec, /* synonym for "imgfetch" */ + }, + { + .name = "kernel", + .exec = kernel_exec, + }, + { + .name = "chain", + .exec = chain_exec, + }, + { + .name = "imgload", + .exec = imgload_exec, + }, + { + .name = "imgargs", + .exec = imgargs_exec, + }, + { + .name = "imgexec", + .exec = imgexec_exec, + }, + { + .name = "boot", /* synonym for "imgexec" */ + .exec = imgexec_exec, + }, + { + .name = "imgstat", + .exec = imgstat_exec, + }, + { + .name = "imgfree", + .exec = imgfree_exec, + }, +}; |