New version with additional bugfixes and man page. The man page formatting is broken, I'd appreciate help from someone who knows how to fix the formatting.
Add optional SPI command blacklisting to the flash chip emulator in the dummy programmer.
Usage: flashrom -p dummy:spi_blacklist=hexstring
If hexstring is 0302, flashrom will blacklist command 0x03 (READ) and command 0x02 (WRITE). The hexstring can have up to 521 bytes (256 commands) length, and must not start with 0x.
TODO: Should 0x at the beginning of hexstring be tolerated?
Very useful for testing corner cases if you don't own a locked down Intel chipset and want to simulate such a thing.
Fix out-of-bounds access in the simulator command checking code.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-emulate_spi_flashchip_command_blacklist/dummyflasher.c =================================================================== --- flashrom-emulate_spi_flashchip_command_blacklist/dummyflasher.c (Revision 1252) +++ flashrom-emulate_spi_flashchip_command_blacklist/dummyflasher.c (Arbeitskopie) @@ -19,6 +19,7 @@
#include <string.h> #include <stdlib.h> +#include <stdio.h> #include "flash.h" #include "chipdrivers.h" #include "programmer.h" @@ -55,6 +56,8 @@ static int emu_jedec_be_d8_size = 0; static int emu_jedec_ce_60_size = 0; static int emu_jedec_ce_c7_size = 0; +unsigned char spi_blacklist[256]; +int spi_blacklist_size = 0; #endif #endif
@@ -64,6 +67,8 @@ { char *bustext = NULL; char *tmp = NULL; + char *tmp2 = NULL; + int i; #if EMULATE_CHIP struct stat image_stat; #endif @@ -109,6 +114,35 @@ } }
+ tmp = extract_programmer_param("spi_blacklist"); + if (tmp) { + tolower_string(tmp); + tmp2 = tmp; + if (!strncmp(tmp2, "0x", 2)) { + tmp2 += 2; + } + i = strlen(tmp2); + if ((i > 512) || (i % 2)) { + msg_perr("Invalid SPI command blacklist length\n"); + free(tmp); + return 1; + } + if (strspn(tmp2, "0123456789abcdef") != i) { + msg_perr("Invalid chars in SPI command blacklist\n"); + free(tmp); + return 1; + } + spi_blacklist_size = i / 2; + for (i = 0; i < spi_blacklist_size; i++) { + sscanf(tmp2 + 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); + #if EMULATE_CHIP tmp = extract_programmer_param("emulate"); if (!tmp) { @@ -278,7 +312,7 @@ static int emulate_spi_chip_response(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { - int offs; + int offs, i; static int aai_offs; static int aai_active = 0;
@@ -286,7 +320,16 @@ msg_perr("No command sent to the chip!\n"); return 1; } - /* TODO: Implement command blacklists here. */ + for (i = 0; i < spi_blacklist_size; i++) { + if (writearr[0] == spi_blacklist[i]) { + msg_perr("Refusing blacklisted SPI command 0x%02x\n", + spi_blacklist[i]); + /* FIXME: Do we want a separate return code for + * command unavailable? + */ + return 1; + } + } switch (writearr[0]) { case JEDEC_RES: if (emu_chip != EMULATE_ST_M25P10_RES) @@ -395,7 +438,7 @@ } offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; if (offs & (emu_jedec_se_size - 1)) - msg_pdbg("Unaligned SECTOR ERASE 0x20\n"); + msg_pdbg("Unaligned SECTOR ERASE 0x20: 0x%x\n", offs); offs &= ~(emu_jedec_se_size - 1); memset(flashchip_contents + offs, 0xff, emu_jedec_se_size); break; @@ -412,7 +455,7 @@ } offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; if (offs & (emu_jedec_be_52_size - 1)) - msg_pdbg("Unaligned BLOCK ERASE 0x52\n"); + msg_pdbg("Unaligned BLOCK ERASE 0x52: 0x%x\n", offs); offs &= ~(emu_jedec_be_52_size - 1); memset(flashchip_contents + offs, 0xff, emu_jedec_be_52_size); break; @@ -429,7 +472,7 @@ } offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; if (offs & (emu_jedec_be_d8_size - 1)) - msg_pdbg("Unaligned BLOCK ERASE 0xd8\n"); + msg_pdbg("Unaligned BLOCK ERASE 0xd8: 0x%x\n", offs); offs &= ~(emu_jedec_be_d8_size - 1); memset(flashchip_contents + offs, 0xff, emu_jedec_be_d8_size); break; @@ -444,12 +487,9 @@ msg_perr("CHIP ERASE 0x60 insize invalid!\n"); return 1; } - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - if (offs & (emu_jedec_ce_60_size - 1)) - msg_pdbg("Unaligned CHIP ERASE 0x60\n"); - offs &= ~(emu_jedec_ce_60_size - 1); + /* JEDEC_CE_60_OUTSIZE is 1 (no address) -> no offset. */ /* emu_jedec_ce_60_size is emu_chip_size. */ - memset(flashchip_contents + offs, 0xff, emu_jedec_ce_60_size); + memset(flashchip_contents, 0xff, emu_jedec_ce_60_size); break; case JEDEC_CE_C7: if (!emu_jedec_ce_c7_size) @@ -462,10 +502,7 @@ msg_perr("CHIP ERASE 0xc7 insize invalid!\n"); return 1; } - offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; - if (offs & (emu_jedec_ce_c7_size - 1)) - msg_pdbg("Unaligned CHIP ERASE 0xc7\n"); - offs &= ~(emu_jedec_ce_c7_size - 1); + /* JEDEC_CE_C7_OUTSIZE is 1 (no address) -> no offset. */ /* emu_jedec_ce_c7_size is emu_chip_size. */ memset(flashchip_contents, 0xff, emu_jedec_ce_c7_size); break; Index: flashrom-emulate_spi_flashchip_command_blacklist/flashrom.8 =================================================================== --- flashrom-emulate_spi_flashchip_command_blacklist/flashrom.8 (Revision 1252) +++ flashrom-emulate_spi_flashchip_command_blacklist/flashrom.8 (Arbeitskopie) @@ -161,7 +161,7 @@ .sp .BR "* internal" " (default, for in-system flashing in the mainboard)" .sp -.BR "* dummy" " (just prints all operations and accesses)" +.BR "* dummy" " (prints all operations and accesses, can emulate flash chips)" .sp .BR "* nic3com" " (for flash ROMs on 3COM network cards)" .sp @@ -320,6 +320,38 @@ .sp Example: .B "flashrom -p dummy:bus=lpc+fwh" +.sp +The dummy programmer supports flash chip emulation for automated self-tests +without hardware access. You have to choose between +.sp +* no emulation +.sp +* ST M25P10.RES SPI flash chip (RES, page write) +.sp +* SST SST25VF040.REMS SPI flash chip (REMS, byte write) +.sp +* SST SST25VF032B SPI flash chip (RDID, AAI write) +.sp + +Example usage: flashrom -p dummy:emulate=SST25VF032B + +Flash image persistence is available as well. +Example usage: flashrom -p dummy:image=dummy_simulator.rom + +Allow setting the max chunksize for page write with the dummy +programmer. +Example usage: flashrom -p dummy:spi_write_256_chunksize=5 + +optional SPI command blacklisting to the flash chip emulator in the +dummy programmer. + +Usage: +flashrom -p dummy:spi_blacklist=hexstring + +If hexstring is 0302, flashrom will blacklist command 0x03 (READ) and +command 0x02 (WRITE). The hexstring can have up to 512 characters (256 +commands) length, and must not start with 0x. + .TP .BR "nic3com" , " nicrealtek" , " nicsmc1211" , " nicnatsemi" , " gfxnvidia\ " , " satasii " and " atahpt " programmers