DO NOT MERGE - Merge Android 10 into master
Bug: 139893257
Change-Id: Iefbd04396ee0ae07fc0f5abea3b34714ad893cee
diff --git a/.checkpatch.conf b/.checkpatch.conf
new file mode 100644
index 0000000..e8e9db6
--- /dev/null
+++ b/.checkpatch.conf
@@ -0,0 +1,7 @@
+# Not Linux, so don't expect a Linux tree.
+--no-tree
+
+# Ignore aspects we don't follow here.
+--ignore FILE_PATH_CHANGES
+--ignore GIT_COMMIT_ID
+--ignore SPLIT_STRING
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..d13eeba
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,2 @@
+BasedOnStyle: Google
+ColumnLimit: 80
diff --git a/BUILD b/BUILD
index 9c8b007..74f705e 100644
--- a/BUILD
+++ b/BUILD
@@ -5,6 +5,7 @@
"nugget/include/app_transport_test.h",
"nugget/include/application.h",
"nugget/include/avb.h",
+ "nugget/include/citadel_events.h",
"nugget/include/flash_layout.h",
"nugget/include/keymaster.h",
"nugget/include/signed_header.h",
diff --git a/citadel/updater/updater.cpp b/citadel/updater/updater.cpp
index 4a8549e..ec8fb3f 100644
--- a/citadel/updater/updater.cpp
+++ b/citadel/updater/updater.cpp
@@ -18,6 +18,7 @@
#include <vector>
#include <getopt.h>
+#include <inttypes.h>
#include <openssl/sha.h>
#include <stdarg.h>
#include <stddef.h>
@@ -30,6 +31,7 @@
/* From Nugget OS */
#include <application.h>
#include <app_nugget.h>
+#include <citadel_events.h>
#include <flash_layout.h>
#include <signed_header.h>
@@ -67,6 +69,7 @@
int id;
int repo_snapshot;
int stats;
+ int statsd;
int ro;
int rw;
int reboot;
@@ -80,6 +83,11 @@
char **selftest_args;
/* generic connection options */
const char *device;
+ int suzyq;
+ int board_id;
+ int event;
+ char **board_id_args;
+ int console;
} options;
enum no_short_opts_for_these {
@@ -87,6 +95,7 @@
OPT_ID,
OPT_REPO_SNAPSHOT,
OPT_STATS,
+ OPT_STATSD,
OPT_RO,
OPT_RW,
OPT_REBOOT,
@@ -97,9 +106,12 @@
OPT_ERASE,
OPT_AP_UART,
OPT_SELFTEST,
+ OPT_SUZYQ,
+ OPT_BOARD_ID,
+ OPT_EVENT,
};
-const char *short_opts = ":hvlV:fF:";
+const char *short_opts = ":hvlV:fF:c";
const struct option long_opts[] = {
/* name hasarg *flag val */
{"version", 0, NULL, 'v'},
@@ -109,6 +121,7 @@
{"repo_snapshot", 0, NULL, OPT_REPO_SNAPSHOT},
{"repo-snapshot", 0, NULL, OPT_REPO_SNAPSHOT},
{"stats", 0, NULL, OPT_STATS},
+ {"statsd", 0, NULL, OPT_STATSD},
{"ro", 0, NULL, OPT_RO},
{"rw", 0, NULL, OPT_RW},
{"reboot", 0, NULL, OPT_REBOOT},
@@ -124,6 +137,9 @@
{"ap_uart", 0, NULL, OPT_AP_UART},
{"ap-uart", 0, NULL, OPT_AP_UART},
{"selftest", 0, NULL, OPT_SELFTEST},
+ {"suzyq", 0, NULL, OPT_SUZYQ},
+ {"board_id", 0, NULL, OPT_BOARD_ID},
+ {"event", 0, NULL, OPT_EVENT},
#ifndef ANDROID
{"device", 1, NULL, OPT_DEVICE},
#endif
@@ -160,6 +176,8 @@
" -l, --long_version Display the full version info\n"
" --id Display the Citadel device ID\n"
" --stats Display Low Power stats\n"
+ " --statsd Display Low Power stats cached by citadeld\n"
+ "\n"
" -V SECTION Show Citadel headers for RO_A | RO_B | RW_A | RW_B\n"
" -f Show image file version info\n"
" -F SECTION Show file headers for RO_A | RO_B | RW_A | RW_B\n"
@@ -183,6 +201,13 @@
" --selftest [ARGS] Run one or more selftests. With no ARGS, it runs\n"
" a default suite. This command will consume all\n"
" following args, so run it alone for best results.\n"
+ "\n"
+ " --suzyq [0|1] Set the SuzyQable detection setting\n"
+ "\n"
+ " --board_id [TYPE FLAG] Get/Set board ID values\n"
+ "\n"
+ " --event [NUM] Get NUM pending event records (default 1)\n"
+ "\n"
#ifndef ANDROID
"\n"
"Options:\n"
@@ -512,7 +537,7 @@
hdr = reinterpret_cast<const struct SignedHeader*>(ptr);
printf("%s: %d.%d.%d/%08x %s\n", name,
hdr->epoch_, hdr->major_, hdr->minor_, be32toh(hdr->img_chk_),
- hdr->magic == MAGIC_VALID ? "ok" : "--");
+ hdr->magic == SIGNED_HEADER_MAGIC_CITADEL ? "ok" : "--");
}
static void show_rw_string(const char *name, const uint8_t *ptr)
@@ -522,10 +547,11 @@
if (v->cookie1 == CROS_EC_VERSION_COOKIE1 &&
v->cookie2 == CROS_EC_VERSION_COOKIE2 &&
- (v->hdr.magic == MAGIC_DEFAULT || v->hdr.magic == MAGIC_VALID)) {
+ (v->hdr.magic == SIGNED_HEADER_MAGIC_HAVEN ||
+ v->hdr.magic == SIGNED_HEADER_MAGIC_CITADEL)) {
printf("%s: %d.%d.%d/%s %s\n", name,
v->hdr.epoch_, v->hdr.major_, v->hdr.minor_, v->version,
- v->hdr.magic == MAGIC_VALID ? "ok" : "--");
+ v->hdr.magic == SIGNED_HEADER_MAGIC_CITADEL ? "ok" : "--");
} else {
printf("<invalid>\n");
}
@@ -600,7 +626,7 @@
{
uint32_t retval;
std::vector<uint8_t> buffer;
- buffer.reserve(1200);
+ buffer.reserve(2048);
retval = app.Call(NUGGET_PARAM_REPO_SNAPSHOT, buffer, &buffer);
@@ -611,6 +637,62 @@
return retval;
}
+uint32_t do_console(AppClient &app, int argc, char *argv[])
+{
+ std::vector<uint8_t> buffer;
+ uint32_t rv;
+ size_t got;
+
+ if (options.console < argc) {
+ char *s = argv[options.console];
+ char c;
+ do {
+ c = *s++;
+ buffer.push_back(c);
+ } while (c);
+ }
+
+ do {
+ buffer.reserve(4096);
+ rv = app.Call(NUGGET_PARAM_CONSOLE, buffer, &buffer);
+ got = buffer.size();
+
+ if (is_app_success(rv)){
+ buffer.push_back('\0');
+ printf("%s", buffer.data());
+ }
+
+ buffer.resize(0);
+ } while (rv == APP_SUCCESS && got > 0);
+
+ return rv;
+}
+
+static void print_stats(const struct nugget_app_low_power_stats *s)
+{
+ printf("hard_reset_count %" PRIu64 "\n", s->hard_reset_count);
+ printf("time_since_hard_reset %" PRIu64 "\n",
+ s->time_since_hard_reset);
+ printf("wake_count %" PRIu64 "\n", s->wake_count);
+ printf("time_at_last_wake %" PRIu64 "\n", s->time_at_last_wake);
+ printf("time_spent_awake %" PRIu64 "\n", s->time_spent_awake);
+ printf("deep_sleep_count %" PRIu64 "\n", s->deep_sleep_count);
+ printf("time_at_last_deep_sleep %" PRIu64 "\n",
+ s->time_at_last_deep_sleep);
+ printf("time_spent_in_deep_sleep %" PRIu64 "\n",
+ s->time_spent_in_deep_sleep);
+ if (s->time_at_ap_reset == UINT64_MAX)
+ printf("time_at_ap_reset 0x%" PRIx64 "\n", s->time_at_ap_reset);
+ else
+ printf("time_at_ap_reset %" PRIu64 "\n", s->time_at_ap_reset);
+ if (s->time_at_ap_bootloader_done == UINT64_MAX)
+ printf("time_at_ap_bootloader_done 0x%" PRIx64 "\n",
+ s->time_at_ap_bootloader_done);
+ else
+ printf("time_at_ap_bootloader_done %" PRIu64 "\n",
+ s->time_at_ap_bootloader_done);
+}
+
uint32_t do_stats(AppClient &app)
{
struct nugget_app_low_power_stats stats;
@@ -618,34 +700,53 @@
uint32_t retval;
buffer.reserve(sizeof(stats));
-
retval = app.Call(NUGGET_PARAM_GET_LOW_POWER_STATS, buffer, &buffer);
if (is_app_success(retval)) {
- if (buffer.size() < sizeof(stats)) {
- fprintf(stderr, "Only got %zd / %zd bytes back",
+ if (buffer.size() < sizeof(stats)) { // old firmware?
+ fprintf(stderr, "# only got %zd / %zd bytes back\n",
buffer.size(), sizeof(stats));
- return -1;
+ memset(&stats, 0, sizeof(stats));
}
-
- memcpy(&stats, buffer.data(), sizeof(stats));
-
- printf("hard_reset_count %" PRIu64 "\n", stats.hard_reset_count);
- printf("time_since_hard_reset %" PRIu64 "\n",
- stats.time_since_hard_reset);
- printf("wake_count %" PRIu64 "\n", stats.wake_count);
- printf("time_at_last_wake %" PRIu64 "\n", stats.time_at_last_wake);
- printf("time_spent_awake %" PRIu64 "\n", stats.time_spent_awake);
- printf("deep_sleep_count %" PRIu64 "\n", stats.deep_sleep_count);
- printf("time_at_last_deep_sleep %" PRIu64 "\n",
- stats.time_at_last_deep_sleep);
- printf("time_spent_in_deep_sleep %" PRIu64 "\n",
- stats.time_spent_in_deep_sleep);
+ memcpy(&stats, buffer.data(), std::min(sizeof(stats), buffer.size()));
+ print_stats(&stats);
}
return retval;
}
+#ifdef ANDROID
+uint32_t do_statsd(CitadeldProxyClient &client)
+{
+ struct nugget_app_low_power_stats stats;
+ std::vector<uint8_t> buffer;
+
+ buffer.reserve(sizeof(stats));
+ ::android::binder::Status s = client.Citadeld().getCachedStats(&buffer);
+
+ if (s.isOk()) {
+ if (buffer.size() < sizeof(stats)) { // old citadeld?
+ fprintf(stderr, "# only got %zd / %zd bytes back\n",
+ buffer.size(), sizeof(stats));
+ memset(&stats, 0, sizeof(stats));
+ }
+ memcpy(&stats, buffer.data(), std::min(sizeof(stats), buffer.size()));
+ print_stats(&stats);
+ } else {
+ printf("ERROR: binder exception %d\n", s.exceptionCode());
+ return APP_ERROR_IO;
+ }
+
+ return 0;
+}
+#else
+uint32_t do_statsd(NuggetClient &client)
+{
+ Error("citadeld isn't attached to this interface");
+ return APP_ERROR_BOGUS_ARGS;
+}
+#endif
+
uint32_t do_reboot(AppClient &app)
{
uint32_t retval;
@@ -740,6 +841,190 @@
return rv;
}
+static uint32_t do_suzyq(AppClient &app, int argc, char *argv[])
+{
+ int i, j;
+ std::vector<uint8_t> buffer;
+
+ for (i = options.suzyq; i < argc; i++) {
+ for (j = 0; argv[i][j]; j++) {
+ buffer.push_back(strtol(argv[i], NULL, 10));
+ }
+ }
+
+ buffer.reserve(1);
+ uint32_t rv = app.Call(NUGGET_PARAM_RDD_CFG, buffer, &buffer);
+
+ if (is_app_success(rv))
+ printf("Current SuzyQable detection setting is %d\n", buffer[0]);
+
+ return rv;
+}
+
+static void parse_hex_value(uint32_t *val, const char *str)
+{
+ char *e = 0;
+ uint32_t tmp = strtoul(str, &e, 16);
+
+ if (e && *e)
+ Error("Invalid arg: \"%s\"", str);
+ else
+ *val = tmp;
+}
+
+static void show_board_id(const struct nugget_app_board_id *id)
+{
+ printf("0x%08x 0x%08x 0x%08x # ", id->type, id->flag, id->inv);
+
+ if (id->type == 0xffffffff && id->flag == 0xffffffff &&
+ id->inv == 0xffffffff) {
+ printf("unset\n");
+ return;
+ }
+
+ if (id->type ^ ~id->inv) {
+ printf("corrupted\n");
+ return;
+ }
+
+ printf("%s, ", id->flag & 0x80 ? "MP" : "Pre-MP");
+ switch (id->flag & 0x7f) {
+ case 0x7f:
+ printf("DEVBOARD\n");
+ break;
+ case 0x7e:
+ printf("Proto1\n");
+ break;
+ case 0x7c:
+ printf("Proto2+\n");
+ break;
+ case 0x78:
+ printf("EVT1\n");
+ break;
+ case 0x70:
+ printf("EVT2+\n");
+ break;
+ case 0x60:
+ printf("DVT1\n");
+ break;
+ case 0x40:
+ printf("DVT2+\n");
+ break;
+ case 0x00:
+ printf("PVT/MP\n");
+ break;
+ default:
+ printf("(unknown)\n");
+ break;
+ }
+}
+
+static uint32_t do_board_id(AppClient &app, int argc, char *argv[])
+{
+ uint32_t rv;
+ std::vector<uint8_t> request;
+ std::vector<uint8_t> response(sizeof(struct nugget_app_board_id));
+ struct nugget_app_board_id board_id;
+ char answer = 0;
+
+ // User must input both board_type and board_flag to make a set request
+ if (argc - options.board_id >= 2) {
+ uint32_t tmp = 0;
+
+ parse_hex_value(&tmp, argv[options.board_id]);
+ board_id.type = tmp;
+
+ parse_hex_value(&tmp, argv[options.board_id + 1]);
+ board_id.flag = tmp;
+
+ // optional third arg must equal ~type to avoid confirmation
+ if (argc - options.board_id > 2) {
+ parse_hex_value(&tmp, argv[options.board_id + 2]);
+ board_id.inv = tmp;
+ } else {
+ board_id.inv = ~board_id.type;
+ }
+
+ // Any problems parsing args?
+ if (errorcnt)
+ return errorcnt;
+
+ // Confirm unless correct type_inv arg is given
+ if (argc - options.board_id == 2 || board_id.type ^ ~board_id.inv) {
+ printf("\nWriting Board ID: ");
+ show_board_id(&board_id);
+ printf("\nWARNING: Setting board-id is irreversible!\n");
+ printf("Are you sure? (y/n) ");
+ fflush(stdout);
+ scanf(" %c", &answer);
+ if (answer != 'y'){
+ Error("Operation cancelled");
+ return errorcnt;
+ }
+ board_id.inv = ~board_id.type;
+ printf("\n");
+ }
+
+ request.resize(sizeof(board_id));
+ memcpy(request.data(), &board_id, sizeof(board_id));
+ }
+
+ rv = app.Call(NUGGET_PARAM_BOARD_ID, request, &response);
+
+ if (is_app_success(rv)) {
+ memcpy(&board_id, response.data(), sizeof(board_id));
+ show_board_id(&board_id);
+ }
+
+ return rv;
+}
+
+static uint32_t do_event(AppClient &app, int argc, char *argv[])
+{
+ uint32_t rv;
+ int i, num = 1;
+
+ if (options.event < argc) {
+ num = atoi(argv[options.event]);
+ }
+
+ for (i = 0; i < num; i++) {
+ struct event_record evt;
+ std::vector<uint8_t> buffer;
+ buffer.reserve(sizeof(evt));
+
+ rv = app.Call(NUGGET_PARAM_GET_EVENT_RECORD, buffer, &buffer);
+
+ if (!is_app_success(rv)) {
+ // That check also displays any errors
+ break;
+ }
+
+ if (buffer.size() == 0) {
+ printf("-- no event_records --\n");
+ continue;
+ }
+
+ if (buffer.size() != sizeof(evt)) {
+ fprintf(stderr, "Error: expected %zd bytes, got %zd instead\n",
+ sizeof(evt), buffer.size());
+ rv = 1;
+ break;
+ }
+
+ /* We got an event, let's show it */
+ memcpy(&evt, buffer.data(), sizeof(evt));
+ uint64_t secs = evt.uptime_usecs / 1000000UL;
+ uint64_t usecs = evt.uptime_usecs - (secs * 1000000UL);
+ printf("event record %" PRIu64 "/%" PRIu64 ".%06" PRIu64 ": ",
+ evt.reset_count, secs, usecs);
+ printf("%d 0x%08x 0x%08x 0x%08x\n", evt.id,
+ evt.u.raw.w[0], evt.u.raw.w[1], evt.u.raw.w[2]);
+ }
+
+ return rv;
+}
+
static uint32_t do_erase(AppClient &app)
{
std::vector<uint8_t> data(sizeof(uint32_t));
@@ -863,6 +1148,11 @@
return 2;
}
+ if (options.statsd &&
+ do_statsd(client) != APP_SUCCESS) {
+ return 2;
+ }
+
if (options.repo_snapshot &&
do_repo_snapshot(app) != APP_SUCCESS) {
return 2;
@@ -902,6 +1192,26 @@
return 1;
}
+ if (options.suzyq &&
+ do_suzyq(app, argc, argv) != APP_SUCCESS) {
+ return 1;
+ }
+
+ if (options.board_id &&
+ do_board_id(app, argc, argv) != APP_SUCCESS) {
+ return 1;
+ }
+
+ if (options.console &&
+ do_console(app, argc, argv) != APP_SUCCESS) {
+ return 1;
+ }
+
+ if (options.event &&
+ do_event(app, argc, argv) != APP_SUCCESS) {
+ return 1;
+ }
+
return 0;
}
@@ -949,6 +1259,10 @@
options.section = parse_section(optarg);
got_action = 1;
break;
+ case 'c':
+ options.console = optind;
+ got_action = 1;
+ break;
case 'f':
options.file_version = 1;
need_file = 1;
@@ -971,6 +1285,10 @@
options.stats = 1;
got_action = 1;
break;
+ case OPT_STATSD:
+ options.statsd = 1;
+ got_action = 1;
+ break;
case OPT_RO:
options.ro = 1;
need_file = 1;
@@ -1012,6 +1330,19 @@
options.ap_uart = 1;
got_action = 1;
break;
+ case OPT_SUZYQ:
+ options.suzyq = optind;
+ got_action = 1;
+ break;
+ case OPT_BOARD_ID:
+ options.board_id = optind;
+ options.board_id_args = argv;
+ got_action = 1;
+ break;
+ case OPT_EVENT:
+ options.event = optind;
+ got_action = 1;
+ break;
case OPT_SELFTEST:
options.selftest = optind;
options.selftest_args = argv;
diff --git a/libnos_datagram/include/nos/device.h b/libnos_datagram/include/nos/device.h
index d3d6055..d4c29c3 100644
--- a/libnos_datagram/include/nos/device.h
+++ b/libnos_datagram/include/nos/device.h
@@ -23,7 +23,7 @@
#endif
/* Max data size for read/write.
- * TODO: Yes, it's a magic number. */
+ * Yes, it's a magic number. See b/37675056#comment8. */
#define MAX_DEVICE_TRANSFER 2044
struct nos_device_ops {
diff --git a/libnos_transport/WORKSPACE b/libnos_transport/WORKSPACE
index c9384bc..14884e6 100644
--- a/libnos_transport/WORKSPACE
+++ b/libnos_transport/WORKSPACE
@@ -1,11 +1,12 @@
workspace(name = "nugget_host_generic_libnos_transport")
-new_http_archive(
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
name = "gtest",
- url = "https://github.com/google/googletest/archive/release-1.8.0.zip",
- build_file = "../../../core/nugget/BUILD.gtest",
- sha256 = "f3ed3b58511efd272eb074a3a6d6fb79d7c2e6a0e374323d1e6bcbcc1ef141bf",
- strip_prefix = "googletest-release-1.8.0",
+ url = "https://github.com/google/googletest/archive/release-1.8.1.zip",
+ sha256 = "927827c183d01734cc5cfef85e0ff3f5a92ffe6188e0d18e909c5efebf28a0c7",
+ strip_prefix = "googletest-release-1.8.1",
)
local_repository(
diff --git a/libnos_transport/transport.c b/libnos_transport/transport.c
index 7dad955..551c89a 100644
--- a/libnos_transport/transport.c
+++ b/libnos_transport/transport.c
@@ -325,7 +325,7 @@
/* Tell the app to handle the request while also sending the command_info
* which will be ignored by the v0 protocol. */
- NLOGD("Write app %d command 0x%08x, crc %04x...", ctx->app_id, command, command_info.crc);
+ NLOGD("Send app %d go command 0x%08x", ctx->app_id, command);
if (0 != nos_device_write(ctx->dev, command, &command_info, sizeof(command_info))) {
NLOGE("Failed to send command datagram to app %d", ctx->app_id);
return APP_ERROR_IO;
diff --git a/nugget/include/app_nugget.h b/nugget/include/app_nugget.h
index 2c3d980..2e96c97 100644
--- a/nugget/include/app_nugget.h
+++ b/nugget/include/app_nugget.h
@@ -262,6 +262,54 @@
* @errors APP_ERROR_BOGUS_ARGS
*/
+#define NUGGET_PARAM_RDD_CFG 0x000e
+/*
+ * Set / Get Board ID
+ *
+ * This sets or gets the Board ID of the device.
+ *
+ * @param args <none> OR nugget_app_board_id
+ * @param arg_len 0 OR sizeof nugget_app_board_id
+ * @param reply struct nugget_app_board_id
+ * @param reply_len sizeof struct nugget_app_board_id
+ *
+ * @errors APP_ERROR_BOGUS_ARGS
+ */
+struct nugget_app_board_id {
+ uint32_t type;
+ uint32_t flag;
+ uint32_t inv; /* must equal ~type when setting */
+} __packed;
+#define NUGGET_PARAM_BOARD_ID 0x000f
+
+/*
+ * Enable/Disable the RDD SuzyQable Deteaction
+ *
+ * This always returns the current state of the RDD SuezyQable detection
+ * feature.
+ *
+ * The AP can request that the RDD SuezyQable detection to be disabled (0) or
+ * enabled (1).
+ *
+ * @param args 0 OR 1
+ * @param arg_len 0 OR 1 byte
+ * @param reply 0 OR 1 current state
+ * @param reply_len 1 byte
+ *
+ * @errors APP_ERROR_BOGUS_ARGS
+ */
+
+#define NUGGET_PARAM_GET_EVENT_RECORD 0x0010
+/*
+ * This retrieves one pending event_record (defined in citadel_events.h).
+ * If none are pending, it returns nothing.
+ *
+ * @param args <none>
+ * @param arg_len 0
+ * @param reply struct event_record
+ * @param reply_len sizeof struct event_record OR 0
+ */
+
/****************************************************************************/
/* Test related commands */
@@ -309,6 +357,8 @@
uint64_t deep_sleep_count;
uint64_t time_at_last_deep_sleep;
uint64_t time_spent_in_deep_sleep;
+ uint64_t time_at_ap_reset;
+ uint64_t time_at_ap_bootloader_done;
} __packed;
#define NUGGET_PARAM_GET_LOW_POWER_STATS 0x200
@@ -327,10 +377,7 @@
/* UNIMPLEMENTED */
/****************************************************************************/
-/* These are bringup / debug functions only.
- *
- * TODO(b/65067435): Remove all of these.
- */
+/* These are bringup / debug functions only. */
#define NUGGET_PARAM_READ32 0xF000
/*
@@ -363,6 +410,16 @@
* @param reply_len 0
*/
+#define NUGGET_PARAM_CONSOLE 0xF002
+/*
+ * Send optional command, return recent console output
+ *
+ * @param args command, if any
+ * @param arg_len sizeof(command)
+ * @param reply recent console output
+ * @param reply_len len(recent console output)
+ */
+
#ifdef __cplusplus
}
#endif
diff --git a/nugget/include/application.h b/nugget/include/application.h
index 6dd402a..ddc7600 100644
--- a/nugget/include/application.h
+++ b/nugget/include/application.h
@@ -76,6 +76,7 @@
/* Fake apps used only for testing */
#define APP_ID_AVB_TEST 0x11
#define APP_ID_TRANSPORT_TEST 0x12
+#define APP_ID_FACEAUTH_TEST 0x13
/* This app ID should only be used by tests. */
#define APP_ID_TEST 0xff
@@ -269,11 +270,11 @@
};
/*
- * TODO(b/66104849): Note that request and response buffers are transferred as
- * byte streams. However, if they will eventually represent structs, the usual
- * ABI alignment requirements will be required. Until we've declared all
- * applications structs in a union, we will need to align the buffers manually.
- * Use this to declare the uint8_t buffers until then:
+ * Note that request and response buffers are transferred as byte streams.
+ * However, if they will eventually represent structs, the usual ABI alignment
+ * requirements will be required. Until we've declared all applications structs
+ * in a union, we will need to align the buffers manually. Use this to declare
+ * the uint8_t buffers until then:
*/
#define __TRANSPORT_ALIGNED__ __attribute__((aligned(8)))
diff --git a/nugget/include/citadel_events.h b/nugget/include/citadel_events.h
new file mode 100644
index 0000000..336f3c5
--- /dev/null
+++ b/nugget/include/citadel_events.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __CROS_EC_INCLUDE_CITADEL_EVENTS_H
+#define __CROS_EC_INCLUDE_CITADEL_EVENTS_H
+
+#include <assert.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+/*
+ * When Citadel needs to tell the AP something without waiting to be asked, the
+ * process is as follows:
+ *
+ * 1. Citadel adds an event_record to its internal queue, then asserts
+ * the CTDL_AP_IRQ signal to notify the AP.
+ *
+ * 2. The AP (citadeld) requests pending events from Citadel until they've
+ * all been retrieved.
+ *
+ * 3. Citadel deasserts CTDL_AP_IRQ.
+ *
+ * Because we may want to compare the history and evolution of events over a
+ * long time and for multiple releases, we should only APPEND to this file
+ * instead of changing things.
+ */
+
+/* Please do not change the size of this struct */
+#define EVENT_RECORD_SIZE 64
+struct event_record {
+ uint64_t reset_count; /* zeroed by Citadel power cycle */
+ uint64_t uptime_usecs; /* since last Citadel reset */
+ uint32_t id;
+ union {
+ /* id-specific information goes here */
+ struct {
+ uint32_t intr_sts[3];
+ } alert;
+ struct {
+ uint32_t bad_thing;
+ } citadel;
+ struct {
+ uint32_t okay_thing;
+ } info;
+
+ /* uninterpreted */
+ union {
+ uint32_t w[11];
+ uint16_t h[22];
+ uint8_t b[44];
+ } raw;
+ } u;
+} __packed;
+/* Please do not change the size of this struct */
+static_assert(sizeof(struct event_record) == EVENT_RECORD_SIZE,
+ "Muting the Immutable");
+
+/*
+ * Event ID values live forever.
+ * Add to the list, but NEVER change or delete existing entries.
+*/
+enum event_id {
+ EVENT_NONE = 0, /* No valid event exists with this ID */
+ EVENT_ALERT = 1, /* Security alert reported */
+ EVENT_CITADEL = 2, /* Bad: panic, stack overflow, etc. */
+ EVENT_INFO = 3, /* FYI: normal reboot, etc. */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CROS_EC_INCLUDE_CITADEL_EVENTS_H */
diff --git a/nugget/include/flash_layout.h b/nugget/include/flash_layout.h
index 0e82c88..7d65705 100644
--- a/nugget/include/flash_layout.h
+++ b/nugget/include/flash_layout.h
@@ -18,8 +18,13 @@
*/
/* Flash is directly addressable */
+#if defined(CHIP_H1D1)
+#define CHIP_FLASH_BASE 0x80000
+#define CHIP_FLASH_SIZE (1024 * 1024)
+#else
#define CHIP_FLASH_BASE 0x40000
#define CHIP_FLASH_SIZE (512 * 1024)
+#endif
#define CHIP_FLASH_HALF (CHIP_FLASH_SIZE >> 1)
/* Each half has to leave room for the image's signed header */
diff --git a/nugget/include/signed_header.h b/nugget/include/signed_header.h
index 81be877..d98d456 100644
--- a/nugget/include/signed_header.h
+++ b/nugget/include/signed_header.h
@@ -1,15 +1,10 @@
-/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __EC_UTIL_SIGNER_COMMON_SIGNED_HEADER_H
#define __EC_UTIL_SIGNER_COMMON_SIGNED_HEADER_H
-/* This is citadel */
-#define CHIP_C
-#define MAGIC_DEFAULT (-1u)
-#define MAGIC_VALID (-2u)
-
#ifdef __cplusplus
#include <endian.h>
#include <stdio.h>
@@ -18,7 +13,6 @@
#include <assert.h>
#include <inttypes.h>
-#include <stdint.h>
#include <string.h>
#define FUSE_MAX 128
@@ -26,14 +20,21 @@
#define FUSE_PADDING 0x55555555
// B chips
-#define FUSE_IGNORE_B 0xa3badaac // baked in rom!
+#define FUSE_IGNORE_B 0xa3badaac // baked in rom!
#define INFO_IGNORE_B 0xaa3c55c3 // baked in rom!
// Citadel chips
-#define FUSE_IGNORE_C 0x3aabadac // baked in rom!
+#define FUSE_IGNORE_C 0x3aabadac // baked in rom!
#define INFO_IGNORE_C 0xa5c35a3c // baked in rom!
-#if defined(CHIP_C)
+// D2 chips
+#define FUSE_IGNORE_D 0xdaa3baca // baked in rom!
+#define INFO_IGNORE_D 0x5a3ca5c3 // baked in rom!
+
+#if defined(CHIP_D)
+#define FUSE_IGNORE FUSE_IGNORE_D
+#define INFO_IGNORE INFO_IGNORE_D
+#elif defined(CHIP_C)
#define FUSE_IGNORE FUSE_IGNORE_C
#define INFO_IGNORE INFO_IGNORE_C
#else
@@ -41,10 +42,17 @@
#define INFO_IGNORE INFO_IGNORE_B
#endif
+#define SIGNED_HEADER_MAGIC_HAVEN (-1u)
+#define SIGNED_HEADER_MAGIC_CITADEL (-2u)
+#define SIGNED_HEADER_MAGIC_D2 (-3u)
+
+/* Default value for _pad[] words */
+#define SIGNED_HEADER_PADDING 0x33333333
+
typedef struct SignedHeader {
#ifdef __cplusplus
SignedHeader()
- : magic(-1),
+ : magic(SIGNED_HEADER_MAGIC_HAVEN),
image_size(0),
epoch_(0x1337),
major_(0),
@@ -54,13 +62,20 @@
config1_(0),
err_response_(0),
expect_response_(0),
+ swap_mark({0, 0}),
dev_id0_(0),
dev_id1_(0) {
memset(signature, 'S', sizeof(signature));
memset(tag, 'T', sizeof(tag));
memset(fusemap, 0, sizeof(fusemap));
memset(infomap, 0, sizeof(infomap));
- memset(&_pad, '3', sizeof(_pad));
+ memset(&_pad, SIGNED_HEADER_PADDING, sizeof(_pad));
+ // Below all evolved out of _pad, thus must also be initialized to '3'
+ // for backward compatibility.
+ memset(&rw_product_family_, SIGNED_HEADER_PADDING,
+ sizeof(rw_product_family_));
+ memset(&u, SIGNED_HEADER_PADDING, sizeof(u));
+ memset(&board_id_, SIGNED_HEADER_PADDING, sizeof(board_id_));
}
void markFuse(uint32_t n) {
@@ -73,16 +88,48 @@
infomap[n / 32] |= 1 << (n & 31);
}
- static uint32_t fuseIgnore(bool c) {
- return c ? FUSE_IGNORE_C : FUSE_IGNORE_B;
+ static uint32_t fuseIgnore(bool c, bool d) {
+ return d ? FUSE_IGNORE_D : c ? FUSE_IGNORE_C : FUSE_IGNORE_B;
}
- static uint32_t infoIgnore(bool c) {
- return c ? INFO_IGNORE_C : INFO_IGNORE_B;
+ static uint32_t infoIgnore(bool c, bool d) {
+ return d ? INFO_IGNORE_D : c ? INFO_IGNORE_C : INFO_IGNORE_B;
+ }
+
+ bool plausible() const {
+ switch (magic) {
+ case SIGNED_HEADER_MAGIC_HAVEN:
+ case SIGNED_HEADER_MAGIC_CITADEL:
+ case SIGNED_HEADER_MAGIC_D2:
+ break;
+ default:
+ return false;
+ }
+ if (keyid == -1u) return false;
+ if (ro_base >= ro_max) return false;
+ if (rx_base >= rx_max) return false;
+ if (_pad[0] != SIGNED_HEADER_PADDING) return false;
+ return true;
}
void print() const {
- printf("hdr.magic : %08x\n", magic);
+ printf("hdr.magic : %08x (", magic);
+ switch (magic) {
+ case SIGNED_HEADER_MAGIC_HAVEN:
+ printf("Haven B");
+ break;
+ case SIGNED_HEADER_MAGIC_CITADEL:
+ printf("Citadel");
+ break;
+ case SIGNED_HEADER_MAGIC_D2:
+ printf("D2");
+ break;
+ default:
+ printf("?");
+ break;
+ }
+ printf(")\n");
+ printf("hdr.ro_base : %08x\n", ro_base);
printf("hdr.keyid : %08x\n", keyid);
printf("hdr.tag : ");
const uint8_t* p = reinterpret_cast<const uint8_t*>(&tag);
@@ -95,11 +142,6 @@
printf("hdr.minor : %08x\n", minor_);
printf("hdr.timestamp : %016" PRIx64 ", %s", timestamp_,
asctime(localtime(reinterpret_cast<const time_t*>(×tamp_))));
- printf("hdr.image_size : %08x\n", image_size);
- printf("hdr.ro_base : %08x\n", ro_base);
- printf("hdr.ro_max : %08x\n", ro_max);
- printf("hdr.rx_base : %08x\n", rx_base);
- printf("hdr.rx_max : %08x\n", rx_max);
printf("hdr.img_chk : %08x\n", be32toh(img_chk_));
printf("hdr.fuses_chk : %08x\n", be32toh(fuses_chk_));
printf("hdr.info_chk : %08x\n", be32toh(info_chk_));
@@ -108,8 +150,8 @@
printf("hdr.err_response : %08x\n", err_response_);
printf("hdr.expect_response: %08x\n", expect_response_);
- if (dev_id0_) printf("hdr.dev_id0 : %08x\n", dev_id0_);
- if (dev_id1_) printf("hdr.dev_id1 : %08x\n", dev_id1_);
+ if (dev_id0_) printf("hdr.dev_id0 : %08x (%d)\n", dev_id0_, dev_id0_);
+ if (dev_id1_) printf("hdr.dev_id1 : %08x (%d)\n", dev_id1_, dev_id1_);
printf("hdr.fusemap : ");
for (size_t i = 0; i < sizeof(fusemap) / sizeof(fusemap[0]); ++i) {
@@ -147,16 +189,48 @@
uint32_t config1_; // bits to mesh with FUSE_FW_DEFINED_BROM_CONFIG1
uint32_t err_response_; // bits to or with FUSE_FW_DEFINED_BROM_ERR_RESPONSE
uint32_t expect_response_; // action to take when expectation is violated
+
union {
- uint32_t
- _pad[256 - 1 - 96 - 1 - 7 - 1 - 96 - 5 * 1 - 4 - 4 - 9 * 1 - 2 - 1 - 2];
+ // 2nd FIPS signature (gnubby RW)
struct {
- // 2nd FIPS signature (gnubby RW)
uint32_t keyid;
uint32_t r[8];
uint32_t s[8];
} ext_sig;
- } _pad;
+
+ // FLASH trim override (D2 RO)
+ // iff config1_ & 65536
+ struct {
+ uint32_t FSH_SMW_SETTING_OPTION3;
+ uint32_t FSH_SMW_SETTING_OPTION2;
+ uint32_t FSH_SMW_SETTING_OPTIONA;
+ uint32_t FSH_SMW_SETTING_OPTIONB;
+ uint32_t FSH_SMW_SMP_WHV_OPTION1;
+ uint32_t FSH_SMW_SMP_WHV_OPTION0;
+ uint32_t FSH_SMW_SME_WHV_OPTION1;
+ uint32_t FSH_SMW_SME_WHV_OPTION0;
+ } fsh;
+ } u;
+
+ // Spare space
+ uint32_t _pad[5];
+
+ struct {
+ unsigned size : 12;
+ unsigned offset : 20;
+ } swap_mark;
+ uint32_t rw_product_family_; // 0 == PRODUCT_FAMILY_ANY
+ // Stored as (^SIGNED_HEADER_PADDING)
+ // TODO(ntaha): add reference to product family
+ // enum when available.
+
+ struct {
+ // CR50 board class locking
+ uint32_t type; // Board type
+ uint32_t type_mask; // Mask of board type bits to use.
+ uint32_t flags; // Flags
+ } board_id_;
+
uint32_t dev_id0_; // node id, if locked
uint32_t dev_id1_;
uint32_t fuses_chk_; // top 32 bit of expected fuses hash
diff --git a/nugget/proto/nugget/app/keymaster/keymaster_defs.proto b/nugget/proto/nugget/app/keymaster/keymaster_defs.proto
index 40ec84f..644a9b3 100644
--- a/nugget/proto/nugget/app/keymaster/keymaster_defs.proto
+++ b/nugget/proto/nugget/app/keymaster/keymaster_defs.proto
@@ -257,6 +257,15 @@
STRONGBOX = 2;
};
+// NOTE: these enum values must be kept in sync with the HAL,
+// as they are used in an HMAC calculation.
+enum HardwareAuthenticatorType {
+ HW_AUTH_NONE = 0;
+ HW_AUTH_PASSWORD = 1;
+ HW_AUTH_FINGERPRINT = 2;
+ // Additional entries must be powers of 2.
+};
+
enum KeyFormat {
X509 = 0; /* for public key export */
PKCS8 = 1; /* for asymmetric key pair import */
diff --git a/nugget/proto/nugget/app/protoapi/diagnostics_api.proto b/nugget/proto/nugget/app/protoapi/diagnostics_api.proto
index 0fe5327..f659acc 100644
--- a/nugget/proto/nugget/app/protoapi/diagnostics_api.proto
+++ b/nugget/proto/nugget/app/protoapi/diagnostics_api.proto
@@ -29,7 +29,7 @@
DiagnosticTest aes_tests = 2;
DiagnosticTest aes_performance = 3;
DiagnosticTest ana_batmon = 4;
- // TODO (skeys) add remaining applicable tests here
+ // TODO: add remaining applicable tests here
}
message DiagnosticActions {