Index: flashrom-eraseblocks/flash.h
===================================================================
--- flashrom-eraseblocks/flash.h	(Revision 592)
+++ flashrom-eraseblocks/flash.h	(Arbeitskopie)
@@ -138,6 +138,17 @@
 	CHIP_BUSTYPE_UNKNOWN	= CHIP_BUSTYPE_PARALLEL | CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI,
 };
 
+/*
+ * How many different contiguous runs of erase blocks with one size each do
+ * we have for a given erase function?
+ */
+#define NUM_ERASEREGIONS 5
+
+/*
+ * How many different erase functions do we have per chip?
+ */
+#define NUM_ERASEFUNCTIONS 5
+
 struct flashchip {
 	const char *vendor;
 	const char *name;
@@ -166,6 +177,19 @@
 	/* Delay after "enter/exit ID mode" commands in microseconds. */
 	int probe_timing;
 	int (*erase) (struct flashchip *flash);
+
+	/*
+	 * Erase blocks and associated erase function. The default entry is a
+	 * chip-sized virtual block together with the chip erase function.
+	 */
+	struct block_eraser {
+		struct eraseblock{
+			unsigned int size; /* Eraseblock size */
+			unsigned int count; /* Number of contiguous blocks with that size */
+		} eraseblocks[NUM_ERASEREGIONS];
+		int (*block_erase) (struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen);
+	} block_erasers[NUM_ERASEFUNCTIONS];
+
 	int (*write) (struct flashchip *flash, uint8_t *buf);
 	int (*read) (struct flashchip *flash, uint8_t *buf);
 
@@ -729,6 +753,7 @@
 #define printf_debug(x...) { if (verbose) printf(x); }
 void map_flash_registers(struct flashchip *flash);
 int read_memmapped(struct flashchip *flash, uint8_t *buf);
+int erase_flash(struct flashchip *flash);
 int min(int a, int b);
 extern char *pcidev_bdf;
 
@@ -767,8 +792,11 @@
 int spi_chip_erase_c7(struct flashchip *flash);
 int spi_chip_erase_60_c7(struct flashchip *flash);
 int spi_chip_erase_d8(struct flashchip *flash);
-int spi_block_erase_52(const struct flashchip *flash, unsigned long addr);
-int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr);
+int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_60(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_c7(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
 int spi_chip_write_1(struct flashchip *flash, uint8_t *buf);
 int spi_chip_write_256(struct flashchip *flash, uint8_t *buf);
 int spi_chip_read(struct flashchip *flash, uint8_t *buf);
Index: flashrom-eraseblocks/flashchips.c
===================================================================
--- flashrom-eraseblocks/flashchips.c	(Revision 592)
+++ flashrom-eraseblocks/flashchips.c	(Arbeitskopie)
@@ -1203,7 +1203,30 @@
 		.tested		= TEST_UNTESTED,
 		.probe		= probe_spi_rdid,
 		.probe_timing	= TIMING_ZERO,
-		.erase		= spi_chip_erase_60_c7,
+		.erase		= NULL,
+		.block_erasers	=
+		{
+			{
+				.eraseblocks = { {4 * 1024, 16} },
+				.block_erase = spi_block_erase_20,
+			},
+			{
+				.eraseblocks = { {64 * 1024, 1} },
+				.block_erase = spi_block_erase_52,
+			},
+			{
+				.eraseblocks = { {64 * 1024, 1} },
+				.block_erase = spi_block_erase_d8,
+			},
+			{
+				.eraseblocks = { {64 * 1024, 1} },
+				.block_erase = spi_block_erase_60,
+			},
+			{
+				.eraseblocks = { {64 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			},
+		},
 		.write		= spi_chip_write_256,
 		.read		= spi_chip_read,
 	},
@@ -1219,7 +1242,26 @@
 		.tested		= TEST_UNTESTED,
 		.probe		= probe_spi_rdid,
 		.probe_timing	= TIMING_ZERO,
-		.erase		= spi_chip_erase_60_c7,
+		.erase		= NULL,
+		.block_erasers	=
+		{
+			{
+				.eraseblocks = { {4 * 1024, 32} },
+				.block_erase = spi_block_erase_20,
+			},
+			{
+				.eraseblocks = { {64 * 1024, 2} },
+				.block_erase = spi_block_erase_d8,
+			},
+			{
+				.eraseblocks = { {128 * 1024, 1} },
+				.block_erase = spi_block_erase_60,
+			},
+			{
+				.eraseblocks = { {128 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			},
+		},
 		.write		= spi_chip_write_256,
 		.read		= spi_chip_read,
 	},
Index: flashrom-eraseblocks/spi.c
===================================================================
--- flashrom-eraseblocks/spi.c	(Revision 592)
+++ flashrom-eraseblocks/spi.c	(Arbeitskopie)
@@ -468,11 +468,34 @@
 	return result;
 }
 
-int spi_block_erase_52(const struct flashchip *flash, unsigned long addr)
+/* Sector size is usually 4k, though Macronix eliteflash has 64k */
+int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
 {
-	unsigned char cmd[JEDEC_BE_52_OUTSIZE] = {JEDEC_BE_52};
+	unsigned char cmd[JEDEC_SE_OUTSIZE] = { JEDEC_SE, };
 	int result;
+	
+	cmd[1] = (addr & 0x00ff0000) >> 16;
+	cmd[2] = (addr & 0x0000ff00) >> 8;
+	cmd[3] = (addr & 0x000000ff);
 
+	result = spi_write_enable();
+	if (result)
+		return result;
+	/* Send SE (Sector Erase) */
+	spi_command(sizeof(cmd), 0, cmd, NULL);
+	/* Wait until the Write-In-Progress bit is cleared.
+	 * This usually takes 15-800 ms, so wait in 10 ms steps.
+	 */
+	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+		programmer_delay(10 * 1000);
+	return 0;
+}
+
+int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
+{
+	unsigned char cmd[JEDEC_BE_52_OUTSIZE] = {JEDEC_BE_52, };
+	int result;
+
 	cmd[1] = (addr & 0x00ff0000) >> 16;
 	cmd[2] = (addr & 0x0000ff00) >> 8;
 	cmd[3] = (addr & 0x000000ff);
@@ -494,9 +517,9 @@
  * 32k for SST
  * 4-32k non-uniform for EON
  */
-int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr)
+int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
 {
-	unsigned char cmd[JEDEC_BE_D8_OUTSIZE] = { JEDEC_BE_D8 };
+	unsigned char cmd[JEDEC_BE_D8_OUTSIZE] = { JEDEC_BE_D8, };
 	int result;
 
 	cmd[1] = (addr & 0x00ff0000) >> 16;
@@ -526,7 +549,7 @@
 	printf("Erasing chip: \n");
 
 	for (i = 0; i < total_size / erase_size; i++) {
-		rc = spi_block_erase_d8(flash, i * erase_size);
+		rc = spi_block_erase_d8(flash, i * erase_size, erase_size);
 		if (rc) {
 			printf("Error erasing block at 0x%x\n", i);
 			break;
@@ -538,27 +561,22 @@
 	return rc;
 }
 
-/* Sector size is usually 4k, though Macronix eliteflash has 64k */
-int spi_sector_erase(const struct flashchip *flash, unsigned long addr)
+int spi_block_erase_60(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
 {
-	unsigned char cmd[JEDEC_SE_OUTSIZE] = { JEDEC_SE };
-	int result;
-	
-	cmd[1] = (addr & 0x00ff0000) >> 16;
-	cmd[2] = (addr & 0x0000ff00) >> 8;
-	cmd[3] = (addr & 0x000000ff);
+	if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
+		fprintf(stderr, "%s called with incorrect arguments\n", __func__);
+		return -1;
+	}
+	return spi_chip_erase_60(flash);
+}
 
-	result = spi_write_enable();
-	if (result)
-		return result;
-	/* Send SE (Sector Erase) */
-	spi_command(sizeof(cmd), 0, cmd, NULL);
-	/* Wait until the Write-In-Progress bit is cleared.
-	 * This usually takes 15-800 ms, so wait in 10 ms steps.
-	 */
-	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
-		programmer_delay(10 * 1000);
-	return 0;
+int spi_block_erase_c7(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
+{
+	if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
+		fprintf(stderr, "%s called with incorrect arguments\n", __func__);
+		return -1;
+	}
+	return spi_chip_erase_c7(flash);
 }
 
 int spi_write_status_enable(void)
@@ -790,7 +808,7 @@
 	default:
 		break;
 	}
-	flash->erase(flash);
+	erase_flash(flash);
 	result = spi_write_enable();
 	if (result)
 		return result;
Index: flashrom-eraseblocks/wbsio_spi.c
===================================================================
--- flashrom-eraseblocks/wbsio_spi.c	(Revision 592)
+++ flashrom-eraseblocks/wbsio_spi.c	(Arbeitskopie)
@@ -196,7 +196,7 @@
 		return 1;
 	}
 
-	flash->erase(flash);
+	erase_flash(flash);
 	result = spi_write_enable();
 	if (result)
 		return result;
Index: flashrom-eraseblocks/w39v040c.c
===================================================================
--- flashrom-eraseblocks/w39v040c.c	(Revision 592)
+++ flashrom-eraseblocks/w39v040c.c	(Arbeitskopie)
@@ -81,7 +81,7 @@
 	int page_size = flash->page_size;
 	chipaddr bios = flash->virtual_memory;
 
-	if (flash->erase(flash))
+	if (erase_flash(flash))
 		return -1;
 
 	printf("Programming page: ");
Index: flashrom-eraseblocks/sb600spi.c
===================================================================
--- flashrom-eraseblocks/sb600spi.c	(Revision 592)
+++ flashrom-eraseblocks/sb600spi.c	(Arbeitskopie)
@@ -63,7 +63,7 @@
 
 	/* Erase first */
 	printf("Erasing flash before programming... ");
-	flash->erase(flash);
+	erase_flash(flash);
 	printf("done.\n");
 
 	printf("Programming flash");
Index: flashrom-eraseblocks/flashrom.c
===================================================================
--- flashrom-eraseblocks/flashrom.c	(Revision 592)
+++ flashrom-eraseblocks/flashrom.c	(Arbeitskopie)
@@ -377,31 +377,52 @@
 
 int erase_flash(struct flashchip *flash)
 {
-	uint32_t erasedbytes;
-	unsigned long size = flash->total_size * 1024;
-	unsigned char *buf = calloc(size, sizeof(char));
+	int i, j, k, found = 0;
+
 	printf("Erasing flash chip... ");
-	if (NULL == flash->erase) {
-		printf("FAILED!\n");
+	for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
+		unsigned long done = 0;
+		struct block_eraser eraser = flash->block_erasers[k];
+
+		printf_debug("Looking at blockwise erase function %i... ", k);
+		if (!eraser.block_erase && !eraser.eraseblocks[0].count) {
+			printf_debug("not defined. "
+				"Looking for another erase function.\n");
+			continue;
+		}
+		if (!eraser.block_erase && eraser.eraseblocks[0].count) {
+			printf_debug("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) {
+			printf_debug("block erase function found, but "
+				"eraseblock layout is unknown. "
+				"Looking for another erase function.\n");
+			continue;
+		}
+		found = 1;
+		printf_debug("trying... ");
+		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++) {
+				eraser.block_erase(flash, done + eraser.eraseblocks[i].size * j, eraser.eraseblocks[i].size);
+			}
+		}
+	}
+	if ((!found) && (flash->erase)) {
+		found = 1;
+		printf_debug("Trying whole-chip erase function... ");
+		flash->erase(flash);
+	}
+	if (!found) {
 		fprintf(stderr, "ERROR: flashrom has no erase function for this flash chip.\n");
 		return 1;
 	}
-	flash->erase(flash);
 
-	if (!flash->read) {
-		printf("FAILED!\n");
-		fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
-		return 1;
-	} else
-		flash->read(flash, buf);
-
-	for (erasedbytes = 0; erasedbytes < size; erasedbytes++)
-		if (0xff != buf[erasedbytes]) {
-			printf("FAILED!\n");
-			fprintf(stderr, "ERROR at 0x%08x: Expected=0xff, Read=0x%02x\n",
-				erasedbytes, buf[erasedbytes]);
-			return 1;
-		}
 	printf("SUCCESS.\n");
 	return 0;
 }
Index: flashrom-eraseblocks/ichspi.c
===================================================================
--- flashrom-eraseblocks/ichspi.c	(Revision 592)
+++ flashrom-eraseblocks/ichspi.c	(Arbeitskopie)
@@ -674,7 +674,7 @@
 		 * For this, we need to add a block erase function to
 		 * struct flashchip.
 		 */
-		rc = spi_block_erase_d8(flash, i * erase_size);
+		rc = spi_block_erase_d8(flash, i * erase_size, erase_size);
 		if (rc) {
 			printf("Error erasing block at 0x%x\n", i);
 			break;
