Anastasia Klimchuk has uploaded this change for review.

View Change

flashrom.c: Delete legacy erase and write logic

Current code path for erase and write has been enabled in the tree
since May 2023, which is more than 1 year ago (15 months ago),
and legacy path has been disabled since the same time.

Current logic has been officially released in v1.4.0 in July 2024.

Change-Id: I08fd686fecf6a5313eea2d66b368661c664f4800
Signed-off-by: Anastasia Klimchuk <aklm@flashrom.org>
---
M flashrom.c
1 file changed, 0 insertions(+), 366 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/46/83846/1
diff --git a/flashrom.c b/flashrom.c
index dbf06cf..b0edcf8 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -36,8 +36,6 @@
#include "chipdrivers.h"
#include "erasure_layout.h"

-static bool use_legacy_erase_path = false;
-
const char flashrom_version[] = FLASHROM_VERSION;

static const struct programmer_entry *programmer = NULL;
@@ -1330,248 +1328,6 @@
}

typedef int (*erasefn_t)(struct flashctx *, unsigned int addr, unsigned int len);
-/**
- * @private
- *
- * For read-erase-write, `curcontents` and `newcontents` shall point
- * to buffers of the chip's size. Both are supposed to be prefilled
- * with at least the included layout regions of the current flash
- * contents (`curcontents`) and the data to be written to the flash
- * (`newcontents`).
- *
- * For erase, `curcontents` and `newcontents` shall be NULL-pointers.
- *
- * The `chipoff_t` values are used internally by `walk_by_layout()`.
- */
-struct walk_info {
- uint8_t *curcontents;
- const uint8_t *newcontents;
- chipoff_t region_start;
- chipoff_t region_end;
- chipoff_t erase_start;
- chipoff_t erase_end;
-};
-/* returns 0 on success, 1 to retry with another erase function, 2 for immediate abort */
-typedef int (*per_blockfn_t)(struct flashctx *, const struct walk_info *, erasefn_t, bool *);
-
-static int walk_eraseblocks(struct flashctx *const flashctx,
- struct walk_info *const info,
- const size_t erasefunction, const per_blockfn_t per_blockfn,
- bool *all_skipped)
-{
- int ret;
- size_t i, j;
- bool first = true;
- struct block_eraser *const eraser = &flashctx->chip->block_erasers[erasefunction];
-
- info->erase_start = 0;
- for (i = 0; i < NUM_ERASEREGIONS; ++i) {
- /* count==0 for all automatically initialized array
- members so the loop below won't be executed for them. */
- for (j = 0; j < eraser->eraseblocks[i].count; ++j, info->erase_start = info->erase_end + 1) {
- info->erase_end = info->erase_start + eraser->eraseblocks[i].size - 1;
-
- /* Skip any eraseblock that is completely outside the current region. */
- if (info->erase_end < info->region_start)
- continue;
- if (info->region_end < info->erase_start)
- break;
-
- /* Print this for every block except the first one. */
- if (first)
- first = false;
- else
- msg_cdbg(", ");
- msg_cdbg("0x%06"PRIx32"-0x%06"PRIx32":", info->erase_start, info->erase_end);
-
- erasefunc_t *erase_func = lookup_erase_func_ptr(eraser);
- ret = per_blockfn(flashctx, info, erase_func, all_skipped);
- if (ret)
- return ret;
- }
- if (info->region_end < info->erase_start)
- break;
- }
- msg_cdbg("\n");
- return 0;
-}
-
-static int walk_by_layout(struct flashctx *const flashctx, struct walk_info *const info,
- const per_blockfn_t per_blockfn, bool *all_skipped)
-{
- const struct flashrom_layout *const layout = get_layout(flashctx);
- const struct romentry *entry = NULL;
-
- *all_skipped = true;
- msg_cinfo("Erasing and writing flash chip... ");
-
- while ((entry = layout_next_included(layout, entry))) {
- const struct flash_region *region = &entry->region;
- info->region_start = region->start;
- info->region_end = region->end;
-
- size_t j;
- int error = 1; /* retry as long as it's 1 */
- for (j = 0; j < NUM_ERASEFUNCTIONS; ++j) {
- if (j != 0)
- msg_cinfo("Looking for another erase function.\n");
- msg_cdbg("Trying erase function %zi... ", j);
- if (check_block_eraser(flashctx, j, 1))
- continue;
-
- error = walk_eraseblocks(flashctx, info, j, per_blockfn, all_skipped);
- if (error != 1)
- break;
-
- if (info->curcontents) {
- msg_cinfo("Reading current flash chip contents... ");
- if (read_by_layout(flashctx, info->curcontents)) {
- /* 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
- retrying with another erase function is pointless. */
- error = 2;
- break;
- }
- msg_cinfo("done. ");
- }
- }
- if (error == 1)
- msg_cinfo("No usable erase functions left.\n");
- if (error) {
- msg_cerr("FAILED!\n");
- return 1;
- }
- }
- if (*all_skipped)
- msg_cinfo("\nWarning: Chip content is identical to the requested image.\n");
- msg_cinfo("Erase/write done.\n");
- return 0;
-}
-
-static int erase_block(struct flashctx *const flashctx,
- const struct walk_info *const info, const erasefn_t erasefn,
- bool *all_skipped)
-{
- const unsigned int erase_len = info->erase_end + 1 - info->erase_start;
- const bool region_unaligned = info->region_start > info->erase_start ||
- info->erase_end > info->region_end;
- uint8_t *backup_contents = NULL, *erased_contents = NULL;
- int ret = 2;
-
- /*
- * If the region is not erase-block aligned, merge current flash con-
- * tents into a new buffer `backup_contents`.
- */
- if (region_unaligned) {
- backup_contents = malloc(erase_len);
- erased_contents = malloc(erase_len);
- if (!backup_contents || !erased_contents) {
- msg_cerr("Out of memory!\n");
- ret = 1;
- goto _free_ret;
- }
- memset(backup_contents, ERASED_VALUE(flashctx), erase_len);
- memset(erased_contents, ERASED_VALUE(flashctx), erase_len);
-
- msg_cdbg("R");
- /* Merge data preceding the current region. */
- if (info->region_start > info->erase_start) {
- const chipoff_t start = info->erase_start;
- const chipsize_t len = info->region_start - info->erase_start;
- if (read_flash(flashctx, backup_contents, start, len)) {
- msg_cerr("Can't read! Aborting.\n");
- goto _free_ret;
- }
- }
- /* Merge data following the current region. */
- if (info->erase_end > info->region_end) {
- const chipoff_t start = info->region_end + 1;
- const chipoff_t rel_start = start - info->erase_start; /* within this erase block */
- const chipsize_t len = info->erase_end - info->region_end;
- if (read_flash(flashctx, backup_contents + rel_start, start, len)) {
- msg_cerr("Can't read! Aborting.\n");
- goto _free_ret;
- }
- }
- }
-
- ret = 1;
- *all_skipped = false;
-
- msg_cdbg("E");
-
- if (!flashctx->flags.skip_unwritable_regions) {
- if (check_for_unwritable_regions(flashctx, info->erase_start, erase_len))
- goto _free_ret;
- }
-
- unsigned int len;
- for (unsigned int addr = info->erase_start; addr < info->erase_start + erase_len; addr += len) {
- struct flash_region region;
- get_flash_region(flashctx, addr, &region);
-
- len = min(info->erase_start + erase_len, region.end + 1) - addr;
-
- if (region.write_prot) {
- msg_gdbg("%s: cannot erase inside %s region (%#08"PRIx32"..%#08"PRIx32"), skipping range (%#08x..%#08x).\n",
- __func__, region.name, region.start, region.end, addr, addr + len - 1);
- free(region.name);
- continue;
- }
-
- msg_gdbg("%s: %s region (%#08"PRIx32"..%#08"PRIx32") is writable, erasing range (%#08x..%#08x).\n",
- __func__, region.name, region.start, region.end, addr, addr + len - 1);
- free(region.name);
-
- if (erasefn(flashctx, addr, len))
- goto _free_ret;
- if (check_erased_range(flashctx, addr, len)) {
- msg_cerr("ERASE FAILED!\n");
- goto _free_ret;
- }
- }
-
-
- if (region_unaligned) {
- unsigned int starthere = 0, lenhere = 0, writecount = 0;
- /* get_next_write() sets starthere to a new value after the call. */
- while ((lenhere = get_next_write(erased_contents + starthere, backup_contents + starthere,
- erase_len - starthere, &starthere, flashctx->chip->gran))) {
- if (!writecount++)
- msg_cdbg("W");
- /* Needs the partial write function signature. */
- if (write_flash(flashctx, backup_contents + starthere,
- info->erase_start + starthere, lenhere))
- goto _free_ret;
- starthere += lenhere;
- }
- }
-
- ret = 0;
-
-_free_ret:
- free(erased_contents);
- free(backup_contents);
- return ret;
-}
-
-/**
- * @brief Erases the included layout regions.
- *
- * If there is no layout set in the given flash context, the whole chip will
- * be erased.
- *
- * @param flashctx Flash context to be used.
- * @return 0 on success,
- * 1 if all available erase functions failed.
- */
-static int erase_by_layout_legacy(struct flashctx *const flashctx)
-{
- struct walk_info info = { 0 };
- bool all_skipped = true;
- return walk_by_layout(flashctx, &info, &erase_block, &all_skipped);
-}

