diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-11-14 10:50:27 +0000 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2012-11-14 10:50:27 +0000 |
commit | 4c7278413ef068bd8239fd8a6c69d64bd2c0a385 (patch) | |
tree | 4c39e8872de7babc24bed9fe528df28c8d82d427 /com32/modules | |
parent | 749297b070d1fe3d82fd9e5c4306b4aaf257f2a1 (diff) | |
parent | 348ae6af01350a9a46f3076a2facd27918f0f603 (diff) | |
download | syslinux-4c7278413ef068bd8239fd8a6c69d64bd2c0a385.tar.gz syslinux-4c7278413ef068bd8239fd8a6c69d64bd2c0a385.tar.xz syslinux-4c7278413ef068bd8239fd8a6c69d64bd2c0a385.zip |
Merge tag 'syslinux-5.00-pre10' into for-hpa/elflink/firmware
Pull in the latest prerelease that includes some bug fixes for ldlinux
and a realloc() bug in core/.
Conflicts:
com32/cmenu/Makefile
com32/elflink/ldlinux/Makefile
com32/lib/Makefile
core/pxelinux.asm
Diffstat (limited to 'com32/modules')
-rw-r--r-- | com32/modules/Makefile | 3 | ||||
-rw-r--r-- | com32/modules/hexdump.c | 245 | ||||
-rw-r--r-- | com32/modules/linux.c | 200 |
3 files changed, 410 insertions, 38 deletions
diff --git a/com32/modules/Makefile b/com32/modules/Makefile index d87127dc..e794b3b9 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -23,7 +23,8 @@ MODULES = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \ kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 ls.c32 gpxecmd.c32 \ ifcpu.c32 cpuid.c32 cat.c32 pwd.c32 ifplop.c32 zzjson.c32 \ - whichsys.c32 prdhcp.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32 + whichsys.c32 prdhcp.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32 \ + hexdump.c32 TESTFILES = diff --git a/com32/modules/hexdump.c b/com32/modules/hexdump.c new file mode 100644 index 00000000..bc2c70dd --- /dev/null +++ b/com32/modules/hexdump.c @@ -0,0 +1,245 @@ +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <console.h> +#include <errno.h> +#include <syslinux/loadfile.h> + +/* Macros */ +#define ROWS_PER_PAGE 24 +#define COLS_PER_ROW 16 +#define BYTES_PER_PAGE (ROWS_PER_PAGE * COLS_PER_ROW) + +/* Functions declarations */ +static int usage(void); +static void eat_stdin(void); +static int do_page(void); +static void hexdump(const void *memory, size_t bytes); + +/* Objects */ +static const char *prog_name; +static int opt_page; +static int opt_no_buffer; +static int opt_extended_ascii; + +int main(int argc, char **argv) +{ + int rc; + const char *filename; + int i; + void *file_data; + size_t file_sz; + FILE *f; + size_t len; + const char *cur_pos; + + /* Assume failure */ + rc = EXIT_FAILURE; + + /* Determine the program name, as invoked */ + if (argc < 1 || !argv || !argv[0]) { + fprintf(stderr, "argc or argv failure!\n"); + goto err_prog_name; + } + prog_name = argv[0]; + + /* Process arguments */ + filename = NULL; + for (i = 1; i < argc; ++i) { + if (!argv[i]) { + fprintf(stderr, "argc and argv mismatch!\n"); + goto err_argv; + } + + if (!strncmp(argv[i], "--page", sizeof "--page") || + !strncmp(argv[i], "-p", sizeof "-p")) { + opt_page = 1; + continue; + } + + if (!strncmp(argv[i], "--no-buffer", sizeof "--no-buffer")) { + opt_no_buffer = 1; + continue; + } + + if (!strncmp(argv[i], "--extended-ascii", sizeof "--extended-ascii")) { + opt_extended_ascii = 1; + continue; + } + + if (!strncmp(argv[i], "--help", sizeof "--help") || + !strncmp(argv[i], "-h", sizeof "-h") || + !strncmp(argv[i], "-?", sizeof "-?")) + return usage(); + + /* Otherwise, interpret as a filename, but only accept one */ + if (filename) + return usage(); + filename = argv[i]; + } + if (!filename) + return usage(); + fprintf(stdout, "Dumping file: %s\n", filename); + + /* Either fetch the whole file, or just allocate a buffer */ + f = NULL; + if (opt_no_buffer) { + errno = 0; + if (loadfile(filename, &file_data, &file_sz)) { + fprintf(stderr, "Couldn't load file. Error: %d\n", errno); + goto err_file_data; + } + } else { + file_sz = BYTES_PER_PAGE; + file_data = malloc(file_sz); + if (!file_data) { + fprintf(stderr, "Couldn't allocate file data buffer\n"); + goto err_file_data; + } + errno = 0; + f = fopen(filename, "r"); + if (!f) { + fprintf(stderr, "Couldn't open file. Error: %d\n", errno); + goto err_f; + } + } + + /* Dump the data */ + len = BYTES_PER_PAGE; + cur_pos = file_data; + do { + if (f) { + /* Buffered */ + len = fread(file_data, 1, file_sz, f); + cur_pos = file_data; + } else { + /* Non-buffered */ + if (file_sz < len) + len = file_sz; + } + if (!len) + break; + + hexdump(cur_pos, len); + + /* Pause, if requested */ + if (opt_page) { + /* The user might choose to quit */ + if (do_page()) + break; + } + + /* Reduce file_sz for non-buffered mode */ + if (!f) + file_sz -= len; + } while (cur_pos += len); + + rc = EXIT_SUCCESS; + + if (f) + fclose(f); + err_f: + + free(file_data); + err_file_data: + + err_argv: + + err_prog_name: + + return rc; +} + +static int usage(void) +{ + static const char usage[] = + "Usage: %s [<option> [...]] <filename> [<option> [...]]\n" + "\n" + "Options: -p\n" + " --page . . . . . . . Pause output every 24 lines\n" + " --no-buffer . . . . Load the entire file before dumping\n" + " --extended-ascii . . Use extended ASCII chars in dump\n" + " -?\n" + " -h\n" + " --help . . . . . . Display this help\n"; + + fprintf(stderr, usage, prog_name); + return EXIT_FAILURE; +} + +static void eat_stdin(void) +{ + int i; + + while (1) { + i = fgetc(stdin); + if (i == EOF || i == '\n') + return; + } +} +static int do_page(void) +{ + int i; + + while (1) { + fprintf(stdout, "Continue? [Y|n]: "); + i = fgetc(stdin); + switch (i) { + case 'n': + case 'N': + eat_stdin(); + return 1; + + case EOF: + fprintf(stderr, "No response. Continuing...\n"); + /* Fall through to "yes" */ + + case 'y': + case 'Y': + eat_stdin(); + case '\n': + return 0; + + default: + fprintf(stderr, "Invalid choice\n"); + eat_stdin(); + } + } +} + +static void hexdump(const void *memory, size_t bytes) +{ + const unsigned char *p, *q; + int i; + + p = memory; + while (bytes) { + q = p; + printf("%p: ", (void *) p); + for (i = 0; i < 16 && bytes; ++i) { + printf("%02X ", *p); + ++p; + --bytes; + } + bytes += i; + while (i < 16) { + printf("XX "); + ++i; + } + printf("| "); + p = q; + for (i = 0; i < 16 && bytes; ++i) { + printf("%c", isprint(*p) && !isspace(*p) ? *p : ' '); + ++p; + --bytes; + } + while (i < 16) { + printf(" "); + ++i; + } + printf("\n"); + } + return; +} diff --git a/com32/modules/linux.c b/com32/modules/linux.c index e4c067ff..f657eab4 100644 --- a/com32/modules/linux.c +++ b/com32/modules/linux.c @@ -48,6 +48,14 @@ #include <syslinux/linux.h> #include <syslinux/pxe.h> +enum ldmode { + ldmode_raw, + ldmode_cpio, + ldmodes +}; + +typedef int f_ldinitramfs(struct initramfs *, char *); + const char *progname = "linux.c32"; /* Find the last instance of a particular command line argument @@ -59,13 +67,34 @@ static char *find_argument(char **argv, const char *argument) char *ptr = NULL; for (arg = argv; *arg; arg++) { - if (!memcmp(*arg, argument, la)) + if (!strncmp(*arg, argument, la)) ptr = *arg + la; } return ptr; } +/* Find the next instance of a particular command line argument */ +static char **find_arguments(char **argv, char **ptr, + const char *argument) +{ + int la = strlen(argument); + char **arg; + + for (arg = argv; *arg; arg++) { + if (!strncmp(*arg, argument, la)) { + *ptr = *arg + la; + break; + } + } + + /* Exhausted all arguments */ + if (!*arg) + return NULL; + + return arg; +} + /* Search for a boolean argument; return its position, or 0 if not present */ static int find_boolean(char **argv, const char *argument) { @@ -109,6 +138,99 @@ static char *make_cmdline(char **argv) return cmdline; } +static f_ldinitramfs ldinitramfs_raw; +static int ldinitramfs_raw(struct initramfs *initramfs, char *fname) +{ + return initramfs_load_archive(initramfs, fname); +} + +static f_ldinitramfs ldinitramfs_cpio; +static int ldinitramfs_cpio(struct initramfs *initramfs, char *fname) +{ + char *target_fname, *p; + int do_mkdir, unmangle, rc; + + /* Choose target_fname based on presence of "@" syntax */ + target_fname = strchr(fname, '@'); + if (target_fname) { + /* Temporarily mangle */ + unmangle = 1; + *target_fname++ = '\0'; + + /* Make parent directories? */ + do_mkdir = !!strchr(target_fname, '/'); + } else { + unmangle = 0; + + /* Forget the source path */ + target_fname = fname; + while ((p = strchr(target_fname, '/'))) + target_fname = p + 1; + + /* The user didn't specify a desired path */ + do_mkdir = 0; + } + + /* + * Load the file, encapsulate it with the desired path, make the + * parent directories if the desired path contains them, add to initramfs + */ + rc = initramfs_load_file(initramfs, fname, target_fname, do_mkdir, 0755); + + /* Unmangle, if needed*/ + if (unmangle) + *--target_fname = '@'; + + return rc; +} + +/* It only makes sense to call this function from main */ +static int process_initramfs_args(char *arg, struct initramfs *initramfs, + const char *kernel_name, enum ldmode mode, + bool opt_quiet) +{ + const char *mode_msg; + f_ldinitramfs *ldinitramfs; + char *p; + + switch (mode) { + case ldmode_raw: + mode_msg = "Loading"; + ldinitramfs = ldinitramfs_raw; + break; + case ldmode_cpio: + mode_msg = "Encapsulating"; + ldinitramfs = ldinitramfs_cpio; + break; + case ldmodes: + default: + return 1; + } + + do { + p = strchr(arg, ','); + if (p) + *p = '\0'; + + if (!opt_quiet) + printf("%s %s... ", mode_msg, arg); + errno = 0; + if (ldinitramfs(initramfs, arg)) { + if (opt_quiet) + printf("Loading %s ", kernel_name); + printf("failed: "); + return 1; + } + if (!opt_quiet) + printf("ok\n"); + + if (p) + *p++ = ','; + } while ((arg = p)); + + return 0; +} + static int setup_data_file(struct setup_data *setup_data, uint32_t type, const char *filename, bool opt_quiet) @@ -142,7 +264,7 @@ int main(int argc, char *argv[]) bool opt_quiet = false; void *dhcpdata; size_t dhcplen; - char **argp, **argl, *arg, *p; + char **argp, **argl, *arg; (void)argc; argp = argv + 1; @@ -207,27 +329,27 @@ int main(int argc, char *argv[]) goto bail; } + /* Process initramfs arguments */ if ((arg = find_argument(argp, "initrd="))) { - do { - p = strchr(arg, ','); - if (p) - *p = '\0'; - - if (!opt_quiet) - printf("Loading %s... ", arg); - errno = 0; - if (initramfs_load_archive(initramfs, arg)) { - if (opt_quiet) - printf("Loading %s ", kernel_name); - printf("failed: "); - goto bail; - } - if (!opt_quiet) - printf("ok\n"); - - if (p) - *p++ = ','; - } while ((arg = p)); + if (process_initramfs_args(arg, initramfs, kernel_name, ldmode_raw, + opt_quiet)) + goto bail; + } + + argl = argv; + while ((argl = find_arguments(argl, &arg, "initrd+="))) { + argl++; + if (process_initramfs_args(arg, initramfs, kernel_name, ldmode_raw, + opt_quiet)) + goto bail; + } + + argl = argv; + while ((argl = find_arguments(argl, &arg, "initrdfile="))) { + argl++; + if (process_initramfs_args(arg, initramfs, kernel_name, ldmode_cpio, + opt_quiet)) + goto bail; } /* Append the DHCP info */ @@ -246,24 +368,28 @@ int main(int argc, char *argv[]) if (!setup_data) goto bail; - for (argl = argv; (arg = *argl); argl++) { - if (!memcmp(arg, "dtb=", 4)) { - if (setup_data_file(setup_data, SETUP_DTB, arg+4, opt_quiet)) - goto bail; - } else if (!memcmp(arg, "blob.", 5)) { - uint32_t type; - char *ep; + argl = argv; + while ((argl = find_arguments(argl, &arg, "dtb="))) { + argl++; + if (setup_data_file(setup_data, SETUP_DTB, arg, opt_quiet)) + goto bail; + } + + argl = argv; + while ((argl = find_arguments(argl, &arg, "blob."))) { + uint32_t type; + char *ep; - type = strtoul(arg + 5, &ep, 10); - if (ep[0] != '=' || !ep[1]) - continue; + argl++; + type = strtoul(arg, &ep, 10); + if (ep[0] != '=' || !ep[1]) + continue; - if (!type) - continue; + if (!type) + continue; - if (setup_data_file(setup_data, type, ep+1, opt_quiet)) - goto bail; - } + if (setup_data_file(setup_data, type, ep+1, opt_quiet)) + goto bail; } /* This should not return... */ |