spi: Add function to probe erase command opcode for all spi_master

Add a field, probe_opcode, to struct spi_master which points to a
function returning a bool by checking if a given command is supported by
the programmer in use. This is used for getting a whitelist of commands
supported by the programmer, as some programmers like ichspi don't
support all opcodes.

Most programmers use the default function, which just returns true.
ICHSPI and dummyflasher use their specialized function.

flashrom-stable: Added `.probe_opcode` for `dirtyjtag_spi`, `ich7`.

Change-Id: I6852ef92788221f471a859c879f8aff42558d36d
Signed-off-by: Aarya Chaumal <aarya.chaumal@gmail.com>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/65183
Original-Reviewed-by: Thomas Heijligen <src@posteo.de>
Original-Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
Original-Reviewed-by: Nico Huber <nico.h@gmx.de>
Original-Reviewed-by: Felix Singer <felixsinger@posteo.net>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72539
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/bitbang_spi.c b/bitbang_spi.c
index 30f6519..850ca32 100644
--- a/bitbang_spi.c
+++ b/bitbang_spi.c
@@ -77,6 +77,7 @@
 	.multicommand	= default_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 #if 0 // until it is needed
diff --git a/buspirate_spi.c b/buspirate_spi.c
index f4d2f0b..2909a3e 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -146,6 +146,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= buspirate_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static const struct buspirate_speeds spispeeds[] = {
diff --git a/ch341a_spi.c b/ch341a_spi.c
index b023562..9b07ef0 100644
--- a/ch341a_spi.c
+++ b/ch341a_spi.c
@@ -398,6 +398,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= ch341a_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static int ch341a_spi_shutdown(void *data)
diff --git a/dediprog.c b/dediprog.c
index a5d35d1..dfbb949 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -1020,6 +1020,7 @@
 	.write_256	= dediprog_spi_write_256,
 	.write_aai	= dediprog_spi_write_aai,
 	.shutdown	= dediprog_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 /*
diff --git a/digilent_spi.c b/digilent_spi.c
index a05b958..20f3b1e 100644
--- a/digilent_spi.c
+++ b/digilent_spi.c
@@ -323,6 +323,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= digilent_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 
diff --git a/dirtyjtag_spi.c b/dirtyjtag_spi.c
index 4002c7c..0abaacf 100644
--- a/dirtyjtag_spi.c
+++ b/dirtyjtag_spi.c
@@ -198,6 +198,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= dirtyjtag_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static int dirtyjtag_spi_init(void)
diff --git a/dummyflasher.c b/dummyflasher.c
index 02b75b1..ba40c6e 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -112,6 +112,7 @@
 static uint16_t dummy_chip_readw(const struct flashctx *flash, const chipaddr addr);
 static uint32_t dummy_chip_readl(const struct flashctx *flash, const chipaddr addr);
 static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len);
+static bool dummy_spi_probe_opcode(struct flashctx *flash, uint8_t opcode);
 
 static const struct spi_master spi_master_dummyflasher = {
 	.features	= SPI_MASTER_4BA,
@@ -121,6 +122,7 @@
 	.multicommand	= default_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= dummy_spi_write_256,
+	.probe_opcode	= dummy_spi_probe_opcode,
 };
 
 static const struct par_master par_master_dummyflasher = {
@@ -1185,6 +1187,17 @@
 	return spi_write_chunked(flash, buf, start, len, data->spi_write_256_chunksize);
 }
 
+static bool dummy_spi_probe_opcode(struct flashctx *flash, uint8_t opcode)
+{
+	size_t i;
+	struct emu_data *emu_data = flash->mst->spi.data;
+	for (i = 0; i < emu_data->spi_blacklist_size; i++) {
+		if (emu_data->spi_blacklist[i] == opcode)
+			return false;
+	}
+	return true;
+}
+
 const struct programmer_entry programmer_dummy = {
 	.name			= "dummy",
 	.type			= OTHER,
diff --git a/ft2232_spi.c b/ft2232_spi.c
index 921672c..4784f46 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -296,6 +296,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= ft2232_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 /* Returns 0 upon success, a negative number upon errors. */
diff --git a/ichspi.c b/ichspi.c
index fc3c9a9..ee29288 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -1572,6 +1572,11 @@
 	return ret;
 }
 
+static bool ich_spi_probe_opcode(struct flashctx *flash, uint8_t opcode)
+{
+	return find_opcode(curopcodes, opcode) >= 0;
+}
+
 #define ICH_BMWAG(x) ((x >> 24) & 0xff)
 #define ICH_BMRAG(x) ((x >> 16) & 0xff)
 #define ICH_BRWA(x)  ((x >>  8) & 0xff)
@@ -1698,6 +1703,7 @@
 	.multicommand	= ich_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= ich_spi_probe_opcode,
 };
 
 static const struct spi_master spi_master_ich9 = {
@@ -1707,6 +1713,7 @@
 	.multicommand	= ich_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= ich_spi_probe_opcode,
 };
 
 static const struct opaque_master opaque_master_ich_hwseq = {
@@ -2073,6 +2080,7 @@
 	.multicommand	= ich_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= ich_spi_probe_opcode,
 };
 
 int via_init_spi(uint32_t mmio_base)
