mirror of
				https://review.coreboot.org/flashrom.git
				synced 2025-11-04 07:00:39 +01:00 
			
		
		
		
	dummyflasher: Wire variable size feature via opaque infra
Wire "variable size" feature in dummy programmer via opaque infra. This patch fixes the broken build with CONFIG_DUMMY=no. Dummyflasher registers opaque master for the case when it is initialised with EMULATE_VARIABLE_SIZE. Dummy opaque master emulates read/write/erase as simple memory operations over `data->flashchip_contents`. The feature works via "Opaque flash chip" in flashchips.c which has one block eraser at the moment. If this changes in future, each block eraser needs to be updated in `probe_variable_size`. Fixes: https://ticket.coreboot.org/issues/365 TEST=the following scenarious run successfully Testing build $ make clean && make CONFIG_DUMMY=no $ flashrom -h : dummy is not in the list $ make clean && make CONFIG_EVERYTHING=yes $ flashrom -h : dummy is in the list Testing "variable size" feature $ flashrom -p dummy:size=8388608,emulate=VARIABLE_SIZE -V $ flashrom -p dummy:size=8388608,emulate=VARIABLE_SIZE -r /tmp/dump.bin -V $ head -c 8388608 </dev/urandom >/tmp/image.bin $ flashrom -p dummy:image=/tmp/image.bin,size=8388608,emulate=VARIABLE_SIZE -w /tmp/dump.bin -V also same as above with erase_to_zero=yes Testing standard flow $ flashrom -p dummy:emulate=W25Q128FV -V $ flashrom -p dummy:emulate=W25Q128FV -r /tmp/dump.bin -V $ head -c 16777216 </dev/urandom >/tmp/image.bin $ flashrom -p dummy:image=/tmp/image.bin,emulate=W25Q128FV -w /tmp/dump.bin -V Testing invalid combination of programmer params (`init_data` fails and prints error message which is WAI) $ flashrom -p dummy:size=8388608 -V -> init_data: size parameter is only valid for VARIABLE_SIZE chip. $ flashrom -p dummy:emulate=VARIABLE_SIZE -V -> init_data: the size parameter is not given. $ flashrom -p dummy:emulate=W25Q128FV,erase_to_zero=yes -V -> init_data: erase_to_zero parameter is not valid for real chip. Change-Id: I76402bfdf8b1a75489e4509fec92c9a777d0cf58 Signed-off-by: Anastasia Klimchuk <aklm@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/64488 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
This commit is contained in:
		
				
					committed by
					
						
						Nico Huber
					
				
			
			
				
	
			
			
			
						parent
						
							5b78c08156
						
					
				
				
					commit
					a721181a08
				
			
							
								
								
									
										140
									
								
								dummyflasher.c
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								dummyflasher.c
									
									
									
									
									
								
							@@ -119,6 +119,72 @@ static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsig
 | 
			
		||||
				 emu_data->spi_write_256_chunksize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int probe_variable_size(struct flashctx *flash)
 | 
			
		||||
{
 | 
			
		||||
	const struct emu_data *emu_data = flash->mst->opaque.data;
 | 
			
		||||
 | 
			
		||||
	/* Skip the probing if we don't emulate "variable size" chip. */
 | 
			
		||||
	if (!emu_data || emu_data->emu_chip != EMULATE_VARIABLE_SIZE)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	flash->chip->total_size = emu_data->emu_chip_size / 1024;
 | 
			
		||||
	msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__,
 | 
			
		||||
	         flash->chip->total_size);
 | 
			
		||||
 | 
			
		||||
	flash->chip->tested = TEST_OK_PREW;
 | 
			
		||||
 | 
			
		||||
	if (emu_data->erase_to_zero)
 | 
			
		||||
		flash->chip->feature_bits |= FEATURE_ERASED_ZERO;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Update the first count of the block_eraser.
 | 
			
		||||
	 * Opaque flash chip entry in flashchips.c has only one block eraser.
 | 
			
		||||
	 *
 | 
			
		||||
	 * If this changes in future, the code below needs to be adjusted
 | 
			
		||||
	 * to update all block erasers.
 | 
			
		||||
	 */
 | 
			
		||||
	struct block_eraser *eraser = &flash->chip->block_erasers[0];
 | 
			
		||||
	if (!eraser->block_erase)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	eraser->eraseblocks[0].count = 1;
 | 
			
		||||
	eraser->eraseblocks[0].size = emu_data->emu_chip_size;
 | 
			
		||||
	msg_cdbg("%s: eraser.size=%d, .count=%d\n",
 | 
			
		||||
		 __func__, eraser->eraseblocks[0].size,
 | 
			
		||||
		 eraser->eraseblocks[0].count);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dummy_opaque_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	const struct emu_data *emu_data = flash->mst->opaque.data;
 | 
			
		||||
 | 
			
		||||
	memcpy(buf, emu_data->flashchip_contents + start, len);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dummy_opaque_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	struct emu_data *emu_data = flash->mst->opaque.data;
 | 
			
		||||
 | 
			
		||||
	memcpy(emu_data->flashchip_contents + start, buf, len);
 | 
			
		||||
	emu_data->emu_modified = 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dummy_opaque_erase(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
 | 
			
		||||
{
 | 
			
		||||
	struct emu_data *emu_data = flash->mst->opaque.data;
 | 
			
		||||
 | 
			
		||||
	memset(emu_data->flashchip_contents + blockaddr, emu_data->erase_to_zero ? 0x00 : 0xff, blocklen);
 | 
			
		||||
	emu_data->emu_modified = 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
@@ -270,7 +336,7 @@ static int erase_flash_data(struct emu_data *data, uint32_t start, uint32_t len)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME: take data->erase_to_zero into account. */
 | 
			
		||||
	/* FIXME: Maybe use ERASED_VALUE(flash) instead of 0xff ? */
 | 
			
		||||
	memset(data->flashchip_contents + start, 0xff, len);
 | 
			
		||||
	data->emu_modified = 1;
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -814,6 +880,13 @@ static const struct par_master par_master_dummyflasher = {
 | 
			
		||||
		.chip_writen		= dummy_chip_writen,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct opaque_master opaque_master_dummyflasher = {
 | 
			
		||||
	.probe          = probe_variable_size,
 | 
			
		||||
	.read           = dummy_opaque_read,
 | 
			
		||||
	.write          = dummy_opaque_write,
 | 
			
		||||
	.erase          = dummy_opaque_erase,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int init_data(struct emu_data *data, enum chipbustype *dummy_buses_supported)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@@ -827,7 +900,7 @@ static int init_data(struct emu_data *data, enum chipbustype *dummy_buses_suppor
 | 
			
		||||
	bustext = extract_programmer_param("bus");
 | 
			
		||||
	msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default");
 | 
			
		||||
	if (!bustext)
 | 
			
		||||
		bustext = strdup("parallel+lpc+fwh+spi");
 | 
			
		||||
		bustext = strdup("parallel+lpc+fwh+spi+prog");
 | 
			
		||||
	/* Convert the parameters to lowercase. */
 | 
			
		||||
	tolower_string(bustext);
 | 
			
		||||
 | 
			
		||||
@@ -848,6 +921,10 @@ static int init_data(struct emu_data *data, enum chipbustype *dummy_buses_suppor
 | 
			
		||||
		*dummy_buses_supported |= BUS_SPI;
 | 
			
		||||
		msg_pdbg("Enabling support for %s flash.\n", "SPI");
 | 
			
		||||
	}
 | 
			
		||||
	if (strstr(bustext, "prog")) {
 | 
			
		||||
		*dummy_buses_supported |= BUS_PROG;
 | 
			
		||||
		msg_pdbg("Enabling support for %s flash.\n", "PROG");
 | 
			
		||||
	}
 | 
			
		||||
	if (*dummy_buses_supported == BUS_NONE)
 | 
			
		||||
		msg_pdbg("Support for all flash bus types disabled.\n");
 | 
			
		||||
	free(bustext);
 | 
			
		||||
@@ -1010,6 +1087,10 @@ static int init_data(struct emu_data *data, enum chipbustype *dummy_buses_suppor
 | 
			
		||||
 | 
			
		||||
	tmp = extract_programmer_param("emulate");
 | 
			
		||||
	if (!tmp) {
 | 
			
		||||
		if (size != -1) {
 | 
			
		||||
			msg_perr("%s: size parameter is only valid for VARIABLE_SIZE chip.\n", __func__);
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
		msg_pdbg("Not emulating any flash chip.\n");
 | 
			
		||||
		/* Nothing else to do. */
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -1107,6 +1188,10 @@ static int init_data(struct emu_data *data, enum chipbustype *dummy_buses_suppor
 | 
			
		||||
		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);
 | 
			
		||||
	} else if (size != -1) {
 | 
			
		||||
		msg_perr("%s: size parameter is only valid for VARIABLE_SIZE chip.\n", __func__);
 | 
			
		||||
		free(tmp);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (data->emu_chip == EMULATE_NONE) {
 | 
			
		||||
@@ -1119,6 +1204,11 @@ static int init_data(struct emu_data *data, enum chipbustype *dummy_buses_suppor
 | 
			
		||||
	/* Should emulated flash erase to zero (yes/no)? */
 | 
			
		||||
	tmp = extract_programmer_param("erase_to_zero");
 | 
			
		||||
	if (tmp) {
 | 
			
		||||
		if (data->emu_chip != EMULATE_VARIABLE_SIZE) {
 | 
			
		||||
			msg_perr("%s: erase_to_zero parameter is not valid for real chip.\n", __func__);
 | 
			
		||||
			free(tmp);
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcmp(tmp, "yes")) {
 | 
			
		||||
			msg_pdbg("Emulated chip will erase to 0x00\n");
 | 
			
		||||
			data->erase_to_zero = 1;
 | 
			
		||||
@@ -1241,6 +1331,9 @@ dummy_init_out:
 | 
			
		||||
		free(data);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dummy_buses_supported & BUS_PROG)
 | 
			
		||||
		register_opaque_master(&opaque_master_dummyflasher, data);
 | 
			
		||||
	if (dummy_buses_supported & BUS_NONSPI)
 | 
			
		||||
		register_par_master(&par_master_dummyflasher,
 | 
			
		||||
				    dummy_buses_supported & BUS_NONSPI,
 | 
			
		||||
@@ -1251,49 +1344,6 @@ dummy_init_out:
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int probe_variable_size(struct flashctx *flash)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	const struct emu_data *emu_data = flash->mst->spi.data;
 | 
			
		||||
 | 
			
		||||
	/* Skip the probing if we don't emulate this chip. */
 | 
			
		||||
	if (!emu_data || emu_data->emu_chip != EMULATE_VARIABLE_SIZE)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * This will break if one day flashctx becomes read-only.
 | 
			
		||||
	 * Once that happens, we need to have special hacks in functions:
 | 
			
		||||
	 *
 | 
			
		||||
	 *     erase_and_write_flash() in flashrom.c
 | 
			
		||||
	 *     do_read()
 | 
			
		||||
	 *     handle_romentries()
 | 
			
		||||
	 *     ...
 | 
			
		||||
	 *
 | 
			
		||||
	 * Search "total_size * 1024" in code.
 | 
			
		||||
	 */
 | 
			
		||||
	flash->chip->total_size = emu_data->emu_chip_size / 1024;
 | 
			
		||||
	msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__,
 | 
			
		||||
	         flash->chip->total_size);
 | 
			
		||||
 | 
			
		||||
	if (emu_data->erase_to_zero)
 | 
			
		||||
		flash->chip->feature_bits |= FEATURE_ERASED_ZERO;
 | 
			
		||||
 | 
			
		||||
	/* Update the first count of each of the block_erasers. */
 | 
			
		||||
	for (i = 0; i < NUM_ERASEFUNCTIONS; i++) {
 | 
			
		||||
		struct block_eraser *eraser = &flash->chip->block_erasers[i];
 | 
			
		||||
		if (!eraser->block_erase)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		eraser->eraseblocks[0].count = 1;
 | 
			
		||||
		eraser->eraseblocks[0].size = emu_data->emu_chip_size;
 | 
			
		||||
		msg_cdbg("%s: eraser.size=%d, .count=%d\n",
 | 
			
		||||
		         __func__, eraser->eraseblocks[0].size,
 | 
			
		||||
		         eraser->eraseblocks[0].count);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct programmer_entry programmer_dummy = {
 | 
			
		||||
	.name			= "dummy",
 | 
			
		||||
	.type			= OTHER,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								flashchips.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								flashchips.c
									
									
									
									
									
								
							@@ -19962,28 +19962,6 @@ const struct flashchip flashchips[] = {
 | 
			
		||||
		.read		= NULL,
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		.vendor		= "Generic",
 | 
			
		||||
		.name		= "Variable Size SPI chip",
 | 
			
		||||
		.bustype	= BUS_SPI,
 | 
			
		||||
		.manufacture_id	= PROGMANUF_ID,
 | 
			
		||||
		.model_id	= PROGDEV_ID,
 | 
			
		||||
		.total_size	= 64,  /* This size is set temporarily */
 | 
			
		||||
		.page_size	= 256,
 | 
			
		||||
		.feature_bits	= FEATURE_4BA_READ | FEATURE_4BA_WRITE,
 | 
			
		||||
		.tested		= TEST_OK_PREW,
 | 
			
		||||
		.probe		= probe_variable_size,
 | 
			
		||||
		.block_erasers	=
 | 
			
		||||
		{
 | 
			
		||||
			{
 | 
			
		||||
				.eraseblocks = { {64 * 1024, 1} },
 | 
			
		||||
				.block_erase = spi_block_erase_c7,
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		.write		= spi_chip_write_256,
 | 
			
		||||
		.read		= spi_chip_read,
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		.vendor		= "Generic",
 | 
			
		||||
		.name		= "unknown SPI chip (RDID)",
 | 
			
		||||
 
 | 
			
		||||
@@ -201,9 +201,6 @@ int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int
 | 
			
		||||
int probe_en29lv640b(struct flashctx *flash);
 | 
			
		||||
int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
 | 
			
		||||
 | 
			
		||||
/* dummyflasher.c */
 | 
			
		||||
int probe_variable_size(struct flashctx *flash);
 | 
			
		||||
 | 
			
		||||
/* edi.c */
 | 
			
		||||
int edi_chip_block_erase(struct flashctx *flash, unsigned int page, unsigned int size);
 | 
			
		||||
int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user