diff options
author | Anastasia Klimchuk <aklm@chromium.org> | 2021-02-15 14:57:56 +1100 |
---|---|---|
committer | Edward O'Callaghan <quasisec@chromium.org> | 2021-02-16 23:35:33 +0000 |
commit | 7469710d05677c7bc050621cae90ecc044a41231 (patch) | |
tree | 098bd0fb80d3be6e537038c7265cd558e21d3b4c | |
parent | 6cad608483924cd9c0c0c201ae69ee7e513a0f9e (diff) | |
download | flashrom-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.c | 888 |
1 files changed, 438 insertions, 450 deletions
diff --git a/dummyflasher.c b/dummyflasher.c index 92c30ee2..5190282c 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 |