Use separate functions for managing the Bus Pirate command/data buffer. Open-coding the buffer management was the first step, now the goal is to make it readable. This is the buffer management part of "Re: [flashrom] [PATCH] Make Bus Pirate init more robust, speed up flashing"
The buffer management of the Bus Pirate driver has been revamped to use grow-only buffers with a reasonable initial default size so realloc() will not have to be called in normal operation. A side effect is the ability to switch to a static buffer without major hassle. Handle OOM gracefully.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-buspirate_buffermanagement/flash.h =================================================================== --- flashrom-buspirate_buffermanagement/flash.h (Revision 1184) +++ flashrom-buspirate_buffermanagement/flash.h (Arbeitskopie) @@ -35,6 +35,9 @@
#define ERROR_PTR ((void*)-1)
+/* Error codes */ +#define OOM_ERROR -100 + typedef unsigned long chipaddr;
int register_shutdown(void (*function) (void *data), void *data); Index: flashrom-buspirate_buffermanagement/buspirate_spi.c =================================================================== --- flashrom-buspirate_buffermanagement/buspirate_spi.c (Revision 1184) +++ flashrom-buspirate_buffermanagement/buspirate_spi.c (Arbeitskopie) @@ -46,6 +46,55 @@ #define sp_flush_incoming(...) 0 #endif
+static unsigned char *bp_commbuf = NULL; +static int bp_commbufsize = 0; + +static int buspirate_commbuf_resize(int bufsize) +{ + unsigned char *tmpbuf; + + /* Never shrink. realloc() calls are expensive. */ + if (bufsize <= bp_commbufsize) + return 0; + + tmpbuf = realloc(bp_commbuf, bufsize); + if (!tmpbuf) { + /* This is debatable. Do we really want to free the existing + * buffer or do we want to keep it around, especially if memory + * is already tight? + */ + free(bp_commbuf); + bp_commbuf = NULL; + bp_commbufsize = 0; + msg_perr("Out of memory!\n"); + return OOM_ERROR; + } + + bp_commbuf = tmpbuf; + bp_commbufsize = bufsize; + return 0; +} + +static int buspirate_commbuf_init(int bufsize) +{ + bp_commbuf = malloc(bufsize); + if (!bp_commbuf) { + bp_commbufsize = 0; + msg_perr("Out of memory!\n"); + return OOM_ERROR; + } + + bp_commbufsize = bufsize; + return 0; +} + +static void buspirate_commbuf_shutdown(void) +{ + free(bp_commbuf); + bp_commbuf = NULL; + bp_commbufsize = 0; +} + static int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt, unsigned int readcnt) { int i, ret = 0; @@ -231,6 +280,10 @@ return 1; }
+ /* Sensible default buffer size. */ + if (buspirate_commbuf_init(16 + 3)) + return OOM_ERROR; + buses_supported = CHIP_BUSTYPE_SPI; spi_controller = SPI_CONTROLLER_BUSPIRATE;
@@ -267,6 +320,9 @@ ret = serialport_shutdown(); if (ret) return ret; + + buspirate_commbuf_shutdown(); + msg_pdbg("Bus Pirate shutdown completed.\n");
return 0; @@ -275,55 +331,51 @@ int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { - static unsigned char *buf = NULL; int i = 0, ret = 0;
if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16) return SPI_INVALID_LENGTH;
/* 3 bytes extra for CS#, len, CS#. */ - buf = realloc(buf, writecnt + readcnt + 3); - if (!buf) { - msg_perr("Out of memory!\n"); - exit(1); // -1 - } + if (buspirate_commbuf_resize(writecnt + readcnt + 3)) + return OOM_ERROR;
/* Assert CS# */ - buf[i++] = 0x02; + bp_commbuf[i++] = 0x02;
- buf[i++] = 0x10 | (writecnt + readcnt - 1); - memcpy(buf + i, writearr, writecnt); + bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1); + memcpy(bp_commbuf + i, writearr, writecnt); i += writecnt; - memset(buf + i, 0, readcnt); + memset(bp_commbuf + i, 0, readcnt);
i += readcnt; /* De-assert CS# */ - buf[i++] = 0x03; + bp_commbuf[i++] = 0x03;
- ret = buspirate_sendrecv(buf, i, i); + ret = buspirate_sendrecv(bp_commbuf, i, i);
if (ret) { msg_perr("Bus Pirate communication error!\n"); return SPI_GENERIC_ERROR; }
- if (buf[0] != 0x01) { + if (bp_commbuf[0] != 0x01) { msg_perr("Protocol error while lowering CS#!\n"); return SPI_GENERIC_ERROR; }
- if (buf[1] != 0x01) { + if (bp_commbuf[1] != 0x01) { msg_perr("Protocol error while reading/writing SPI!\n"); return SPI_GENERIC_ERROR; }
- if (buf[i - 1] != 0x01) { + if (bp_commbuf[i - 1] != 0x01) { msg_perr("Protocol error while raising CS#!\n"); return SPI_GENERIC_ERROR; }
/* Skip CS#, length, writearr. */ - memcpy(readarr, buf + 2 + writecnt, readcnt); + memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt);
return ret; }