diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2016-02-26 16:42:16 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-02-27 00:38:28 -0800 |
commit | d1bf3aecfafcfc82cd7ff0233b6487f11b11c114 (patch) | |
tree | 2ad1ea4172375294217400707a069b8c9d4f0a45 /util | |
parent | b47c1fed2027c45f3062705e0ee9943601bdeba7 (diff) | |
download | chrome-ec-d1bf3aecfafcfc82cd7ff0233b6487f11b11c114.tar.gz |
cr50: signer: sync up with upstream
This change just copies files shared between two repositories which
have changed since the last sync up. This time it is as of @CL85098.
BRANCH=none
BUG=none
TEST=the signed image boots fine on the b1 board.
Change-Id: I7a1d1b344119e6f6729a38bbea04da75f2d3371c
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/329407
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/signer/codesigner.cc | 257 | ||||
-rw-r--r-- | util/signer/common/signed_header.h | 7 | ||||
-rw-r--r-- | util/signer/gnubby.cc | 14 | ||||
-rw-r--r-- | util/signer/image.cc | 288 |
4 files changed, 264 insertions, 302 deletions
diff --git a/util/signer/codesigner.cc b/util/signer/codesigner.cc index 293490a9e2..a2a840509b 100644 --- a/util/signer/codesigner.cc +++ b/util/signer/codesigner.cc @@ -7,8 +7,8 @@ #include <getopt.h> #include <inttypes.h> #include <stddef.h> -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> @@ -19,12 +19,12 @@ #include <rapidjson/document.h> #endif -#include <string> #include <map> +#include <string> #include <vector> -#include <iostream> #include <fstream> +#include <iostream> #include <sstream> #include <libxml/parser.h> @@ -32,17 +32,24 @@ using namespace std; -#define VERBOSE(...) do{if(FLAGS_verbose)fprintf(stderr, __VA_ARGS__);}while(0) -#define FATAL(...) do{fprintf(stderr, __VA_ARGS__);abort();}while(0) +#define VERBOSE(...) \ + do { \ + if (FLAGS_verbose) fprintf(stderr, __VA_ARGS__); \ + } while (0) +#define FATAL(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + abort(); \ + } while (0) bool FLAGS_verbose = false; +bool FLAGS_cros = false; int last_logical_offset = -1; int fuse_index = 0; // Brute xml parsing. // Find HashItem w/ key == name, return val field, recursively. -static -xmlChar* get_val(xmlNodePtr node, const char* key) { +static xmlChar* get_val(xmlNodePtr node, const char* key) { xmlNode* cur_node = NULL; xmlChar* val = NULL; @@ -75,9 +82,8 @@ xmlChar* get_val(xmlNodePtr node, const char* key) { return val; } -static -bool get_fuse(xmlNodePtr a_node, - map<string, uint32_t>* ids, map<string, uint32_t>* bits) { +static bool get_fuse(xmlNodePtr a_node, map<string, uint32_t>* ids, + map<string, uint32_t>* bits) { bool result = false; // Interested in <HashType> @@ -110,9 +116,8 @@ bool get_fuse(xmlNodePtr a_node, return result; } -static -bool find_fuses(xmlNodePtr a_node, - map<string, uint32_t>* ids, map<string, uint32_t>* bits) { +static bool find_fuses(xmlNodePtr a_node, map<string, uint32_t>* ids, + map<string, uint32_t>* bits) { xmlNode* cur_node = NULL; bool done = false; @@ -137,9 +142,8 @@ bool find_fuses(xmlNodePtr a_node, return done; } -static -bool find_default_reg_value(xmlNodePtr a_node, - const string& regname, string* result) { +static bool find_default_reg_value(xmlNodePtr a_node, const string& regname, + string* result) { xmlNode* cur_node = NULL; bool done = false; @@ -168,12 +172,9 @@ bool find_default_reg_value(xmlNodePtr a_node, return done; } - // Read XML, populate two maps, name -> val -bool readXML(const string& filename, - map<string, uint32_t>* ids, - map<string, uint32_t>* bits, - uint32_t* p4cl) { +bool readXML(const string& filename, map<string, uint32_t>* ids, + map<string, uint32_t>* bits, uint32_t* p4cl) { bool result = false; LIBXML_TEST_VERSION @@ -182,7 +183,8 @@ bool readXML(const string& filename, if (doc) { result = find_fuses(xmlDocGetRootElement(doc), ids, bits); string p4clStr; - result &= find_default_reg_value(xmlDocGetRootElement(doc), "SWDP_P4_LAST_SYNC", &p4clStr); + result &= find_default_reg_value(xmlDocGetRootElement(doc), + "SWDP_P4_LAST_SYNC", &p4clStr); if (result) { *p4cl = atoi(p4clStr.c_str()); } @@ -195,84 +197,14 @@ bool readXML(const string& filename, return result; } -// Write minified XML -bool writeXML(const string& filename, - map<string, uint32_t>& ids, - map<string, uint32_t>& bits, - uint32_t p4cl) { - bool result = false; - - // Get the names in order. - vector<string> names; - names.resize(ids.size()); - for (map<string, uint32_t>::const_iterator it = ids.begin(); it != ids.end(); ++it) { - const string& name = it->first; - uint32_t offset = it->second; - names[offset] = name; - } - - // Write out as nodes. - ofstream ofs(filename.c_str(), ofstream::out); - if (ofs) { - ofs << "<ArrayType>" << endl; - for (size_t i = 0; i < names.size(); ++i) { - const string& name = names[i]; - ofs << "<ArrayItem>" << endl; - ofs << " <HashType>" << endl; - ofs << " <HashItem>" << endl; - ofs << " <Key>RegName</Key>" << endl; - ofs << " <Value>" << name << "</Value>" << endl; - ofs << " </HashItem>" << endl; - ofs << " <HashItem>" << endl; - ofs << " <Key>FuseLogicalOffset</Key>" << endl; - ofs << " <Value>" << i << "</Value>" << endl; - ofs << " </HashItem>" << endl; - ofs << " <HashItem>" << endl; - ofs << " <Key>Width</Key>" << endl; - ofs << " <Value>" << bits[name] << "</Value>" << endl; - ofs << " </HashItem>" << endl; - ofs << " </HashType>" << endl; - ofs << "</ArrayItem>" << endl; - } - - // Write p4cl - ofs << "<ArrayItem>" << endl; - ofs << "<HashType>" << endl; - ofs << " <HashItem>" << endl; - ofs << " <Key>RegName</Key>" << endl; - ofs << " <Value>SWDP_P4_LAST_SYNC</Value>" << endl; - ofs << " </HashItem>" << endl; - ofs << " <HashItem>" << endl; - ofs << " <Key>Default</Key>" << endl; - ofs << " <Value>" << p4cl << "</Value>" << endl; - ofs << " </HashItem>" << endl; - // Write fake offset to make parser happy - ofs << " <HashItem>" << endl; - ofs << " <Key>FuseLogicalOffset</Key>" << endl; - ofs << " <Value>0</Value>" << endl; - ofs << " </HashItem>" << endl; - ofs << "</HashType>" << endl; - ofs << "</ArrayItem>" << endl; - - ofs << "</ArrayType>" << endl; - - result = true; - } - - return result; -} - // Read JSON, populate map, name -> val -bool readJSON(const string& filename, - string* tag, - map<string, uint32_t>* values, - map<string, uint32_t>* fusemap, +bool readJSON(const string& filename, string* tag, + map<string, uint32_t>* values, map<string, uint32_t>* fusemap, map<string, uint32_t>* infomap) { bool result = false; #ifdef HAVE_JSON ifstream ifs(filename.c_str()); if (ifs) { - // Touch up a bit to allow for comments. // Beware: we drop everything past and including '//' from any line. // Thus '//' cannot be substring of any value.. @@ -290,27 +222,35 @@ bool readJSON(const string& filename, // Try parse. rapidjson::Document d; if (d.Parse(s.c_str()).HasParseError()) { - FATAL("JSON %s[%lu]: parse error\n", filename.c_str(), d.GetErrorOffset()); + FATAL("JSON %s[%lu]: parse error\n", filename.c_str(), + d.GetErrorOffset()); } else { - -#define CHECKVALUE(x) do { \ - if (!d.HasMember(x)){FATAL("manifest is lacking field '%s'\n", x);}; \ +#define CHECKVALUE(x) \ + do { \ + if (!d.HasMember(x)) { \ + FATAL("manifest is lacking field '%s'\n", x); \ + }; \ } while (0) -#define GETVALUE(x) do { \ - if (!d.HasMember(x)){FATAL("manifest is lacking field '%s'\n", x);}; \ - (*values)[x] = d[x].GetInt(); \ +#define GETVALUE(x) \ + do { \ + if (!d.HasMember(x)) { \ + FATAL("manifest is lacking field '%s'\n", x); \ + }; \ + (*values)[x] = d[x].GetInt(); \ } while (0) CHECKVALUE("fuses"); const rapidjson::Document::ValueType& fuses = d["fuses"]; - for (rapidjson::Value::ConstMemberIterator it = fuses.MemberBegin(); it != fuses.MemberEnd(); ++it) { + for (rapidjson::Value::ConstMemberIterator it = fuses.MemberBegin(); + it != fuses.MemberEnd(); ++it) { (*fusemap)[it->name.GetString()] = it->value.GetInt(); } CHECKVALUE("info"); const rapidjson::Document::ValueType& infos = d["info"]; - for (rapidjson::Value::ConstMemberIterator it = infos.MemberBegin(); it != infos.MemberEnd(); ++it) { + for (rapidjson::Value::ConstMemberIterator it = infos.MemberBegin(); + it != infos.MemberEnd(); ++it) { (*infomap)[it->name.GetString()] = it->value.GetInt(); } @@ -333,7 +273,6 @@ bool readJSON(const string& filename, #undef GETVALUE #undef CHECKVALUE - } } #endif // HAVE_JSON @@ -351,53 +290,57 @@ string hashesFilename; bool fillPattern = false; uint32_t pattern = -1; bool fillRandom = false; -string xmlOutputFilename; void usage(int argc, char* argv[]) { - fprintf(stderr, "Usage: %s options\n" + fprintf(stderr, + "Usage: %s options\n" "--input=$elf-filename\n" "--output=output-filename\n" "--key=$pem-filename\n" + "[--cros] to sign for the ChromeOS realm w/o manifest\n" "[--xml=$xml-filename] typically 'havenTop.xml'\n" "[--json=$json-filename] the signing manifest\n" "[--format=bin|hex] output file format, hex is default\n" "[--signature=$sig-filename] replace signature with file content\n" - "[--hashes=$hashes-filename] destination file for intermediary hashes to be signed\n" + "[--hashes=$hashes-filename] destination file for intermediary " + "hashes to be signed\n" "[--randomfill] to pad image to 512K with random bits\n" "[--patternfill=N] to pad image to 512K with pattern N\n" - "[--writefuses=$xml-filename] to write out shortened xml\n" "[--verbose]\n", argv[0]); } int getOptions(int argc, char* argv[]) { static struct option long_options[] = { - // name, has_arg - {"format", required_argument, NULL, 'f'}, - {"help", no_argument, NULL, 'h'}, - {"input", required_argument, NULL, 'i'}, - {"json", required_argument, NULL, 'j'}, - {"key", required_argument, NULL, 'k'}, - {"output", required_argument, NULL, 'o'}, - {"verbose", no_argument, NULL, 'v'}, - {"xml", required_argument, NULL, 'x'}, - {"signature", required_argument, NULL, 's'}, - {"hashes", required_argument, NULL, 'H'}, - {"randomfill", no_argument, NULL, 'r'}, - {"patternfill", required_argument, NULL, 'p'}, - {"writefuses", required_argument, NULL, 'w'}, - {0, 0, 0, 0} - }; + // name, has_arg + {"cros", no_argument, NULL, 'c'}, + {"format", required_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, + {"input", required_argument, NULL, 'i'}, + {"json", required_argument, NULL, 'j'}, + {"key", required_argument, NULL, 'k'}, + {"output", required_argument, NULL, 'o'}, + {"verbose", no_argument, NULL, 'v'}, + {"xml", required_argument, NULL, 'x'}, + {"signature", required_argument, NULL, 's'}, + {"hashes", required_argument, NULL, 'H'}, + {"randomfill", no_argument, NULL, 'r'}, + {"patternfill", required_argument, NULL, 'p'}, + {"writefuses", required_argument, NULL, 'w'}, + {0, 0, 0, 0}}; int c, option_index = 0; outputFormat.assign("hex"); - while ((c = getopt_long(argc, argv, "i:o:p:k:x:j:f:s:H:w:hvr", - long_options, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "i:o:p:k:x:j:f:s:H:chvr", long_options, + &option_index)) != -1) { switch (c) { case 0: fprintf(stderr, "option %s", long_options[option_index].name); if (optarg) fprintf(stderr, " with arg %s", optarg); fprintf(stderr, "\n"); break; + case 'c': + FLAGS_cros = true; + break; case 'i': inputFilename.assign(optarg); break; @@ -410,9 +353,6 @@ int getOptions(int argc, char* argv[]) { case 'x': xmlFilename.assign(optarg); break; - case 'w': - xmlOutputFilename.assign(optarg); - break; case 's': signatureFilename.assign(optarg); break; @@ -444,9 +384,7 @@ int getOptions(int argc, char* argv[]) { return 1; } } - if (inputFilename.empty() || - outputFilename.empty() || - keyFilename.empty() || + if (inputFilename.empty() || outputFilename.empty() || keyFilename.empty() || ((outputFormat != "bin") && (outputFormat != "hex"))) { usage(argc, argv); return 1; @@ -476,8 +414,10 @@ int main(int argc, char* argv[]) { hdr.ro_base = image.ro_base(); hdr.ro_max = image.ro_max(); hdr.rx_base = image.rx_base(); - hdr.rx_max = image.rx_max() + 12; // TODO: m3 I prefetch sets off GLOBALSEC when too tight - // make sure these are nops or such? + hdr.rx_max = + image.rx_max() + + 12; // TODO: m3 instruction prefetch sets off GLOBALSEC when too tight + // make sure these are nops or such? hdr.timestamp_ = time(NULL); // Parse signing manifest. @@ -501,7 +441,8 @@ int main(int argc, char* argv[]) { } // Fill in more of hdr, per manifest values - for (map<string, uint32_t>::const_iterator it = values.begin(); it != values.end(); ++it) { + for (map<string, uint32_t>::const_iterator it = values.begin(); + it != values.end(); ++it) { VERBOSE("%s : %u\n", it->first.c_str(), it->second); } @@ -522,13 +463,21 @@ int main(int argc, char* argv[]) { FATAL("mismatched keyid JSON %d vs. key %d\n", values["keyid"], hdr.keyid); } + if (FLAGS_cros) { + if (!tag.empty()) { + FATAL("--cros whilst also specifying tag per manifest is a no go"); + } + tag = "\x01\x00\x00\x00"; // cros realm identifier in rwr[0] + } + // Fill in tag. VERBOSE("tag: \"%s\"\n", tag.c_str()); strncpy((char*)(&hdr.tag), tag.c_str(), sizeof(hdr.tag)); // List the specific fuses and values. VERBOSE("care about %lu fuses:\n", fuses.size()); - for (map<string, uint32_t>::const_iterator it = fuses.begin(); it != fuses.end(); ++it) { + for (map<string, uint32_t>::const_iterator it = fuses.begin(); + it != fuses.end(); ++it) { VERBOSE("fuse '%s' should have value %u\n", it->first.c_str(), it->second); } @@ -543,8 +492,7 @@ int main(int argc, char* argv[]) { } if (values["p4cl"] != xml_p4cl) { - FATAL("mismatching p4cl: xml %u vs. json %u\n", - xml_p4cl, values["p4cl"]); + FATAL("mismatching p4cl: xml %u vs. json %u\n", xml_p4cl, values["p4cl"]); } VERBOSE("found %lu fuse definitions\n", fuse_ids.size()); @@ -560,24 +508,18 @@ int main(int argc, char* argv[]) { fuse_ids["FW_DEFINED_DATA_EXTRA_BLK6"] = 125; fuse_bits["FW_DEFINED_DATA_EXTRA_BLK6"] = 5; - for (map<string, uint32_t>::const_iterator it = fuse_ids.begin(); it != fuse_ids.end(); ++it) { - VERBOSE("fuse '%s' at %u, width %u\n", - it->first.c_str(), it->second, fuse_bits[it->first]); - } - - // Write condensed XML if asked to. - if (!xmlOutputFilename.empty()) { - writeXML(xmlOutputFilename, - fuse_ids, - fuse_bits, - xml_p4cl); + for (map<string, uint32_t>::const_iterator it = fuse_ids.begin(); + it != fuse_ids.end(); ++it) { + VERBOSE("fuse '%s' at %u, width %u\n", it->first.c_str(), it->second, + fuse_bits[it->first]); } // Compute fuse_values array, according to manifest and xml. uint32_t fuse_values[FUSE_MAX]; for (size_t i = 0; i < FUSE_MAX; ++i) fuse_values[i] = FUSE_IGNORE; - for (map<string, uint32_t>::const_iterator x = fuses.begin(); x != fuses.end(); ++x) { + for (map<string, uint32_t>::const_iterator x = fuses.begin(); + x != fuses.end(); ++x) { map<string, uint32_t>::const_iterator it = fuse_ids.find(x->first); if (it == fuse_ids.end()) { FATAL("cannot find definition for fuse '%s'\n", x->first.c_str()); @@ -596,20 +538,18 @@ int main(int argc, char* argv[]) { } // Print out fuse hash input. - VERBOSE("expected fuse state:"); + VERBOSE("expected fuse state:\n"); for (size_t i = 0; i < FUSE_MAX; ++i) { - if (! (i % 8)) - VERBOSE("\n"); VERBOSE("%08x ", fuse_values[i]); } VERBOSE("\n"); - // Compute info_values array, according to manifest. uint32_t info_values[INFO_MAX]; for (size_t i = 0; i < INFO_MAX; ++i) info_values[i] = INFO_IGNORE; - for (map<string, uint32_t>::const_iterator x = infos.begin(); x != infos.end(); ++x) { + for (map<string, uint32_t>::const_iterator x = infos.begin(); + x != infos.end(); ++x) { uint32_t index = atoi(x->first.c_str()); assert(index < INFO_MAX); @@ -621,10 +561,8 @@ int main(int argc, char* argv[]) { // TODO: read values from JSON or implement version logic here. // Print out info hash input. - VERBOSE("expected info state:"); + VERBOSE("expected info state:\n"); for (size_t i = 0; i < INFO_MAX; ++i) { - if (! (i % 8)) - VERBOSE("\n"); VERBOSE("%08x ", info_values[i]); } VERBOSE("\n"); @@ -635,7 +573,8 @@ int main(int argc, char* argv[]) { int n = ::read(fd, hdr.signature, sizeof(hdr.signature)); ::close(fd); - if (n != sizeof(hdr.signature)) FATAL("cannot read from '%s'\n", signatureFilename.c_str()); + if (n != sizeof(hdr.signature)) + FATAL("cannot read from '%s'\n", signatureFilename.c_str()); VERBOSE("provided signature\n"); } else { diff --git a/util/signer/common/signed_header.h b/util/signer/common/signed_header.h index 82a6a7cbda..2012285f82 100644 --- a/util/signer/common/signed_header.h +++ b/util/signer/common/signed_header.h @@ -5,6 +5,10 @@ #ifndef __EC_UTIL_SIGNER_COMMON_SIGNED_HEADER_H #define __EC_UTIL_SIGNER_COMMON_SIGNED_HEADER_H +#include <assert.h> +#include <string.h> +#include <inttypes.h> + #define FUSE_PADDING 0x55555555 // baked in hw! #define FUSE_IGNORE 0xa3badaac // baked in rom! #define FUSE_MAX 128 // baked in rom! @@ -33,6 +37,9 @@ typedef struct SignedHeader { assert(n < INFO_MAX); infomap[n / 32] |= 1 << (n & 31); } + + void print() const { + } #endif // __cplusplus uint32_t magic; // -1 (thanks, boot_sys!) diff --git a/util/signer/gnubby.cc b/util/signer/gnubby.cc index 549daa319c..478d77470f 100644 --- a/util/signer/gnubby.cc +++ b/util/signer/gnubby.cc @@ -294,8 +294,7 @@ void getPIN(uint8_t* out) { static std::string tokenFilename(const uint8_t* fp) { const char* home = getenv("HOME"); - if (home == NULL) - home = getpwuid(getuid())->pw_dir; + if (home == NULL) getpwuid(getuid())->pw_dir; std::string s(home); s.append("/.tmp/"); for (int i = 0; i < 32; ++i) { @@ -568,10 +567,6 @@ int Gnubby::write_bn(uint8_t p1, BIGNUM* n, size_t length) { UCHAR resp[1024]; DWORD resp_len = 0; - if (!handle_) { - open(); - } - memcpy(req, "\x00\x66\x00\x00\x00\x00\x00", 7); req[2] = p1; req[5] = length >> 8; @@ -600,6 +595,11 @@ int Gnubby::write(RSA* rsa) { UCHAR resp[2048]; DWORD resp_len = 0; + if (!handle_) { + result = (open() != 1); + if (result) goto __fail; + } + // lock(100) result = gnubby_lock(handle_, (UCHAR)100); if (result != 0) goto __fail; @@ -627,7 +627,7 @@ int Gnubby::write(RSA* rsa) { __fail: // (always try to) unlock - gnubby_lock(handle_, 0); + if (handle_) gnubby_lock(handle_, 0); return result; } diff --git a/util/signer/image.cc b/util/signer/image.cc index 7945bf88d8..a2e4d5c2fc 100644 --- a/util/signer/image.cc +++ b/util/signer/image.cc @@ -2,20 +2,9 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <common/image.h> -// global C++ includes -#include <string> - -// global C includes -#include <assert.h> #include <fcntl.h> -#include <gelf.h> -#include <libelf.h> -#include <openssl/bn.h> -#include <openssl/evp.h> -#include <openssl/pem.h> -#include <openssl/rand.h> -#include <openssl/rsa.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> @@ -24,27 +13,51 @@ #include <sys/types.h> #include <unistd.h> -// local includes +#include <gelf.h> +#include <libelf.h> + #include <common/publickey.h> -#include <common/image.h> + +#include <openssl/bn.h> +#include <openssl/evp.h> +#include <openssl/pem.h> +#include <openssl/rand.h> +#include <openssl/rsa.h> + #include <common/signed_header.h> +#include <string> using namespace std; extern bool FLAGS_verbose; -#define VERBOSE(...) do{if(FLAGS_verbose)fprintf(stderr, __VA_ARGS__);}while(0) -#define WARN(...) do{fprintf(stderr, __VA_ARGS__);}while(0) -#define FATAL(...) do{fprintf(stderr, __VA_ARGS__);abort();}while(0) - -static const int FLASH_START = 0x40000; +#define VERBOSE(...) \ + do { \ + if (FLAGS_verbose) fprintf(stderr, __VA_ARGS__); \ + } while (0) +#define WARN(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + } while (0) +#define FATAL(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + abort(); \ + } while (0) + +static const int FLASH_START = 0x4000; static const int FLASH_END = FLASH_START + 512 * 1024; Image::Image() - : success_(true), low_(FLASH_END - FLASH_START), high_(0), - base_(0), ro_base_(FLASH_END), rx_base_(FLASH_END), - ro_max_(0), rx_max_(0) { + : success_(true), + low_(FLASH_END - FLASH_START), + high_(0), + base_(0), + ro_base_(FLASH_END * 16), + rx_base_(FLASH_END * 16), + ro_max_(0), + rx_max_(0) { memset(mem_, 0xff, sizeof(mem_)); // default memory content } @@ -78,9 +91,9 @@ bool Image::fromElf(const string& filename) { goto fail; } -// printf("Elf filesize: %lu\n", elf_stats.st_size); + // printf("Elf filesize: %lu\n", elf_stats.st_size); - if ((base_ptr = (char*) malloc(elf_stats.st_size)) == NULL) { + if ((base_ptr = (char*)malloc(elf_stats.st_size)) == NULL) { WARN("cannot malloc %lu\n", elf_stats.st_size); goto fail; } @@ -91,8 +104,8 @@ bool Image::fromElf(const string& filename) { } // Sniff content for sanity - if (*(uint32_t*) base_ptr != 0x464c457f) { -// WARN("'%s' is not elf file\n", filename); + if (*(uint32_t*)base_ptr != 0x464c457f) { + // WARN("'%s' is not elf file\n", filename); goto fail; } @@ -107,53 +120,49 @@ bool Image::fromElf(const string& filename) { gelf_getshdr(scn, &shdr); VERBOSE("type %08x; flags %08lx ", shdr.sh_type, shdr.sh_flags); - VERBOSE("%08lx(@%08lx)[%08lx] align %lu ", - shdr.sh_addr, shdr.sh_offset, shdr.sh_size, shdr.sh_addralign); + VERBOSE("%08lx(@%08lx)[%08lx] align %lu\n", shdr.sh_addr, shdr.sh_offset, + shdr.sh_size, shdr.sh_addralign); // Ignore sections that are not alloc if (!(shdr.sh_flags & SHF_ALLOC)) { - VERBOSE("non aloc, ignored\n"); continue; } // Ignore sections that are not exec if (!(shdr.sh_flags & SHF_EXECINSTR)) { - VERBOSE("non exec, ignored\n"); continue; } // Ignore sections outside our flash range - if (shdr.sh_addr < FLASH_START || - shdr.sh_addr + shdr.sh_size >= FLASH_END) { - VERBOSE("out of bounds, ignored\n"); + if (shdr.sh_addr < FLASH_START * 16 || + shdr.sh_addr + shdr.sh_size >= FLASH_END * 16) { continue; } - VERBOSE("\n"); - // Track rx boundaries if (shdr.sh_addr < rx_base_) { rx_base_ = shdr.sh_addr; } - if (shdr.sh_addr + shdr.sh_size> rx_max_) { + if (shdr.sh_addr + shdr.sh_size > rx_max_) { rx_max_ = shdr.sh_addr + shdr.sh_size; } } // Load image per program headers and track total ro segment for (int index = 0; gelf_getphdr(elf, index, &phdr); ++index) { - VERBOSE("phdr %08lx(@%08lx) [%08lx/%08lx]", - phdr.p_vaddr, phdr.p_paddr, phdr.p_filesz, phdr.p_memsz); + VERBOSE("phdr %08lx(@%08lx) [%08lx/%08lx]", phdr.p_vaddr, phdr.p_paddr, + phdr.p_filesz, phdr.p_memsz); - if (phdr.p_filesz != phdr.p_memsz) { - VERBOSE(" (size mismatch, not loading)\n"); + // Ignore sections outside our flash range + if (phdr.p_paddr < FLASH_START * 16 || + phdr.p_paddr + phdr.p_filesz >= FLASH_END * 16) { + VERBOSE(" (outside flash, skipped)\n"); continue; } - // Ignore sections outside our flash range - if (phdr.p_paddr < FLASH_START || - phdr.p_paddr + phdr.p_memsz >= FLASH_END) { - VERBOSE(" (out of bounds, not loading)\n"); + // Ignore p_offset 0, which ELF hdr; cannot be legit. + if (phdr.p_offset == 0) { + VERBOSE(" (offset 0, ignoring)\n"); continue; } @@ -169,8 +178,7 @@ bool Image::fromElf(const string& filename) { // Copy data into image for (size_t n = 0; n < phdr.p_filesz; ++n) { - store(phdr.p_paddr + n - FLASH_START, - base_ptr[phdr.p_offset + n]); + store(phdr.p_paddr + n - FLASH_START * 16, base_ptr[phdr.p_offset + n]); } } @@ -178,7 +186,7 @@ bool Image::fromElf(const string& filename) { base_ = low_; // Set ro_base to start, so app can read its own header. - ro_base_ = base_ + FLASH_START; + ro_base_ = base_ + FLASH_START * 16; // Set rx_base to just past header, where interrupt vectors are, // since fetching a vector gets done on the I bus. rx_base_ = ro_base_ + sizeof(SignedHeader); @@ -216,54 +224,53 @@ bool Image::fromIntelHex(const string& filename, bool withSignature) { continue; } if (line[7] != '0') { - WARN("unknown record type %s", line); - success_ = false; - } else switch (line[8]) { - case '1': { // 01 eof - } break; - case '2': { // 02 segment - if (!strncmp(line, ":02000002", 9)) { - char* p = line + 9; - int s = parseWord(&p); - if (s != 0x1000) { - if (s >= FLASH_START/16 && s <= FLASH_END/16) { - seg = s - FLASH_START/16; - //WARN("at segment %04x\n", seg); - } else { - WARN("data should fit in range %x-%x: %s\n", - FLASH_START, FLASH_END, line); - success_ = false; + WARN("unknown record type %s", line); + success_ = false; + } else + switch (line[8]) { + case '1': { // 01 eof + } break; + case '2': { // 02 segment + if (!strncmp(line, ":02000002", 9)) { + char* p = line + 9; + int s = parseWord(&p); + if (s != 0x1000) { + if (s >= FLASH_START && s <= FLASH_END) { + seg = s - FLASH_START; + // WARN("at segment %04x\n", seg); + } else { + WARN("data should in range %x-%x: %s\n", FLASH_START, + FLASH_END, line); + success_ = false; + } } } - } - isRam = !strcmp(line, ":020000021000EC"); - } break; - case '0': { // 00 data - char* p = line + 1; - int len = parseByte(&p); - int adr = parseWord(&p); - parseByte(&p); - while (len--) { - if (isRam) { - int v = parseByte(&p); - if (v != 0) { - WARN("WARNING: non-zero RAM byte %02x at %04x\n", - v, adr); - + isRam = !strcmp(line, ":020000021000EC"); + } break; + case '0': { // 00 data + char* p = line + 1; + int len = parseByte(&p); + int adr = parseWord(&p); + parseByte(&p); + while (len--) { + if (isRam) { + int v = parseByte(&p); + if (v != 0) { + WARN("WARNING: non-zero RAM byte %02x at %04x\n", v, adr); + } + ++adr; + } else { + store((seg * 16) + adr++, parseByte(&p)); } - ++adr; - } else { - store((seg * 16) + adr++, parseByte(&p)); } - } - } break; - case '3': { // 03 entry point - } break; - default: { - WARN("unknown record type %s", line); - success_ = false; - } break; - } + } break; + case '3': { // 03 entry point + } break; + default: { + WARN("unknown record type %s", line); + success_ = false; + } break; + } } fclose(fp); } else { @@ -290,14 +297,14 @@ bool Image::fromIntelHex(const string& filename, bool withSignature) { } if (success_) { - VERBOSE("low %08x, high %08x\n", - FLASH_START + low_, FLASH_START + high_); + VERBOSE("low %08x, high %08x\n", FLASH_START * 16 + low_, + FLASH_START * 16 + high_); // Round image to multiple of 2K. high_ = ((high_ + 2047) / 2048) * 2048; - ro_base_ = FLASH_START + base_; - rx_base_ = FLASH_START + base_; - ro_max_ = FLASH_START + base_ + size(); - rx_max_ = FLASH_START + base_ + size(); + ro_base_ = FLASH_START * 16 + base_; + rx_base_ = FLASH_START * 16 + base_; + ro_max_ = FLASH_START * 16 + base_ + size(); + rx_max_ = FLASH_START * 16 + base_ + size(); VERBOSE("base %08lx, size %08lx\n", ro_base_, size()); } @@ -306,20 +313,20 @@ bool Image::fromIntelHex(const string& filename, bool withSignature) { Image::~Image() {} -void Image::toIntelHex(FILE *fout) const { +void Image::toIntelHex(FILE* fout) const { for (int i = base_; i < high_; i += 16) { // spit out segment record at start of segment. - if (!((i - base_)&0xffff)) { - int s = FLASH_START/16 + (base_>>4) + ((i - base_)>>4); + if (!((i - base_) & 0xffff)) { + int s = FLASH_START + (base_ >> 4) + ((i - base_) >> 4); fprintf(fout, ":02000002%04X%02X\n", s, - (~((2 + 2 + (s>>8)) & 255) + 1) & 255); + (~((2 + 2 + (s >> 8)) & 255) + 1) & 255); } // spit out data records, 16 bytes each. - fprintf(fout, ":10%04X00", (i - base_)&0xffff); - int crc = 16 + (((i - base_)>>8)&255) + ((i - base_)&255); + fprintf(fout, ":10%04X00", (i - base_) & 0xffff); + int crc = 16 + (((i - base_) >> 8) & 255) + ((i - base_) & 255); for (int n = 0; n < 16; ++n) { - fprintf(fout, "%02X", mem_[i+n]); - crc += mem_[i+n]; + fprintf(fout, "%02X", mem_[i + n]); + crc += mem_[i + n]; } fprintf(fout, "%02X", (~(crc & 255) + 1) & 255); fprintf(fout, "\n"); @@ -327,7 +334,7 @@ void Image::toIntelHex(FILE *fout) const { } void Image::fillPattern(uint32_t pattern) { - for (int i = high_ - base_; i < 512*1024 - 2048; i += 4) { + for (int i = high_ - base_; i < 512 * 1024 - 2048; i += 4) { *(uint32_t*)(mem_ + i) = pattern; } high_ = 512 * 1024 - 2048; @@ -335,7 +342,7 @@ void Image::fillPattern(uint32_t pattern) { void Image::fillRandom() { srand(time(NULL)); - for (int i = high_ - base_; i < 512*1024 - 2048; i += 4) { + for (int i = high_ - base_; i < 512 * 1024 - 2048; i += 4) { *(uint32_t*)(mem_ + i) = rand(); } high_ = 512 * 1024 - 2048; @@ -352,18 +359,37 @@ void Image::generate(const std::string& filename, bool hex_output) const { fclose(fout); } - int Image::nibble(char n) { switch (n) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return n - '0'; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; + case 'a': + case 'A': + return 10; + case 'b': + case 'B': + return 11; + case 'c': + case 'C': + return 12; + case 'd': + case 'D': + return 13; + case 'e': + case 'E': + return 14; + case 'f': + case 'F': + return 15; default: WARN("bad hex digit '%c'\n", n); success_ = false; @@ -393,15 +419,14 @@ void Image::store(int adr, int v) { success_ = false; return; } + // VERBOSE("mem_[0x%08x]=0x%02x\n", adr, v&255); mem_[adr] = v; if (adr > high_) high_ = adr; if (adr < low_) low_ = adr; } -bool Image::sign(PublicKey& key, - const SignedHeader* input_hdr, - const uint32_t fuses[FUSE_MAX], - const uint32_t info[INFO_MAX], +bool Image::sign(PublicKey& key, const SignedHeader* input_hdr, + const uint32_t fuses[FUSE_MAX], const uint32_t info[INFO_MAX], const string& hashesFilename) { BIGNUM* sig = NULL; SignedHeader* hdr = (SignedHeader*)(&mem_[base_]); @@ -428,22 +453,16 @@ bool Image::sign(PublicKey& key, SHA256_Update(&sha256, fuses, FUSE_MAX * sizeof(uint32_t)); SHA256_Final(hashes.fuses_hash, &sha256); - hdr->fuses_chk_ = - (hashes.fuses_hash[0] << 0) - | (hashes.fuses_hash[1] << 8) - | (hashes.fuses_hash[2] << 16) - | (hashes.fuses_hash[3] << 24); + hdr->fuses_chk_ = (hashes.fuses_hash[0] << 0) | (hashes.fuses_hash[1] << 8) | + (hashes.fuses_hash[2] << 16) | (hashes.fuses_hash[3] << 24); // Hash info SHA256_Init(&sha256); SHA256_Update(&sha256, info, INFO_MAX * sizeof(uint32_t)); SHA256_Final(hashes.info_hash, &sha256); - hdr->info_chk_ = - (hashes.info_hash[0] << 0) - | (hashes.info_hash[1] << 8) - | (hashes.info_hash[2] << 16) - | (hashes.info_hash[3] << 24); + hdr->info_chk_ = (hashes.info_hash[0] << 0) | (hashes.info_hash[1] << 8) | + (hashes.info_hash[2] << 16) | (hashes.info_hash[3] << 24); // Hash img int size = this->size() - offsetof(SignedHeader, tag); @@ -451,11 +470,8 @@ bool Image::sign(PublicKey& key, SHA256_Update(&sha256, &hdr->tag, size); SHA256_Final(hashes.img_hash, &sha256); - hdr->img_chk_ = - (hashes.img_hash[0] << 0) - | (hashes.img_hash[1] << 8) - | (hashes.img_hash[2] << 16) - | (hashes.img_hash[3] << 24); + hdr->img_chk_ = (hashes.img_hash[0] << 0) | (hashes.img_hash[1] << 8) | + (hashes.img_hash[2] << 16) | (hashes.img_hash[3] << 24); // Dump out values for comparing against boot_rom VERBOSE("Himg ="); @@ -478,7 +494,7 @@ bool Image::sign(PublicKey& key, if (!hashesFilename.empty()) { // Write hashes to file for subsequent extraneous (re)signing. - int fd = open(hashesFilename.c_str(), O_CREAT|O_TRUNC|O_RDWR, 0600); + int fd = open(hashesFilename.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0600); if (fd >= 0) { write(fd, &hashes, sizeof(hashes)); close(fd); |