summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-02-26 16:42:16 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-02-27 00:38:28 -0800
commitd1bf3aecfafcfc82cd7ff0233b6487f11b11c114 (patch)
tree2ad1ea4172375294217400707a069b8c9d4f0a45 /util
parentb47c1fed2027c45f3062705e0ee9943601bdeba7 (diff)
downloadchrome-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.cc257
-rw-r--r--util/signer/common/signed_header.h7
-rw-r--r--util/signer/gnubby.cc14
-rw-r--r--util/signer/image.cc288
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);