buspirate_spi.c: Refactor singleton states into reentrant pattern

Move global singleton states into a struct and store within
the spi_master data field for the life-time of the driver.

This is one of the steps on the way to move spi_master data
memory management behind the initialisation API, for more
context see other patches under the same topic "register_master_api".

Change-Id: I418bbfff15fb126b042fbc9be09dbf59f4d243b8
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/52958
Original-Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Original-Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72209
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/buspirate_spi.c b/buspirate_spi.c
index 6c9ee4a..34fabe7 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -51,26 +51,28 @@
 #define sp_flush_incoming(...) 0
 #endif
 
-static unsigned char *bp_commbuf = NULL;
-static int bp_commbufsize = 0;
+struct bp_spi_data {
+	unsigned char *bp_commbuf;
+	int bp_commbufsize;
+};
 
-static int buspirate_commbuf_grow(int bufsize)
+static int buspirate_commbuf_grow(int bufsize, unsigned char **bp_commbuf, int *bp_commbufsize)
 {
 	unsigned char *tmpbuf;
 
 	/* Never shrink. realloc() calls are expensive. */
-	if (bufsize <= bp_commbufsize)
+	if (bufsize <= *bp_commbufsize)
 		return 0;
 
-	tmpbuf = realloc(bp_commbuf, bufsize);
+	tmpbuf = realloc(*bp_commbuf, bufsize);
 	if (!tmpbuf) {
 		/* Keep the existing buffer because memory is already tight. */
 		msg_perr("Out of memory!\n");
 		return ERROR_OOM;
 	}
 
-	bp_commbuf = tmpbuf;
-	bp_commbufsize = bufsize;
+	*bp_commbuf = tmpbuf;
+	*bp_commbufsize = bufsize;
 	return 0;
 }
 
@@ -168,6 +170,8 @@
 
 static int buspirate_spi_shutdown(void *data)
 {
+	struct bp_spi_data *bp_data = data;
+	unsigned char *const bp_commbuf = bp_data->bp_commbuf;
 	int ret = 0, ret2 = 0;
 	/* No need to allocate a buffer here, we know that bp_commbuf is at least DEFAULT_BUFSIZE big. */
 
@@ -195,14 +199,14 @@
 	/* Keep the oldest error, it is probably the best indicator. */
 	if (ret2 && !ret)
 		ret = ret2;
-	bp_commbufsize = 0;
+
 	free(bp_commbuf);
-	bp_commbuf = NULL;
 	if (ret)
 		msg_pdbg("Bus Pirate shutdown failed.\n");
 	else
 		msg_pdbg("Bus Pirate shutdown completed.\n");
 
+	free(data);
 	return ret;
 }
 
@@ -230,6 +234,8 @@
 	int ret = 0;
 	bool pullup = false;
 	bool psu = false;
