diff --git a/me7sum.c b/me7sum.c index bf8ca61..622d65f 100644 --- a/me7sum.c +++ b/me7sum.c @@ -31,9 +31,13 @@ #include #include #include +#include /* isprint() */ #if _MSC_VER #define snprintf _snprintf +#include "os/getopt.h" +#else +#include #endif #include "inifile_prop.h" @@ -110,45 +114,82 @@ static int DoChecksumBlk(struct ImageHandle *ih, uint32_t nStartBlk); * */ +static void usage(const char *prog) +{ + printf("Usage: %s [-i ] [outrom.bin]\n", prog); + exit(-1); +} + int main(int argc, char **argv) { int iTemp; int result; int num_of; + char *prog=argv[0]; + char *inifile=NULL; + char *input=NULL; + char *output=NULL; + char c; struct ImageHandle ih; - struct section *osconfig; + struct section *osconfig=NULL; // information about the tool printf("ME7Tool [ Management tool for Bosch ME7.x firmwares]\n"); printf("Inspiration from Andy Whittaker's tools and information\n"); printf("Written by 360trev and nyet [BSD License Open Source]. \n\n"); - if(argc < 3 || argc > 4) + opterr=0; + + while ((c = getopt(argc, argv, "i:")) != -1) { - printf("Usage: %s [outrom.bin]\n",argv[0]); - return -1; + switch (c) + { + case 'i': + inifile=optarg; + break; + case '?': + if (optopt == 'i') + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + else if (isprint(optopt)) + fprintf(stderr, "Unknown option '-%c'.\n", optopt); + // break; // fallthrough + default: + usage(prog); + return -1; + } } - if(argc==3) - { + argc-=optind; + argv+=optind; + + if (argc==0 || argc>2) + usage(prog); + + input = argv[0]; + + if (argc>1) + output = argv[1]; + else Config.readonly=1; - } - printf("Attemping to open firmware config file %s\n",argv[1]); - // load properties file into memory - osconfig = read_properties(argv[1]); - if(osconfig == NULL) + if (inifile) { - printf("failed to open config file\n"); - return -1; + printf("Attemping to open firmware config file %s\n",inifile); + // load properties file into memory + osconfig = read_properties(inifile); + if(osconfig == NULL) + { + printf("failed to open config file\n"); + return -1; + } } // get rom region information from config file (see defined property list) result = process_properties_list(osconfig, romProps); // open the firmware file - printf("\nAttemping to open firmware file %s\n",argv[2]); - if (iload_file(&ih, argv[2], 0)) + printf("\nAttemping to open firmware file %s\n",input); + if (iload_file(&ih, input, 0)) { printf("failed to open firmware file\n"); goto out; @@ -230,9 +271,9 @@ int main(int argc, char **argv) printf("Skipping Multipoint Checksum Block... undefined\n"); } - if(argc>3 && ErrorsCorrected > 0) { + if(output && ErrorsCorrected > 0) { // write crc corrected file out - save_file(argv[3],ih.d.p,ih.len); + save_file(output,ih.d.p,ih.len); } out: diff --git a/nmakefile b/nmakefile index 7a659b9..6ddc4a9 100644 --- a/nmakefile +++ b/nmakefile @@ -1,5 +1,5 @@ TARGET = me7sum.exe -SOURCES = crc32.c inifile_prop.c me7sum.c utils.c inifile/inifile.c +SOURCES = crc32.c inifile_prop.c me7sum.c utils.c inifile/inifile.c os/pgetopt.c all: $(TARGET) $(TARGET):$(SOURCES) diff --git a/os/getopt.h b/os/getopt.h new file mode 100644 index 0000000..26c32f9 --- /dev/null +++ b/os/getopt.h @@ -0,0 +1,12 @@ +#ifndef _GETOPT_H +#define _GETOPT_H + +#include "pgetopt.h" +#define getopt pgetopt +/* popterr does the WRONG thing */ +static int opterr; +#define optind poptind +#define optarg poptarg +#define optopt poptopt + +#endif diff --git a/os/pgetopt.c b/os/pgetopt.c new file mode 100644 index 0000000..9851488 --- /dev/null +++ b/os/pgetopt.c @@ -0,0 +1,233 @@ +/* + * pgetopt.c - Portable implementation of getopt() command line args parser, + * originally made available by IBM and the authors listed below. + * + * Created on 8/8/08. + * Portions of this document are Copyright (C) 2008, PlexFX, + * All Rights Reserved. + * + * History: + * Original Date Unknown + * This code is quite old, but it was originally called GETOPT.C + * in the comments, along with a GETOPT.H thin header, and used the + * same namespace as the getopt() implementation on my UNIX variant + * platforms. The original date has been lost. It may date back + * to even pre-ANSI C. The development team at PlexFX has been + * using it (primarily for Windows command line tools, but also on + * other platforms for many years. A search for historical dates + * via web search engines found it widely used, but no date stamps + * on its original form seem to have been preserved. + * It can be found in various forms in open source packages, such + * as using a search engine on one or both of the author strings + * shown in the original comment block below. For example, as of + * the creation date on this file, a slightly modified verion of + * it was used in library code found in the CVS tree for + * OpenSolaris. + * + * It was also included on at least some of the MSDN Library discs + * Around the early 2001-2003 time frame. + * + * 2008-08-08 This version is a modified version of the original IBM code, but + * the filename and namespace used has been altered along with some + * calling convention changes. As such, it can be used as a drop- + * in replacement for getopt() even on UNIX or Linux systems that + * have their own getopt() implementations in libc without naming + * collisions. This means it can be used portably on any OS with + * a conforming C compiler. It does *not* attempt to implement the + * more long-winded getopt_long() interface. Naming of APIs, + * headers and the optarg/optind externs have been prefixed with + * 'p' to accomplish this. Examples: pgetopt(), poptarg, poptind, + * pgetopt.c, pgetopt.h. + * Note: This interface keeps external state (to match original + * calling conventions). As such, it is not thread safe, + * and should be called in only one thread (use from main() + * before additional threads are started). As the command + * line should never change, this should not be an issue. + * + */ + +/* Original IBM "AS IS" license follows */ + +/***************************************************************************** + * + * MODULE NAME : GETOPT.C + * + * COPYRIGHTS: + * This module contains code made available by IBM + * Corporation on an AS IS basis. Any one receiving the + * module is considered to be licensed under IBM copyrights + * to use the IBM-provided source code in any way he or she + * deems fit, including copying it, compiling it, modifying + * it, and redistributing it, with or without + * modifications. No license under any IBM patents or + * patent applications is to be implied from this copyright + * license. + * + * A user of the module should understand that IBM cannot + * provide technical support for the module and will not be + * responsible for any consequences of use of the program. + * + * Any notices, including this one, are not to be removed + * from the module without the prior written consent of + * IBM. + * + * AUTHOR: Original author: + * G. R. Blair (BOBBLAIR at AUSVM1) + * Internet: bobblair@bobblair.austin.ibm.com + * + * Extensively revised by: + * John Q. Walker II, Ph.D. (JOHHQ at RALVM6) + * Internet: johnq@ralvm6.vnet.ibm.com + * + *****************************************************************************/ + +/****************************************************************************** + * pgetopt() + * + * The pgetopt() function is a command line parser. It returns the next + * option character in argv that matches an option character in optstring. + * + * The argv argument points to an array of argc+1 elements containing argc + * pointers to character strings followed by a null pointer. + * + * The optstring argument points to a string of option characters; if an + * option character is followed by a colon, the option is expected to have + * an argument that may or may not be separated from it by white space. + * The external variable poptarg is set to point to the start of the option + * argument on return from pgetopt(). + * + * The pgetopt() function places in poptind the argv index of the next argument + * to be processed. The system initializes the external variable poptind to + * 1 before the first call to pgetopt(). + * + * When all options have been processed (that is, up to the first nonoption + * argument), pgetopt() returns -1. The special option "--" may be used to + * delimit the end of the options; -1 will be returned, and "--" will be + * skipped. + * + * The pgetopt() function returns a question mark (?) when it encounters an + * option character not included in optstring. This error message can be + * disabled by setting popterr to zero. Otherwise, it returns the option + * character that was detected. + * + * If the special option "--" is detected, or all options have been + * processed, -1 is returned. + * + * Options are marked by either a minus sign (-) or a slash (/). + * + * No other errors are defined. + *****************************************************************************/ + +//#include /* for EOF */ +#include /* for strchr() */ +#include "pgetopt.h" /* pgetopt() interface and example code */ + +/* global variables that are specified as exported by pgetopt() */ +char *poptarg = NULL; /* pointer to the start of the option argument */ +int poptind = 1; /* number of the next argv[] to be evaluated */ +int popterr = 1; /* non-zero if a question mark should be returned + * when a non-valid option character is detected */ +int poptopt = 0; /* original opt when we return ? */ + +/* handle possible future character set concerns by putting this in a macro */ +#define _next_char(string) (char)(*(string+1)) + +int +pgetopt(int argc, char *argv[], char *optstring) +{ + static char *IndexPosition = NULL; /* place inside current argv string */ + char *ArgString = NULL; /* where to start from next */ + char *OptString; /* the string in our program */ + + + if (IndexPosition != NULL) { + /* we last left off inside an argv string */ + if (*(++IndexPosition)) { + /* there is more to come in the most recent argv */ + ArgString = IndexPosition; + } + } + + if (ArgString == NULL) { + /* we didn't leave off in the middle of an argv string */ + if (poptind >= argc) { + /* more command-line arguments than the argument count */ + IndexPosition = NULL; /* not in the middle of anything */ + return -1; /* used up all command-line arguments */ + } + + /*--------------------------------------------------------------------- + * If the next argv[] is not an option, there can be no more options. + *-------------------------------------------------------------------*/ + ArgString = argv[poptind++]; /* set this to the next argument ptr */ + + if (('/' != *ArgString) && /* doesn't start with a slash or a dash? */ + ('-' != *ArgString)) { + --poptind; /* point to current arg once we're done */ + poptarg = NULL; /* no argument follows the option */ + IndexPosition = NULL; /* not in the middle of anything */ + return -1; /* used up all the command-line flags */ + } + + /* check for special end-of-flags markers */ + if ((strcmp(ArgString, "-") == 0) || + (strcmp(ArgString, "--") == 0)) { + poptarg = NULL; /* no argument follows the option */ + IndexPosition = NULL; /* not in the middle of anything */ + return -1; /* encountered the special flag */ + } + + ArgString++; /* look past the / or - */ + } + + if (':' == *ArgString) { /* is it a colon? */ + /*--------------------------------------------------------------------- + * Rare case: if opterr is non-zero, return a question mark; + * otherwise, just return the colon we're on. + *-------------------------------------------------------------------*/ + return (popterr ? (int)'?' : (int)':'); + } + else if ((OptString = strchr(optstring, *ArgString)) == 0) { + /*--------------------------------------------------------------------- + * The letter on the command-line wasn't any good. + *-------------------------------------------------------------------*/ + poptarg = NULL; /* no argument follows the option */ + IndexPosition = NULL; /* not in the middle of anything */ + poptopt = (int)*ArgString; + return (popterr ? (int)'?' : (int)*ArgString); + } + else { + /*--------------------------------------------------------------------- + * The letter on the command-line matches one we expect to see + *-------------------------------------------------------------------*/ + if (':' == _next_char(OptString)) { /* is the next letter a colon? */ + /* It is a colon. Look for an argument string. */ + if ('\0' != _next_char(ArgString)) { /* argument in this argv? */ + poptarg = &ArgString[1]; /* Yes, it is */ + } + else { + /*------------------------------------------------------------- + * The argument string must be in the next argv. + * But, what if there is none (bad input from the user)? + * In that case, return the letter, and poptarg as NULL. + *-----------------------------------------------------------*/ + if (poptind < argc) + poptarg = argv[poptind++]; + else { + poptarg = NULL; + poptopt = (int)*ArgString; + return (popterr ? (int)'?' : (int)*ArgString); + } + } + IndexPosition = NULL; /* not in the middle of anything */ + } + else { + /* it's not a colon, so just return the letter */ + poptarg = NULL; /* no argument follows the option */ + IndexPosition = ArgString; /* point to the letter we're on */ + } + return (int)*ArgString; /* return the letter that matched */ + } +} + + diff --git a/os/pgetopt.h b/os/pgetopt.h new file mode 100644 index 0000000..7b1fe53 --- /dev/null +++ b/os/pgetopt.h @@ -0,0 +1,135 @@ +/* + * pgetopt.h - Portable implementation of getopt() command line args parser, + * originally made available by IBM and the authors listed below. + * + * Created on 8/8/08. + * Portions of this document are Copyright (C) 2008, PlexFX, + * All Rights Reserved. + * + * History: + * Original Date Unknown + * This code is quite old, but it was originally called GETOPT.H + * in the comments, along with a GETOPT.C source file, and used the + * same namespace as the getopt() implementation on my UNIX variant + * platforms. The original date has been lost. It may date back + * to even pre-ANSI C. The development team at PlexFX has been + * using it (primarily for Windows command line tools, but also on + * other platforms for many years. A search for historical dates + * via web search engines found it widely used, but no date stamps + * on its original form seem to have been preserved. + * It can be found in various forms in open source packages, such + * as using a search engine on one or both of the author strings + * shown in the original comment block below. For example, as of + * the creation date on this file, a slightly modified verion of + * it was used in library code found in the CVS tree for + * OpenSolaris. + * + * It was also included on at least some of the MSDN Library discs + * Around the early 2001-2003 time frame. + * + * 2008-08-08 This version is a modified version of the original IBM code, but + * the filename and namespace used has been altered along with some + * calling convention changes. As such, it can be used as a drop- + * in replacement for getopt() even on UNIX or Linux systems that + * have their own getopt() implementations in libc without naming + * collisions. This means it can be used portably on any OS with + * a conforming C compiler. It does *not* attempt to implement the + * more long-winded getopt_long() interface. Naming of APIs, + * headers and the optarg/optind externs have been prefixed with + * 'p' to accomplish this. Examples: pgetopt(), poptarg, poptind, + * pgetopt.c, pgetopt.h. Also added some comments to clarify usage + * for the popterr extern. + * Note: This interface keeps external state (to match original + * calling conventions). As such, it is not thread safe, + * and should be called in only one thread (use from main() + * before additional threads are started). As the command + * line should never change, this should not be an issue. + * + */ + +/* Original IBM "AS IS" license follows */ + +/***************************************************************************** + * + * MODULE NAME : GETOPT.H + * + * COPYRIGHTS: + * This module contains code made available by IBM + * Corporation on an AS IS basis. Any one receiving the + * module is considered to be licensed under IBM copyrights + * to use the IBM-provided source code in any way he or she + * deems fit, including copying it, compiling it, modifying + * it, and redistributing it, with or without + * modifications. No license under any IBM patents or + * patent applications is to be implied from this copyright + * license. + * + * A user of the module should understand that IBM cannot + * provide technical support for the module and will not be + * responsible for any consequences of use of the program. + * + * Any notices, including this one, are not to be removed + * from the module without the prior written consent of + * IBM. + * + * AUTHOR: Original author: + * G. R. Blair (BOBBLAIR at AUSVM1) + * Internet: bobblair@bobblair.austin.ibm.com + * + * Extensively revised by: + * John Q. Walker II, Ph.D. (JOHHQ at RALVM6) + * Internet: johnq@ralvm6.vnet.ibm.com + * + *****************************************************************************/ + +#ifndef H_PGETOPT +#define H_PGETOPT 1 + +extern char * poptarg; /* carries the optional argument when a command line + * arg is specified with a ':' after it in the optstring + * and is usually handled by the caller in a switch() + * block. */ +extern int poptind; /* The caller should not need to adjust this normally */ +extern int popterr; /* The pgetopt() function returns a question mark (?) + * when it encounters an option character not included in + * optstring. This error message can be disabled by + * setting popterr to zero. Otherwise, it returns the + * option character that was detected. */ +extern int poptopt; /* actual option character */ + +int pgetopt(int argc, char *argv[], char *optstring); + +/* Example code by PlexFX to demonstrate calling of and parsing optional extra + * args. This is a sample code fragment, untested, minimal or non-existent + * error handling, and some headers variable declarations are omitted. + */ + +#if 0 /* remove, for example purposes only */ + +/* Note the ':' shown below in the pattern string, to specify additional arg */ +char opt_pattern[] = "s:V?"; + +while ((c = pgetopt(argc, argv, opt_pattern)) != -1) +{ + switch(c) + { + case 's': /* specify a /s option with a numeric size parameter + * which is provided in poptarg, a char * + * Example: $ someprogram /s 100 + */ + + some_size = atoi(poptarg); /* should use strtol() in new code */ + break; + case 'V': /* specify a /V version option, with no parameter */ + puts("someprogram: Version 1.0"); + break; + case '?': /* explicit allows of -? or /? */ + default: /* and give usage any time invalid arguments are given */ + PrintUsage(); /* call some function to show usage */ + break; + } +} +#endif /* 0 */ + +#endif /* ! H_GETOPT */ +