From 6d475ec4ab99d7ff912cc491b861ca40a07ecf26 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 14 Aug 2022 16:51:46 +0300 Subject: writeprotect.c: skip unnecessary writes * Don't write register because of RO and OTP bits. * Skip the write of RW bits if register state wouldn't change by it. Change-Id: I81d2d3fc0a103ee00ced78838d77fe33a9d3056a Signed-off-by: Sergii Dmytruk Reviewed-on: https://review.coreboot.org/c/flashrom/+/66754 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan Reviewed-by: Nikolai Artemiev --- writeprotect.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/writeprotect.c b/writeprotect.c index f72c362ba..3e8a83661 100644 --- a/writeprotect.c +++ b/writeprotect.c @@ -110,12 +110,16 @@ static enum flashrom_wp_result read_wp_bits(struct wp_bits *bits, struct flashct /** Helper function for write_wp_bits(). */ static void set_reg_bit( - uint8_t *reg_values, uint8_t *write_masks, + uint8_t *reg_values, uint8_t *bit_masks, uint8_t *write_masks, struct reg_bit_info bit, uint8_t value) { if (bit.reg != INVALID_REG) { reg_values[bit.reg] |= value << bit.bit_index; - write_masks[bit.reg] |= 1 << bit.bit_index; + bit_masks[bit.reg] |= 1 << bit.bit_index; + + /* Avoid RO and OTP bits causing a register update */ + if (bit.writability == RW) + write_masks[bit.reg] |= 1 << bit.bit_index; } } @@ -125,22 +129,23 @@ static enum flashrom_wp_result write_wp_bits(struct flashctx *flash, struct wp_b size_t i; const struct reg_bit_map *reg_bits = &flash->chip->reg_bits; - /* Convert wp_bits to register values and write masks */ + /* Convert wp_bits to register values and masks */ uint8_t reg_values[MAX_REGISTERS] = {0}; - uint8_t write_masks[MAX_REGISTERS] = {0}; + uint8_t bit_masks[MAX_REGISTERS] = {0}; /* masks of valid bits */ + uint8_t write_masks[MAX_REGISTERS] = {0}; /* masks of written bits */ for (i = 0; i < bits.bp_bit_count; i++) - set_reg_bit(reg_values, write_masks, reg_bits->bp[i], bits.bp[i]); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->bp[i], bits.bp[i]); - set_reg_bit(reg_values, write_masks, reg_bits->tb, bits.tb); - set_reg_bit(reg_values, write_masks, reg_bits->sec, bits.sec); - set_reg_bit(reg_values, write_masks, reg_bits->cmp, bits.cmp); - set_reg_bit(reg_values, write_masks, reg_bits->srp, bits.srp); - set_reg_bit(reg_values, write_masks, reg_bits->srl, bits.srl); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->tb, bits.tb); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->sec, bits.sec); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->cmp, bits.cmp); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->srp, bits.srp); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->srl, bits.srl); /* Note: always setting WPS bit to zero until its fully supported. */ - set_reg_bit(reg_values, write_masks, reg_bits->wps, 0); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->wps, 0); - /* Write each register */ + /* Write each register whose value was updated */ for (enum flash_reg reg = STATUS1; reg < MAX_REGISTERS; reg++) { if (!write_masks[reg]) continue; @@ -149,16 +154,22 @@ static enum flashrom_wp_result write_wp_bits(struct flashctx *flash, struct wp_b if (wp_read_register(flash, reg, &value)) return FLASHROM_WP_ERR_READ_FAILED; - value = (value & ~write_masks[reg]) | (reg_values[reg] & write_masks[reg]); + /* Skip unnecessary register writes */ + uint8_t actual = value & write_masks[reg]; + uint8_t expected = reg_values[reg] & write_masks[reg]; + if (actual == expected) + continue; + + value = (value & ~write_masks[reg]) | expected; if (wp_write_register(flash, reg, value)) return FLASHROM_WP_ERR_WRITE_FAILED; } enum flashrom_wp_result ret = FLASHROM_WP_OK; - /* Verify each register */ + /* Verify each register even if write to it was skipped */ for (enum flash_reg reg = STATUS1; reg < MAX_REGISTERS; reg++) { - if (!write_masks[reg]) + if (!bit_masks[reg]) continue; uint8_t value; @@ -166,8 +177,8 @@ static enum flashrom_wp_result write_wp_bits(struct flashctx *flash, struct wp_b return FLASHROM_WP_ERR_READ_FAILED; msg_cdbg2("%s: wp_verify reg:%u value:0x%x\n", __func__, reg, value); - uint8_t actual = value & write_masks[reg]; - uint8_t expected = reg_values[reg] & write_masks[reg]; + uint8_t actual = value & bit_masks[reg]; + uint8_t expected = reg_values[reg] & bit_masks[reg]; if (actual != expected) { msg_cdbg("%s: wp_verify failed: reg:%u actual:0x%x expected:0x%x\n", -- cgit v1.2.3