Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/71680 )
Change subject: flashrom.c: squash subregion fix ......................................................................
flashrom.c: squash subregion fix
Change-Id: I0cce707ed88f6c4b600ba76926bb9e60b93e066b Signed-off-by: Edward O'Callaghan quasisec@google.com --- M flashrom.c 1 file changed, 82 insertions(+), 6 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/80/71680/1
diff --git a/flashrom.c b/flashrom.c index 62f38f8..6f5d54c 100644 --- a/flashrom.c +++ b/flashrom.c @@ -1187,6 +1187,65 @@ return chip - flashchips; }
+/* + * Gets the lowest erase granularity; it is used when + * deciding if the layout map needs to be adjusted such that erase boundaries + * match this granularity. Returns -1 if unsuccessful. + */ +static int get_required_erase_size(struct flashctx *flash) +{ + int i, erase_size_found = 0; + unsigned int required_erase_size; + /* + * Find eraseable block size for read alignment. + * FIXME: This assumes the smallest block erase size is useable + * by erase_and_write_flash(). + */ + required_erase_size = ~0; + for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { + struct block_eraser eraser = flash->chip->block_erasers[i]; + int j; + for (j = 0; j < NUM_ERASEREGIONS; j++) { + unsigned int size = eraser.eraseblocks[j].size; + if (size && (size < required_erase_size)) { + required_erase_size = size; + erase_size_found = 1; + } + } + } + /* likely an error in flashchips[] */ + if (!erase_size_found) { + msg_cerr("%s: No usable erase size found.\n", __func__); + return -1; + } + return required_erase_size; +} +static int round_to_erasable_block_boundary(const int required_erase_size, + const struct romentry *entry, + chipoff_t *rounded_start, + chipsize_t* rounded_len) { + unsigned int start_align, len_align; + const struct flash_region *region = &entry->region; + if (required_erase_size < 0) + return 1; + /* round down to nearest eraseable block boundary */ + start_align = region->start % required_erase_size; + *rounded_start = region->start - start_align; + /* round up to nearest eraseable block boundary */ + *rounded_len = region->end - *rounded_start + 1; + len_align = *rounded_len % required_erase_size; + if (len_align) + *rounded_len = *rounded_len + required_erase_size - len_align; + if (start_align || len_align) { + msg_gdbg("\n%s: Re-aligned partial read due to eraseable " + "block size requirement:\n\tstart: 0x%06x, " + "len: 0x%06x, aligned start: 0x%06x, len: 0x%06x\n", + __func__, region->start, region->end - region->start + 1, + *rounded_start, *rounded_len); + } + return 0; +} + /** * @brief Reads the included layout regions into a buffer. * @@ -1198,15 +1257,22 @@ * @return 0 on success, * 1 if any read fails. */ -static int read_by_layout(struct flashctx *const flashctx, uint8_t *const buffer) +static int read_by_layout(struct flashctx *const flashctx, uint8_t *const buffer, + bool align_to_erasable_block_boundary) { const struct flashrom_layout *const layout = get_layout(flashctx); const struct romentry *entry = NULL; + const int required_erase_size = get_required_erase_size(flashctx);
while ((entry = layout_next_included(layout, entry))) { const struct flash_region *region = &entry->region; - const chipoff_t region_start = region->start; - const chipsize_t region_len = region->end - region->start + 1; + chipoff_t region_start = region->start; + chipsize_t region_len = region->end - region->start + 1; + + if (align_to_erasable_block_boundary && + round_to_erasable_block_boundary(required_erase_size, entry, + ®ion_start, ®ion_len)) + return 1;
if (read_flash(flashctx, buffer + region_start, region_start, region_len)) return 1; @@ -1386,7 +1452,7 @@
if (info->curcontents) { msg_cinfo("Reading current flash chip contents... "); - if (read_by_layout(flashctx, info->curcontents)) { + if (read_by_layout(flashctx, info->curcontents, true)) { /* Now we are truly screwed. Read failed as well. */ msg_cerr("Can't read anymore! Aborting.\n"); /* We have no idea about the flash chip contents, so @@ -1990,7 +2056,7 @@ msg_cinfo("Reading flash... ");
int ret = 1; - if (read_by_layout(flashctx, buffer)) { + if (read_by_layout(flashctx, buffer, false)) { msg_cerr("Read operation failed!\n"); msg_cinfo("FAILED.\n"); goto _finalize_ret; @@ -2089,7 +2155,7 @@ } memcpy(curcontents, oldcontents, flash_size); } else { - if (read_by_layout(flashctx, curcontents)) { + if (read_by_layout(flashctx, curcontents, true)) { msg_cinfo("FAILED.\n"); goto _finalize_ret; }