Merge remote-tracking branch 'goog/upstream-master' into doodle_wip7
* goog/upstream-master:
libnos_transport: Don't show crc in log messages
Prepare Nugget OS to report problems to the AP
Remove meaningless output in citadel_updater
citadel_updater: Support NUGGET_PARAM_CONSOLE
keymaster: add defs for HardwareAuthToken
Track AP reset and HLOS boot times
signed_header: obfuscate chip name as D2
Bug: 131177129
Bug: 126618512
Bug: 129892600
Bug: 34946126
Test: manual
Change-Id: Iee164d45f9693e9204a05eb24c125d35dcbe61b9
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 8a3b3a4..9fd370c 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>
@@ -83,7 +85,9 @@
const char *device;
int suzyq;
int board_id;
+ int event;
char **board_id_args;
+ int console;
} options;
enum no_short_opts_for_these {
@@ -104,9 +108,10 @@
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'},
@@ -134,6 +139,7 @@
{"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
@@ -200,6 +206,8 @@
"\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"
@@ -629,19 +637,60 @@
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);
+ 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)
@@ -654,13 +703,12 @@
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));
+ memcpy(&stats, buffer.data(), std::min(sizeof(stats), buffer.size()));
print_stats(&stats);
}
@@ -670,27 +718,32 @@
#ifdef ANDROID
uint32_t do_statsd(CitadeldProxyClient &client)
{
- struct nugget_app_low_power_stats stats;
- std::vector<uint8_t> buffer;
+ struct nugget_app_low_power_stats stats;
+ std::vector<uint8_t> buffer;
- buffer.reserve(sizeof(stats));
- ::android::binder::Status s = client.Citadeld().getCachedStats(&buffer);
+ buffer.reserve(sizeof(stats));
+ ::android::binder::Status s = client.Citadeld().getCachedStats(&buffer);
- if (s.isOk()) {
- memcpy(&stats, buffer.data(), sizeof(stats));
- print_stats(&stats);
- } else {
- printf("ERROR: binder exception %d\n", s.exceptionCode());
- return APP_ERROR_IO;
+ 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;
+ return 0;
}
#else
uint32_t do_statsd(NuggetClient &client)
{
- Error("citadeld isn't attached to this interface");
- return APP_ERROR_BOGUS_ARGS;
+ Error("citadeld isn't attached to this interface");
+ return APP_ERROR_BOGUS_ARGS;
}
#endif
@@ -821,8 +874,6 @@
static void show_board_id(const struct nugget_app_board_id *id)
{
- uint8_t feature;
-
printf("0x%08x 0x%08x 0x%08x # ", id->type, id->flag, id->inv);
if (id->type == 0xffffffff && id->flag == 0xffffffff &&
@@ -836,18 +887,6 @@
return;
}
- feature = (id->type & 0xff000000) >> 24;
- switch (feature) {
- case 0x00:
- printf("Pixel 3, ");
- break;
- case 0x01:
- printf("Pixel 4, ");
- break;
- default:
- printf("feature 0x%2x, ", feature);
- }
-
printf("%s, ", id->flag & 0x80 ? "MP" : "Pre-MP");
switch (id->flag & 0x7f) {
case 0x7f:
@@ -940,6 +979,52 @@
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));
@@ -1117,6 +1202,16 @@
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;
}
@@ -1164,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;
@@ -1240,6 +1339,10 @@
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_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 2efeb07..2e96c97 100644
--- a/nugget/include/app_nugget.h
+++ b/nugget/include/app_nugget.h
@@ -299,6 +299,17 @@
* @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 */
@@ -346,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
@@ -397,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/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/signed_header.h b/nugget/include/signed_header.h
index 612d22e..d98d456 100644
--- a/nugget/include/signed_header.h
+++ b/nugget/include/signed_header.h
@@ -27,7 +27,7 @@
#define FUSE_IGNORE_C 0x3aabadac // baked in rom!
#define INFO_IGNORE_C 0xa5c35a3c // baked in rom!
-// Dauntless chips
+// D2 chips
#define FUSE_IGNORE_D 0xdaa3baca // baked in rom!
#define INFO_IGNORE_D 0x5a3ca5c3 // baked in rom!
@@ -44,7 +44,7 @@
#define SIGNED_HEADER_MAGIC_HAVEN (-1u)
#define SIGNED_HEADER_MAGIC_CITADEL (-2u)
-#define SIGNED_HEADER_MAGIC_DAUNTLESS (-3u)
+#define SIGNED_HEADER_MAGIC_D2 (-3u)
/* Default value for _pad[] words */
#define SIGNED_HEADER_PADDING 0x33333333
@@ -100,7 +100,7 @@
switch (magic) {
case SIGNED_HEADER_MAGIC_HAVEN:
case SIGNED_HEADER_MAGIC_CITADEL:
- case SIGNED_HEADER_MAGIC_DAUNTLESS:
+ case SIGNED_HEADER_MAGIC_D2:
break;
default:
return false;
@@ -121,8 +121,8 @@
case SIGNED_HEADER_MAGIC_CITADEL:
printf("Citadel");
break;
- case SIGNED_HEADER_MAGIC_DAUNTLESS:
- printf("Dauntless");
+ case SIGNED_HEADER_MAGIC_D2:
+ printf("D2");
break;
default:
printf("?");
@@ -198,7 +198,7 @@
uint32_t s[8];
} ext_sig;
- // FLASH trim override (Dauntless RO)
+ // FLASH trim override (D2 RO)
// iff config1_ & 65536
struct {
uint32_t FSH_SMW_SETTING_OPTION3;
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 */