summaryrefslogtreecommitdiffstats
path: root/fcp/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'fcp/src/main.c')
-rw-r--r--fcp/src/main.c709
1 files changed, 709 insertions, 0 deletions
diff --git a/fcp/src/main.c b/fcp/src/main.c
new file mode 100644
index 0000000..c122c3f
--- /dev/null
+++ b/fcp/src/main.c
@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2012
+ *
+ * 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
+ * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * File: fcp_main.c
+ * Author: Shaun Wetzstein <shaun@us.ibm.com>
+ * Descr: cp for FFS files
+ * Date: 04/25/2013
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ctype.h>
+#include <regex.h>
+
+#include <clib/attribute.h>
+#include <clib/assert.h>
+#include <clib/list.h>
+#include <clib/list_iter.h>
+#include <clib/misc.h>
+#include <clib/min.h>
+#include <clib/err.h>
+#include <clib/raii.h>
+
+#include "misc.h"
+#include "main.h"
+
+args_t args;
+size_t page_size;
+
+int verbose;
+int debug;
+
+static const char copyright[] __unused__ =
+ "Licensed Internal Code - Property of IBM\n"
+ "IBM Support Processor Licensed Internal Code\n"
+ "(c) Copyright IBM Corp 2013 All Rights Reserved\n"
+ "US Government Users Restricted Rights - Use, duplication\n"
+ "or disclosure restricted by GSA ADP Schedule Contract\n"
+ "with IBM Corp.";
+
+static void usage(bool verbose)
+{
+ FILE *e = stderr;
+
+ fprintf(e,
+ "fcp - FFS copy v%d.%d.%d -- Authors: "
+ "<shaun@us.ibm.com>\n (c) Copyright IBM Corp 2013 All Rights "
+ "Reserved\n", FCP_MAJOR, FCP_MINOR, FCP_PATCH);
+
+ fprintf(e, "\n");
+ fprintf(e, "Usage:\n");
+ fprintf(e," fcp [<src_type>:]<src_target>[:<src_name>] -PLETU"
+ "\n [-b <size>] [-o <offset,...>] [-fpvdh]\n");
+ fprintf(e," fcp [<src_type>:]<src_target>[:<src_name>] "
+ "[<dst_type>:]<dst_target>[:<dst_name>] -RWCM"
+ "\n [-b <size>] [-o <offset,...>] [-fpvdh]\n");
+ fprintf(e, "\n");
+ fprintf(e, " <type>\n");
+ fprintf(e, " 'aa' : Aardvark USB probe\n");
+ fprintf(e, " 'rw' : RISCWatch Ethernet probe\n");
+ fprintf(e, " 'sfc' : FSP SFC character device\n");
+ fprintf(e, " 'file' : UNIX regular file\n");
+ fprintf(e, " <target>\n");
+ fprintf(e, " 'aa' : <number> USB device number [0..9]\n");
+ fprintf(e, " 'rw' : <hostname>@<port> RISCwatch probe\n");
+ fprintf(e, " 'sfc' : <path> to SFC char device\n");
+ fprintf(e, " 'file' : <path> to UNIX regular file\n");
+ fprintf(e, " <name>\n");
+ fprintf(e, " : FFS name, e.g. bank0/bootenv/card\n");
+ fprintf(e, "\n");
+
+ if (verbose) {
+ fprintf(e, "Examples:\n");
+ fprintf(e, " fcp -P aa:0\n");
+ fprintf(e, " fcp -P rw:riscwatch.ibm.com\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -L aa:0\n");
+ fprintf(e, " fcp -L rw:riscwatch.ibm.com\n");
+ fprintf(e, " fcp -L nor.mif\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -E 0 nor.mif:bank0\n");
+ fprintf(e, " fcp -E 0xff nor.mif:bank0/spl\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -W ipl.bin file:nor:bank0/ipl\n");
+ fprintf(e, " fcp -R file:nor:bank0/ipl ipl.bin\n");
+ fprintf(e, "\n");
+ fprintf(e, " cat ipl.bin | fcp -R file:nor:bank0/ipl -\n");
+ fprintf(e, " fcp -W file:nor:bank0/ipl - | cat > ipl.bin\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -C file:nor:bank0 rw:host.ibm.com:bank0\n");
+ fprintf(e, " fcp -C file:nor rw:host.ibm.com@6470\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -M file:nor:bank0 rw:host.ibm.com:bank0\n");
+ fprintf(e, " fcp -M file:nor:* rw:host.ibm.com@6470:*\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -C nor.mif:bank0 nor.mif:bank1\n");
+ fprintf(e, " fcp -C rw:host:bank0/ipl aa:0:bank1/ipl\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -M nor.mif:bank0 nor.mif:bank1\n");
+ fprintf(e, " fcp -M rw:host:bank0/ipl aa:0:bank1/ipl\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -T nor.mif:bank0/spl\n");
+ fprintf(e, " fcp -T 0 nor.mif:bank0/spl\n");
+ fprintf(e, "\n");
+ fprintf(e, " fcp -U nor.mif:bank0/spl\n");
+ fprintf(e, " fcp -U 0 1 2 nor.mif:bank0/spl\n");
+ fprintf(e, " fcp -U 0=0xffffffff 1=0 nor.mif:bank0/spl\n");
+ fprintf(e, "\n");
+ }
+
+ /* =============================== */
+
+ fprintf(e, "Commands:\n");
+
+ fprintf(e, " -P, --probe\n");
+ if (verbose)
+ fprintf(e,
+ "\n Read the SPI NOR device Id\n\n");
+
+ fprintf(e, " -L, --list\n");
+ if (verbose)
+ fprintf(e,
+ "\n List the contents of a partition table\n\n");
+
+ fprintf(e, " -R, --read\n");
+ if (verbose)
+ fprintf(e,
+ "\n Read the contents of a partition and write "
+ "the data to an output file (use\n '-' for stdout)."
+ "\n\n");
+
+ fprintf(e, " -W, --write\n");
+ if (verbose)
+ fprintf(e,
+ "\n Read the contents of an input file (use '-' for "
+ "stdin) and write the data\n to a partition.\n\n");
+
+ fprintf(e, " -E, --erase <value>\n");
+ if (verbose)
+ fprintf(e,
+ "\n Fill the contents of a partition with <value>. "
+ "<value> is a decimal (or hex)\n number, default is "
+ "0xFF.\n\n");
+
+ fprintf(e, " -C, --copy\n");
+ if (verbose)
+ fprintf(e,
+ "\n Copy source partition(s) to destination "
+ "partition(s). Both source and\n destination name(s) " "can specify either 'data' or 'logical' partitions."
+ "\n\n");
+
+ fprintf(e, " -T, --trunc <size>\n");
+ if (verbose)
+ fprintf(e,
+ "\n Truncate the actual size of partition(s) to "
+ "<size> size bytes. <size> is\n a decimal (or hex) "
+ "number, default is the partition entry size\n\n");
+
+ fprintf(e, " -M, --compare\n");
+ if (verbose)
+ fprintf(e,
+ "\n Compare source partition(s) to destination "
+ "partition(s). Both source and\n destination name(s) "
+ "can specify either 'data' or 'logical' partitions."
+ "\n\n");
+
+ fprintf(e, " -U, --user [<word>[=<value>] ...]\n");
+ if (verbose)
+ fprintf(e,
+ "\n Get or set a user word. <word> and <value> are "
+ "decimal (or hex) numbers.\n");
+
+ fprintf(e, "\n");
+
+ fprintf(e, "Options:\n");
+ fprintf(e, " -o, --offset <offset[,offset]>\n");
+ if (verbose)
+ fprintf(e, "\n Specifies a comma (,) separated list of"
+ " partition table offsets, in bytes\n from the start"
+ " of the target file (or device).\n\n");
+
+ fprintf(e, " -b, --buffer <value>\n");
+ if (verbose)
+ fprintf(e,
+ "\n Specifies the buffer size used by --read, --write,"
+ " --copy and --compare\n commands <value> is a "
+ "decimal (or hex) number, default is buffer size.\n\n");
+ fprintf(e, "\n");
+
+ /* =============================== */
+
+ fprintf(e, "Flags:\n");
+
+ fprintf(e, " -f, --force\n");
+ if (verbose)
+ fprintf(e, "\n Override command safe guards\n\n");
+
+ fprintf(e, " -p, --protected\n");
+ if (verbose)
+ fprintf(e, "\n Do not ignore protected partition "
+ "entries\n\n");
+
+ fprintf(e, " -v, --verbose\n");
+ if (verbose)
+ fprintf(e, "\n Write progress messages to stdout\n\n");
+
+ fprintf(e, " -d, --debug\n");
+ if (verbose)
+ fprintf(e, "\n Write debug messages to stdout\n\n");
+
+ fprintf(e, " -h, --help\n");
+ if (verbose)
+ fprintf(e, "\n Write this help text to stdout and exit\n");
+
+ fprintf(e, "\n");
+
+ fprintf(e, "Report bugs to <https://bugzilla.linux.ibm.com/>"
+ " (vendor='MCP for FSP*')\n");
+}
+
+static int process_argument(args_t * args, int opt, const char *optarg)
+{
+ assert(args != NULL);
+
+ switch (opt) {
+ case c_PROBE: /* probe */
+ case c_LIST: /* list */
+ case c_READ: /* read */
+ case c_WRITE: /* write */
+ case c_ERASE: /* erase */
+ case c_COPY: /* copy */
+ case c_TRUNC: /* trunc */
+ case c_COMPARE: /* compare */
+ case c_USER: /* user */
+ if (args->cmd != c_ERROR) {
+ UNEXPECTED("commands '%c' and '%c' are mutually "
+ "exclusive", args->cmd, opt);
+ return -1;
+ }
+ args->cmd = (cmd_t) opt;
+ break;
+ case o_OFFSET: /* offset */
+ args->offset = strdup(optarg);
+ break;
+ case o_BUFFER: /* buffer */
+ args->buffer = strdup(optarg);
+ break;
+ case f_FORCE: /* force */
+ args->force = (flag_t) opt;
+ break;
+ case f_PROTECTED: /* protected */
+ args->protected = (flag_t) opt;
+ break;
+ case f_VERBOSE: /* verbose */
+ verbose = 1;
+ args->verbose = (flag_t) opt;
+ break;
+ case f_DEBUG: /* debug */
+ debug = 1;
+ args->debug = (flag_t) opt;
+ break;
+ case f_HELP: /* help */
+ usage(true);
+ exit(EXIT_SUCCESS);
+ break;
+ case '?': /* error */
+ default:
+ UNEXPECTED("unknown option '%c', please see --help for "
+ "details\n", opt);
+ return -1;
+ }
+ return 0;
+}
+
+static int process_option(args_t * args, const char *opt)
+{
+ assert(args != NULL);
+ assert(opt != NULL);
+
+ if (args->opt_sz <= args->opt_nr) {
+ size_t size = sizeof(*args->opt);
+
+ args->opt_sz += 5;
+ args->opt = (const char **)realloc(args->opt,
+ size * args->opt_sz);
+ if (args->opt == NULL) {
+ ERRNO(errno);
+ return -1;
+ }
+
+ memset(args->opt + args->opt_nr, 0,
+ size * (args->opt_sz - args->opt_nr));
+ }
+
+ args->opt[args->opt_nr] = strdup(opt);
+ args->opt_nr++;
+
+ return 0;
+}
+
+/*
+ * probe:
+ * fcp [<type>:]<target>[:<path>] -P
+ * list:
+ * fcp <path> -L
+ * fcp [<type>:]<target>[:<path>] -L
+ * erase:
+ * fcp [<type>:]<target>[:<path>] -E <pad>
+ * trunc:
+ * fcp [<type>:]<target>[:<path>] -T <size>
+ * user:
+ * fcp [<type>:]<target>[:<path>] -U <word>[=<value>] ...
+ * write:
+ * fcp <path> [<type>:]<target>:<path> -W
+ * read:
+ * fcp [<type>:]<target>:<path> <path> -R
+ * copy:
+ * fcp <type>:]<target>:<source> [<type>:]<target>:<dest> -C
+ * fcp [<type>:]<source>:<path> [<type>:]<destination>:<path> -C
+ * compare:
+ * fcp <type>:]<target>:<source> [<type>:]<target>:<dest> -M
+ * fcp [<type>:]<source>:<path> [<type>:]<destination>:<path> -M
+ */
+static int validate_args(args_t * args)
+{
+ assert(args != NULL);
+
+ if (args->offset == NULL) {
+ UNEXPECTED("--offset is required for all '%s' "
+ "commands", args->short_name);
+ return -1;
+ }
+
+ switch (args->cmd) {
+ case c_PROBE:
+ case c_LIST:
+ case c_ERASE:
+ case c_TRUNC:
+ case c_USER:
+ if (args->opt_nr < 1) {
+ UNEXPECTED("invalid options, please see --help for "
+ "details");
+ return -1;
+ }
+
+ if (parse_path(args->opt[0], &args->dst_type,
+ &args->dst_target, &args->dst_name) < 0)
+ return -1;
+
+ break;
+ case c_READ:
+ case c_WRITE:
+ case c_COPY:
+ case c_COMPARE:
+ if (args->opt_nr < 2) {
+ UNEXPECTED("invalid options, please see --help for "
+ "details");
+ return -1;
+ }
+
+ if (parse_path(args->opt[0], &args->src_type,
+ &args->src_target, &args->src_name) < 0)
+ return -1;
+ if (parse_path(args->opt[1], &args->dst_type,
+ &args->dst_target, &args->dst_name) < 0)
+ return -1;
+
+ break;
+ case 0:
+ UNEXPECTED("specify a command, or please see --help "
+ "for details");
+ return -1;
+ default:
+ UNEXPECTED("invalid command '%c', please see --help for "
+ "details", args->cmd);
+ return -1;
+
+ }
+
+ debug("cmd[%c]\n", args->cmd);
+
+ debug(" src_type: '%s'\n", args->src_type);
+ debug("src_target: '%s'\n", args->src_target);
+ debug(" src_name: '%s'\n", args->src_name);
+
+ debug(" dst_type: '%s'\n", args->dst_type);
+ debug("dst_target: '%s'\n", args->dst_target);
+ debug(" dst_name: '%s'\n", args->dst_name);
+
+ #define REQ_OPT(name,cmd) ({ \
+ if (args->name == 0) { \
+ UNEXPECTED("--%s is required for the --%s command", \
+ #name, #cmd); \
+ syntax(); \
+ return -1; \
+ } \
+ })
+
+ #define REQ_FIELD(name,cmd) ({ \
+ if (args->name == 0) { \
+ UNEXPECTED("<%s> is required for the --%s command", \
+ #name, #cmd); \
+ syntax(); \
+ return -1; \
+ } \
+ })
+
+ #define UNSUP_OPT(name,cmd) ({ \
+ if (args->name != 0) { \
+ UNEXPECTED("--%s is unsupported for the --%s command", \
+ #name, #cmd); \
+ syntax(); \
+ return -1; \
+ } \
+ })
+
+ if (args->cmd == c_PROBE) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<dst_type>:]<dst_target>"
+ "[:<dst_name>] --probe [--verbose]\n",
+ args->short_name);
+ }
+ if (args->opt_nr != 1) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+
+ UNSUP_OPT(buffer, probe);
+ } else if (args->cmd == c_LIST) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<dst_type>:]<dst_target>"
+ "[:<dst_name>] --list [--verbose]\n",
+ args->short_name);
+ }
+ if (args->opt_nr != 1) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+
+ UNSUP_OPT(buffer, list);
+ } else if (args->cmd == c_READ) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<src_type>:]<src_source>"
+ ":<src_name> <path> --read [--verbose] "
+ "[--force] [--protected] [--buffer <value>]\n",
+ args->short_name);
+ }
+ if (args->opt_nr != 2) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+
+ REQ_FIELD(src_name, read);
+ } else if (args->cmd == c_WRITE) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s <path> [<dst_type>:]"
+ "<dst_target>:<dst_name> --write [--verbose] "
+ "[--force] [--protected] [--buffer <value>]\n",
+ args->short_name);
+ }
+ if (args->opt_nr != 2) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+
+
+ REQ_FIELD(dst_name, write);
+ } else if (args->cmd == c_ERASE) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<dst_type>:]<dst_target>"
+ ":<dst_name> --erase <value> [--verbose] "
+ "[--force] [--protected] [--buffer <value>]\n",
+ args->short_name);
+ }
+ if (args->opt_nr != 2) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+
+ REQ_FIELD(dst_name, erase);
+ } else if (args->cmd == c_TRUNC) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<dst_type>:]<dst_target>"
+ ":<dst_name> --trunc <value> [--verbose] "
+ "[--force] [--protected]\n", args->short_name);
+ }
+ if (2 < args->opt_nr) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+
+ REQ_FIELD(dst_name, trunc);
+
+ UNSUP_OPT(buffer, trunc);
+ } else if (args->cmd == c_USER) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<dst_type>:]<dst_target>"
+ ":<dst_name> --user <value>[=<value] "
+ "[--verbose] [--force] [--protected]\n",
+ args->short_name);
+ }
+
+ REQ_FIELD(dst_name, user);
+
+ UNSUP_OPT(buffer, user);
+ } else if (args->cmd == c_COPY) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<src_type>:]<src_target>"
+ "[:<src_name>] [<dst_type>:]<dst_target>"
+ "[:<dst_name>] --copy [--verbose] [--force] "
+ "[--protected] [--buffer <value>]\n",
+ args->short_name);
+ }
+ if (args->opt_nr != 2) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+ } else if (args->cmd == c_COMPARE) {
+ void syntax(void) {
+ fprintf(stderr, "Syntax: %s [<src_type>:]<src_target>"
+ "[:<src_name>] [<dst_type>:]<dst_target>"
+ "[:<dst_name>] --compare [--verbose] [--force] "
+ "[--protected] [--buffer <value>]\n",
+ args->short_name);
+ }
+ if (args->opt_nr != 2) {
+ syntax();
+ UNEXPECTED("syntax error");
+ return -1;
+ }
+ } else {
+ UNEXPECTED("invalid command '%c'", args->cmd);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int process_args(args_t * args)
+{
+ assert(args != NULL);
+ int rc = 0;
+
+ switch (args->cmd) {
+ case c_PROBE:
+ //rc = command_probe(args);
+ break;
+ case c_LIST:
+ rc = command_list(args);
+ break;
+ case c_READ:
+ rc = command_read(args);
+ break;
+ case c_WRITE:
+ rc = command_write(args);
+ break;
+ case c_ERASE:
+ rc = command_erase(args);
+ break;
+ case c_TRUNC:
+ rc = command_trunc(args);
+ break;
+ case c_USER:
+ rc = command_user(args);
+ break;
+ case c_COPY:
+ case c_COMPARE:
+ rc = command_copy_compare(args);
+ break;
+ default:
+ UNEXPECTED("NOT IMPLEMENTED YET => '%c'", args->cmd);
+ rc = -1;
+ }
+
+ return rc;
+}
+
+static void args_dump(args_t * args)
+{
+ assert(args != NULL);
+
+ if (args->short_name != NULL)
+ printf("short_name[%s]\n", args->short_name);
+ printf("cmd[%c]\n", args->cmd);
+ if (args->offset != NULL)
+ printf("offset[%s]\n", args->offset);
+ if (args->buffer != NULL)
+ printf("buffer[%s]\n", args->buffer);
+ if (args->force != 0)
+ printf("force[%c]\n", args->force);
+ if (args->protected != 0)
+ printf("protected[%c]\n", args->protected);
+ if (args->verbose != 0)
+ printf("verbose[%c]\n", args->verbose);
+ if (args->debug != 0)
+ printf("debug[%c]\n", args->debug);
+
+ for (int i = 0; i < args->opt_nr; i++) {
+ if (args->opt[i] != NULL)
+ printf("opt%d[%s]\n", i, args->opt[i]);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ static const struct option long_opt[] = {
+ /* commands */
+ {"probe", no_argument, NULL, c_PROBE},
+ {"list", no_argument, NULL, c_LIST},
+ {"read", no_argument, NULL, c_READ},
+ {"write", no_argument, NULL, c_WRITE},
+ {"erase", no_argument, NULL, c_ERASE},
+ {"copy", no_argument, NULL, c_COPY},
+ {"trunc", no_argument, NULL, c_TRUNC},
+ {"compare", no_argument, NULL, c_COMPARE},
+ {"user", no_argument, NULL, c_USER},
+ /* options */
+ {"offset", required_argument, NULL, o_OFFSET},
+ {"buffer", required_argument, NULL, o_BUFFER},
+ /* flags */
+ {"force", no_argument, NULL, f_FORCE},
+ {"protected", no_argument, NULL, f_PROTECTED},
+ {"verbose", no_argument, NULL, f_VERBOSE},
+ {"debug", no_argument, NULL, f_DEBUG},
+ {"help", no_argument, NULL, f_HELP},
+ {0, 0, 0, 0}
+ };
+
+ static const char *short_opt;
+ short_opt = "PLRWECTMUo:b:fpvdh";
+
+ int rc = EXIT_FAILURE;
+
+ setlinebuf(stdout);
+
+ if (argc == 1)
+ usage(false), exit(rc);
+
+ int opt = 0, idx = 0;
+ while ((opt = getopt_long(argc, argv, short_opt, long_opt, &idx)) != -1)
+ if (process_argument(&args, opt, optarg) < 0)
+ goto error;
+
+ /* getopt_long doesn't know what to do with orphans, */
+ /* so we'll scoop them up here, and deal with them later */
+
+ while (optind < argc)
+ if (process_option(&args, argv[optind++]) < 0)
+ goto error;
+
+ if (args.debug == f_DEBUG)
+ args_dump(&args);
+
+ if (validate_args(&args) < 0)
+ goto error;
+ if (process_args(&args) < 0)
+ goto error;
+
+ rc = EXIT_SUCCESS;
+
+ if (false) {
+error:
+ dump_errors(args.short_name, stderr);
+ }
+
+ return rc;
+}
+
+static void __ctor__(void) __constructor;
+static void __ctor__(void)
+{
+ page_size = sysconf(_SC_PAGESIZE);
+
+ args.short_name = program_invocation_short_name;
+ args.offset = "0x3F0000,0x7F0000";
+}
OpenPOWER on IntegriCloud