summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnastasia Klimchuk <aklm@chromium.org>2021-02-15 14:57:56 +1100
committerEdward O'Callaghan <quasisec@chromium.org>2021-02-16 23:35:33 +0000
commit7469710d05677c7bc050621cae90ecc044a41231 (patch)
tree098bd0fb80d3be6e537038c7265cd558e21d3b4c
parent6cad608483924cd9c0c0c201ae69ee7e513a0f9e (diff)
downloadflashrom-7469710d05677c7bc050621cae90ecc044a41231.tar.gz
flashrom-7469710d05677c7bc050621cae90ecc044a41231.tar.bz2
flashrom-7469710d05677c7bc050621cae90ecc044a41231.zip
dummyflasher.c: Remove forward-declarations
Reorder functions to avoid forward-declarations BUG=b:140394053 TEST=builds Change-Id: Ibfe9f556316ed509cbec522b4c9cb4c9041e5fdd Signed-off-by: Anastasia Klimchuk <aklm@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/50712 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Sam McNally <sammc@google.com> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
-rw-r--r--dummyflasher.c888
1 files changed, 438 insertions, 450 deletions
diff --git a/dummyflasher.c b/dummyflasher.c
index 92c30ee27..5190282c8 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -102,445 +102,8 @@ static const uint8_t sfdp_table[] = {
#endif
static unsigned int spi_write_256_chunksize = 256;
-
-static int dummy_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr);
-static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf,
- unsigned int start, unsigned int len);
-static void dummy_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
-static void dummy_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr);
-static void dummy_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr);
-static void dummy_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len);
-static uint8_t dummy_chip_readb(const struct flashctx *flash, const chipaddr addr);
-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 struct spi_master spi_master_dummyflasher = {
- .features = SPI_MASTER_4BA,
- .max_data_read = MAX_DATA_READ_UNLIMITED,
- .max_data_write = MAX_DATA_UNSPECIFIED,
- .command = dummy_spi_send_command,
- .multicommand = default_spi_send_multicommand,
- .read = default_spi_read,
- .write_256 = dummy_spi_write_256,
- .write_aai = default_spi_write_aai,
-};
-
-static struct par_master par_master_dummy = {
- .chip_readb = dummy_chip_readb,
- .chip_readw = dummy_chip_readw,
- .chip_readl = dummy_chip_readl,
- .chip_readn = dummy_chip_readn,
- .chip_writeb = dummy_chip_writeb,
- .chip_writew = dummy_chip_writew,
- .chip_writel = dummy_chip_writel,
- .chip_writen = dummy_chip_writen,
-};
-
static enum chipbustype dummy_buses_supported = BUS_NONE;
-static int dummy_shutdown(void *data)
-{
- msg_pspew("%s\n", __func__);
-#if EMULATE_CHIP
- struct emu_data *emu_data = (struct emu_data *)data;
- if (emu_data->emu_chip != EMULATE_NONE) {
- if (emu_data->emu_persistent_image && emu_data->emu_modified) {
- msg_pdbg("Writing %s\n", emu_data->emu_persistent_image);
- write_buf_to_file(flashchip_contents,
- emu_data->emu_chip_size,
- emu_data->emu_persistent_image);
- free(emu_data->emu_persistent_image);
- emu_data->emu_persistent_image = NULL;
- }
- free(flashchip_contents);
- }
-#endif
- return 0;
-}
-
-int dummy_init(void)
-{
- char *bustext = NULL;
- char *tmp = NULL;
- unsigned int i;
-#if EMULATE_SPI_CHIP
- char *status = NULL;
- int size = -1; /* size for VARIABLE_SIZE chip device */
-#endif
-#if EMULATE_CHIP
- struct stat image_stat;
-#endif
-
- struct emu_data *data = calloc(1, sizeof(struct emu_data));
- if (!data) {
- msg_perr("Out of memory!\n");
- return 1;
- }
- data->emu_chip = EMULATE_NONE;
- data->delay_us = 0;
- spi_master_dummyflasher.data = data;
- par_master_dummy.data = data;
-
- msg_pspew("%s\n", __func__);
-
- bustext = extract_programmer_param("bus");
- msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default");
- if (!bustext)
- bustext = strdup("parallel+lpc+fwh+spi");
- /* Convert the parameters to lowercase. */
- tolower_string(bustext);
-
- dummy_buses_supported = BUS_NONE;
- if (strstr(bustext, "parallel")) {
- dummy_buses_supported |= BUS_PARALLEL;
- msg_pdbg("Enabling support for %s flash.\n", "parallel");
- }
- if (strstr(bustext, "lpc")) {
- dummy_buses_supported |= BUS_LPC;
- msg_pdbg("Enabling support for %s flash.\n", "LPC");
- }
- if (strstr(bustext, "fwh")) {
- dummy_buses_supported |= BUS_FWH;
- msg_pdbg("Enabling support for %s flash.\n", "FWH");
- }
- if (strstr(bustext, "spi")) {
- dummy_buses_supported |= BUS_SPI;
- msg_pdbg("Enabling support for %s flash.\n", "SPI");
- }
- if (dummy_buses_supported == BUS_NONE)
- msg_pdbg("Support for all flash bus types disabled.\n");
- free(bustext);
-
- tmp = extract_programmer_param("spi_write_256_chunksize");
- if (tmp) {
- spi_write_256_chunksize = atoi(tmp);
- free(tmp);
- if (spi_write_256_chunksize < 1) {
- msg_perr("invalid spi_write_256_chunksize\n");
- return 1;
- }
- }
-
- tmp = extract_programmer_param("spi_blacklist");
- if (tmp) {
- i = strlen(tmp);
- if (!strncmp(tmp, "0x", 2)) {
- i -= 2;
- memmove(tmp, tmp + 2, i + 1);
- }
- if ((i > 512) || (i % 2)) {
- msg_perr("Invalid SPI command blacklist length\n");
- free(tmp);
- return 1;
- }
- data->spi_blacklist_size = i / 2;
- for (i = 0; i < data->spi_blacklist_size * 2; i++) {
- if (!isxdigit((unsigned char)tmp[i])) {
- msg_perr("Invalid char \"%c\" in SPI command "
- "blacklist\n", tmp[i]);
- free(tmp);
- return 1;
- }
- }
- for (i = 0; i < data->spi_blacklist_size; i++) {
- unsigned int tmp2;
- /* SCNx8 is apparently not supported by MSVC (and thus
- * MinGW), so work around it with an extra variable
- */
- sscanf(tmp + i * 2, "%2x", &tmp2);
- data->spi_blacklist[i] = (uint8_t)tmp2;
- }
- msg_pdbg("SPI blacklist is ");
- for (i = 0; i < data->spi_blacklist_size; i++)
- msg_pdbg("%02x ", data->spi_blacklist[i]);
- msg_pdbg(", size %u\n", data->spi_blacklist_size);
- }
- free(tmp);
-
- tmp = extract_programmer_param("spi_ignorelist");
- if (tmp) {
- i = strlen(tmp);
- if (!strncmp(tmp, "0x", 2)) {
- i -= 2;
- memmove(tmp, tmp + 2, i + 1);
- }
- if ((i > 512) || (i % 2)) {
- msg_perr("Invalid SPI command ignorelist length\n");
- free(tmp);
- return 1;
- }
- data->spi_ignorelist_size = i / 2;
- for (i = 0; i < data->spi_ignorelist_size * 2; i++) {
- if (!isxdigit((unsigned char)tmp[i])) {
- msg_perr("Invalid char \"%c\" in SPI command "
- "ignorelist\n", tmp[i]);
- free(tmp);
- return 1;
- }
- }
- for (i = 0; i < data->spi_ignorelist_size; i++) {
- unsigned int tmp2;
- /* SCNx8 is apparently not supported by MSVC (and thus
- * MinGW), so work around it with an extra variable
- */
- sscanf(tmp + i * 2, "%2x", &tmp2);
- data->spi_ignorelist[i] = (uint8_t)tmp2;
- }
- msg_pdbg("SPI ignorelist is ");
- for (i = 0; i < data->spi_ignorelist_size; i++)
- msg_pdbg("%02x ", data->spi_ignorelist[i]);
- msg_pdbg(", size %u\n", data->spi_ignorelist_size);
- }
- free(tmp);
-
- /* frequency to emulate in Hz (default), KHz, or MHz */
- tmp = extract_programmer_param("freq");
- if (tmp) {
- unsigned long int freq;
- char *units = tmp;
- char *end = tmp + strlen(tmp);
-
- errno = 0;
- freq = strtoul(tmp, &units, 0);
- if (errno) {
- msg_perr("Invalid frequency \"%s\", %s\n",
- tmp, strerror(errno));
- free(tmp);
- return 1;
- }
-
- if ((units > tmp) && (units < end)) {
- int units_valid = 0;
-
- if (units < end - 3) {
- ;
- } else if (units == end - 2) {
- if (!strcasecmp(units, "hz"))
- units_valid = 1;
- } else if (units == end - 3) {
- if (!strcasecmp(units, "khz")) {
- freq *= 1000;
- units_valid = 1;
- } else if (!strcasecmp(units, "mhz")) {
- freq *= 1000000;
- units_valid = 1;
- }
- }
-
- if (!units_valid) {
- msg_perr("Invalid units: %s\n", units);
- free(tmp);
- return 1;
- }
- }
-
- /* Assume we only work with bytes and transfer at 1 bit/Hz */
- data->delay_us = (1000000 * 8) / freq;
- }
- free(tmp);
-
-#if EMULATE_CHIP
-#if EMULATE_SPI_CHIP
- tmp = extract_programmer_param("size");
- if (tmp) {
- size = strtol(tmp, NULL, 10);
- if (size <= 0 || (size % 1024 != 0)) {
- msg_perr("%s: Chip size is not a multipler of 1024: %s\n",
- __func__, tmp);
- free(tmp);
- return 1;
- }
- free(tmp);
- }
-#endif
-
- tmp = extract_programmer_param("emulate");
- if (!tmp) {
- msg_pdbg("Not emulating any flash chip.\n");
- /* Nothing else to do. */
- goto dummy_init_out;
- }
-#if EMULATE_SPI_CHIP
- if (!strcmp(tmp, "M25P10.RES")) {
- data->emu_chip = EMULATE_ST_M25P10_RES;
- data->emu_chip_size = 128 * 1024;
- data->emu_max_byteprogram_size = 128;
- data->emu_max_aai_size = 0;
- data->emu_jedec_se_size = 0;
- data->emu_jedec_be_52_size = 0;
- data->emu_jedec_be_d8_size = 32 * 1024;
- data->emu_jedec_ce_60_size = 0;
- data->emu_jedec_ce_c7_size = data->emu_chip_size;
- msg_pdbg("Emulating ST M25P10.RES SPI flash chip (RES, page "
- "write)\n");
- }
- if (!strcmp(tmp, "SST25VF040.REMS")) {
- data->emu_chip = EMULATE_SST_SST25VF040_REMS;
- data->emu_chip_size = 512 * 1024;
- data->emu_max_byteprogram_size = 1;
- data->emu_max_aai_size = 0;
- data->emu_jedec_se_size = 4 * 1024;
- data->emu_jedec_be_52_size = 32 * 1024;
- data->emu_jedec_be_d8_size = 0;
- data->emu_jedec_ce_60_size = data->emu_chip_size;
- data->emu_jedec_ce_c7_size = 0;
- msg_pdbg("Emulating SST SST25VF040.REMS SPI flash chip (REMS, "
- "byte write)\n");
- }
- if (!strcmp(tmp, "SST25VF032B")) {
- data->emu_chip = EMULATE_SST_SST25VF032B;
- data->emu_chip_size = 4 * 1024 * 1024;
- data->emu_max_byteprogram_size = 1;
- data->emu_max_aai_size = 2;
- data->emu_jedec_se_size = 4 * 1024;
- data->emu_jedec_be_52_size = 32 * 1024;
- data->emu_jedec_be_d8_size = 64 * 1024;
- data->emu_jedec_ce_60_size = data->emu_chip_size;
- data->emu_jedec_ce_c7_size = data->emu_chip_size;
- msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI "
- "write)\n");
- }
- if (!strcmp(tmp, "MX25L6436")) {
- data->emu_chip = EMULATE_MACRONIX_MX25L6436;
- data->emu_chip_size = 8 * 1024 * 1024;
- data->emu_max_byteprogram_size = 256;
- data->emu_max_aai_size = 0;
- data->emu_jedec_se_size = 4 * 1024;
- data->emu_jedec_be_52_size = 32 * 1024;
- data->emu_jedec_be_d8_size = 64 * 1024;
- data->emu_jedec_ce_60_size = data->emu_chip_size;
- data->emu_jedec_ce_c7_size = data->emu_chip_size;
- msg_pdbg("Emulating Macronix MX25L6436 SPI flash chip (RDID, "
- "SFDP)\n");
- }
- if (!strcmp(tmp, "W25Q128FV")) {
- data->emu_chip = EMULATE_WINBOND_W25Q128FV;
- data->emu_chip_size = 16 * 1024 * 1024;
- data->emu_max_byteprogram_size = 256;
- data->emu_max_aai_size = 0;
- data->emu_jedec_se_size = 4 * 1024;
- data->emu_jedec_be_52_size = 32 * 1024;
- data->emu_jedec_be_d8_size = 64 * 1024;
- data->emu_jedec_ce_60_size = data->emu_chip_size;
- data->emu_jedec_ce_c7_size = data->emu_chip_size;
- msg_pdbg("Emulating Winbond W25Q128FV SPI flash chip (RDID)\n");
- }
-
- /* The name of variable-size virtual chip. A 4 MiB flash example:
- * flashrom -p dummy:emulate=VARIABLE_SIZE,size=4194304
- */
- if (!strcmp(tmp, "VARIABLE_SIZE")) {
- if (size == -1) {
- msg_perr("%s: the size parameter is not given.\n", __func__);
- free(tmp);
- return 1;
- }
- data->emu_chip = EMULATE_VARIABLE_SIZE;
- data->emu_chip_size = size;
- data->emu_max_byteprogram_size = 256;
- data->emu_max_aai_size = 0;
- data->emu_jedec_se_size = 4 * 1024;
- data->emu_jedec_be_52_size = 32 * 1024;
- data->emu_jedec_be_d8_size = 64 * 1024;
- data->emu_jedec_ce_60_size = data->emu_chip_size;
- data->emu_jedec_ce_c7_size = data->emu_chip_size;
- msg_pdbg("Emulating generic SPI flash chip (size=%d bytes)\n",
- data->emu_chip_size);
- }
-#endif
- if (data->emu_chip == EMULATE_NONE) {
- msg_perr("Invalid chip specified for emulation: %s\n", tmp);
- free(tmp);
- return 1;
- }
- free(tmp);
-
- /* Should emulated flash erase to zero (yes/no)? */
- tmp = extract_programmer_param("erase_to_zero");
- if (tmp) {
- if (!strcmp(tmp, "yes")) {
- msg_pdbg("Emulated chip will erase to 0x00\n");
- data->erase_to_zero = 1;
- } else if (!strcmp(tmp, "no")) {
- msg_pdbg("Emulated chip will erase to 0xff\n");
- } else {
- msg_perr("erase_to_zero can be \"yes\" or \"no\"\n");
- free(tmp);
- return 1;
- }
- }
- free(tmp);
-
- flashchip_contents = malloc(data->emu_chip_size);
- if (!flashchip_contents) {
- msg_perr("Out of memory!\n");
- return 1;
- }
-
-#ifdef EMULATE_SPI_CHIP
- status = extract_programmer_param("spi_status");
- if (status) {
- char *endptr;
- errno = 0;
- data->emu_status = strtoul(status, &endptr, 0);
- free(status);
- if (errno != 0 || status == endptr) {
- msg_perr("Error: initial status register specified, "
- "but the value could not be converted.\n");
- return 1;
- }
- msg_pdbg("Initial status register is set to 0x%02x.\n",
- data->emu_status);
- }
-#endif
-
- msg_pdbg("Filling fake flash chip with 0x%02x, size %i\n",
- data->erase_to_zero ? 0x00 : 0xff, data->emu_chip_size);
- memset(flashchip_contents, data->erase_to_zero ? 0x00 : 0xff, data->emu_chip_size);
-
- /* Will be freed by shutdown function if necessary. */
- data->emu_persistent_image = extract_programmer_param("image");
- if (!data->emu_persistent_image) {
- /* Nothing else to do. */
- goto dummy_init_out;
- }
- /* We will silently (in default verbosity) ignore the file if it does not exist (yet) or the size does
- * not match the emulated chip. */
- if (!stat(data->emu_persistent_image, &image_stat)) {
- msg_pdbg("Found persistent image %s, %jd B ",
- data->emu_persistent_image, (intmax_t)image_stat.st_size);
- if ((uintmax_t)image_stat.st_size == data->emu_chip_size) {
- msg_pdbg("matches.\n");
- msg_pdbg("Reading %s\n", data->emu_persistent_image);
- if (read_buf_from_file(flashchip_contents, data->emu_chip_size,
- data->emu_persistent_image)) {
- msg_perr("Unable to read %s\n", data->emu_persistent_image);
- free(flashchip_contents);
- return 1;
- }
- } else {
- msg_pdbg("doesn't match.\n");
- }
- }
-#endif
-
-dummy_init_out:
- if (register_shutdown(dummy_shutdown, data)) {
- free(flashchip_contents);
- free(data);
- return 1;
- }
- if (dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH))
- register_par_master(&par_master_dummy,
- dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH));
- if (dummy_buses_supported & BUS_SPI)
- register_spi_master(&spi_master_dummyflasher);
-
- return 0;
-}
-
void *dummy_map(const char *descr, uintptr_t phys_addr, size_t len)
{
msg_pspew("%s: Mapping %s, 0x%zx bytes at 0x%0*" PRIxPTR "\n",
@@ -553,6 +116,12 @@ void dummy_unmap(void *virt_addr, size_t len)
msg_pspew("%s: Unmapping 0x%zx bytes at %p\n", __func__, len, virt_addr);
}
+static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
+{
+ return spi_write_chunked(flash, buf, start, len,
+ spi_write_256_chunksize);
+}
+
static void dummy_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%02x\n", __func__, addr, val);
@@ -604,6 +173,16 @@ static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf, const c
return;
}
+static struct emu_data* get_data_from_context(const struct flashctx *flash)
+{
+ if (dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH))
+ return (struct emu_data *)flash->mst->par.data;
+ else if (dummy_buses_supported & BUS_SPI)
+ return (struct emu_data *)flash->mst->spi.data;
+
+ return NULL; /* buses was set to BUS_NONE. */
+}
+
#if EMULATE_SPI_CHIP
static int emulate_spi_chip_response(unsigned int writecnt,
unsigned int readcnt,
@@ -983,16 +562,6 @@ static int emulate_spi_chip_response(unsigned int writecnt,
}
#endif
-static struct emu_data* get_data_from_context(const struct flashctx *flash)
-{
- if (dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH))
- return (struct emu_data *)flash->mst->par.data;
- else if (dummy_buses_supported & BUS_SPI)
- return (struct emu_data *)flash->mst->spi.data;
-
- return NULL; /* buses was set to BUS_NONE. */
-}
-
static int dummy_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
const unsigned char *writearr,
@@ -1040,10 +609,429 @@ static int dummy_spi_send_command(const struct flashctx *flash, unsigned int wri
return 0;
}
-static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
+
+
+static struct spi_master spi_master_dummyflasher = {
+ .features = SPI_MASTER_4BA,
+ .max_data_read = MAX_DATA_READ_UNLIMITED,
+ .max_data_write = MAX_DATA_UNSPECIFIED,
+ .command = dummy_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = default_spi_read,
+ .write_256 = dummy_spi_write_256,
+ .write_aai = default_spi_write_aai,
+};
+
+static struct par_master par_master_dummy = {
+ .chip_readb = dummy_chip_readb,
+ .chip_readw = dummy_chip_readw,
+ .chip_readl = dummy_chip_readl,
+ .chip_readn = dummy_chip_readn,
+ .chip_writeb = dummy_chip_writeb,
+ .chip_writew = dummy_chip_writew,
+ .chip_writel = dummy_chip_writel,
+ .chip_writen = dummy_chip_writen,
+};
+
+static int dummy_shutdown(void *data)
{
- return spi_write_chunked(flash, buf, start, len,
- spi_write_256_chunksize);
+ msg_pspew("%s\n", __func__);
+#if EMULATE_CHIP
+ struct emu_data *emu_data = (struct emu_data *)data;
+ if (emu_data->emu_chip != EMULATE_NONE) {
+ if (emu_data->emu_persistent_image && emu_data->emu_modified) {
+ msg_pdbg("Writing %s\n", emu_data->emu_persistent_image);
+ write_buf_to_file(flashchip_contents,
+ emu_data->emu_chip_size,
+ emu_data->emu_persistent_image);
+ free(emu_data->emu_persistent_image);
+ emu_data->emu_persistent_image = NULL;
+ }
+ free(flashchip_contents);
+ }
+#endif
+ return 0;
+}
+
+int dummy_init(void)
+{
+ char *bustext = NULL;
+ char *tmp = NULL;
+ unsigned int i;
+#if EMULATE_SPI_CHIP
+ char *status = NULL;
+ int size = -1; /* size for VARIABLE_SIZE chip device */
+#endif
+#if EMULATE_CHIP
+ struct stat image_stat;
+#endif
+
+ struct emu_data *data = calloc(1, sizeof(struct emu_data));
+ if (!data) {
+ msg_perr("Out of memory!\n");
+ return 1;
+ }
+ data->emu_chip = EMULATE_NONE;
+ data->delay_us = 0;
+ spi_master_dummyflasher.data = data;
+ par_master_dummy.data = data;
+
+ msg_pspew("%s\n", __func__);
+
+ bustext = extract_programmer_param("bus");
+ msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default");
+ if (!bustext)
+ bustext = strdup("parallel+lpc+fwh+spi");
+ /* Convert the parameters to lowercase. */
+ tolower_string(bustext);
+
+ dummy_buses_supported = BUS_NONE;
+ if (strstr(bustext, "parallel")) {
+ dummy_buses_supported |= BUS_PARALLEL;
+ msg_pdbg("Enabling support for %s flash.\n", "parallel");
+ }
+ if (strstr(bustext, "lpc")) {
+ dummy_buses_supported |= BUS_LPC;
+ msg_pdbg("Enabling support for %s flash.\n", "LPC");
+ }
+ if (strstr(bustext, "fwh")) {
+ dummy_buses_supported |= BUS_FWH;
+ msg_pdbg("Enabling support for %s flash.\n", "FWH");
+ }
+ if (strstr(bustext, "spi")) {
+ dummy_buses_supported |= BUS_SPI;
+ msg_pdbg("Enabling support for %s flash.\n", "SPI");
+ }
+ if (dummy_buses_supported == BUS_NONE)
+ msg_pdbg("Support for all flash bus types disabled.\n");
+ free(bustext);
+
+ tmp = extract_programmer_param("spi_write_256_chunksize");
+ if (tmp) {
+ spi_write_256_chunksize = atoi(tmp);
+ free(tmp);
+ if (spi_write_256_chunksize < 1) {
+ msg_perr("invalid spi_write_256_chunksize\n");
+ return 1;
+ }
+ }
+
+ tmp = extract_programmer_param("spi_blacklist");
+ if (tmp) {
+ i = strlen(tmp);
+ if (!strncmp(tmp, "0x", 2)) {
+ i -= 2;
+ memmove(tmp, tmp + 2, i + 1);
+ }
+ if ((i > 512) || (i % 2)) {
+ msg_perr("Invalid SPI command blacklist length\n");
+ free(tmp);
+ return 1;
+ }
+ data->spi_blacklist_size = i / 2;
+ for (i = 0; i < data->spi_blacklist_size * 2; i++) {
+ if (!isxdigit((unsigned char)tmp[i])) {
+ msg_perr("Invalid char \"%c\" in SPI command "
+ "blacklist\n", tmp[i]);
+ free(tmp);
+ return 1;
+ }
+ }
+ for (i = 0; i < data->spi_blacklist_size; i++) {
+ unsigned int tmp2;
+ /* SCNx8 is apparently not supported by MSVC (and thus
+ * MinGW), so work around it with an extra variable
+ */
+ sscanf(tmp + i * 2, "%2x", &tmp2);
+ data->spi_blacklist[i] = (uint8_t)tmp2;
+ }
+ msg_pdbg("SPI blacklist is ");
+ for (i = 0; i < data->spi_blacklist_size; i++)
+ msg_pdbg("%02x ", data->spi_blacklist[i]);
+ msg_pdbg(", size %u\n", data->spi_blacklist_size);
+ }
+ free(tmp);
+
+ tmp = extract_programmer_param("spi_ignorelist");
+ if (tmp) {
+ i = strlen(tmp);
+ if (!strncmp(tmp, "0x", 2)) {
+ i -= 2;
+ memmove(tmp, tmp + 2, i + 1);
+ }
+ if ((i > 512) || (i % 2)) {
+ msg_perr("Invalid SPI command ignorelist length\n");
+ free(tmp);
+ return 1;
+ }
+ data->spi_ignorelist_size = i / 2;
+ for (i = 0; i < data->spi_ignorelist_size * 2; i++) {
+ if (!isxdigit((unsigned char)tmp[i])) {
+ msg_perr("Invalid char \"%c\" in SPI command "
+ "ignorelist\n", tmp[i]);
+ free(tmp);
+ return 1;
+ }
+ }
+ for (i = 0; i < data->spi_ignorelist_size; i++) {
+ unsigned int tmp2;
+ /* SCNx8 is apparently not supported by MSVC (and thus
+ * MinGW), so work around it with an extra variable
+ */
+ sscanf(tmp + i * 2, "%2x", &tmp2);
+ data->spi_ignorelist[i] = (uint8_t)tmp2;
+ }
+ msg_pdbg("SPI ignorelist is ");
+ for (i = 0; i < data->spi_ignorelist_size; i++)
+ msg_pdbg("%02x ", data->spi_ignorelist[i]);
+ msg_pdbg(", size %u\n", data->spi_ignorelist_size);
+ }
+ free(tmp);
+
+ /* frequency to emulate in Hz (default), KHz, or MHz */
+ tmp = extract_programmer_param("freq");
+ if (tmp) {
+ unsigned long int freq;
+ char *units = tmp;
+ char *end = tmp + strlen(tmp);
+
+ errno = 0;
+ freq = strtoul(tmp, &units, 0);
+ if (errno) {
+ msg_perr("Invalid frequency \"%s\", %s\n",
+ tmp, strerror(errno));
+ free(tmp);
+ return 1;
+ }
+
+ if ((units > tmp) && (units < end)) {
+ int units_valid = 0;
+
+ if (units < end - 3) {
+ ;
+ } else if (units == end - 2) {
+ if (!strcasecmp(units, "hz"))
+ units_valid = 1;
+ } else if (units == end - 3) {
+ if (!strcasecmp(units, "khz")) {
+ freq *= 1000;
+ units_valid = 1;
+ } else if (!strcasecmp(units, "mhz")) {
+ freq *= 1000000;
+ units_valid = 1;
+ }
+ }
+
+ if (!units_valid) {
+ msg_perr("Invalid units: %s\n", units);
+ free(tmp);
+ return 1;
+ }
+ }
+
+ /* Assume we only work with bytes and transfer at 1 bit/Hz */
+ data->delay_us = (1000000 * 8) / freq;
+ }
+ free(tmp);
+
+#if EMULATE_CHIP
+#if EMULATE_SPI_CHIP
+ tmp = extract_programmer_param("size");
+ if (tmp) {
+ size = strtol(tmp, NULL, 10);
+ if (size <= 0 || (size % 1024 != 0)) {
+ msg_perr("%s: Chip size is not a multipler of 1024: %s\n",
+ __func__, tmp);
+ free(tmp);
+ return 1;
+ }
+ free(tmp);
+ }
+#endif
+
+ tmp = extract_programmer_param("emulate");
+ if (!tmp) {
+ msg_pdbg("Not emulating any flash chip.\n");
+ /* Nothing else to do. */
+ goto dummy_init_out;
+ }
+#if EMULATE_SPI_CHIP
+ if (!strcmp(tmp, "M25P10.RES")) {
+ data->emu_chip = EMULATE_ST_M25P10_RES;
+ data->emu_chip_size = 128 * 1024;
+ data->emu_max_byteprogram_size = 128;
+ data->emu_max_aai_size = 0;
+ data->emu_jedec_se_size = 0;
+ data->emu_jedec_be_52_size = 0;
+ data->emu_jedec_be_d8_size = 32 * 1024;
+ data->emu_jedec_ce_60_size = 0;
+ data->emu_jedec_ce_c7_size = data->emu_chip_size;
+ msg_pdbg("Emulating ST M25P10.RES SPI flash chip (RES, page "
+ "write)\n");
+ }
+ if (!strcmp(tmp, "SST25VF040.REMS")) {
+ data->emu_chip = EMULATE_SST_SST25VF040_REMS;
+ data->emu_chip_size = 512 * 1024;
+ data->emu_max_byteprogram_size = 1;
+ data->emu_max_aai_size = 0;
+ data->emu_jedec_se_size = 4 * 1024;
+ data->emu_jedec_be_52_size = 32 * 1024;
+ data->emu_jedec_be_d8_size = 0;
+ data->emu_jedec_ce_60_size = data->emu_chip_size;
+ data->emu_jedec_ce_c7_size = 0;
+ msg_pdbg("Emulating SST SST25VF040.REMS SPI flash chip (REMS, "
+ "byte write)\n");
+ }
+ if (!strcmp(tmp, "SST25VF032B")) {
+ data->emu_chip = EMULATE_SST_SST25VF032B;
+ data->emu_chip_size = 4 * 1024 * 1024;
+ data->emu_max_byteprogram_size = 1;
+ data->emu_max_aai_size = 2;
+ data->emu_jedec_se_size = 4 * 1024;
+ data->emu_jedec_be_52_size = 32 * 1024;
+ data->emu_jedec_be_d8_size = 64 * 1024;
+ data->emu_jedec_ce_60_size = data->emu_chip_size;
+ data->emu_jedec_ce_c7_size = data->emu_chip_size;
+ msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI "
+ "write)\n");
+ }
+ if (!strcmp(tmp, "MX25L6436")) {
+ data->emu_chip = EMULATE_MACRONIX_MX25L6436;
+ data->emu_chip_size = 8 * 1024 * 1024;
+ data->emu_max_byteprogram_size = 256;
+ data->emu_max_aai_size = 0;
+ data->emu_jedec_se_size = 4 * 1024;
+ data->emu_jedec_be_52_size = 32 * 1024;
+ data->emu_jedec_be_d8_size = 64 * 1024;
+ data->emu_jedec_ce_60_size = data->emu_chip_size;
+ data->emu_jedec_ce_c7_size = data->emu_chip_size;
+ msg_pdbg("Emulating Macronix MX25L6436 SPI flash chip (RDID, "
+ "SFDP)\n");
+ }
+ if (!strcmp(tmp, "W25Q128FV")) {
+ data->emu_chip = EMULATE_WINBOND_W25Q128FV;
+ data->emu_chip_size = 16 * 1024 * 1024;
+ data->emu_max_byteprogram_size = 256;
+ data->emu_max_aai_size = 0;
+ data->emu_jedec_se_size = 4 * 1024;
+ data->emu_jedec_be_52_size = 32 * 1024;
+ data->emu_jedec_be_d8_size = 64 * 1024;
+ data->emu_jedec_ce_60_size = data->emu_chip_size;
+ data->emu_jedec_ce_c7_size = data->emu_chip_size;
+ msg_pdbg("Emulating Winbond W25Q128FV SPI flash chip (RDID)\n");
+ }
+
+ /* The name of variable-size virtual chip. A 4 MiB flash example:
+ * flashrom -p dummy:emulate=VARIABLE_SIZE,size=4194304
+ */
+ if (!strcmp(tmp, "VARIABLE_SIZE")) {
+ if (size == -1) {
+ msg_perr("%s: the size parameter is not given.\n", __func__);
+ free(tmp);
+ return 1;
+ }
+ data->emu_chip = EMULATE_VARIABLE_SIZE;
+ data->emu_chip_size = size;
+ data->emu_max_byteprogram_size = 256;
+ data->emu_max_aai_size = 0;
+ data->emu_jedec_se_size = 4 * 1024;
+ data->emu_jedec_be_52_size = 32 * 1024;
+ data->emu_jedec_be_d8_size = 64 * 1024;
+ data->emu_jedec_ce_60_size = data->emu_chip_size;
+ data->emu_jedec_ce_c7_size = data->emu_chip_size;
+ msg_pdbg("Emulating generic SPI flash chip (size=%d bytes)\n",
+ data->emu_chip_size);
+ }
+#endif
+ if (data->emu_chip == EMULATE_NONE) {
+ msg_perr("Invalid chip specified for emulation: %s\n", tmp);
+ free(tmp);
+ return 1;
+ }
+ free(tmp);
+
+ /* Should emulated flash erase to zero (yes/no)? */
+ tmp = extract_programmer_param("erase_to_zero");
+ if (tmp) {
+ if (!strcmp(tmp, "yes")) {
+ msg_pdbg("Emulated chip will erase to 0x00\n");
+ data->erase_to_zero = 1;
+ } else if (!strcmp(tmp, "no")) {
+ msg_pdbg("Emulated chip will erase to 0xff\n");
+ } else {
+ msg_perr("erase_to_zero can be \"yes\" or \"no\"\n");
+ free(tmp);
+ return 1;
+ }
+ }
+ free(tmp);
+
+ flashchip_contents = malloc(data->emu_chip_size);
+ if (!flashchip_contents) {
+ msg_perr("Out of memory!\n");
+ return 1;
+ }
+
+#ifdef EMULATE_SPI_CHIP
+ status = extract_programmer_param("spi_status");
+ if (status) {
+ char *endptr;
+ errno = 0;
+ data->emu_status = strtoul(status, &endptr, 0);
+ free(status);
+ if (errno != 0 || status == endptr) {
+ msg_perr("Error: initial status register specified, "
+ "but the value could not be converted.\n");
+ return 1;
+ }
+ msg_pdbg("Initial status register is set to 0x%02x.\n",
+ data->emu_status);
+ }
+#endif
+
+ msg_pdbg("Filling fake flash chip with 0x%02x, size %i\n",
+ data->erase_to_zero ? 0x00 : 0xff, data->emu_chip_size);
+ memset(flashchip_contents, data->erase_to_zero ? 0x00 : 0xff, data->emu_chip_size);
+
+ /* Will be freed by shutdown function if necessary. */
+ data->emu_persistent_image = extract_programmer_param("image");
+ if (!data->emu_persistent_image) {
+ /* Nothing else to do. */
+ goto dummy_init_out;
+ }
+ /* We will silently (in default verbosity) ignore the file if it does not exist (yet) or the size does
+ * not match the emulated chip. */
+ if (!stat(data->emu_persistent_image, &image_stat)) {
+ msg_pdbg("Found persistent image %s, %jd B ",
+ data->emu_persistent_image, (intmax_t)image_stat.st_size);
+ if ((uintmax_t)image_stat.st_size == data->emu_chip_size) {
+ msg_pdbg("matches.\n");
+ msg_pdbg("Reading %s\n", data->emu_persistent_image);
+ if (read_buf_from_file(flashchip_contents, data->emu_chip_size,
+ data->emu_persistent_image)) {
+ msg_perr("Unable to read %s\n", data->emu_persistent_image);
+ free(flashchip_contents);
+ return 1;
+ }
+ } else {
+ msg_pdbg("doesn't match.\n");
+ }
+ }
+#endif
+
+dummy_init_out:
+ if (register_shutdown(dummy_shutdown, data)) {
+ free(flashchip_contents);
+ free(data);
+ return 1;
+ }
+ if (dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH))
+ register_par_master(&par_master_dummy,
+ dummy_buses_supported & (BUS_PARALLEL | BUS_LPC | BUS_FWH));
+ if (dummy_buses_supported & BUS_SPI)
+ register_spi_master(&spi_master_dummyflasher);
+
+ return 0;
}
#if EMULATE_CHIP && EMULATE_SPI_CHIP