Edward O'Callaghan has uploaded this change for review.

View Change

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,
+ &region_start, &region_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;
}

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

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I0cce707ed88f6c4b600ba76926bb9e60b93e066b
Gerrit-Change-Number: 71680
Gerrit-PatchSet: 1
Gerrit-Owner: Edward O'Callaghan <quasisec@chromium.org>
Gerrit-MessageType: newchange