diff --git a/src/config.h b/src/config.h index 47e91119..d6e01134 100644 --- a/src/config.h +++ b/src/config.h @@ -120,6 +120,7 @@ #define CONFIG_CMD /* Option configuration console */ #define IFMGMT_CMD /* Interface management commands */ #define ROUTE_CMD /* Routing table management commands */ +#define IMAGE_CMD /* Image management commands */ /* @END general.h */ diff --git a/src/core/config.c b/src/core/config.c index e2b1a362..6120fc3b 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -157,6 +157,9 @@ REQUIRE_OBJECT ( ifmgmt_cmd ); #ifdef ROUTE_CMD REQUIRE_OBJECT ( route_cmd ); #endif +#ifdef IMAGE_CMD +REQUIRE_OBJECT ( image_cmd ); +#endif /* * Drag in miscellaneous objects diff --git a/src/hci/commands/image_cmd.c b/src/hci/commands/image_cmd.c new file mode 100644 index 00000000..e38ecc90 --- /dev/null +++ b/src/hci/commands/image_cmd.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2007 Michael Brown . + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * Image management commands + * + */ + +/** + * Print image description + * + */ + +/** + * "fetch"/"module"/"kernel" command syntax message + * + * @v argv Argument list + */ +static void fetch_syntax ( char **argv ) { + printf ( "Usage:\n" + " %s [-n|--name ] filename [arguments...]\n" + "\n" + "Fetch executable/loadable image\n", + argv[0] ); +} + +/** + * The "fetch"/"module"/"kernel" command body + * + * @v argc Argument count + * @v argv Argument list + * @v name Default name for image, or NULL + * @ret rc Exit code + */ +static int fetch_exec_name ( int argc, char **argv, const char *name ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { "name", required_argument, NULL, 'n' }, + { NULL, 0, NULL, 0 }, + }; + struct image *image; + const char *filename; + char cmdline[ sizeof ( image->cmdline ) ]; + size_t used = 0; + 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 */ + fetch_syntax ( argv ); + return 1; + } + } + + /* Need at least a filename remaining after the options */ + if ( optind >= argc ) { + fetch_syntax ( argv ); + return 1; + } + filename = argv[optind++]; + + /* Build command line */ + while ( ( used < sizeof ( cmdline ) ) && ( optind < argc ) ) { + used += snprintf ( &cmdline[used], sizeof ( cmdline ) - used, + " %s", argv[optind++] ); + } + + /* Allocate and fill struct image */ + image = malloc ( sizeof ( *image ) ); + if ( ! image ) { + printf ( "Out of memory\n" ); + return 1; + } + memset ( image, 0, sizeof ( *image ) ); + if ( name ) + strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) ); + if ( used ) + memcpy ( image->cmdline, cmdline, sizeof ( image->cmdline ) ); + + /* Fetch the file */ + if ( ( rc = fetch ( image, filename ) ) != 0 ) { + printf ( "Could not fetch %s: %s\n", filename, + strerror ( rc ) ); + free ( image ); + return 1; + } + + /* Register the image */ + if ( ( rc = register_image ( image ) ) != 0 ) { + printf ( "Could not register %s: %s\n", filename, + strerror ( rc ) ); + free ( image ); + return 1; + } + + imgstat ( image ); + return 0; +} + +/** + * The "fetch"/"module" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int fetch_exec ( int argc, char **argv ) { + return fetch_exec_name ( argc, argv, NULL ); +} + +/** + * The "kernel" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int kernel_exec ( int argc, char **argv ) { + return fetch_exec_name ( argc, argv, "kernel" ); +} + +/** + * "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 __unused, char **argv __unused ) { + 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; + } + } + + /* Need at least a filename remaining after the options */ + if ( optind != argc ) { + imgstat_syntax ( argv ); + return 1; + } + + /* Show status of all images */ + for_each_image ( image ) { + imgstat ( image ); + } + return 0; +} + +/** Image management commands */ +struct command image_commands[] __command = { + { + .name = "fetch", + .exec = fetch_exec, + }, + { + .name = "module", + .exec = fetch_exec, /* synonym for "fetch" */ + }, + { + .name = "kernel", + .exec = kernel_exec, + }, + { + .name = "imgstat", + .exec = imgstat_exec, + }, +}; diff --git a/src/include/usr/fetch.h b/src/include/usr/fetch.h new file mode 100644 index 00000000..e7c035be --- /dev/null +++ b/src/include/usr/fetch.h @@ -0,0 +1,13 @@ +#ifndef _USR_FETCH_H +#define _USR_FETCH_H + +/** + * @file + * + * Fetch file as executable/loadable image + * + */ + +extern int fetch ( struct image *image, const char *filename ); + +#endif /* _USR_FETCH_H */ diff --git a/src/include/usr/imgmgmt.h b/src/include/usr/imgmgmt.h new file mode 100644 index 00000000..da58ffb1 --- /dev/null +++ b/src/include/usr/imgmgmt.h @@ -0,0 +1,12 @@ +#ifndef _USR_IMGMGMT_H +#define _USR_IMGMGMT_H + +/** @file + * + * Image management + * + */ + +extern void imgstat ( struct image *image ); + +#endif /* _USR_IMGMGMT_H */ diff --git a/src/usr/fetch.c b/src/usr/fetch.c new file mode 100644 index 00000000..f7f3a771 --- /dev/null +++ b/src/usr/fetch.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007 Michael Brown . + * + * 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 + * + * Fetch file as executable/loadable image + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/** + * Fetch file as executable/loadable image + * + * @v image Executable/loadable image + * @v filename Filename + * @ret rc Return status code + */ +int fetch ( struct image *image, const char *filename ) { + struct buffer buffer; + int rc; + + /* Name the image, if it isn't explicitly named */ + if ( ! image->name[0] ) { + strncpy ( image->name, basename ( filename ), + ( sizeof ( image->name ) - 1 ) ); + } + + /* Allocate an expandable buffer to hold the file */ + if ( ( rc = ebuffer_alloc ( &buffer, 0 ) ) != 0 ) + return rc; + + /* Retrieve the file */ + struct tftp_session tftp; + union { + struct sockaddr_tcpip st; + struct sockaddr_in sin; + } server; + + memset ( &tftp, 0, sizeof ( tftp ) ); + memset ( &server, 0, sizeof ( server ) ); + server.sin.sin_family = AF_INET; + find_global_dhcp_ipv4_option ( DHCP_EB_SIADDR, + &server.sin.sin_addr ); + server.sin.sin_port = htons ( TFTP_PORT ); + udp_connect ( &tftp.udp, &server.st ); + tftp.filename = filename; + tftp.buffer = &buffer; + if ( ( rc = async_wait ( tftp_get ( &tftp ) ) ) != 0 ) { + efree ( buffer.addr ); + return rc; + } + + /* Transfer ownserhip of the data buffer to the image */ + image->data = buffer.addr; + image->len = buffer.fill; + image->free = efree; + + return 0; +} diff --git a/src/usr/imgmgmt.c b/src/usr/imgmgmt.c new file mode 100644 index 00000000..437cf8e4 --- /dev/null +++ b/src/usr/imgmgmt.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 Michael Brown . + * + * 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. + */ + +#include +#include +#include +#include + +/** @file + * + * Image management + * + */ + +/** + * Display status of an image + * + * @v image Executable/loadable image + */ +void imgstat ( struct image *image ) { + printf ( "%s: %zd bytes ", image->name, image->len ); + if ( image->type ) + printf ( " [%s]", image->type->name ); + if ( image->flags & IMAGE_LOADED ) + printf ( " [LOADED]" ); + if ( image->cmdline[0] ) + printf ( "\"%s\"", image->cmdline ); + printf ( "\n" ); +} +