aboutsummaryrefslogtreecommitdiffstats
path: root/com32/modules
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2012-11-14 10:50:27 +0000
committerMatt Fleming <matt.fleming@intel.com>2012-11-14 10:50:27 +0000
commit4c7278413ef068bd8239fd8a6c69d64bd2c0a385 (patch)
tree4c39e8872de7babc24bed9fe528df28c8d82d427 /com32/modules
parent749297b070d1fe3d82fd9e5c4306b4aaf257f2a1 (diff)
parent348ae6af01350a9a46f3076a2facd27918f0f603 (diff)
downloadsyslinux-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/Makefile3
-rw-r--r--com32/modules/hexdump.c245
-rw-r--r--com32/modules/linux.c200
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... */