Home | History | Annotate | Line # | Download | only in elftosb2
      1  1.1  jkunz /*
      2  1.1  jkunz  * File:	elftosb.cpp
      3  1.1  jkunz  *
      4  1.1  jkunz  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
      5  1.1  jkunz  * See included license file for license details.
      6  1.1  jkunz  */
      7  1.1  jkunz 
      8  1.1  jkunz #include "stdafx.h"
      9  1.1  jkunz #include <iostream>
     10  1.1  jkunz #include <fstream>
     11  1.1  jkunz #include <sstream>
     12  1.1  jkunz #include <stdlib.h>
     13  1.1  jkunz #include <stdexcept>
     14  1.1  jkunz #include "ConversionController.h"
     15  1.1  jkunz #include "options.h"
     16  1.1  jkunz #include "Version.h"
     17  1.1  jkunz #include "EncoreBootImage.h"
     18  1.1  jkunz #include "smart_ptr.h"
     19  1.1  jkunz #include "Logging.h"
     20  1.1  jkunz #include "EncoreBootImageGenerator.h"
     21  1.1  jkunz #include "SearchPath.h"
     22  1.1  jkunz #include "format_string.h"
     23  1.1  jkunz 
     24  1.1  jkunz //! An array of strings.
     25  1.1  jkunz typedef std::vector<std::string> string_vector_t;
     26  1.1  jkunz 
     27  1.1  jkunz //! The tool's name.
     28  1.1  jkunz const char k_toolName[] = "elftosb";
     29  1.1  jkunz 
     30  1.1  jkunz //! Current version number for the tool.
     31  1.1  jkunz const char k_version[] = "2.6.1";
     32  1.1  jkunz 
     33  1.1  jkunz //! Copyright string.
     34  1.1  jkunz const char k_copyright[] = "Copyright (c) 2004-2010 Freescale Semiconductor, Inc.\nAll rights reserved.";
     35  1.1  jkunz 
     36  1.1  jkunz static const char * k_optionsDefinition[] = {
     37  1.1  jkunz 	"?|help",
     38  1.1  jkunz 	"v|version",
     39  1.1  jkunz 	"f:chip-family <family>",
     40  1.1  jkunz 	"c:command <file>",
     41  1.1  jkunz 	"o:output <file>",
     42  1.1  jkunz 	"P:product <version>",
     43  1.1  jkunz 	"C:component <version>",
     44  1.1  jkunz 	"k:key <file>",
     45  1.1  jkunz 	"z|zero-key",
     46  1.1  jkunz 	"D:define <const>",
     47  1.1  jkunz 	"O:option <option>",
     48  1.1  jkunz 	"d|debug",
     49  1.1  jkunz 	"q|quiet",
     50  1.1  jkunz 	"V|verbose",
     51  1.1  jkunz 	"p:search-path <path>",
     52  1.1  jkunz 	NULL
     53  1.1  jkunz };
     54  1.1  jkunz 
     55  1.1  jkunz //! Help string.
     56  1.1  jkunz const char k_usageText[] = "\nOptions:\n\
     57  1.1  jkunz   -?/--help                    Show this help\n\
     58  1.1  jkunz   -v/--version                 Display tool version\n\
     59  1.1  jkunz   -f/--chip-family <family>    Select the chip family (default is 37xx)\n\
     60  1.1  jkunz   -c/--command <file>          Use this command file\n\
     61  1.1  jkunz   -o/--output <file>           Write output to this file\n\
     62  1.1  jkunz   -p/--search-path <path>      Add a search path used to find input files\n\
     63  1.1  jkunz   -P/--product <version        Set product version\n\
     64  1.1  jkunz   -C/--component <version>     Set component version\n\
     65  1.1  jkunz   -k/--key <file>              Add OTP key, enable encryption\n\
     66  1.1  jkunz   -z/--zero-key                Add default key of all zeroes\n\
     67  1.1  jkunz   -D/--define <const>=<int>    Define or override a constant value\n\
     68  1.1  jkunz   -O/--option <name>=<value>   Set or override a processing option\n\
     69  1.1  jkunz   -d/--debug                   Enable debug output\n\
     70  1.1  jkunz   -q/--quiet                   Output only warnings and errors\n\
     71  1.1  jkunz   -V/--verbose                 Print extra detailed log information\n\n";
     72  1.1  jkunz 
     73  1.1  jkunz // prototypes
     74  1.1  jkunz int main(int argc, char* argv[], char* envp[]);
     75  1.1  jkunz 
     76  1.1  jkunz /*!
     77  1.1  jkunz  * \brief Class that encapsulates the elftosb tool.
     78  1.1  jkunz  *
     79  1.1  jkunz  * A single global logger instance is created during object construction. It is
     80  1.1  jkunz  * never freed because we need it up to the last possible minute, when an
     81  1.1  jkunz  * exception could be thrown.
     82  1.1  jkunz  */
     83  1.1  jkunz class elftosbTool
     84  1.1  jkunz {
     85  1.1  jkunz protected:
     86  1.1  jkunz 	//! Supported chip families.
     87  1.1  jkunz 	enum chip_family_t
     88  1.1  jkunz 	{
     89  1.1  jkunz 		k37xxFamily,	//!< 37xx series.
     90  1.1  jkunz 		kMX28Family,	//!< Catskills series.
     91  1.1  jkunz 	};
     92  1.1  jkunz 
     93  1.1  jkunz 	/*!
     94  1.1  jkunz 	 * \brief A structure describing an entry in the table of chip family names.
     95  1.1  jkunz 	 */
     96  1.1  jkunz 	struct FamilyNameTableEntry
     97  1.1  jkunz 	{
     98  1.1  jkunz 		const char * const name;
     99  1.1  jkunz 		chip_family_t family;
    100  1.1  jkunz 	};
    101  1.1  jkunz 
    102  1.1  jkunz 	//! \brief Table that maps from family name strings to chip family constants.
    103  1.1  jkunz 	static const FamilyNameTableEntry kFamilyNameTable[];
    104  1.1  jkunz 
    105  1.1  jkunz 	int m_argc;							//!< Number of command line arguments.
    106  1.1  jkunz 	char ** m_argv;						//!< String value for each command line argument.
    107  1.1  jkunz 	StdoutLogger * m_logger;			//!< Singleton logger instance.
    108  1.1  jkunz 	string_vector_t m_keyFilePaths;		//!< Paths to OTP key files.
    109  1.1  jkunz 	string_vector_t m_positionalArgs;	//!< Arguments coming after explicit options.
    110  1.1  jkunz 	bool m_isVerbose;					//!< Whether the verbose flag was turned on.
    111  1.1  jkunz 	bool m_useDefaultKey;					//!< Include a default (zero) crypto key.
    112  1.1  jkunz 	const char * m_commandFilePath;		//!< Path to the elftosb command file.
    113  1.1  jkunz 	const char * m_outputFilePath;		//!< Path to the output .sb file.
    114  1.1  jkunz 	const char * m_searchPath;			//!< Optional search path for input files.
    115  1.1  jkunz 	elftosb::version_t m_productVersion;	//!< Product version specified on command line.
    116  1.1  jkunz 	elftosb::version_t m_componentVersion;	//!< Component version specified on command line.
    117  1.1  jkunz 	bool m_productVersionSpecified;		//!< True if the product version was specified on the command line.
    118  1.1  jkunz 	bool m_componentVersionSpecified;		//!< True if the component version was specified on the command line.
    119  1.1  jkunz 	chip_family_t m_family;				//!< Chip family that the output file is formatted for.
    120  1.1  jkunz 	elftosb::ConversionController m_controller;	//!< Our conversion controller instance.
    121  1.1  jkunz 
    122  1.1  jkunz public:
    123  1.1  jkunz 	/*!
    124  1.1  jkunz 	 * Constructor.
    125  1.1  jkunz 	 *
    126  1.1  jkunz 	 * Creates the singleton logger instance.
    127  1.1  jkunz 	 */
    128  1.1  jkunz 	elftosbTool(int argc, char * argv[])
    129  1.1  jkunz 	:	m_argc(argc),
    130  1.1  jkunz 		m_argv(argv),
    131  1.1  jkunz 		m_logger(0),
    132  1.1  jkunz 		m_keyFilePaths(),
    133  1.1  jkunz 		m_positionalArgs(),
    134  1.1  jkunz 		m_isVerbose(false),
    135  1.1  jkunz 		m_useDefaultKey(false),
    136  1.1  jkunz 		m_commandFilePath(NULL),
    137  1.1  jkunz 		m_outputFilePath(NULL),
    138  1.1  jkunz 		m_searchPath(NULL),
    139  1.1  jkunz 		m_productVersion(),
    140  1.1  jkunz 		m_componentVersion(),
    141  1.1  jkunz 		m_productVersionSpecified(false),
    142  1.1  jkunz 		m_componentVersionSpecified(false),
    143  1.1  jkunz 		m_family(k37xxFamily),
    144  1.1  jkunz 		m_controller()
    145  1.1  jkunz 	{
    146  1.1  jkunz 		// create logger instance
    147  1.1  jkunz 		m_logger = new StdoutLogger();
    148  1.1  jkunz 		m_logger->setFilterLevel(Logger::INFO);
    149  1.1  jkunz 		Log::setLogger(m_logger);
    150  1.1  jkunz 	}
    151  1.1  jkunz 
    152  1.1  jkunz 	/*!
    153  1.1  jkunz 	 * Destructor.
    154  1.1  jkunz 	 */
    155  1.1  jkunz 	~elftosbTool()
    156  1.1  jkunz 	{
    157  1.1  jkunz 	}
    158  1.1  jkunz 
    159  1.1  jkunz 	/*!
    160  1.1  jkunz 	 * \brief Searches the family name table.
    161  1.1  jkunz 	 *
    162  1.1  jkunz 	 * \retval true The \a name was found in the table, and \a family is valid.
    163  1.1  jkunz 	 * \retval false No matching family name was found. The \a family argument is not modified.
    164  1.1  jkunz 	 */
    165  1.1  jkunz 	bool lookupFamilyName(const char * name, chip_family_t * family)
    166  1.1  jkunz 	{
    167  1.1  jkunz 		// Create a local read-write copy of the argument string.
    168  1.1  jkunz 		std::string familyName(name);
    169  1.1  jkunz 
    170  1.1  jkunz 		// Convert the argument string to lower case for case-insensitive comparison.
    171  1.1  jkunz 		for (int n=0; n < familyName.length(); n++)
    172  1.1  jkunz 		{
    173  1.1  jkunz 			familyName[n] = tolower(familyName[n]);
    174  1.1  jkunz 		}
    175  1.1  jkunz 
    176  1.1  jkunz         // Exit the loop if we hit the NULL terminator entry.
    177  1.1  jkunz 		const FamilyNameTableEntry * entry = &kFamilyNameTable[0];
    178  1.1  jkunz 		for (; entry->name; entry++)
    179  1.1  jkunz 		{
    180  1.1  jkunz 			// Compare lowercased name with the table entry.
    181  1.1  jkunz 			if (familyName == entry->name)
    182  1.1  jkunz 			{
    183  1.1  jkunz 				*family = entry->family;
    184  1.1  jkunz 				return true;
    185  1.1  jkunz 			}
    186  1.1  jkunz 		}
    187  1.1  jkunz 
    188  1.1  jkunz 		// Failed to find a matching name.
    189  1.1  jkunz 		return false;
    190  1.1  jkunz 	}
    191  1.1  jkunz 
    192  1.1  jkunz 	/*!
    193  1.1  jkunz 	 * Reads the command line options passed into the constructor.
    194  1.1  jkunz 	 *
    195  1.1  jkunz 	 * This method can return a return code to its caller, which will cause the
    196  1.1  jkunz 	 * tool to exit immediately with that return code value. Normally, though, it
    197  1.1  jkunz 	 * will return -1 to signal that the tool should continue to execute and
    198  1.1  jkunz 	 * all options were processed successfully.
    199  1.1  jkunz 	 *
    200  1.1  jkunz 	 * The Options class is used to parse command line options. See
    201  1.1  jkunz 	 * #k_optionsDefinition for the list of options and #k_usageText for the
    202  1.1  jkunz 	 * descriptive help for each option.
    203  1.1  jkunz 	 *
    204  1.1  jkunz 	 * \retval -1 The options were processed successfully. Let the tool run normally.
    205  1.1  jkunz 	 * \return A zero or positive result is a return code value that should be
    206  1.1  jkunz 	 *		returned from the tool as it exits immediately.
    207  1.1  jkunz 	 */
    208  1.1  jkunz 	int processOptions()
    209  1.1  jkunz 	{
    210  1.1  jkunz 		Options options(*m_argv, k_optionsDefinition);
    211  1.1  jkunz 		OptArgvIter iter(--m_argc, ++m_argv);
    212  1.1  jkunz 
    213  1.1  jkunz 		// process command line options
    214  1.1  jkunz 		int optchar;
    215  1.1  jkunz 		const char * optarg;
    216  1.1  jkunz 		while (optchar = options(iter, optarg))
    217  1.1  jkunz 		{
    218  1.1  jkunz 			switch (optchar)
    219  1.1  jkunz 			{
    220  1.1  jkunz 				case '?':
    221  1.1  jkunz 					printUsage(options);
    222  1.1  jkunz 					return 0;
    223  1.1  jkunz 
    224  1.1  jkunz 				case 'v':
    225  1.1  jkunz 					printf("%s %s\n%s\n", k_toolName, k_version, k_copyright);
    226  1.1  jkunz 					return 0;
    227  1.1  jkunz 
    228  1.1  jkunz 				case 'f':
    229  1.1  jkunz 					if (!lookupFamilyName(optarg, &m_family))
    230  1.1  jkunz 					{
    231  1.1  jkunz 						Log::log(Logger::ERROR, "error: unknown chip family '%s'\n", optarg);
    232  1.1  jkunz 						printUsage(options);
    233  1.1  jkunz 						return 0;
    234  1.1  jkunz 					}
    235  1.1  jkunz 					break;
    236  1.1  jkunz 
    237  1.1  jkunz 				case 'c':
    238  1.1  jkunz 					m_commandFilePath = optarg;
    239  1.1  jkunz 					break;
    240  1.1  jkunz 
    241  1.1  jkunz 				case 'o':
    242  1.1  jkunz 					m_outputFilePath = optarg;
    243  1.1  jkunz 					break;
    244  1.1  jkunz 
    245  1.1  jkunz 				case 'P':
    246  1.1  jkunz 					m_productVersion.set(optarg);
    247  1.1  jkunz 					m_productVersionSpecified = true;
    248  1.1  jkunz 					break;
    249  1.1  jkunz 
    250  1.1  jkunz 				case 'C':
    251  1.1  jkunz 					m_componentVersion.set(optarg);
    252  1.1  jkunz 					m_componentVersionSpecified = true;
    253  1.1  jkunz 					break;
    254  1.1  jkunz 
    255  1.1  jkunz 				case 'k':
    256  1.1  jkunz 					m_keyFilePaths.push_back(optarg);
    257  1.1  jkunz 					break;
    258  1.1  jkunz 
    259  1.1  jkunz 				case 'z':
    260  1.1  jkunz 					m_useDefaultKey = true;
    261  1.1  jkunz 					break;
    262  1.1  jkunz 
    263  1.1  jkunz 				case 'D':
    264  1.1  jkunz 					overrideVariable(optarg);
    265  1.1  jkunz 					break;
    266  1.1  jkunz 
    267  1.1  jkunz 				case 'O':
    268  1.1  jkunz 					overrideOption(optarg);
    269  1.1  jkunz 					break;
    270  1.1  jkunz 
    271  1.1  jkunz 				case 'd':
    272  1.1  jkunz 					Log::getLogger()->setFilterLevel(Logger::DEBUG);
    273  1.1  jkunz 					break;
    274  1.1  jkunz 
    275  1.1  jkunz 				case 'q':
    276  1.1  jkunz 					Log::getLogger()->setFilterLevel(Logger::WARNING);
    277  1.1  jkunz 					break;
    278  1.1  jkunz 
    279  1.1  jkunz 				case 'V':
    280  1.1  jkunz 					m_isVerbose = true;
    281  1.1  jkunz 					break;
    282  1.1  jkunz 
    283  1.1  jkunz 				case 'p':
    284  1.1  jkunz 				{
    285  1.1  jkunz 					std::string newSearchPath(optarg);
    286  1.1  jkunz 					PathSearcher::getGlobalSearcher().addSearchPath(newSearchPath);
    287  1.1  jkunz 					break;
    288  1.1  jkunz 				}
    289  1.1  jkunz 
    290  1.1  jkunz 				default:
    291  1.1  jkunz 					Log::log(Logger::ERROR, "error: unrecognized option\n\n");
    292  1.1  jkunz 					printUsage(options);
    293  1.1  jkunz 					return 0;
    294  1.1  jkunz 			}
    295  1.1  jkunz 		}
    296  1.1  jkunz 
    297  1.1  jkunz 		// handle positional args
    298  1.1  jkunz 		if (iter.index() < m_argc)
    299  1.1  jkunz 		{
    300  1.1  jkunz 			Log::SetOutputLevel leveler(Logger::DEBUG);
    301  1.1  jkunz 			Log::log("positional args:\n");
    302  1.1  jkunz 			int i;
    303  1.1  jkunz 			for (i = iter.index(); i < m_argc; ++i)
    304  1.1  jkunz 			{
    305  1.1  jkunz 				Log::log("%d: %s\n", i - iter.index(), m_argv[i]);
    306  1.1  jkunz 				m_positionalArgs.push_back(m_argv[i]);
    307  1.1  jkunz 			}
    308  1.1  jkunz 		}
    309  1.1  jkunz 
    310  1.1  jkunz 		// all is well
    311  1.1  jkunz 		return -1;
    312  1.1  jkunz 	}
    313  1.1  jkunz 
    314  1.1  jkunz 	/*!
    315  1.1  jkunz 	 * Prints help for the tool.
    316  1.1  jkunz 	 */
    317  1.1  jkunz 	void printUsage(Options & options)
    318  1.1  jkunz 	{
    319  1.1  jkunz 		options.usage(std::cout, "files...");
    320  1.2  joerg 		printf("%s", k_usageText);
    321  1.1  jkunz 	}
    322  1.1  jkunz 
    323  1.1  jkunz 	/*!
    324  1.1  jkunz 	 * \brief Core of the tool.
    325  1.1  jkunz 	 *
    326  1.1  jkunz 	 * Calls processOptions() to handle command line options before performing the
    327  1.1  jkunz 	 * real work the tool does.
    328  1.1  jkunz 	 */
    329  1.1  jkunz 	int run()
    330  1.1  jkunz 	{
    331  1.1  jkunz 		try
    332  1.1  jkunz 		{
    333  1.1  jkunz 			// read command line options
    334  1.1  jkunz 			int result;
    335  1.1  jkunz 			if ((result = processOptions()) != -1)
    336  1.1  jkunz 			{
    337  1.1  jkunz 				return result;
    338  1.1  jkunz 			}
    339  1.1  jkunz 
    340  1.1  jkunz 			// set verbose logging
    341  1.1  jkunz 			setVerboseLogging();
    342  1.1  jkunz 
    343  1.1  jkunz 			// check argument values
    344  1.1  jkunz 			checkArguments();
    345  1.1  jkunz 
    346  1.1  jkunz 			// set up the controller
    347  1.1  jkunz 			m_controller.setCommandFilePath(m_commandFilePath);
    348  1.1  jkunz 
    349  1.1  jkunz 			// add external paths to controller
    350  1.1  jkunz 			string_vector_t::iterator it = m_positionalArgs.begin();
    351  1.1  jkunz 			for (; it != m_positionalArgs.end(); ++it)
    352  1.1  jkunz 			{
    353  1.1  jkunz 				m_controller.addExternalFilePath(*it);
    354  1.1  jkunz 			}
    355  1.1  jkunz 
    356  1.1  jkunz 			// run conversion
    357  1.1  jkunz 			convert();
    358  1.1  jkunz 		}
    359  1.1  jkunz 		catch (std::exception & e)
    360  1.1  jkunz 		{
    361  1.1  jkunz 			Log::log(Logger::ERROR, "error: %s\n", e.what());
    362  1.1  jkunz 			return 1;
    363  1.1  jkunz 		}
    364  1.1  jkunz 		catch (...)
    365  1.1  jkunz 		{
    366  1.1  jkunz 			Log::log(Logger::ERROR, "error: unexpected exception\n");
    367  1.1  jkunz 			return 1;
    368  1.1  jkunz 		}
    369  1.1  jkunz 
    370  1.1  jkunz 		return 0;
    371  1.1  jkunz 	}
    372  1.1  jkunz 
    373  1.1  jkunz 	/*!
    374  1.1  jkunz 	 * \brief Validate arguments that can be checked.
    375  1.1  jkunz 	 * \exception std::runtime_error Thrown if an argument value fails to pass validation.
    376  1.1  jkunz 	 */
    377  1.1  jkunz 	void checkArguments()
    378  1.1  jkunz 	{
    379  1.1  jkunz 		if (m_commandFilePath == NULL)
    380  1.1  jkunz 		{
    381  1.1  jkunz 			throw std::runtime_error("no command file was specified");
    382  1.1  jkunz 		}
    383  1.1  jkunz 		if (m_outputFilePath == NULL)
    384  1.1  jkunz 		{
    385  1.1  jkunz 			throw std::runtime_error("no output file was specified");
    386  1.1  jkunz 		}
    387  1.1  jkunz 	}
    388  1.1  jkunz 
    389  1.1  jkunz 	/*!
    390  1.1  jkunz 	 * \brief Turns on verbose logging.
    391  1.1  jkunz 	 */
    392  1.1  jkunz 	void setVerboseLogging()
    393  1.1  jkunz 	{
    394  1.1  jkunz 		if (m_isVerbose)
    395  1.1  jkunz 		{
    396  1.1  jkunz 			// verbose only affects the INFO and DEBUG filter levels
    397  1.1  jkunz 			// if the user has selected quiet mode, it overrides verbose
    398  1.1  jkunz 			switch (Log::getLogger()->getFilterLevel())
    399  1.1  jkunz 			{
    400  1.1  jkunz 				case Logger::INFO:
    401  1.1  jkunz 					Log::getLogger()->setFilterLevel(Logger::INFO2);
    402  1.1  jkunz 					break;
    403  1.1  jkunz 				case Logger::DEBUG:
    404  1.1  jkunz 					Log::getLogger()->setFilterLevel(Logger::DEBUG2);
    405  1.1  jkunz 					break;
    406  1.1  jkunz 			}
    407  1.1  jkunz 		}
    408  1.1  jkunz 	}
    409  1.1  jkunz 
    410  1.1  jkunz 	/*!
    411  1.1  jkunz 	 * \brief Returns the integer value for a string.
    412  1.1  jkunz 	 *
    413  1.1  jkunz 	 * Metric multiplier prefixes are supported.
    414  1.1  jkunz 	 */
    415  1.1  jkunz 	uint32_t parseIntValue(const char * value)
    416  1.1  jkunz 	{
    417  1.1  jkunz 		// Accept 'true'/'yes' and 'false'/'no' as integer values.
    418  1.1  jkunz 		if ((strcmp(value, "true") == 0) || (strcmp(value, "yes") == 0))
    419  1.1  jkunz 		{
    420  1.1  jkunz 			return 1;
    421  1.1  jkunz 		}
    422  1.1  jkunz 		else if ((strcmp(value, "false") == 0) || (strcmp(value, "no") == 0))
    423  1.1  jkunz 		{
    424  1.1  jkunz 			return 0;
    425  1.1  jkunz 		}
    426  1.1  jkunz 
    427  1.1  jkunz 		uint32_t intValue = strtoul(value, NULL, 0);
    428  1.1  jkunz 		unsigned multiplier;
    429  1.1  jkunz 		switch (value[strlen(value) - 1])
    430  1.1  jkunz 		{
    431  1.1  jkunz 			case 'G':
    432  1.1  jkunz 				multiplier = 1024 * 1024 * 1024;
    433  1.1  jkunz 				break;
    434  1.1  jkunz 			case 'M':
    435  1.1  jkunz 				multiplier = 1024 * 1024;
    436  1.1  jkunz 				break;
    437  1.1  jkunz 			case 'K':
    438  1.1  jkunz 				multiplier = 1024;
    439  1.1  jkunz 				break;
    440  1.1  jkunz 			default:
    441  1.1  jkunz 				multiplier = 1;
    442  1.1  jkunz 		}
    443  1.1  jkunz 		intValue *= multiplier;
    444  1.1  jkunz 		return intValue;
    445  1.1  jkunz 	}
    446  1.1  jkunz 
    447  1.1  jkunz 	/*!
    448  1.1  jkunz 	 * \brief Parses the -D option to override a constant value.
    449  1.1  jkunz 	 */
    450  1.1  jkunz 	void overrideVariable(const char * optarg)
    451  1.1  jkunz 	{
    452  1.1  jkunz 		// split optarg into two strings
    453  1.1  jkunz 		std::string constName(optarg);
    454  1.1  jkunz 		int i;
    455  1.1  jkunz 		for (i=0; i < strlen(optarg); ++i)
    456  1.1  jkunz 		{
    457  1.1  jkunz 			if (optarg[i] == '=')
    458  1.1  jkunz 			{
    459  1.1  jkunz 				constName.resize(i++);
    460  1.1  jkunz 				break;
    461  1.1  jkunz 			}
    462  1.1  jkunz 		}
    463  1.1  jkunz 
    464  1.1  jkunz 		uint32_t constValue = parseIntValue(&optarg[i]);
    465  1.1  jkunz 
    466  1.1  jkunz 		elftosb::EvalContext & context = m_controller.getEvalContext();
    467  1.1  jkunz 		context.setVariable(constName, constValue);
    468  1.1  jkunz 		context.lockVariable(constName);
    469  1.1  jkunz 	}
    470  1.1  jkunz 
    471  1.1  jkunz 	/*!
    472  1.1  jkunz 	 * \brief
    473  1.1  jkunz 	 */
    474  1.1  jkunz 	void overrideOption(const char * optarg)
    475  1.1  jkunz 	{
    476  1.1  jkunz 		// split optarg into two strings
    477  1.1  jkunz 		std::string optionName(optarg);
    478  1.1  jkunz 		int i;
    479  1.1  jkunz 		for (i=0; i < strlen(optarg); ++i)
    480  1.1  jkunz 		{
    481  1.1  jkunz 			if (optarg[i] == '=')
    482  1.1  jkunz 			{
    483  1.1  jkunz 				optionName.resize(i++);
    484  1.1  jkunz 				break;
    485  1.1  jkunz 			}
    486  1.1  jkunz 		}
    487  1.1  jkunz 
    488  1.1  jkunz 		// handle quotes for option value
    489  1.1  jkunz 		const char * valuePtr = &optarg[i];
    490  1.1  jkunz 		bool isString = false;
    491  1.1  jkunz 		int len;
    492  1.1  jkunz 		if (valuePtr[0] == '"')
    493  1.1  jkunz 		{
    494  1.1  jkunz 			// remember that the value is a string and get rid of the opening quote
    495  1.1  jkunz 			isString = true;
    496  1.1  jkunz 			valuePtr++;
    497  1.1  jkunz 
    498  1.1  jkunz 			// remove trailing quote if present
    499  1.1  jkunz 			len = strlen(valuePtr);
    500  1.1  jkunz 			if (valuePtr[len] == '"')
    501  1.1  jkunz 			{
    502  1.1  jkunz 				len--;
    503  1.1  jkunz 			}
    504  1.1  jkunz 		}
    505  1.1  jkunz 
    506  1.1  jkunz 		elftosb::Value * value;
    507  1.1  jkunz 		if (isString)
    508  1.1  jkunz 		{
    509  1.1  jkunz 			std::string stringValue(valuePtr);
    510  1.1  jkunz 			stringValue.resize(len);	// remove trailing quote
    511  1.1  jkunz 			value = new elftosb::StringValue(stringValue);
    512  1.1  jkunz 		}
    513  1.1  jkunz 		else
    514  1.1  jkunz 		{
    515  1.1  jkunz 			value = new elftosb::IntegerValue(parseIntValue(valuePtr));
    516  1.1  jkunz 		}
    517  1.1  jkunz 
    518  1.1  jkunz 		// Set and lock the option in the controller
    519  1.1  jkunz 		m_controller.setOption(optionName, value);
    520  1.1  jkunz 		m_controller.lockOption(optionName);
    521  1.1  jkunz 	}
    522  1.1  jkunz 
    523  1.1  jkunz 	/*!
    524  1.1  jkunz 	 * \brief Do the conversion.
    525  1.1  jkunz 	 * \exception std::runtime_error This exception is thrown if the conversion controller does
    526  1.1  jkunz 	 *		not produce a boot image, or if the output file cannot be opened. Other errors
    527  1.1  jkunz 	 *		internal to the conversion controller may also produce this exception.
    528  1.1  jkunz 	 */
    529  1.1  jkunz 	void convert()
    530  1.1  jkunz 	{
    531  1.1  jkunz 		// create a generator for the chosen chip family
    532  1.1  jkunz 		smart_ptr<elftosb::BootImageGenerator> generator;
    533  1.1  jkunz 		switch (m_family)
    534  1.1  jkunz 		{
    535  1.1  jkunz 			case k37xxFamily:
    536  1.1  jkunz 				generator = new elftosb::EncoreBootImageGenerator;
    537  1.1  jkunz 				elftosb::g_enableHABSupport = false;
    538  1.1  jkunz 				break;
    539  1.1  jkunz 
    540  1.1  jkunz 			case kMX28Family:
    541  1.1  jkunz 				generator = new elftosb::EncoreBootImageGenerator;
    542  1.1  jkunz 				elftosb::g_enableHABSupport = true;
    543  1.1  jkunz 				break;
    544  1.1  jkunz 		}
    545  1.1  jkunz 
    546  1.1  jkunz 		// process input and get a boot image
    547  1.1  jkunz 		m_controller.run();
    548  1.1  jkunz 		smart_ptr<elftosb::BootImage> image = m_controller.generateOutput(generator);
    549  1.1  jkunz 		if (!image)
    550  1.1  jkunz 		{
    551  1.1  jkunz 			throw std::runtime_error("failed to produce output!");
    552  1.1  jkunz 		}
    553  1.1  jkunz 
    554  1.1  jkunz 		// set version numbers if they were provided on the command line
    555  1.1  jkunz 		if (m_productVersionSpecified)
    556  1.1  jkunz 		{
    557  1.1  jkunz 			image->setProductVersion(m_productVersion);
    558  1.1  jkunz 		}
    559  1.1  jkunz 		if (m_componentVersionSpecified)
    560  1.1  jkunz 		{
    561  1.1  jkunz 			image->setComponentVersion(m_componentVersion);
    562  1.1  jkunz 		}
    563  1.1  jkunz 
    564  1.1  jkunz 		// special handling for each family
    565  1.1  jkunz 		switch (m_family)
    566  1.1  jkunz 		{
    567  1.1  jkunz 			case k37xxFamily:
    568  1.1  jkunz 			case kMX28Family:
    569  1.1  jkunz 			{
    570  1.1  jkunz 				// add OTP keys
    571  1.1  jkunz 				elftosb::EncoreBootImage * encoreImage = dynamic_cast<elftosb::EncoreBootImage*>(image.get());
    572  1.1  jkunz 				if (encoreImage)
    573  1.1  jkunz 				{
    574  1.1  jkunz 					// add keys
    575  1.1  jkunz 					addCryptoKeys(encoreImage);
    576  1.1  jkunz 
    577  1.1  jkunz 					// print debug image
    578  1.1  jkunz 					encoreImage->debugPrint();
    579  1.1  jkunz 				}
    580  1.1  jkunz 				break;
    581  1.1  jkunz 			}
    582  1.1  jkunz 		}
    583  1.1  jkunz 
    584  1.1  jkunz 		// write output
    585  1.1  jkunz 		std::ofstream outputStream(m_outputFilePath, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
    586  1.1  jkunz 		if (outputStream.is_open())
    587  1.1  jkunz 		{
    588  1.1  jkunz 			image->writeToStream(outputStream);
    589  1.1  jkunz 		}
    590  1.1  jkunz 		else
    591  1.1  jkunz 		{
    592  1.1  jkunz 			throw std::runtime_error(format_string("could not open output file %s", m_outputFilePath));
    593  1.1  jkunz 		}
    594  1.1  jkunz 	}
    595  1.1  jkunz 
    596  1.1  jkunz 	/*!
    597  1.1  jkunz 	 * \brief
    598  1.1  jkunz 	 */
    599  1.1  jkunz 	void addCryptoKeys(elftosb::EncoreBootImage * encoreImage)
    600  1.1  jkunz 	{
    601  1.1  jkunz 		string_vector_t::iterator it = m_keyFilePaths.begin();
    602  1.1  jkunz 		for (; it != m_keyFilePaths.end(); ++it)
    603  1.1  jkunz 		{
    604  1.1  jkunz 			std::string & keyPath = *it;
    605  1.1  jkunz 
    606  1.1  jkunz 			std::string actualPath;
    607  1.1  jkunz 			bool found = PathSearcher::getGlobalSearcher().search(keyPath, PathSearcher::kFindFile, true, actualPath);
    608  1.1  jkunz 			if (!found)
    609  1.1  jkunz 			{
    610  1.1  jkunz 				throw std::runtime_error(format_string("unable to find key file %s\n", keyPath.c_str()));
    611  1.1  jkunz 			}
    612  1.1  jkunz 
    613  1.1  jkunz 			std::ifstream keyStream(actualPath.c_str(), std::ios_base::in);
    614  1.1  jkunz 			if (!keyStream.is_open())
    615  1.1  jkunz 			{
    616  1.1  jkunz 				throw std::runtime_error(format_string("unable to read key file %s\n", keyPath.c_str()));
    617  1.1  jkunz 			}
    618  1.1  jkunz 			keyStream.seekg(0);
    619  1.1  jkunz 
    620  1.1  jkunz 			try
    621  1.1  jkunz 			{
    622  1.1  jkunz 				// read as many keys as possible from the stream
    623  1.1  jkunz 				while (true)
    624  1.1  jkunz 				{
    625  1.1  jkunz 					AESKey<128> key(keyStream);
    626  1.1  jkunz 					encoreImage->addKey(key);
    627  1.1  jkunz 
    628  1.1  jkunz 					// dump key bytes
    629  1.1  jkunz 					dumpKey(key);
    630  1.1  jkunz 				}
    631  1.1  jkunz 			}
    632  1.1  jkunz 			catch (...)
    633  1.1  jkunz 			{
    634  1.1  jkunz 				// ignore the exception -- there are just no more keys in the stream
    635  1.1  jkunz 			}
    636  1.1  jkunz 		}
    637  1.1  jkunz 
    638  1.1  jkunz 		// add the default key of all zero bytes if requested
    639  1.1  jkunz 		if (m_useDefaultKey)
    640  1.1  jkunz 		{
    641  1.1  jkunz 			AESKey<128> defaultKey;
    642  1.1  jkunz 			encoreImage->addKey(defaultKey);
    643  1.1  jkunz 		}
    644  1.1  jkunz 	}
    645  1.1  jkunz 
    646  1.1  jkunz 	/*!
    647  1.1  jkunz 	 * \brief Write the value of each byte of the \a key to the log.
    648  1.1  jkunz 	 */
    649  1.1  jkunz 	void dumpKey(const AESKey<128> & key)
    650  1.1  jkunz 	{
    651  1.1  jkunz 		// dump key bytes
    652  1.1  jkunz 		Log::log(Logger::DEBUG, "key bytes: ");
    653  1.1  jkunz 		AESKey<128>::key_t the_key;
    654  1.1  jkunz 		key.getKey(&the_key);
    655  1.1  jkunz 		int q;
    656  1.1  jkunz 		for (q=0; q<16; q++)
    657  1.1  jkunz 		{
    658  1.1  jkunz 			Log::log(Logger::DEBUG, "%02x ", the_key[q]);
    659  1.1  jkunz 		}
    660  1.1  jkunz 		Log::log(Logger::DEBUG, "\n");
    661  1.1  jkunz 	}
    662  1.1  jkunz 
    663  1.1  jkunz };
    664  1.1  jkunz 
    665  1.1  jkunz const elftosbTool::FamilyNameTableEntry elftosbTool::kFamilyNameTable[] =
    666  1.1  jkunz 	{
    667  1.1  jkunz 		{ "37xx", k37xxFamily },
    668  1.1  jkunz 		{ "377x", k37xxFamily },
    669  1.1  jkunz 		{ "378x", k37xxFamily },
    670  1.1  jkunz 		{ "mx23", k37xxFamily },
    671  1.1  jkunz 		{ "imx23", k37xxFamily },
    672  1.1  jkunz 		{ "i.mx23", k37xxFamily },
    673  1.1  jkunz 		{ "mx28", kMX28Family },
    674  1.1  jkunz 		{ "imx28", kMX28Family },
    675  1.1  jkunz 		{ "i.mx28", kMX28Family },
    676  1.1  jkunz 
    677  1.1  jkunz 		// Null terminator entry.
    678  1.1  jkunz 		{ NULL, k37xxFamily }
    679  1.1  jkunz 	};
    680  1.1  jkunz 
    681  1.1  jkunz /*!
    682  1.1  jkunz  * Main application entry point. Creates an sbtool instance and lets it take over.
    683  1.1  jkunz  */
    684  1.1  jkunz int main(int argc, char* argv[], char* envp[])
    685  1.1  jkunz {
    686  1.1  jkunz 	try
    687  1.1  jkunz 	{
    688  1.1  jkunz 		return elftosbTool(argc, argv).run();
    689  1.1  jkunz 	}
    690  1.1  jkunz 	catch (...)
    691  1.1  jkunz 	{
    692  1.1  jkunz 		Log::log(Logger::ERROR, "error: unexpected exception\n");
    693  1.1  jkunz 		return 1;
    694  1.1  jkunz 	}
    695  1.1  jkunz 
    696  1.1  jkunz 	return 0;
    697  1.1  jkunz }
    698  1.1  jkunz 
    699  1.1  jkunz 
    700  1.1  jkunz 
    701