diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2016-05-18 01:47:47 (GMT) |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2016-05-19 22:58:34 (GMT) |
commit | d1011749a93a9b6c542e9bf94d16c8f8406bcdb0 (patch) | |
tree | c8fef6d9c7ece86d1f4abe776ce2d98b4b980951 | |
parent | 9e54e6353522d6910323714736cf906ed9f84ba4 (diff) | |
download | depthcharge-firmware-cyan-7287.57.B.tar.gz depthcharge-firmware-cyan-7287.57.B.tar.xz |
ec: Erase + flash RW image in chunks of image_size / 2firmware-cyan-7287.57.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/346134
-rw-r--r-- | src/drivers/ec/cros/ec.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/src/drivers/ec/cros/ec.c b/src/drivers/ec/cros/ec.c index 7e2505f..4388616 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) |