diff --git a/dummyflasher.c b/dummyflasher.c index 99f81f5f74052e4e8759da2ba139a8c4af4870f4..6281ff898f4d7572ab2efac901349d074d77d18e 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -19,6 +19,8 @@ #include <string.h> #include <stdlib.h> +#include <stdio.h> +#include <ctype.h> #include "flash.h" #include "chipdrivers.h" #include "programmer.h" @@ -55,6 +57,10 @@ static unsigned int emu_jedec_be_52_size = 0; static unsigned int emu_jedec_be_d8_size = 0; static unsigned int emu_jedec_ce_60_size = 0; static unsigned int emu_jedec_ce_c7_size = 0; +unsigned char spi_blacklist[256]; +unsigned char spi_ignorelist[256]; +int spi_blacklist_size = 0; +int spi_ignorelist_size = 0; #endif #endif @@ -126,6 +132,7 @@ int dummy_init(void) { char *bustext = NULL; char *tmp = NULL; + int i; #if EMULATE_CHIP struct stat image_stat; #endif @@ -170,6 +177,68 @@ int dummy_init(void) } } + 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; + } + spi_blacklist_size = i / 2; + for (i = 0; i < 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 < spi_blacklist_size; i++) { + sscanf(tmp + i * 2, "%2hhx", &spi_blacklist[i]); + } + msg_pdbg("SPI blacklist is "); + for (i = 0; i < spi_blacklist_size; i++) + msg_pdbg("%02x ", spi_blacklist[i]); + msg_pdbg(", size %i\n", 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; + } + spi_ignorelist_size = i / 2; + for (i = 0; i < 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 < spi_ignorelist_size; i++) { + sscanf(tmp + i * 2, "%2hhx", &spi_ignorelist[i]); + } + msg_pdbg("SPI ignorelist is "); + for (i = 0; i < spi_ignorelist_size; i++) + msg_pdbg("%02x ", spi_ignorelist[i]); + msg_pdbg(", size %i\n", spi_ignorelist_size); + } + free(tmp); + #if EMULATE_CHIP tmp = extract_programmer_param("emulate"); if (!tmp) { @@ -348,7 +417,7 @@ static int emulate_spi_chip_response(unsigned int writecnt, const unsigned char *writearr, unsigned char *readarr) { - unsigned int offs; + unsigned int offs, i; static int unsigned aai_offs; static int aai_active = 0; @@ -356,7 +425,24 @@ static int emulate_spi_chip_response(unsigned int writecnt, msg_perr("No command sent to the chip!\n"); return 1; } - /* TODO: Implement command blacklists here. */ + /* spi_blacklist has precedence before spi_ignorelist. */ + for (i = 0; i < spi_blacklist_size; i++) { + if (writearr[0] == spi_blacklist[i]) { + msg_pdbg("Refusing blacklisted SPI command 0x%02x\n", + spi_blacklist[i]); + return SPI_INVALID_OPCODE; + } + } + for (i = 0; i < spi_ignorelist_size; i++) { + if (writearr[0] == spi_ignorelist[i]) { + msg_cdbg("Ignoring ignorelisted SPI command 0x%02x\n", + spi_ignorelist[i]); + /* Return success because the command does not fail, + * it is simply ignored. + */ + return 0; + } + } switch (writearr[0]) { case JEDEC_RES: if (emu_chip != EMULATE_ST_M25P10_RES) @@ -563,7 +649,7 @@ static int dummy_spi_send_command(struct flashctx *flash, unsigned int writecnt, case EMULATE_SST_SST25VF032B: if (emulate_spi_chip_response(writecnt, readcnt, writearr, readarr)) { - msg_perr("Invalid command sent to flash chip!\n"); + msg_pdbg("Invalid command sent to flash chip!\n"); return 1; } break; diff --git a/flashrom.8 b/flashrom.8 index 6b25b43dc72e4b6276f5d0453f91003305105395..2f23cb80c72cf005c2a521dc7bcdb8b9983d1ad4 100644 --- a/flashrom.8 +++ b/flashrom.8 @@ -421,6 +421,28 @@ is the number of bytes (min. 1, max. 256). Example: .sp .B " flashrom -p dummy:emulate=M25P10.RES,spi_write_256_chunksize=5" +.sp +To simulate a programmer which refuses to send certain SPI commands to the +flash chip, you can specify a blacklist of SPI commands with the +.sp +.B " flashrom -p dummy:spi_blacklist=commandlist" +.sp +syntax where commandlist is a list of two-digit hexadecimal representations of +SPI commands. If commandlist is e.g. 0302, flashrom will behave as if the SPI +controller refuses to run command 0x03 (READ) and command 0x02 (WRITE). +commandlist may be up to 512 characters (256 commands) long. +Implementation note: flashrom will detect an error during command execution. +.sp +To simulate a flash chip which ignores (doesn't support) certain SPI commands, +you can specify an ignorelist of SPI commands with the +.sp +.B " flashrom -p dummy:spi_ignorelist=commandlist" +.sp +syntax where commandlist is a list of two-digit hexadecimal representations of +SPI commands. If commandlist is e.g. 0302, the emulated flash chip will ignore +command 0x03 (READ) and command 0x02 (WRITE). commandlist may be up to 512 +characters (256 commands) long. +Implementation note: flashrom won't detect an error during command execution. .TP .BR "nic3com" , " nicrealtek" , " nicsmc1211" , " nicnatsemi" , " nicintel\ " , " nicintel_spi" , " gfxnvidia" , " ogp_spi" , " drkaiser" , " satasii\