Disable writes on default for known bad programmers

If a programmer has untested or non-working write/erase code, but
probing/reading works, it makes sense to protect the user against
write/erase accidents. This feature will be used by the Nvidia MCP SPI
code, and it also might make sense for the gfxnvidia driver which has
non-working write/erase.

Corresponding to flashrom svn r1069.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
diff --git a/flash.h b/flash.h
index 9c1a2be..321c59c 100644
--- a/flash.h
+++ b/flash.h
@@ -569,6 +569,7 @@
 	uint32_t spi;
 };
 extern struct decode_sizes max_rom_decode;
+extern int programmer_may_write;
 extern char *programmer_param;
 extern unsigned long flashbase;
 extern int verbose;
diff --git a/flashrom.c b/flashrom.c
index 9f5ab57..090b424 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -103,6 +103,9 @@
 /* If nonzero, used as the start address of bottom-aligned flash. */
 unsigned long flashbase;
 
+/* Is writing allowed with this programmer? */
+int programmer_may_write;
+
 const struct programmer_entry programmer_table[] = {
 #if CONFIG_INTERNAL == 1
 	{
@@ -447,6 +450,8 @@
 	flashbase = 0;
 	/* Registering shutdown functions is now allowed. */
 	may_register_shutdown = 1;
+	/* Default to allowing writes. Broken programmers set this to 0. */
+	programmer_may_write = 1;
 
 	programmer_param = param;
 	msg_pdbg("Initializing %s programmer\n",
@@ -1383,6 +1388,21 @@
 	size = flash->total_size * 1024;
 	buf = (uint8_t *) calloc(size, sizeof(char));
 
+	if (!programmer_may_write && (write_it || erase_it)) {
+		msg_perr("Write/erase is not working yet on your programmer in "
+			 "its current configuration.\n");
+		/* --force is the wrong approach, but it's the best we can do
+		 * until the generic programmer parameter parser is merged.
+		 */
+		if (!force) {
+			msg_perr("Aborting.\n");
+			programmer_shutdown();
+			return 1;
+		} else {
+			msg_cerr("Continuing anyway.\n");
+		}
+	}
+
 	if (erase_it) {
 		if (flash->tested & TEST_BAD_ERASE) {
 			msg_cerr("Erase is not working on this chip. ");