From 8f39d1d51933d21fd243d54ac0f6daa87063ca0a Mon Sep 17 00:00:00 2001 From: Nadim Taha Date: Tue, 26 Jan 2016 19:25:35 -0800 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/324109 Reviewed-by: Bill Richardson --- chip/g/loader/launch.c | 7 +++---- chip/g/loader/main.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--- chip/g/signed_header.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 chip/g/signed_header.h 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 */ -- cgit v1.2.1