summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2016-05-18 01:47:47 (GMT)
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2016-05-20 19:52:43 (GMT)
commit417c605c7006f27da9f6ff8d57aad6b0dcdbe7f1 (patch)
tree377fbbb4730f8ae332c541add6432e9eb138775e
parenta73bd53740c2badfa26fccfe711cc516ceb7a4e0 (diff)
downloaddepthcharge-firmware-edgar-7287.167.B.tar.gz
depthcharge-firmware-edgar-7287.167.B.tar.xz
ec: Erase + flash RW image in chunks of image_size / 2firmware-edgar-7287.167.B
On certain broken EC FW, if the end-of-image byte (0xea) isn't found anywhere in the EC writable region, we may watchdog while searching for it. Ensure that the end-of-image byte will always be found somewhere in the EC writable image by erasing and flashing half of the image at a time. BUG=chrome-os-partner:53370 BRANCH=strago,celes,cyan,edgar,reks,terra,ultima TEST=Manual on cyan. Modify cros_ec_flash_update_rw() to halt after either cros_ec_flash_erase() call. Update RW system FW, reboot system, and proceed to SW sync. Verify that after erase + halt, "reboot" on the EC console boots the AP into software sync once again (and doesn't watchdog). Also, verify that without halts present, SW sync completes successfully. Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Change-Id: I27406dcbb02cffd21513958f8e90c5015db41652 Reviewed-on: https://chromium-review.googlesource.com/345710 Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> (cherry picked from commit d0cf720f3a1141f94ce179dcf3936078590700d0) Reviewed-on: https://chromium-review.googlesource.com/346238
-rw-r--r--src/drivers/ec/cros/ec.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/src/drivers/ec/cros/ec.c b/src/drivers/ec/cros/ec.c
index 3ab2ee2..7c52002 100644
--- a/src/drivers/ec/cros/ec.c
+++ b/src/drivers/ec/cros/ec.c
@@ -799,6 +799,20 @@ static int cros_ec_flash_write_burst_size(int devidx)
info.write_block_size;
}
+/**
+ * Return erase block size
+ */
+static int cros_ec_flash_erase_block_size(int devidx)
+{
+ struct ec_response_flash_info info;
+
+ if (ec_command(EC_CMD_PASSTHRU_OFFSET(devidx) + EC_CMD_FLASH_INFO, 0,
+ NULL, 0, &info, sizeof(info)) < sizeof(info))
+ return 0;
+
+ return info.erase_block_size;
+}
+
int cros_ec_flash_write(int devidx, const uint8_t *data, uint32_t offset,
uint32_t size)
{
@@ -879,8 +893,8 @@ int cros_ec_flash_read(int devidx, uint8_t *data, uint32_t offset,
int cros_ec_flash_update_rw(int devidx, const uint8_t *image, int image_size)
{
- uint32_t rw_offset, rw_size;
- int ret;
+ uint32_t rw_offset, rw_size, rw_half;
+ int ret, erase_size;
if (cros_ec_flash_offset(devidx, EC_FLASH_REGION_RW,
&rw_offset, &rw_size))
@@ -896,16 +910,46 @@ int cros_ec_flash_update_rw(int devidx, const uint8_t *image, int image_size)
* presumably everything past that is 0xff's. But would still need to
* round up to the nearest multiple of erase size.
*/
- ret = cros_ec_flash_erase(devidx, rw_offset, rw_size);
+
+ /*
+ * crosbug.com/p/53370: Erase + flash the image in partitions of
+ * image_size / 2. If spontaneous power-down occurs, we will have
+ * at least half of a valid image, so EC image size detection will not
+ * watchdog.
+ */
+ erase_size = cros_ec_flash_erase_block_size(devidx);
+ if (erase_size == 0)
+ return -1;
+
+ /* Pad halfway point to erase block size */
+ rw_half = image_size / 2;
+ rw_half += (rw_half % erase_size == 0) ?
+ 0 : erase_size - (rw_half % erase_size);
+
+ if (image_size < rw_half)
+ return -1;
+
+ /* Erase the first half of RW */
+ ret = cros_ec_flash_erase(devidx, rw_offset, rw_half);
if (ret)
return ret;
- /* Write the image */
- ret = cros_ec_flash_write(devidx, image, rw_offset, image_size);
+ /* Write the first part of the image */
+ ret = cros_ec_flash_write(devidx, image, rw_offset, rw_half);
if (ret)
return ret;
- return 0;
+ /* Erase the second half of RW */
+ ret = cros_ec_flash_erase(devidx, rw_offset + rw_half,
+ rw_size - rw_half);
+ if (ret)
+ return ret;
+
+ /* Write the second part of the image */
+ ret = cros_ec_flash_write(devidx, image + rw_half,
+ rw_offset + rw_half, image_size - rw_half);
+
+ return ret;
}
int cros_ec_read_vbnvcontext(uint8_t *block)