summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-03-20 21:32:33 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-03-22 22:01:54 -0700
commit9e931878cad2e55094713d7c7da4867533e40f4b (patch)
treee8066b4a76d6c100e67338c6785a31fdd831fb99
parent218f65dda650e775b9e28e5dee9704f6511e8a28 (diff)
downloadchrome-ec-9e931878cad2e55094713d7c7da4867533e40f4b.tar.gz
g: add code to corrupt new header until further notice and move rw to 0.0.19
With the rest of support in place, this patch adds code which would corrupt the headers received during firmware updates. The VENDOR_CC_TURN_UPDATE_ON vendor command will be required to enable the new images. Care should be taken that other commands operating on the inactive image header do not do anything with it before it was enabled, some code is being added for that. The minor RW version is being bumped up to 19 to clearly indicate that the device is expecting the vendor command to enable the new image (this is used by usb_updater when downloading the image without the -p or -u command line options). BRANCH=cr50 BUG=b:35580805 TEST=verified that the new image can be installed and started by the new usb_updater. - the inactive header after uploading with the -p option (the image_size field's offset is 0x32c): > md 0x84320 4 00084320: 00000000 00000000 80033800 00084000 rebooting the device does not start the new image. - the inactive header after uploading without the -p option: > md 0x84320 4 00084320: 00000000 00000000 00033800 00084000 the device running a DBG image reports the following in the end of the image update: [64.176780 FW update: done] turn_update_on: rebooting in 100 ms Change-Id: I4d763eb89c8b1a43a13697033201066779826e85 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/457678 Reviewed-by: Aaron Durbin <adurbin@chromium.org>
-rw-r--r--board/cr50/board.c50
-rw-r--r--chip/g/upgrade_fw.c17
-rw-r--r--util/signer/ec_RW-manifest-dev.json2
-rw-r--r--util/signer/ec_RW-manifest-prod.json2
4 files changed, 53 insertions, 18 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 5079af1f89..81b9c2c22e 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -115,6 +115,25 @@ int board_tpm_uses_spi(void)
return !!(board_properties & BOARD_SLAVE_CONFIG_SPI);
}
+/* Get header address of the backup RW copy. */
+const struct SignedHeader *get_other_rw_addr(void)
+{
+ if (system_get_image_copy() == SYSTEM_IMAGE_RW)
+ return (const struct SignedHeader *)
+ get_program_memory_addr(SYSTEM_IMAGE_RW_B);
+
+ return (const struct SignedHeader *)
+ get_program_memory_addr(SYSTEM_IMAGE_RW);
+}
+
+/* Return true if the other RW is not ready to run. */
+static int other_rw_is_inactive(void)
+{
+ const struct SignedHeader *header = get_other_rw_addr();
+
+ return !!(header->image_size & TOP_IMAGE_SIZE_BIT);
+}
+
/* I2C Port definition */
const struct i2c_port_t i2c_ports[] = {
{"master", I2C_PORT_MASTER, 100,
@@ -638,7 +657,15 @@ static void deferred_tpm_rst_isr(void)
device_state_changed(DEVICE_AP, DEVICE_STATE_ON))
hook_notify(HOOK_CHIPSET_RESUME);
- if (!reboot_request_posted) {
+ /*
+ * If no reboot request is posted, OR if the other RW's header is not
+ * ready to run - do not try rebooting the device, just reset the
+ * TPM.
+ *
+ * The inactive header will have to be restored by the appropriate
+ * vendor command, the device will be rebooted then.
+ */
+ if (!reboot_request_posted || other_rw_is_inactive()) {
/* Reset TPM, no need to wait for completion. */
tpm_reset_request(0, 0);
return;
@@ -1381,27 +1408,16 @@ static enum vendor_cmd_rc vc_invalidate_inactive_rw(enum vendor_cmd_cc code,
size_t input_size,
size_t *response_size)
{
- struct SignedHeader *header;
+ const struct SignedHeader *header;
uint32_t ctrl;
uint32_t base_addr;
uint32_t size;
const char zero[4] = {}; /* value to write to magic. */
- if (system_get_image_copy() == SYSTEM_IMAGE_RW) {
- header = (struct SignedHeader *)
- get_program_memory_addr(SYSTEM_IMAGE_RW_B);
- } else {
- header = (struct SignedHeader *)
- get_program_memory_addr(SYSTEM_IMAGE_RW);
- }
-
*response_size = 0;
- /*
- * First check to see if the inactive region has already been
- * invalidated.
- */
- if (!header->magic) {
- CPRINTS("%s: Inactive region already corrupted", __func__);
+
+ if (other_rw_is_inactive()) {
+ CPRINTS("%s: Inactive region is disabled", __func__);
return VENDOR_RC_SUCCESS;
}
@@ -1410,6 +1426,8 @@ static enum vendor_cmd_rc vc_invalidate_inactive_rw(enum vendor_cmd_cc code,
base_addr = GREG32(GLOBALSEC, FLASH_REGION6_BASE_ADDR);
size = GREG32(GLOBALSEC, FLASH_REGION6_SIZE);
+ header = get_other_rw_addr();
+
/* Enable RW access to the other header. */
GREG32(GLOBALSEC, FLASH_REGION6_BASE_ADDR) = (uint32_t) header;
GREG32(GLOBALSEC, FLASH_REGION6_SIZE) = 1023;
diff --git a/chip/g/upgrade_fw.c b/chip/g/upgrade_fw.c
index 17bffe5f4c..c9c2176265 100644
--- a/chip/g/upgrade_fw.c
+++ b/chip/g/upgrade_fw.c
@@ -383,6 +383,23 @@ void fw_upgrade_command_handler(void *body,
return;
}
+ if ((block_offset == valid_sections.ro_base_offset) ||
+ (block_offset == valid_sections.rw_base_offset)) {
+ /*
+ * This is the header coming, let's corrupt it so that it does
+ * not run until it's time to switch.
+ */
+ struct SignedHeader *header;
+
+ header = (struct SignedHeader *) upgrade_data;
+
+ /*
+ * Set the top bit of the size field. It will be impossible to
+ * run this image until this bit is erased.
+ */
+ header->image_size |= TOP_IMAGE_SIZE_BIT;
+ }
+
CPRINTF("%s: programming at address 0x%x\n", __func__,
block_offset + CONFIG_PROGRAM_MEMORY_BASE);
if (flash_physical_write(block_offset, body_size, upgrade_data)
diff --git a/util/signer/ec_RW-manifest-dev.json b/util/signer/ec_RW-manifest-dev.json
index 22cb6fa9b8..db6bbc3373 100644
--- a/util/signer/ec_RW-manifest-dev.json
+++ b/util/signer/ec_RW-manifest-dev.json
@@ -40,7 +40,7 @@
"timestamp": 0,
"epoch": 0, // FWR diversification contributor, 32 bits.
"major": 0, // FW2_HIK_CHAIN counter.
- "minor": 18, // Mostly harmless version field.
+ "minor": 19, // Mostly harmless version field.
"applysec": -1, // Mask to and with fuse BROM_APPLYSEC.
"config1": 13, // Which BROM_CONFIG1 actions to take before launching.
"err_response": 0, // Mask to or with fuse BROM_ERR_RESPONSE.
diff --git a/util/signer/ec_RW-manifest-prod.json b/util/signer/ec_RW-manifest-prod.json
index 47515f0a72..77bdf15828 100644
--- a/util/signer/ec_RW-manifest-prod.json
+++ b/util/signer/ec_RW-manifest-prod.json
@@ -44,7 +44,7 @@
"timestamp": 1,
"epoch": 0, // FWR diversification contributor, 32 bits.
"major": 0, // FW2_HIK_CHAIN counter.
- "minor": 18, // Mostly harmless version field.
+ "minor": 19, // Mostly harmless version field.
"applysec": -1, // Mask to and with fuse BROM_APPLYSEC.
"config1": 13, // Which BROM_CONFIG1 actions to take before launching.
"err_response": 0, // Mask to or with fuse BROM_ERR_RESPONSE.