static int erase_by_layout_new(struct flashctx *const flashctx)
{
@@ -1618,129 +1374,9 @@

static int erase_by_layout(struct flashctx *const flashctx)
{
- if (use_legacy_erase_path)
- return erase_by_layout_legacy(flashctx);
return erase_by_layout_new(flashctx);
}

-static int read_erase_write_block(struct flashctx *const flashctx,
- const struct walk_info *const info, const erasefn_t erasefn,
- bool *all_skipped)
-{
- const chipsize_t erase_len = info->erase_end + 1 - info->erase_start;
- const bool region_unaligned = info->region_start > info->erase_start ||
- info->erase_end > info->region_end;
- const uint8_t *newcontents = NULL;
- int ret = 2;
-
- /*
- * If the region is not erase-block aligned, merge current flash con-
- * tents into `info->curcontents` and a new buffer `newc`. The former
- * is necessary since we have no guarantee that the full erase block
- * was already read into `info->curcontents`. For the latter a new
- * buffer is used since `info->newcontents` might contain data for
- * other unaligned regions that touch this erase block too.
- */
- if (region_unaligned) {
- msg_cdbg("R");
- uint8_t *const newc = malloc(erase_len);
- if (!newc) {
- msg_cerr("Out of memory!\n");
- return 1;
- }
- memcpy(newc, info->newcontents + info->erase_start, erase_len);
-
- /* Merge data preceding the current region. */
- if (info->region_start > info->erase_start) {
- const chipoff_t start = info->erase_start;
- const chipsize_t len = info->region_start - info->erase_start;
- if (read_flash(flashctx, newc, start, len)) {
- msg_cerr("Can't read! Aborting.\n");
- goto _free_ret;
- }
- memcpy(info->curcontents + start, newc, len);
- }
- /* Merge data following the current region. */
- if (info->erase_end > info->region_end) {
- const chipoff_t start = info->region_end + 1;
- const chipoff_t rel_start = start - info->erase_start; /* within this erase block */
- const chipsize_t len = info->erase_end - info->region_end;
- if (read_flash(flashctx, newc + rel_start, start, len)) {
- msg_cerr("Can't read! Aborting.\n");
- goto _free_ret;
- }
- memcpy(info->curcontents + start, newc + rel_start, len);
- }
-
- newcontents = newc;
- } else {
- newcontents = info->newcontents + info->erase_start;
- }
-
- ret = 1;
- bool skipped = true;
- uint8_t *const curcontents = info->curcontents + info->erase_start;
- const uint8_t erased_value = ERASED_VALUE(flashctx);
- if (!(flashctx->chip->feature_bits & FEATURE_NO_ERASE) &&
- need_erase(curcontents, newcontents, erase_len, flashctx->chip->gran, erased_value)) {
- if (erase_block(flashctx, info, erasefn, all_skipped))
- goto _free_ret;
- /* Erase was successful. Adjust curcontents. */
- memset(curcontents, erased_value, erase_len);
- skipped = false;
- }
-
- unsigned int starthere = 0, lenhere = 0, writecount = 0;
- /* get_next_write() sets starthere to a new value after the call. */
- while ((lenhere = get_next_write(curcontents + starthere, newcontents + starthere,
- erase_len - starthere, &starthere, flashctx->chip->gran))) {
- if (!writecount++)
- msg_cdbg("W");
- /* Needs the partial write function signature. */
- if (write_flash(flashctx, newcontents + starthere,
- info->erase_start + starthere, lenhere))
- goto _free_ret;
- starthere += lenhere;
- skipped = false;
- }
- if (skipped)
- msg_cdbg("S");
- else
- *all_skipped = false;
-
- /* Update curcontents, other regions with overlapping erase blocks
- might rely on this. */
- memcpy(curcontents, newcontents, erase_len);
- ret = 0;
-
-_free_ret:
- if (region_unaligned)
- free((void *)newcontents);
- return ret;
-}
-
-/**
- * @brief Writes the included layout regions from a given image.
- *
- * If there is no layout set in the given flash context, the whole image
- * will be written.
- *
- * @param flashctx Flash context to be used.
- * @param curcontents A buffer of full chip size with current chip contents of included regions.
- * @param newcontents The new image to be written.
- * @return 0 on success,
- * 1 if anything has gone wrong.
- */
-static int write_by_layout_legacy(struct flashctx *const flashctx,
- void *const curcontents, const void *const newcontents,
- bool *all_skipped)
-{
- struct walk_info info;
- info.curcontents = curcontents;
- info.newcontents = newcontents;
- return walk_by_layout(flashctx, &info, read_erase_write_block, all_skipped);
-}
-
static int write_by_layout_new(struct flashctx *const flashctx,
void *const curcontents, const void *const newcontents,
bool *all_skipped)
@@ -1780,8 +1416,6 @@
uint8_t *const curcontents, const uint8_t *const newcontents,
bool *all_skipped)
{
- if (use_legacy_erase_path)
- return write_by_layout_legacy(flashctx, curcontents, newcontents, all_skipped);
return write_by_layout_new(flashctx, curcontents, newcontents, all_skipped);
}


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

Gerrit-MessageType: newchange
Gerrit-Project: flashrom
Gerrit-Branch: main
Gerrit-Change-Id: I08fd686fecf6a5313eea2d66b368661c664f4800
Gerrit-Change-Number: 83846
Gerrit-PatchSet: 1
Gerrit-Owner: Anastasia Klimchuk <aklm@chromium.org>