diff options
author | Edward O'Callaghan <quasisec@google.com> | 2022-11-14 09:16:21 +1100 |
---|---|---|
committer | Anastasia Klimchuk <aklm@chromium.org> | 2023-01-26 20:43:25 +0000 |
commit | 7d888a30827ae4bfc72d3098204083598f375294 (patch) | |
tree | c8df38bd6ee4e73d732a8ba674fcb5a563a69cfa | |
parent | 7ffa626d1278a167c430c55891bbb6f979a5ab92 (diff) | |
download | flashrom-7d888a30827ae4bfc72d3098204083598f375294.tar.gz flashrom-7d888a30827ae4bfc72d3098204083598f375294.tar.bz2 flashrom-7d888a30827ae4bfc72d3098204083598f375294.zip |
flashrom.c: Supplement `chip->unlock()` calls with wp unlocking
The full writeprotect implementation has proper support and
ability to unlock flash over spi25_statusreg.c. Therefore if
the required bits are available for the given chip prefer
proper writeprotect support instead of adhoc spi25_statusreg.c
helpers.
BUG=b:237485865
BRANCH=none
TEST=Tested on grunt DUT (prog: sb600spi, flash: W25Q128.W):
`flashrom --wp-range 0x0,0x1000000 \
flashrom --wp-status # Result: range=0x0,0x1000000 \
flashrom -w random.bin # Result: success \
flashrom -v random.bin # Result: success \
flashrom --wp-status # Result: range=0x0,0x1000000`
TEST=Tested that chips without WP support can still be unlocked
by deleting decode_range for W25Q128.W flashchip and
retesting on the grunt DUT.
Change-Id: I74b3f5d3a17749ea60485b916b2d87467a5d8b2f
CoAuthored-by: Nikolai Artemiev <nartemiev@google.com>
Signed-off-by: Nikolai Artemiev <nartemiev@google.com>
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/69517
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
Reviewed-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
-rw-r--r-- | flashrom.c | 60 |
1 files changed, 56 insertions, 4 deletions
@@ -1907,6 +1907,53 @@ static int chip_safety_check(const struct flashctx *flash, int force, return 0; } +static int restore_flash_wp(struct flashctx *const flash, void *data) +{ + struct flashrom_wp_cfg *wp_cfg = data; + enum flashrom_wp_result ret = flashrom_wp_write_cfg(flash, wp_cfg); + flashrom_wp_cfg_release(wp_cfg); + + return (ret == FLASHROM_WP_OK) ? 0 : -1; +} + +static int save_initial_flash_wp(struct flashctx *const flash) +{ + struct flashrom_wp_cfg *initial_wp_cfg; + if (flashrom_wp_cfg_new(&initial_wp_cfg) != FLASHROM_WP_OK) + return -1; + + if (flashrom_wp_read_cfg(initial_wp_cfg, flash) != FLASHROM_WP_OK) { + flashrom_wp_cfg_release(initial_wp_cfg); + return -1; + } + + if (register_chip_restore(restore_flash_wp, flash, initial_wp_cfg)) { + flashrom_wp_cfg_release(initial_wp_cfg); + return -1; + } + return 0; +} + +static int unlock_flash_wp(struct flashctx *const flash) +{ + /* Save original WP state to be restored later */ + if (save_initial_flash_wp(flash)) + return -1; + + /* Disable WP */ + struct flashrom_wp_cfg *unlocked_wp_cfg; + if (flashrom_wp_cfg_new(&unlocked_wp_cfg) != FLASHROM_WP_OK) + return -1; + + flashrom_wp_set_range(unlocked_wp_cfg, 0, 0); + flashrom_wp_set_mode(unlocked_wp_cfg, FLASHROM_WP_MODE_DISABLED); + enum flashrom_wp_result ret = flashrom_wp_write_cfg(flash, unlocked_wp_cfg); + + flashrom_wp_cfg_release(unlocked_wp_cfg); + + return (ret == FLASHROM_WP_OK) ? 0 : -1; +} + int prepare_flash_access(struct flashctx *const flash, const bool read_it, const bool write_it, const bool erase_it, const bool verify_it) @@ -1927,10 +1974,16 @@ int prepare_flash_access(struct flashctx *const flash, /* Initialize chip_restore_fn_count before chip unlock calls. */ flash->chip_restore_fn_count = 0; - /* Given the existence of read locks, we want to unlock for read, - erase and write. */ - if (flash->chip->unlock) + /* Given the existence of read locks, we want to unlock for read, erase and write. */ + int ret = 1; + if (flash->chip->decode_range != NO_DECODE_RANGE_FUNC) { + ret = unlock_flash_wp(flash); + if (ret) + msg_cerr("Failed to unlock flash status reg with wp support.\n"); + } + if (ret && flash->chip->unlock) { flash->chip->unlock(flash); + } flash->address_high_byte = -1; flash->in_4ba_mode = false; @@ -1947,7 +2000,6 @@ int prepare_flash_access(struct flashctx *const flash, /* Enable/disable 4-byte addressing mode if flash chip supports it */ if (spi_chip_4ba(flash)) { - int ret; if (spi_master_4ba(flash)) ret = spi_enter_4ba(flash); else |