Attention is currently required from: Edward O'Callaghan.
Nikolai Artemiev would like Edward O'Callaghan to review this change.
flashrom: Check for flash access restricitons write_flash()
Make write_flash() skip unwritable regions if
FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS is true. If the flag is false
write operations that include an unwritable region will not write
anything and return an error.
BUG=b:260440773
BRANCH=none
TEST=flashrom -w on dedede (JSL)
Change-Id: Idacf0d5218da9d9929f4877fc7665fe608b87fe0
CoAuthored-by: Edward O'Callaghan <quasisec@google.com>
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Signed-off-by: Nikolai Artemiev <nartemiev@google.com>
---
M flashrom.c
1 file changed, 72 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/16/70516/1
diff --git a/flashrom.c b/flashrom.c
index 76a2801..7a77845 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -932,10 +932,58 @@
return NULL;
}
-static int write_flash(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
+/*
+ * write_flash - wrapper for flash->write() with additional high-level policy
+ *
+ * @param flash flash chip
+ * @param buf buffer to write to flash
+ * @param start start address in flash
+ * @param len number of bytes to write
+ * @return 0 on success,
+ * -1 if any write fails.
+ *
+ * This wrapper simplifies most cases when the flash chip needs to be written
+ * since policy decisions such as non-fatal error handling is centralized.
+ */
+static int write_flash(struct flashctx *flash, const uint8_t *buf,
+ unsigned int start, unsigned int len)
{
- write_func_t *write_func = lookup_write_func_ptr(flash->chip);
- return write_func(flash, buf, start, len);
+ unsigned int write_len;
+ for (unsigned int addr = start; addr < start + len; addr += write_len) {
+ struct flash_region region;
+ get_flash_region(flash, addr, ®ion);
+
+ write_len = min(start + len, region.end) - addr;
+ const uint8_t *rbuf = buf + addr - start;
+
+ if (region.write_prot) {
+ if (flash->flags.skip_unwritable_regions) {
+ msg_gdbg("%s: cannot write inside %s region (%#08x..%#08x), skipping (%#08x..%#08x).\n",
+ __func__, region.name, region.start, region.end - 1, addr, addr + write_len - 1);
+ continue;
+ } else {
+ msg_gerr("%s: cannot write inside %s region (%#08x..%#08x).\n",
+ __func__, region.name, region.start, region.end - 1);
+ free(region.name);
+ return -1;
+ }
+ }
+
+ msg_gdbg("%s: %s region (%#08x..%#08x) is writable, writing range (%#08x..%#08x).\n",
+ __func__, region.name, region.start, region.end - 1, addr, addr + write_len - 1);
+
+ write_func_t *write_func = lookup_write_func_ptr(flash->chip);
+ int ret = write_func(flash, rbuf, addr, write_len);
+ if (ret) {
+ msg_gerr("%s: failed to write (%#08x..%#08x).\n", __func__, addr, addr + write_len - 1);
+ free(region.name);
+ return -1;
+ }
+
+ free(region.name);
+ }
+
+ return 0;
}
typedef int (probe_func_t)(struct flashctx *flash);
To view, visit change 70516. To unsubscribe, or for help writing mail filters, visit settings.