summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadim Taha <ntaha@google.com>2016-01-26 19:25:35 -0800
committerNadim Taha <ntaha@chromium.org>2016-01-28 20:58:32 +0000
commit8f39d1d51933d21fd243d54ac0f6daa87063ca0a (patch)
treec947861338c75061bb0c4f38e6673d2ee93b3d7a
parentf8f0618ca4baf7bee03bebefe083c3911a77e52b (diff)
downloadchrome-ec-8f39d1d51933d21fd243d54ac0f6daa87063ca0a.tar.gz
Modified the bootloader to check PMU_PWRDN_SCRATCH30 and load the newer
of the two RW images if set. Imported the Haven "signed_header.h" file into chip/g and fixed prior references to the util/ copy. BUG=none BRANCH=none TEST=Went through a full update. Simulated a botched update. Change-Id: I1e4c006ef391270a7e350fea6f43cc1a1b057d0e Signed-off-by: Nadim Taha <ntaha@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/324109 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--chip/g/loader/launch.c7
-rw-r--r--chip/g/loader/main.c54
-rw-r--r--chip/g/signed_header.h54
3 files changed, 108 insertions, 7 deletions
diff --git a/chip/g/loader/launch.c b/chip/g/loader/launch.c
index 3e41756ae9..56314bb46b 100644
--- a/chip/g/loader/launch.c
+++ b/chip/g/loader/launch.c
@@ -9,11 +9,10 @@
#include "registers.h"
#include "rom_flash.h"
#include "setup.h"
+#include "signed_header.h"
#include "uart.h"
#include "verify.h"
-#include "util/signer/common/signed_header.h"
-
static int unlockedForExecution(void)
{
return GREAD_FIELD(GLOBALSEC, SB_COMP_STATUS, SB_BL_SIG_MATCH);
@@ -44,7 +43,7 @@ void tryLaunch(uint32_t adr, size_t max_size)
int i;
uint32_t major;
const uint32_t FAKE_rom_hash[8] = {1, 2, 3, 4, 5, 6, 7, 8};
- const SignedHeader *hdr = (const SignedHeader *)(adr);
+ const struct SignedHeader *hdr = (const struct SignedHeader *)(adr);
memset(&hashes, 0, sizeof(hashes));
@@ -77,7 +76,7 @@ void tryLaunch(uint32_t adr, size_t max_size)
GWRITE_FIELD(GLOBALSEC, CPU0_I_STAGING_REGION1_CTRL, EN, 1);
GWRITE_FIELD(GLOBALSEC, CPU0_I_STAGING_REGION1_CTRL, RD_EN, 1);
DCRYPTO_SHA256_hash((uint8_t *) &hdr->tag,
- hdr->image_size - offsetof(SignedHeader, tag),
+ hdr->image_size - offsetof(struct SignedHeader, tag),
(uint8_t *) hashes.img_hash);
VERBOSE("img_hash : %.32h\n", hashes.img_hash);
diff --git a/chip/g/loader/main.c b/chip/g/loader/main.c
index afa4d0067a..d3b60dd91c 100644
--- a/chip/g/loader/main.c
+++ b/chip/g/loader/main.c
@@ -8,6 +8,7 @@
#include "printf.h"
#include "registers.h"
#include "setup.h"
+#include "signed_header.h"
#include "system.h"
#include "trng.h"
#include "uart.h"
@@ -59,8 +60,27 @@ void panic_printf(const char *format, ...)
va_end(args);
}
+/* Returns 1 if version a is newer, 0 otherwise. */
+int is_newer_than(const struct SignedHeader *a, const struct SignedHeader *b)
+{
+ if (a->epoch_ > b->epoch_)
+ return 1;
+ if (a->epoch_ < b->epoch_)
+ return 0;
+ if (a->major_ > b->major_)
+ return 1;
+ if (a->major_ < b->major_)
+ return 0;
+ if (a->minor_ > b->minor_)
+ return 1;
+ if (a->minor_ < b->minor_)
+ return 0;
+ return 0;
+}
+
int main(void)
{
+ const struct SignedHeader *a, *b, *first, *second;
init_trng();
uart_init();
debug_printf("\n\n%s bootloader, %8u_%u@%u, %sUSB, %s crypto\n",
@@ -72,10 +92,38 @@ int main(void)
GC_CONST_SWDP_FPGA_CONFIG_NOUSB_CRYPTO) ? "full" : "8x8");
unlockFlashForRW();
- /* Trying RW A only for now */
- tryLaunch(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF,
- CONFIG_FLASH_SIZE/2 - CONFIG_RW_MEM_OFF);
+ a = (const struct SignedHeader *)(CONFIG_PROGRAM_MEMORY_BASE +
+ CONFIG_RW_MEM_OFF);
+ b = (const struct SignedHeader *)(CONFIG_PROGRAM_MEMORY_BASE +
+ CONFIG_RW_B_MEM_OFF);
+ /* Default to loading the older version first.
+ * Run from bank a if the versions are equal.
+ */
+ if (is_newer_than(a, b)) {
+ first = b;
+ second = a;
+ } else {
+ first = a;
+ second = b;
+ }
+ if (GREG32(PMU, PWRDN_SCRATCH30) == 0xcafebabe) {
+ /* Launch from the alternate bank first.
+ * This knob will be used to attempt to load the newer version
+ * after an update and to run from bank b in the face of flash
+ * integrity issues.
+ */
+ debug_printf("PWRDN_SCRATCH30 set to magic value\n");
+ GREG32(PMU, PWRDN_SCRATCH30) = 0x0;
+ a = first;
+ first = second;
+ second = a;
+ }
+ tryLaunch((uint32_t)first, CONFIG_FLASH_SIZE/2 - CONFIG_RW_MEM_OFF);
+ debug_printf("Failed to launch.\n");
+ debug_printf("Attempting to load the alternate image.\n");
+ tryLaunch((uint32_t)second, CONFIG_FLASH_SIZE/2 - CONFIG_RW_MEM_OFF);
debug_printf("No valid image found, not sure what to do...\n");
+ /* TODO: Some applications might want to reboot instead. */
halt();
return 1;
}
diff --git a/chip/g/signed_header.h b/chip/g/signed_header.h
new file mode 100644
index 0000000000..2da327c10d
--- /dev/null
+++ b/chip/g/signed_header.h
@@ -0,0 +1,54 @@
+/* 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 __CROS_EC_SIGNED_HEADER_H
+#define __CROS_EC_SIGNED_HEADER_H
+
+#include "compile_time_macros.h"
+
+#define FUSE_PADDING 0x55555555 /* baked in hw! */
+#define FUSE_IGNORE 0xa3badaac /* baked in rom! */
+#define FUSE_MAX 128 /* baked in rom! */
+
+#define INFO_MAX 128 /* baked in rom! */
+#define INFO_IGNORE 0xaa3c55c3 /* baked in rom! */
+
+struct SignedHeader {
+ uint32_t magic; /* -1 (thanks, boot_sys!) */
+ uint32_t signature[96];
+ uint32_t img_chk_; /* top 32 bit of expected img_hash */
+ /* --------------------- everything below is part of img_hash */
+ uint32_t tag[7]; /* words 0-6 of RWR/FWR */
+ uint32_t keyid; /* word 7 of RWR */
+ uint32_t key[96]; /* public key to verify signature with */
+ uint32_t image_size;
+ uint32_t ro_base; /* readonly region */
+ uint32_t ro_max;
+ uint32_t rx_base; /* executable region */
+ uint32_t rx_max;
+ uint32_t fusemap[FUSE_MAX / (8 * sizeof(uint32_t))];
+ uint32_t infomap[INFO_MAX / (8 * sizeof(uint32_t))];
+ uint32_t epoch_; /* word 7 of FWR */
+ uint32_t major_; /* keyladder count */
+ uint32_t minor_;
+ uint64_t timestamp_; /* time of signing */
+ uint32_t p4cl_;
+ /* bits to and with FUSE_FW_DEFINED_BROM_APPLYSEC */
+ uint32_t applysec_;
+ /* bits to mesh with FUSE_FW_DEFINED_BROM_CONFIG1 */
+ uint32_t config1_;
+ /* bits to or with FUSE_FW_DEFINED_BROM_ERR_RESPONSE */
+ uint32_t err_response_;
+ /* action to take when expectation is violated */
+ uint32_t expect_response_;
+ uint32_t _pad[256 - 1 - 96 - 1 - 7 - 1 - 96 -
+ 5*1 - 4 - 4 - 9*1 - 2 - 1];
+ uint32_t fuses_chk_; /* top 32 bit of expected fuses hash */
+ uint32_t info_chk_; /* top 32 bit of expected info hash */
+};
+
+BUILD_ASSERT(sizeof(struct SignedHeader) == 1024);
+BUILD_ASSERT(offsetof(struct SignedHeader, info_chk_) == 1020);
+
+#endif /* __CROS_EC_SIGNED_HEADER_H */