Index: flashrom-always_read_no_scary_warning/flash.h
===================================================================
--- flashrom-always_read_no_scary_warning/flash.h	(Revision 1023)
+++ flashrom-always_read_no_scary_warning/flash.h	(Arbeitskopie)
@@ -562,7 +562,7 @@
 int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len);
 int erase_flash(struct flashchip *flash);
 struct flashchip *probe_flash(struct flashchip *first_flash, int force);
-int read_flash(struct flashchip *flash, char *filename);
+int read_flash_write_file(struct flashchip *flash, char *filename);
 void check_chip_supported(struct flashchip *flash);
 int check_max_decode(enum chipbustype buses, uint32_t size);
 int min(int a, int b);
Index: flashrom-always_read_no_scary_warning/cli_classic.c
===================================================================
--- flashrom-always_read_no_scary_warning/cli_classic.c	(Revision 1023)
+++ flashrom-always_read_no_scary_warning/cli_classic.c	(Arbeitskopie)
@@ -419,7 +419,7 @@
 				exit(1);
 			}
 			printf("Please note that forced reads most likely contain garbage.\n");
-			return read_flash(flashes[0], filename);
+			return read_flash_write_file(flashes[0], filename);
 		}
 		// FIXME: flash writes stay enabled!
 		programmer_shutdown();
Index: flashrom-always_read_no_scary_warning/flashrom.c
===================================================================
--- flashrom-always_read_no_scary_warning/flashrom.c	(Revision 1023)
+++ flashrom-always_read_no_scary_warning/flashrom.c	(Arbeitskopie)
@@ -1003,12 +1003,10 @@
 	return ret;
 }
 
-int read_flash(struct flashchip *flash, char *filename)
+int write_buf_to_file(unsigned char *buf, unsigned long size, char *filename)
 {
 	unsigned long numbytes;
 	FILE *image;
-	unsigned long size = flash->total_size * 1024;
-	unsigned char *buf = calloc(size, sizeof(char));
 
 	if (!filename) {
 		msg_gerr("Error: No filename specified.\n");
@@ -1018,23 +1016,32 @@
 		perror(filename);
 		exit(1);
 	}
-	msg_cinfo("Reading flash... ");
-	if (!flash->read) {
-		msg_cinfo("FAILED!\n");
-		msg_cerr("ERROR: flashrom has no read function for this flash chip.\n");
-		return 1;
-	} else
-		flash->read(flash, buf, 0, size);
 
 	numbytes = fwrite(buf, 1, size, image);
 	fclose(image);
-	free(buf);
 	msg_cinfo("%s.\n", numbytes == size ? "done" : "FAILED");
 	if (numbytes != size)
 		return 1;
 	return 0;
 }
 
+int read_flash_write_file(struct flashchip *flash, char *filename)
+{
+	unsigned long size = flash->total_size * 1024;
+	unsigned char *buf = calloc(size, sizeof(char));
+
+	msg_cinfo("Reading flash... ");
+	if (!flash->read) {
+		msg_cinfo("FAILED!\n");
+		msg_cerr("ERROR: flashrom has no read function for this flash chip.\n");
+		return 1;
+	}
+	if (flash->read(flash, buf, 0, size))
+		return 1;
+
+	return write_buf_to_file(buf, flash->total_size * 1024, filename);
+}
+
 /* This function shares a lot of its structure with erase_flash().
  * Even if an error is found, the function will keep going and check the rest.
  */
@@ -1169,6 +1176,19 @@
 	return ret;
 }
 
+void nonfatal_help_message(void)
+{
+	msg_gerr("Writing to the flash chip apparently didn't do anything.\n"
+		"This means we have to add special support for your board, "
+		  "programmer or flash chip.\n"
+		"Please report this on IRC at irc.freenode.net (channel "
+		  "#flashrom) or\n"
+		"mail flashrom@flashrom.org!\n"
+		"-------------------------------------------------------------"
+		  "------------------\n"
+		"You may now reboot or simply leave the machine running.\n");
+}
+
 void emergency_help_message(void)
 {
 	msg_gerr("Your flash chip is in an unknown state.\n"
@@ -1330,7 +1350,7 @@
  */
 int doit(struct flashchip *flash, int force, char *filename, int read_it, int write_it, int erase_it, int verify_it)
 {
-	uint8_t *buf;
+	uint8_t *buf, *oldflashcontents;
 	unsigned long numbytes;
 	FILE *image;
 	int ret = 0;
@@ -1338,7 +1358,31 @@
 
 	size = flash->total_size * 1024;
 	buf = (uint8_t *) calloc(size, sizeof(char));
+	oldflashcontents = (uint8_t *) calloc(size, sizeof(char));
 
+	/* FIXME: This ignores --noverify. */
+	if (read_it || write_it || erase_it) {
+		/* Useful for chips with read lock. */
+		if (flash->unlock)
+			flash->unlock(flash);
+
+		msg_cinfo("Reading flash... ");
+		if (!flash->read) {
+			msg_cinfo("FAILED!\n");
+			msg_cerr("ERROR: flashrom has no read function for "
+				 "this flash chip.\n");
+			msg_cerr("Aborting.\n");
+			programmer_shutdown();
+			return 1;
+		}
+		if (flash->read(flash, oldflashcontents, 0, size)) {
+			msg_cinfo("FAILED!\n");
+			msg_cerr("Aborting.\n");
+			programmer_shutdown();
+			return 1;
+		}
+	}
+
 	if (erase_it) {
 		if (flash->tested & TEST_BAD_ERASE) {
 			msg_cerr("Erase is not working on this chip. ");
@@ -1354,18 +1398,26 @@
 			flash->unlock(flash);
 
 		if (erase_flash(flash)) {
+			msg_cerr("Uh oh. Erase failed. Checking if anything "
+				 "changed.\n");
+			if (!flash->read(flash, buf, 0, size)) {
+				if (!memcmp(oldflashcontents, buf, size)) {
+					msg_cinfo("Good. It seems nothing was "
+						  "changed.\n");
+					nonfatal_help_message();
+					programmer_shutdown();
+					return 1;
+				}
+			}
 			emergency_help_message();
 			programmer_shutdown();
 			return 1;
 		}
 	} else if (read_it) {
-		if (flash->unlock)
-			flash->unlock(flash);
+		ret = write_buf_to_file(buf, flash->total_size * 1024, filename);
 
-		if (read_flash(flash, filename)) {
-			programmer_shutdown();
-			return 1;
-		}
+		programmer_shutdown();
+		return ret;
 	} else {
 		struct stat image_stat;
 
@@ -1421,8 +1473,7 @@
 		}
 	}
 
-	// This should be moved into each flash part's code to do it 
-	// cleanly. This does the job.
+	/* FIXME: handle_romentries should reuse oldflashcontents. */
 	handle_romentries(buf, flash);
 
 	// ////////////////////////////////////////////////////////////
@@ -1436,7 +1487,18 @@
 		}
 		ret = flash->write(flash, buf);
 		if (ret) {
-			msg_cerr("FAILED!\n");
+			msg_cerr("Uh oh. Write failed. Checking if anything "
+				 "changed.\n");
+			/* FIXME: Should we really reuse buf here? */
+			if (!flash->read(flash, buf, 0, size)) {
+				if (!memcmp(oldflashcontents, buf, size)) {
+					msg_cinfo("Good. It seems nothing was "
+						  "changed.\n");
+					nonfatal_help_message();
+					programmer_shutdown();
+					return 1;
+				}
+			}
 			emergency_help_message();
 			programmer_shutdown();
 			return 1;

