diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2017-03-20 21:32:33 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-03-22 22:01:54 -0700 |
commit | 9e931878cad2e55094713d7c7da4867533e40f4b (patch) | |
tree | e8066b4a76d6c100e67338c6785a31fdd831fb99 | |
parent | 218f65dda650e775b9e28e5dee9704f6511e8a28 (diff) | |
download | chrome-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.c | 50 | ||||
-rw-r--r-- | chip/g/upgrade_fw.c | 17 | ||||
-rw-r--r-- | util/signer/ec_RW-manifest-dev.json | 2 | ||||
-rw-r--r-- | util/signer/ec_RW-manifest-prod.json | 2 |
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. |