+	unsigned char *bp_commbuf;
+	int bp_commbufsize;
 
 	dev = extract_programmer_param("dev");
 	if (dev && !strlen(dev)) {
@@ -294,7 +300,6 @@
 #define DEFAULT_BUFSIZE (16 + 3)
 	bp_commbuf = malloc(DEFAULT_BUFSIZE);
 	if (!bp_commbuf) {
-		bp_commbufsize = 0;
 		msg_perr("Out of memory!\n");
 		free(dev);
 		return ERROR_OOM;
@@ -304,12 +309,20 @@
 	ret = buspirate_serialport_setup(dev);
 	free(dev);
 	if (ret) {
-		bp_commbufsize = 0;
 		free(bp_commbuf);
-		bp_commbuf = NULL;
 		return ret;
 	}
 
+
+	struct bp_spi_data *bp_data = calloc(1, sizeof(*bp_data));
+	if (!bp_data) {
+		msg_perr("Unable to allocate space for SPI master data\n");
+		free(bp_commbuf);
+		return 1;
+	}
+	bp_data->bp_commbuf = bp_commbuf;
+	bp_data->bp_commbufsize = bp_commbufsize;
+
 	/* This is the brute force version, but it should work.
 	 * It is likely to fail if a previous flashrom run was aborted during a write with the new SPI commands
 	 * in firmware v5.5 because that firmware may wait for up to 4096 bytes of input before responding to
@@ -406,10 +419,12 @@
 	if (BP_FWVERSION(fw_version_major, fw_version_minor) >= BP_FWVERSION(5, 5)) {
 		msg_pdbg("Using SPI command set v2.\n");
 		/* Sensible default buffer size. */
-		if (buspirate_commbuf_grow(260 + 5)) {
+		if (buspirate_commbuf_grow(260 + 5, &bp_commbuf, &bp_commbufsize)) {
 			ret = ERROR_OOM;
 			goto init_err_cleanup_exit;
 		}
+		bp_data->bp_commbuf = bp_commbuf;
+		bp_data->bp_commbufsize = bp_commbufsize;
 		spi_master_buspirate.max_data_read = 2048;
 		spi_master_buspirate.max_data_write = 256;
 		spi_master_buspirate.command = buspirate_spi_send_command_v2;
@@ -418,10 +433,12 @@
 		msg_pinfo("Reading/writing a flash chip may take hours.\n");
 		msg_pinfo("It is recommended to upgrade to firmware 5.5 or newer.\n");
 		/* Sensible default buffer size. */
-		if (buspirate_commbuf_grow(16 + 3)) {
+		if (buspirate_commbuf_grow(16 + 3, &bp_commbuf, &bp_commbufsize)) {
 			ret = ERROR_OOM;
 			goto init_err_cleanup_exit;
 		}
+		bp_data->bp_commbuf = bp_commbuf;
+		bp_data->bp_commbufsize = bp_commbufsize;
 		spi_master_buspirate.max_data_read = 12;
 		spi_master_buspirate.max_data_write = 12;
 		spi_master_buspirate.command = buspirate_spi_send_command_v1;
@@ -588,22 +605,23 @@
 		goto init_err_cleanup_exit;
 	}
 
-	if (register_shutdown(buspirate_spi_shutdown, NULL) != 0) {
+	if (register_shutdown(buspirate_spi_shutdown, bp_data) != 0) {
 		ret = 1;
 		goto init_err_cleanup_exit;
 	}
-	register_spi_master(&spi_master_buspirate, NULL);
+	register_spi_master(&spi_master_buspirate, bp_data);
 
 	return 0;
 
 init_err_cleanup_exit:
-	buspirate_spi_shutdown(NULL);
+	buspirate_spi_shutdown(bp_data);
 	return ret;
 }
 
 static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
 					 const unsigned char *writearr, unsigned char *readarr)
 {
+	struct bp_spi_data *bp_data = flash->mst->spi.data;
 	unsigned int i = 0;
 	int ret = 0;
 
@@ -611,9 +629,11 @@
 		return SPI_INVALID_LENGTH;
 
 	/* 3 bytes extra for CS#, len, CS#. */
-	if (buspirate_commbuf_grow(writecnt + readcnt + 3))
+	if (buspirate_commbuf_grow(writecnt + readcnt + 3, &bp_data->bp_commbuf, &bp_data->bp_commbufsize))
 		return ERROR_OOM;
 
+	unsigned char *const bp_commbuf = bp_data->bp_commbuf;
+
 	/* Assert CS# */
 	bp_commbuf[i++] = 0x02;
 
@@ -657,6 +677,7 @@
 static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
 					 const unsigned char *writearr, unsigned char *readarr)
 {
+	struct bp_spi_data *bp_data = flash->mst->spi.data;
 	int i = 0, ret = 0;
 
 	if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096)
@@ -665,9 +686,11 @@
 	/* 5 bytes extra for command, writelen, readlen.
 	 * 1 byte extra for Ack/Nack.
 	 */
-	if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1)))
+	if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1), &bp_data->bp_commbuf, &bp_data->bp_commbufsize))
 		return ERROR_OOM;
 
+	unsigned char *const bp_commbuf = bp_data->bp_commbuf;
+
 	/* Combined SPI write/read. */
 	bp_commbuf[i++] = 0x04;
 	bp_commbuf[i++] = (writecnt >> 8) & 0xff;