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