Anastasia Klimchuk submitted this change.

View Change


Approvals: build bot (Jenkins): Verified Edward O'Callaghan: Looks good to me, approved Nikolai Artemiev: Looks good to me, but someone else must approve
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 <sergii.dmytruk@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/66754
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Nikolai Artemiev <nartemiev@google.com>
---
M writeprotect.c
1 file changed, 45 insertions(+), 17 deletions(-)

diff --git a/writeprotect.c b/writeprotect.c
index f72c362..3e8a836 100644
--- a/writeprotect.c
+++ b/writeprotect.c
@@ -110,12 +110,16 @@

/** 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 @@
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 @@
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 @@
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",

To view, visit change 66754. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I81d2d3fc0a103ee00ced78838d77fe33a9d3056a
Gerrit-Change-Number: 66754
Gerrit-PatchSet: 5
Gerrit-Owner: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
Gerrit-Reviewer: Anastasia Klimchuk <aklm@chromium.org>
Gerrit-Reviewer: Edward O'Callaghan <quasisec@chromium.org>
Gerrit-Reviewer: Nico Huber <nico.h@gmx.de>
Gerrit-Reviewer: Nikolai Artemiev <nartemiev@google.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-MessageType: merged