[flashrom] [PATCH] Handle erase failure in partial write, clean up
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Tue Nov 30 01:42:46 CET 2010
Handle erase failure in partial write.
Clean up erase function checking.
Update a few comments and messages to improve readability.
The erase failure handling is a genuine bugfix which is needed on locked
down chipsets and in the unlikely case that write fails halfway through
or an incorrect chip definition is used.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
Index: flashrom-cleanup_erase_and_write/flashrom.c
===================================================================
--- flashrom-cleanup_erase_and_write/flashrom.c (Revision 1236)
+++ flashrom-cleanup_erase_and_write/flashrom.c (Arbeitskopie)
@@ -1429,57 +1429,84 @@
return 0;
}
+static int check_block_eraser(struct flashchip *flash, int k, int log)
+{
+ struct block_eraser eraser = flash->block_erasers[k];
+
+ if (log)
+ msg_cdbg("Looking at blockwise erase function %i... ", k);
+ if (!eraser.block_erase && !eraser.eraseblocks[0].count) {
+ if (log)
+ msg_cdbg("not defined. ");
+ return 1;
+ }
+ if (!eraser.block_erase && eraser.eraseblocks[0].count) {
+ if (log)
+ msg_cdbg("eraseblock layout is known, but no "
+ "matching block erase function found. ");
+ return 1;
+ }
+ if (eraser.block_erase && !eraser.eraseblocks[0].count) {
+ if (log)
+ msg_cdbg("block erase function found, but "
+ "eraseblock layout is unknown. ");
+ return 1;
+ }
+ return 0;
+}
+
int erase_and_write_flash(struct flashchip *flash, uint8_t *oldcontents, uint8_t *newcontents)
{
- int k, ret = 0, found = 0;
+ int k, ret = 0;
uint8_t *curcontents;
unsigned long size = flash->total_size * 1024;
+ int usable_erasefunctions = 0;
+ for (k = 0; k < NUM_ERASEFUNCTIONS; k++)
+ if (!check_block_eraser(flash, k, 0))
+ usable_erasefunctions++;
+ msg_cinfo("Erasing and writing flash chip... ");
+ if (!usable_erasefunctions) {
+ msg_cerr("ERROR: flashrom has no erase function for this flash "
+ "chip.\n");
+ return 1;
+ }
+
curcontents = (uint8_t *) malloc(size);
/* Copy oldcontents to curcontents to avoid clobbering oldcontents. */
memcpy(curcontents, oldcontents, size);
- msg_cinfo("Erasing and writing flash chip... ");
for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
- struct block_eraser eraser = flash->block_erasers[k];
-
- msg_cdbg("Looking at blockwise erase function %i... ", k);
- if (!eraser.block_erase && !eraser.eraseblocks[0].count) {
- msg_cdbg("not defined. "
- "Looking for another erase function.\n");
+ if (check_block_eraser(flash, k, 1) && usable_erasefunctions) {
+ msg_cdbg("Looking for another erase function.\n");
continue;
}
- if (!eraser.block_erase && eraser.eraseblocks[0].count) {
- msg_cdbg("eraseblock layout is known, but no "
- "matching block erase function found. "
- "Looking for another erase function.\n");
- continue;
- }
- if (eraser.block_erase && !eraser.eraseblocks[0].count) {
- msg_cdbg("block erase function found, but "
- "eraseblock layout is unknown. "
- "Looking for another erase function.\n");
- continue;
- }
- found = 1;
+ usable_erasefunctions--;
msg_cdbg("trying... ");
ret = walk_eraseregions(flash, k, &erase_and_write_block_helper, curcontents, newcontents);
msg_cdbg("\n");
/* If everything is OK, don't try another erase function. */
if (!ret)
break;
- /* FIXME: Reread the whole chip here so we know the current
- * chip contents? curcontents might be up to date, but this
- * code is only reached if something failed, and then we don't
- * know exactly what failed, and how.
+ /* Write/erase failed, so try to find out what the current chip
+ * contents are. If no usable erase functions remain, we could
+ * abort the loop instead of continuing, the effect is the same.
+ * The only difference is whether the reason for other unusable
+ * functions is printed or not. If in doubt, verbosity wins.
*/
+ if (!usable_erasefunctions)
+ continue;
+ if (flash->read(flash, curcontents, 0, size)) {
+ /* Now we are truly screwed. Read failed as well. */
+ msg_cerr("Can't read anymore!\n");
+ /* We have no idea about the flash chip contents, so
+ * retrying with another erase function is pointless.
+ */
+ break;
+ }
}
/* Free the scratchpad. */
free(curcontents);
- if (!found) {
- msg_cerr("ERROR: flashrom has no erase function for this flash chip.\n");
- return 1;
- }
if (ret) {
msg_cerr("FAILED!\n");
@@ -1827,18 +1854,15 @@
* preserved, but in that case we might perform unneeded erase which
* takes time as well.
*/
- msg_cdbg("Reading old flash chip contents...\n");
+ msg_cdbg("Reading current flash chip contents...\n");
if (flash->read(flash, oldcontents, 0, size)) {
ret = 1;
goto out;
}
- // This should be moved into each flash part's code to do it
- // cleanly. This does the job.
+ /* Build a new image from the given layout. */
handle_romentries(flash, oldcontents, newcontents);
- // ////////////////////////////////////////////////////////////
-
if (write_it) {
if (erase_and_write_flash(flash, oldcontents, newcontents)) {
msg_cerr("Uh oh. Erase/write failed. Checking if "
--
http://www.hailfinger.org/
More information about the flashrom
mailing list