Anastasia Klimchuk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/52958 )
Change subject: buspirate_spi.c: Refactor singleton states into reentrant pattern ......................................................................
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".
BUG=b:185191942 TEST=builds
Change-Id: I418bbfff15fb126b042fbc9be09dbf59f4d243b8 Signed-off-by: Anastasia Klimchuk aklm@chromium.org --- M buspirate_spi.c 1 file changed, 121 insertions(+), 101 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/58/52958/1
diff --git a/buspirate_spi.c b/buspirate_spi.c index 31d36cd..a8b9163 100644 --- a/buspirate_spi.c +++ b/buspirate_spi.c @@ -50,26 +50,28 @@ #define sp_flush_incoming(...) 0 #endif
-static unsigned char *bp_commbuf = NULL; -static int bp_commbufsize = 0; +struct buspirate_spi_data { + unsigned char *bp_commbuf; + int bp_commbufsize; +};
-static int buspirate_commbuf_grow(int bufsize) +static int buspirate_commbuf_grow(int bufsize, struct buspirate_spi_data *buspirate_data) { unsigned char *tmpbuf;
/* Never shrink. realloc() calls are expensive. */ - if (bufsize <= bp_commbufsize) + if (bufsize <= buspirate_data->bp_commbufsize) return 0;
- tmpbuf = realloc(bp_commbuf, bufsize); + tmpbuf = realloc(buspirate_data->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; + buspirate_data->bp_commbuf = tmpbuf; + buspirate_data->bp_commbufsize = bufsize; return 0; }
@@ -162,26 +164,27 @@
static int buspirate_spi_shutdown(void *data) { + struct buspirate_spi_data *buspirate_data = data; int ret = 0, ret2 = 0; /* No need to allocate a buffer here, we know that bp_commbuf is at least DEFAULT_BUFSIZE big. */
/* Exit raw SPI mode (enter raw bitbang mode) */ - bp_commbuf[0] = 0x00; - if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0))) + buspirate_data->bp_commbuf[0] = 0x00; + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 0))) goto out_shutdown; - if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "BBIO"))) goto out_shutdown; - if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 0, 1))) goto out_shutdown; - msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]); - if (bp_commbuf[0] != '1') { - msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]); + msg_pdbg("Raw bitbang mode version %c\n", buspirate_data->bp_commbuf[0]); + if (buspirate_data->bp_commbuf[0] != '1') { + msg_perr("Can't handle raw bitbang mode version %c!\n", buspirate_data->bp_commbuf[0]); ret = 1; goto out_shutdown; } /* Reset Bus Pirate (return to user terminal) */ - bp_commbuf[0] = 0x0f; - ret = buspirate_sendrecv(bp_commbuf, 1, 0); + buspirate_data->bp_commbuf[0] = 0x0f; + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 0);
out_shutdown: /* Shut down serial port communication */ @@ -189,14 +192,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; + + free(buspirate_data->bp_commbuf); if (ret) msg_pdbg("Bus Pirate shutdown failed.\n"); else msg_pdbg("Bus Pirate shutdown completed.\n");
+ free(data); return ret; }
@@ -205,50 +208,51 @@ { unsigned int i = 0; int ret = 0; + struct buspirate_spi_data *buspirate_data = flash->mst->spi.data;
if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16) 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, buspirate_data)) return ERROR_OOM;
/* Assert CS# */ - bp_commbuf[i++] = 0x02; + buspirate_data->bp_commbuf[i++] = 0x02;
- bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1); - memcpy(bp_commbuf + i, writearr, writecnt); + buspirate_data->bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1); + memcpy(buspirate_data->bp_commbuf + i, writearr, writecnt); i += writecnt; - memset(bp_commbuf + i, 0, readcnt); + memset(buspirate_data->bp_commbuf + i, 0, readcnt);
i += readcnt; /* De-assert CS# */ - bp_commbuf[i++] = 0x03; + buspirate_data->bp_commbuf[i++] = 0x03;
- ret = buspirate_sendrecv(bp_commbuf, i, i); + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, i, i);
if (ret) { msg_perr("Bus Pirate communication error!\n"); return SPI_GENERIC_ERROR; }
- if (bp_commbuf[0] != 0x01) { + if (buspirate_data->bp_commbuf[0] != 0x01) { msg_perr("Protocol error while lowering CS#!\n"); return SPI_GENERIC_ERROR; }
- if (bp_commbuf[1] != 0x01) { + if (buspirate_data->bp_commbuf[1] != 0x01) { msg_perr("Protocol error while reading/writing SPI!\n"); return SPI_GENERIC_ERROR; }
- if (bp_commbuf[i - 1] != 0x01) { + if (buspirate_data->bp_commbuf[i - 1] != 0x01) { msg_perr("Protocol error while raising CS#!\n"); return SPI_GENERIC_ERROR; }
/* Skip CS#, length, writearr. */ - memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt); + memcpy(readarr, buspirate_data->bp_commbuf + 2 + writecnt, readcnt);
return ret; } @@ -257,6 +261,7 @@ const unsigned char *writearr, unsigned char *readarr) { int i = 0, ret = 0; + struct buspirate_spi_data *buspirate_data = flash->mst->spi.data;
if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096) return SPI_INVALID_LENGTH; @@ -264,31 +269,31 @@ /* 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), buspirate_data)) return ERROR_OOM;
/* Combined SPI write/read. */ - bp_commbuf[i++] = 0x04; - bp_commbuf[i++] = (writecnt >> 8) & 0xff; - bp_commbuf[i++] = writecnt & 0xff; - bp_commbuf[i++] = (readcnt >> 8) & 0xff; - bp_commbuf[i++] = readcnt & 0xff; - memcpy(bp_commbuf + i, writearr, writecnt); + buspirate_data->bp_commbuf[i++] = 0x04; + buspirate_data->bp_commbuf[i++] = (writecnt >> 8) & 0xff; + buspirate_data->bp_commbuf[i++] = writecnt & 0xff; + buspirate_data->bp_commbuf[i++] = (readcnt >> 8) & 0xff; + buspirate_data->bp_commbuf[i++] = readcnt & 0xff; + memcpy(buspirate_data->bp_commbuf + i, writearr, writecnt);
- ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt); + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, i + writecnt, 1 + readcnt);
if (ret) { msg_perr("Bus Pirate communication error!\n"); return SPI_GENERIC_ERROR; }
- if (bp_commbuf[0] != 0x01) { + if (buspirate_data->bp_commbuf[0] != 0x01) { msg_perr("Protocol error while sending SPI write/read!\n"); return SPI_GENERIC_ERROR; }
/* Skip Ack. */ - memcpy(readarr, bp_commbuf + 1, readcnt); + memcpy(readarr, buspirate_data->bp_commbuf + 1, readcnt);
return ret; } @@ -316,6 +321,9 @@ int serialspeed_index = -1; int ret = 0; int pullup = 0; + unsigned char *bp_commbuf = NULL; + int bp_commbufsize = 0; + struct buspirate_spi_data *buspirate_data;
dev = extract_programmer_param("dev"); if (dev && !strlen(dev)) { @@ -385,6 +393,18 @@ return ret; }
+ buspirate_data = calloc(1, sizeof(*buspirate_data)); + if (!buspirate_data) { + msg_perr("Unable to allocate space for SPI master data\n"); + bp_commbufsize = 0; + free(bp_commbuf); + bp_commbuf = NULL; + return 1; + } + buspirate_data->bp_commbuf = bp_commbuf; + buspirate_data->bp_commbufsize = bp_commbufsize; + spi_master_buspirate.data = buspirate_data; + /* 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 @@ -392,9 +412,9 @@ */ for (i = 0; i < 20; i++) { /* Enter raw bitbang mode */ - bp_commbuf[0] = 0x00; + buspirate_data->bp_commbuf[0] = 0x00; /* Send the command, don't read the response. */ - ret = buspirate_sendrecv(bp_commbuf, 1, 0); + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 0); if (ret) goto init_err_cleanup_exit; /* The old way to handle responses from a Bus Pirate already in BBIO mode was to flush any @@ -408,65 +428,65 @@ internal_sleep(10000); } /* We know that 20 commands of \0 should elicit at least one BBIO1 response. */ - if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "BBIO"))) goto init_err_cleanup_exit;
/* Reset the Bus Pirate. */ - bp_commbuf[0] = 0x0f; + buspirate_data->bp_commbuf[0] = 0x0f; /* Send the command, don't read the response. */ - if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 0))) goto init_err_cleanup_exit; - if ((ret = buspirate_wait_for_string(bp_commbuf, "irate "))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "irate "))) goto init_err_cleanup_exit; /* Read the hardware version string. Last byte of the buffer is reserved for \0. */ for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) { - if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf + i, 0, 1))) goto init_err_cleanup_exit; - if (strchr("\r\n\t ", bp_commbuf[i])) + if (strchr("\r\n\t ", buspirate_data->bp_commbuf[i])) break; } - bp_commbuf[i] = '\0'; + buspirate_data->bp_commbuf[i] = '\0'; msg_pdbg("Detected Bus Pirate hardware "); - if (bp_commbuf[0] != 'v') + if (buspirate_data->bp_commbuf[0] != 'v') msg_pdbg("(unknown version number format)"); - else if (!strchr("0123456789", bp_commbuf[1])) + else if (!strchr("0123456789", buspirate_data->bp_commbuf[1])) msg_pdbg("(unknown version number format)"); else { - hw_version_major = strtoul((char *)bp_commbuf + 1, &tmp, 10); + hw_version_major = strtoul((char *)buspirate_data->bp_commbuf + 1, &tmp, 10); while ((*tmp != '\0') && !strchr("0123456789", *tmp)) tmp++; hw_version_minor = strtoul(tmp, NULL, 10); msg_pdbg("%u.%u", hw_version_major, hw_version_minor); } - msg_pdbg2(" ("%s")", bp_commbuf); + msg_pdbg2(" ("%s")", buspirate_data->bp_commbuf); msg_pdbg("\n");
- if ((ret = buspirate_wait_for_string(bp_commbuf, "irmware "))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "irmware "))) goto init_err_cleanup_exit; /* Read the firmware version string. Last byte of the buffer is reserved for \0. */ for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) { - if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf + i, 0, 1))) goto init_err_cleanup_exit; - if (strchr("\r\n\t ", bp_commbuf[i])) + if (strchr("\r\n\t ", buspirate_data->bp_commbuf[i])) break; } - bp_commbuf[i] = '\0'; + buspirate_data->bp_commbuf[i] = '\0'; msg_pdbg("Detected Bus Pirate firmware "); - if (bp_commbuf[0] != 'v') + if (buspirate_data->bp_commbuf[0] != 'v') msg_pdbg("(unknown version number format)"); - else if (!strchr("0123456789", bp_commbuf[1])) + else if (!strchr("0123456789", buspirate_data->bp_commbuf[1])) msg_pdbg("(unknown version number format)"); else { - fw_version_major = strtoul((char *)bp_commbuf + 1, &tmp, 10); + fw_version_major = strtoul((char *)buspirate_data->bp_commbuf + 1, &tmp, 10); while ((*tmp != '\0') && !strchr("0123456789", *tmp)) tmp++; fw_version_minor = strtoul(tmp, NULL, 10); msg_pdbg("%u.%u", fw_version_major, fw_version_minor); } - msg_pdbg2(" ("%s")", bp_commbuf); + msg_pdbg2(" ("%s")", buspirate_data->bp_commbuf); msg_pdbg("\n");
- if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "HiZ>"))) goto init_err_cleanup_exit;
/* Tell the user about missing SPI binary mode in firmware 2.3 and older. */ @@ -481,7 +501,7 @@ 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, buspirate_data)) { ret = ERROR_OOM; goto init_err_cleanup_exit; } @@ -493,7 +513,7 @@ 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, buspirate_data)) { ret = ERROR_OOM; goto init_err_cleanup_exit; } @@ -534,24 +554,24 @@ " Continue at your own risk.\n");
/* Enter baud rate configuration mode */ - cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "b\n"); - if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0))) + cnt = snprintf((char *)buspirate_data->bp_commbuf, DEFAULT_BUFSIZE, "b\n"); + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, cnt, 0))) goto init_err_cleanup_exit; - if ((ret = buspirate_wait_for_string(bp_commbuf, ">"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, ">"))) goto init_err_cleanup_exit;
/* Enter manual clock divisor entry mode */ - cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "10\n"); - if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0))) + cnt = snprintf((char *)buspirate_data->bp_commbuf, DEFAULT_BUFSIZE, "10\n"); + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, cnt, 0))) goto init_err_cleanup_exit; - if ((ret = buspirate_wait_for_string(bp_commbuf, ">"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, ">"))) goto init_err_cleanup_exit;
/* Set the clock divisor to the value calculated from the user's input */ - cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "%d\n", + cnt = snprintf((char *)buspirate_data->bp_commbuf, DEFAULT_BUFSIZE, "%d\n", BP_DIVISOR(serialspeeds[serialspeed_index].speed));
- if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, cnt, 0))) goto init_err_cleanup_exit; sleep(1);
@@ -563,9 +583,9 @@
/* Return to the main prompt */ bp_commbuf[0] = ' '; - if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 0))) goto init_err_cleanup_exit; - if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "HiZ>"))) goto init_err_cleanup_exit;
msg_pdbg("Serial speed is %d baud\n", serialspeeds[serialspeed_index].speed); @@ -577,50 +597,50 @@
/* Enter raw bitbang mode */ for (i = 0; i < 20; i++) { - bp_commbuf[0] = 0x00; - if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0))) + buspirate_data->bp_commbuf[0] = 0x00; + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 0))) goto init_err_cleanup_exit; } - if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "BBIO"))) goto init_err_cleanup_exit; - if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 0, 1))) goto init_err_cleanup_exit; msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]); - if (bp_commbuf[0] != '1') { - msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]); + if (buspirate_data->bp_commbuf[0] != '1') { + msg_perr("Can't handle raw bitbang mode version %c!\n", buspirate_data->bp_commbuf[0]); ret = 1; goto init_err_cleanup_exit; } /* Enter raw SPI mode */ - bp_commbuf[0] = 0x01; - ret = buspirate_sendrecv(bp_commbuf, 1, 0); + buspirate_data->bp_commbuf[0] = 0x01; + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 0); if (ret) { ret = 1; goto init_err_cleanup_exit; } - if ((ret = buspirate_wait_for_string(bp_commbuf, "SPI"))) + if ((ret = buspirate_wait_for_string(buspirate_data->bp_commbuf, "SPI"))) goto init_err_cleanup_exit; - if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1))) + if ((ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 0, 1))) goto init_err_cleanup_exit; - msg_pdbg("Raw SPI mode version %c\n", bp_commbuf[0]); - if (bp_commbuf[0] != '1') { + msg_pdbg("Raw SPI mode version %c\n", buspirate_data->bp_commbuf[0]); + if (buspirate_data->bp_commbuf[0] != '1') { msg_perr("Can't handle raw SPI mode version %c!\n", bp_commbuf[0]); ret = 1; goto init_err_cleanup_exit; }
/* Initial setup (SPI peripherals config): Enable power, CS high, AUX */ - bp_commbuf[0] = 0x40 | 0x0b; + buspirate_data->bp_commbuf[0] = 0x40 | 0x0b; if (pullup == 1) { - bp_commbuf[0] |= (1 << 2); + buspirate_data->bp_commbuf[0] |= (1 << 2); msg_pdbg("Enabling pull-up resistors.\n"); } - ret = buspirate_sendrecv(bp_commbuf, 1, 1); + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 1); if (ret) { ret = 1; goto init_err_cleanup_exit; } - if (bp_commbuf[0] != 0x01) { + if (buspirate_data->bp_commbuf[0] != 0x01) { msg_perr("Protocol error while setting power/CS/AUX(/Pull-up resistors)!\n"); ret = 1; goto init_err_cleanup_exit; @@ -628,48 +648,48 @@
/* Set SPI speed */ bp_commbuf[0] = 0x60 | spispeed; - ret = buspirate_sendrecv(bp_commbuf, 1, 1); + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 1); if (ret) { ret = 1; goto init_err_cleanup_exit; } - if (bp_commbuf[0] != 0x01) { + if (buspirate_data->bp_commbuf[0] != 0x01) { msg_perr("Protocol error while setting SPI speed!\n"); ret = 1; goto init_err_cleanup_exit; }
/* Set SPI config: output type, idle, clock edge, sample */ - bp_commbuf[0] = 0x80 | 0xa; + buspirate_data->bp_commbuf[0] = 0x80 | 0xa; if (pullup == 1) { - bp_commbuf[0] &= ~(1 << 3); + buspirate_data->bp_commbuf[0] &= ~(1 << 3); msg_pdbg("Pull-ups enabled, so using HiZ pin output! (Open-Drain mode)\n"); } - ret = buspirate_sendrecv(bp_commbuf, 1, 1); + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 1); if (ret) { ret = 1; goto init_err_cleanup_exit; } - if (bp_commbuf[0] != 0x01) { + if (buspirate_data->bp_commbuf[0] != 0x01) { msg_perr("Protocol error while setting SPI config!\n"); ret = 1; goto init_err_cleanup_exit; }
/* De-assert CS# */ - bp_commbuf[0] = 0x03; - ret = buspirate_sendrecv(bp_commbuf, 1, 1); + buspirate_data->bp_commbuf[0] = 0x03; + ret = buspirate_sendrecv(buspirate_data->bp_commbuf, 1, 1); if (ret) { ret = 1; goto init_err_cleanup_exit; } - if (bp_commbuf[0] != 0x01) { + if (buspirate_data->bp_commbuf[0] != 0x01) { msg_perr("Protocol error while raising CS#!\n"); ret = 1; goto init_err_cleanup_exit; }
- if (register_shutdown(buspirate_spi_shutdown, NULL) != 0) { + if (register_shutdown(buspirate_spi_shutdown, buspirate_data) != 0) { ret = 1; goto init_err_cleanup_exit; } @@ -678,6 +698,6 @@ return 0;
init_err_cleanup_exit: - buspirate_spi_shutdown(NULL); + buspirate_spi_shutdown(buspirate_data); return ret; }