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