Print an error message on read errors and abort instead of proceeding anyway

Improve error checking in file write, chip read and chip verify.
Refactor the read routines a bit to split reading from file writing.

Log for a failed read:
[...]
Found chip "Winbond W25x16" (2048 KB, SPI) at physical address
0xffe00000.
Reading flash... Invalid OPCODE 0x03
Read operation failed!
FAILED.

Corresponding to flashrom svn r1079.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Stephen Kou <stephen@hyarros.com>
diff --git a/cli_classic.c b/cli_classic.c
index 8279cc2..a81a5a7 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -417,7 +417,7 @@
 				exit(1);
 			}
 			printf("Please note that forced reads most likely contain garbage.\n");
-			return read_flash(flashes[0], filename);
+			return read_flash_to_file(flashes[0], filename);
 		}
 		// FIXME: flash writes stay enabled!
 		programmer_shutdown();
diff --git a/flash.h b/flash.h
index a00ad21..cd7cb46 100644
--- a/flash.h
+++ b/flash.h
@@ -579,7 +579,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_to_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);
diff --git a/flashrom.c b/flashrom.c
index 259ce68..6077ae7 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -713,7 +713,12 @@
 		starthere = max(start, i * page_size);
 		/* Length of bytes in the range in this page. */
 		lenhere = min(start + len, (i + 1) * page_size) - starthere;
-		flash->read(flash, readbuf, starthere, lenhere);
+		ret = flash->read(flash, readbuf, starthere, lenhere);
+		if (ret) {
+			msg_gerr("Verification impossible because read failed "
+				 "at 0x%x (len 0x%x)\n", starthere, lenhere);
+			break;
+		}
 		for (j = 0; j < lenhere; j++) {
 			if (cmpbuf[starthere - start + j] != readbuf[j]) {
 				/* Only print the first failure. */
@@ -1064,38 +1069,60 @@
 	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");
+		msg_gerr("No filename specified.\n");
 		return 1;
 	}
 	if ((image = fopen(filename, "wb")) == NULL) {
 		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)
+	if (numbytes != size) {
+		msg_gerr("File %s could not be written completely.\n",
+			 filename);
 		return 1;
+	}
 	return 0;
 }
 
+int read_flash_to_file(struct flashchip *flash, char *filename)
+{
+	unsigned long size = flash->total_size * 1024;
+	unsigned char *buf = calloc(size, sizeof(char));
+	int ret = 0;
+
+	msg_cinfo("Reading flash... ");
+	if (!buf) {
+		msg_gerr("Memory allocation failed!\n");
+		msg_cinfo("FAILED.\n");
+		return 1;
+	}
+	if (!flash->read) {
+		msg_cerr("No read function available for this flash chip.\n");
+		ret = 1;
+		goto out_free;
+	}
+	if (flash->read(flash, buf, 0, size)) {
+		msg_cerr("Read operation failed!\n");
+		ret = 1;
+		goto out_free;
+	}
+
+	ret = write_buf_to_file(buf, flash->total_size * 1024, filename);
+out_free:
+	free(buf);
+	msg_cinfo("%s.\n", ret ? "FAILED" : "done");
+	return ret;
+}
+
 /* 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.
  */
@@ -1444,7 +1471,7 @@
 		if (flash->unlock)
 			flash->unlock(flash);
 
-		if (read_flash(flash, filename)) {
+		if (read_flash_to_file(flash, filename)) {
 			programmer_shutdown();
 			return 1;
 		}