Index: flashrom-me/spi.c
===================================================================
--- flashrom-me.orig/spi.c
+++ flashrom-me/spi.c
@@ -100,25 +100,35 @@ int default_spi_send_multicommand(struct
 int default_spi_read(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len)
 {
 	unsigned int max_data = spi_programmer->max_data_read;
+	int ret;
 	if (max_data == MAX_DATA_UNSPECIFIED) {
 		msg_perr("%s called, but SPI read chunk size not defined "
 			 "on this hardware. Please report a bug at "
 			 "flashrom@flashrom.org\n", __func__);
 		return 1;
 	}
-	return spi_read_chunked(flash, buf, start, len, max_data);
+	rc = spi_read_chunked(flash, buf, start, len, max_data);
+	/* translate SPI-specific access denied error to generic error */
+	if (ret == SPI_ACCESS_DENIED)
+		rc = ACCESS_DENIED;
+	return ret;
 }
 
 int default_spi_write_256(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len)
 {
 	unsigned int max_data = spi_programmer->max_data_write;
+	int ret;
 	if (max_data == MAX_DATA_UNSPECIFIED) {
 		msg_perr("%s called, but SPI write chunk size not defined "
 			 "on this hardware. Please report a bug at "
 			 "flashrom@flashrom.org\n", __func__);
 		return 1;
 	}
-	return spi_write_chunked(flash, buf, start, len, max_data);
+	ret = spi_write_chunked(flash, buf, start, len, max_data);
+	/* translate SPI-specific access denied error to generic error */
+	if (ret == SPI_ACCESS_DENIED)
+		ret = ACCESS_DENIED;
+	return ret;
 }
 
 int spi_chip_read(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len)
Index: flashrom-me/spi.h
===================================================================
--- flashrom-me.orig/spi.h
+++ flashrom-me/spi.h
@@ -125,5 +125,6 @@
 #define SPI_INVALID_LENGTH	-4
 #define SPI_FLASHROM_BUG	-5
 #define SPI_PROGRAMMER_ERROR	-6
+#define SPI_ACCESS_DENIED	-7
 
 #endif		/* !__SPI_H__ */
Index: flashrom-me/spi25.c
===================================================================
--- flashrom-me.orig/spi25.c
+++ flashrom-me/spi25.c
@@ -916,8 +916,10 @@ int spi_nbyte_program(unsigned int addr,
 
 	result = spi_send_multicommand(cmds);
 	if (result) {
-		msg_cerr("%s failed during command execution at address 0x%x\n",
-			__func__, addr);
+		if (result != SPI_ACCESS_DENIED) {
+			msg_cerr("%s failed during command execution at address 0x%x\n",
+				__func__, addr);
+		}
 	}
 	return result;
 }
@@ -970,7 +972,7 @@ int spi_nbyte_read(unsigned int address,
  */
 int spi_read_chunked(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
 {
-	int rc = 0;
+	int rc = 0, chunk_status = 0;
 	unsigned int i, j, starthere, lenhere, toread;
 	unsigned int page_size = flash->page_size;
 
@@ -990,12 +992,26 @@ int spi_read_chunked(struct flashchip *f
 		/* Length of bytes in the range in this page. */
 		lenhere = min(start + len, (i + 1) * page_size) - starthere;
 		for (j = 0; j < lenhere; j += chunksize) {
+			uint8_t *bytes = buf + starthere - start + j;
+
 			toread = min(chunksize, lenhere - j);
-			rc = spi_nbyte_read(starthere + j, buf + starthere - start + j, toread);
-			if (rc)
-				break;
+			chunk_status = spi_nbyte_read(starthere + j, bytes, toread);
+			
+			if (chunk_status) {
+				if (ignore_error(chunk_status)) {
+					/* fill this chunk with 0xff bytes and
+					   let caller know about the error */
+					memset(bytes, 0xff, toread);
+					rc = chunk_status;
+					chunk_status = 0;
+					continue;
+				} else {
+					rc = chunk_status;
+					break;
+				}
+			}
 		}
-		if (rc)
+		if (chunk_status)
 			break;
 	}
 
Index: flashrom-me/flashrom.c
===================================================================
--- flashrom-me.orig/flashrom.c
+++ flashrom-me/flashrom.c
@@ -583,6 +583,7 @@ int verify_range(struct flashchip *flash
 	unsigned int i;
 	uint8_t *readbuf = malloc(len);
 	int ret = 0, failcount = 0;
+	unsigned int chunksize;
 
 	if (!len)
 		goto out_free;
@@ -606,23 +607,35 @@ int verify_range(struct flashchip *flash
 	if (!message)
 		message = "VERIFY";
 
-	ret = flash->read(flash, readbuf, start, len);
-	if (ret) {
-		msg_gerr("Verification impossible because read failed "
-			 "at 0x%x (len 0x%x)\n", start, len);
-		return ret;
-	}
+	chunksize = min(flash->page_size, len);
+	for (i = 0; i < len; i += chunksize) {
+		int tmp, j;
+
+		tmp = flash->read(flash, readbuf + i, start + i, chunksize);
+
+		if (tmp) {
+			ret = tmp;
+			if (ignore_error(tmp)) {
+				chunksize = min(flash->page_size, len - i);
+				continue;
+			} else {
+				goto out_free;
+			}
+		}
 
-	for (i = 0; i < len; i++) {
-		if (cmpbuf[i] != readbuf[i]) {
-			/* Only print the first failure. */
-			if (!failcount++)
-				msg_cerr("%s FAILED at 0x%08x! "
-					 "Expected=0x%02x, Read=0x%02x,",
-					 message, start + i, cmpbuf[i],
-					 readbuf[i]);
+		for (j = 0; j < chunksize; j++) {
+			if (cmpbuf[i + j] != readbuf[i + j]) {
+				/* Only print the first failure. */
+				if (!failcount++)
+					msg_cerr("%s FAILED at 0x%08x! "
+						 "Expected=0x%02x, Read=0x%02x,",
+						 message, start + i + j, cmpbuf[i + j],
+						 readbuf[j]);
+			}
 		}
+		chunksize = min(flash->page_size, len - i);
 	}
+
 	if (failcount) {
 		msg_cerr(" failed byte count from 0x%08x-0x%08x: 0x%x\n",
 			 start, start + len - 1, failcount);
@@ -1057,6 +1070,16 @@ int verify_flash(struct flashchip *flash
 
 	ret = verify_range(flash, buf, 0, total_size, NULL);
 
+	if (ret == ACCESS_DENIED) {
+		msg_gdbg("Could not fully verify due to access error, ");
+		if (access_denied_action == error_ignore) {
+			msg_gdbg("ignoring\n");
+			ret = 0;
+		} else {
+			msg_gdbg("aborting\n");
+		}
+	}
+
 	if (!ret)
 		msg_cinfo("VERIFIED.          \n");
 
@@ -1139,10 +1162,15 @@ int read_flash_to_file(struct flashchip 
 		ret = 1;
 		goto out_free;
 	}
-	if (flash->read(flash, buf, 0, size)) {
-		msg_cerr("Read operation failed!\n");
-		ret = 1;
-		goto out_free;
+
+	ret = flash->read(flash, buf, 0, size);
+	if (ret) {
+		if (ignore_error(ret)) {
+			ret = 0;
+		} else {
+			msg_cerr("Read operation failed!\n");
+			goto out_free;
+		}
 	}
 
 	ret = write_buf_to_file(buf, size, filename);
@@ -1243,8 +1271,14 @@ static int erase_and_write_block_helper(
 	if (need_erase(curcontents, newcontents, len, gran)) {
 		msg_cdbg("E");
 		ret = erasefn(flash, start, len);
-		if (ret)
+		if (ret) {
+			if (ret == ACCESS_DENIED)
+				msg_cdbg("D");
+			else
+				msg_cerr("ERASE FAILED!\n");
 			return ret;
+		}
+
 		if (check_erased_range(flash, start, len)) {
 			msg_cerr("ERASE FAILED!\n");
 			return -1;
@@ -1262,8 +1296,11 @@ static int erase_and_write_block_helper(
 		/* Needs the partial write function signature. */
 		ret = flash->write(flash, newcontents + starthere,
 				   start + starthere, lenhere);
-		if (ret)
+		if (ret) {
+			if (ret == ACCESS_DENIED)
+				msg_cdbg("D");
 			return ret;
+		}
 		starthere += lenhere;
 		skip = 0;
 	}
@@ -1284,7 +1321,7 @@ static int walk_eraseregions(struct flas
 							unsigned int len)),
 			     void *param1, void *param2)
 {
-	int i, j;
+	int i, j, ret = 0;
 	unsigned int start = 0;
 	unsigned int len;
 	struct block_eraser eraser = flash->block_erasers[erasefunction];
@@ -1300,15 +1337,19 @@ static int walk_eraseregions(struct flas
 				msg_cdbg(", ");
 			msg_cdbg("0x%06x-0x%06x", start,
 				     start + len - 1);
-			if (do_something(flash, start, len, param1, param2,
-					 eraser.block_erase)) {
-				return 1;
+			ret = do_something(flash, start, len, param1, param2,
+			                   eraser.block_erase);
+			if (ret) {
+				if (ignore_error(ret))
+					ret = 0;
+				else
+					return ret;
 			}
 			start += len;
 		}
 	}
 	msg_cdbg("\n");
-	return 0;
+	return ret;
 }
 
 static int check_block_eraser(const struct flashchip *flash, int k, int log)
@@ -1695,7 +1736,7 @@ int doit(struct flashchip *flash, int fo
 {
 	uint8_t *oldcontents;
 	uint8_t *newcontents;
-	int ret = 0;
+	int ret = 0, tmp;
 	unsigned long size = flash->total_size * 1024;
 
 	if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) {
@@ -1768,10 +1809,15 @@ int doit(struct flashchip *flash, int fo
 	 * takes time as well.
 	 */
 	msg_cinfo("Reading old flash chip contents... ");
-	if (flash->read(flash, oldcontents, 0, size)) {
-		ret = 1;
-		msg_cinfo("FAILED.\n");
-		goto out;
+	tmp = flash->read(flash, oldcontents, 0, size);
+	if (tmp) {
+		if (ignore_error(tmp)) {
+			msg_gdbg("ignoring error\n");
+		} else {
+			ret = 1;
+			msg_cinfo("FAILED.\n");
+			goto out;
+		}
 	}
 	msg_cinfo("done.\n");
 