diff --git a/include/programmer.h b/include/programmer.h
index c1bce55..b2c47a5 100644
--- a/include/programmer.h
+++ b/include/programmer.h
@@ -307,6 +307,7 @@
 	int (*write_256)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
 	int (*write_aai)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
 	int (*shutdown)(void *data);
+	bool (*probe_opcode)(struct flashctx *flash, uint8_t opcode);
 	void *data;
 };
 
@@ -316,6 +317,7 @@
 int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
 int default_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
 int default_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+bool default_spi_probe_opcode(struct flashctx *flash, uint8_t opcode);
 int register_spi_master(const struct spi_master *mst, void *data);
 
 /* The following enum is needed by ich_descriptor_tool and ich* code as well as in chipset_enable.c. */
diff --git a/it87spi.c b/it87spi.c
index fd71a87..cd3ccef 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -114,6 +114,7 @@
 	.read		= it8716f_spi_chip_read,
 	.write_256	= it8716f_spi_chip_write_256,
 	.write_aai	= spi_chip_write_1,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static uint16_t it87spi_probe(uint16_t port)
diff --git a/jlink_spi.c b/jlink_spi.c
index 09c4dbc..beabe63 100644
--- a/jlink_spi.c
+++ b/jlink_spi.c
@@ -169,6 +169,7 @@
 	.write_256	= default_spi_write_256,
 	.features	= SPI_MASTER_4BA,
 	.shutdown	= jlink_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static int jlink_spi_shutdown(void *data)
diff --git a/linux_spi.c b/linux_spi.c
index 17b3900..4be6eaa 100644
--- a/linux_spi.c
+++ b/linux_spi.c
@@ -68,6 +68,7 @@
 	.read		= linux_spi_read,
 	.write_256	= linux_spi_write_256,
 	.shutdown	= linux_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 /* Read max buffer size from sysfs, or use page size as fallback. */
diff --git a/mstarddc_spi.c b/mstarddc_spi.c
index 2c61d98..4de3c04 100644
--- a/mstarddc_spi.c
+++ b/mstarddc_spi.c
@@ -223,6 +223,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= mstarddc_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 const struct programmer_entry programmer_mstarddc_spi = {
diff --git a/ni845x_spi.c b/ni845x_spi.c
index 0889d35..699c087 100644
--- a/ni845x_spi.c
+++ b/ni845x_spi.c
@@ -632,6 +632,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= ni845x_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 const struct programmer_entry programmer_ni845x_spi = {
diff --git a/pickit2_spi.c b/pickit2_spi.c
index b402421..50e6017 100644
--- a/pickit2_spi.c
+++ b/pickit2_spi.c
@@ -350,6 +350,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= pickit2_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static int pickit2_shutdown(void *data)
diff --git a/sb600spi.c b/sb600spi.c
index 8827fb9..0ba3cfb 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -68,6 +68,7 @@
 	.multicommand	= default_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static struct spi_master spi_master_yangtze = {
@@ -77,6 +78,7 @@
 	.multicommand	= default_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static int find_smbus_dev_rev(uint16_t vendor, uint16_t device)
diff --git a/serprog.c b/serprog.c
index eb15219..e047d6d 100644
--- a/serprog.c
+++ b/serprog.c
@@ -332,6 +332,7 @@
 	.multicommand	= default_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val,
diff --git a/spi.c b/spi.c
index ac79f73..78698ce 100644
--- a/spi.c
+++ b/spi.c
@@ -131,6 +131,11 @@
 	return default_spi_write_aai(flash, buf, start, len);
 }
 
+bool default_spi_probe_opcode(struct flashctx *flash, uint8_t opcode)
+{
+	return true;
+}
+
 int register_spi_master(const struct spi_master *mst, void *data)
 {
 	struct registered_master rmst;
@@ -143,7 +148,7 @@
 	}
 
 	if (!mst->write_256 || !mst->read || !mst->command ||
-	    !mst->multicommand ||
+	    !mst->multicommand || !mst->probe_opcode ||
 	    ((mst->command == default_spi_send_command) &&
 	     (mst->multicommand == default_spi_send_multicommand))) {
 		msg_perr("%s called with incomplete master definition.\n"
diff --git a/stlinkv3_spi.c b/stlinkv3_spi.c
index 59d9c16..a1d062b 100644
--- a/stlinkv3_spi.c
+++ b/stlinkv3_spi.c
@@ -445,6 +445,7 @@
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
 	.shutdown	= stlinkv3_spi_shutdown,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 static int stlinkv3_spi_init(void)
diff --git a/usbblaster_spi.c b/usbblaster_spi.c
index 1a26e36..954967e 100644
--- a/usbblaster_spi.c
+++ b/usbblaster_spi.c
@@ -209,6 +209,7 @@
 	.multicommand	= default_spi_send_multicommand,
 	.read		= default_spi_read,
 	.write_256	= default_spi_write_256,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 const struct programmer_entry programmer_usbblaster_spi = {
diff --git a/wbsio_spi.c b/wbsio_spi.c
index 219afe1..d0029ec 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -71,6 +71,7 @@
 	.read		= wbsio_spi_read,
 	.write_256	= spi_chip_write_1,
 	.write_aai	= spi_chip_write_1,
+	.probe_opcode	= default_spi_probe_opcode,
 };
 
 int wbsio_check_for_spi(void)