mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-29 07:53:44 +02:00
support variable-size SPI chip for dummy programmer
This is designed for firmware updater to pack firmware image preserving some specific partitions in any size. BUG=none TEST=ran the command line below: $ flashrom -p dummy:image=${TMP_FILE},size=16777216, \ emulate=VARIABLE_SIZE -w ${IMG} -V -f $ flashrom -p dummy:image=${TMP_FILE},size=auto, \ emulate=VARIABLE_SIZE -w ${IMG} -V -f Signed-off-by: Namyoon Woo <namyoon@google.com> Change-Id: Iff266e151459561b126ecfd1c47420b385be1db2 Reviewed-on: https://review.coreboot.org/c/flashrom/+/44879 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
This commit is contained in:
parent
0e787b2e79
commit
3149822cd4
@ -196,6 +196,9 @@ int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int
|
|||||||
int probe_en29lv640b(struct flashctx *flash);
|
int probe_en29lv640b(struct flashctx *flash);
|
||||||
int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
|
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 */
|
/* edi.c */
|
||||||
int edi_chip_block_erase(struct flashctx *flash, unsigned int page, unsigned int size);
|
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);
|
int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "chipdrivers.h"
|
#include "chipdrivers.h"
|
||||||
#include "programmer.h"
|
#include "programmer.h"
|
||||||
|
#include "flashchips.h"
|
||||||
|
|
||||||
/* Remove the #define below if you don't want SPI flash chip emulation. */
|
/* Remove the #define below if you don't want SPI flash chip emulation. */
|
||||||
#define EMULATE_SPI_CHIP 1
|
#define EMULATE_SPI_CHIP 1
|
||||||
@ -44,6 +45,7 @@ enum emu_chip {
|
|||||||
EMULATE_SST_SST25VF032B,
|
EMULATE_SST_SST25VF032B,
|
||||||
EMULATE_MACRONIX_MX25L6436,
|
EMULATE_MACRONIX_MX25L6436,
|
||||||
EMULATE_WINBOND_W25Q128FV,
|
EMULATE_WINBOND_W25Q128FV,
|
||||||
|
EMULATE_VARIABLE_SIZE,
|
||||||
};
|
};
|
||||||
static enum emu_chip emu_chip = EMULATE_NONE;
|
static enum emu_chip emu_chip = EMULATE_NONE;
|
||||||
static char *emu_persistent_image = NULL;
|
static char *emu_persistent_image = NULL;
|
||||||
@ -154,6 +156,7 @@ int dummy_init(void)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
#if EMULATE_SPI_CHIP
|
#if EMULATE_SPI_CHIP
|
||||||
char *status = NULL;
|
char *status = NULL;
|
||||||
|
int size = -1; /* size for VARIOUS_SIZE chip device */
|
||||||
#endif
|
#endif
|
||||||
#if EMULATE_CHIP
|
#if EMULATE_CHIP
|
||||||
struct stat image_stat;
|
struct stat image_stat;
|
||||||
@ -272,6 +275,23 @@ int dummy_init(void)
|
|||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
#if EMULATE_CHIP
|
#if EMULATE_CHIP
|
||||||
|
#if EMULATE_SPI_CHIP
|
||||||
|
tmp = extract_programmer_param("size");
|
||||||
|
if (tmp) {
|
||||||
|
size = atoi(tmp);
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
msg_perr("%s: the size parameter is not given.\n", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
tmp = extract_programmer_param("emulate");
|
tmp = extract_programmer_param("emulate");
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
msg_pdbg("Not emulating any flash chip.\n");
|
msg_pdbg("Not emulating any flash chip.\n");
|
||||||
@ -343,6 +363,23 @@ int dummy_init(void)
|
|||||||
emu_jedec_ce_c7_size = emu_chip_size;
|
emu_jedec_ce_c7_size = emu_chip_size;
|
||||||
msg_pdbg("Emulating Winbond W25Q128FV SPI flash chip (RDID)\n");
|
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")) {
|
||||||
|
emu_chip = EMULATE_VARIABLE_SIZE;
|
||||||
|
emu_chip_size = size;
|
||||||
|
emu_max_byteprogram_size = 256;
|
||||||
|
emu_max_aai_size = 0;
|
||||||
|
emu_jedec_se_size = 4 * 1024;
|
||||||
|
emu_jedec_be_52_size = 32 * 1024;
|
||||||
|
emu_jedec_be_d8_size = 64 * 1024;
|
||||||
|
emu_jedec_ce_60_size = emu_chip_size;
|
||||||
|
emu_jedec_ce_c7_size = emu_chip_size;
|
||||||
|
msg_pdbg("Emulating generic SPI flash chip (size=%d bytes)\n",
|
||||||
|
emu_chip_size);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (emu_chip == EMULATE_NONE) {
|
if (emu_chip == EMULATE_NONE) {
|
||||||
msg_perr("Invalid chip specified for emulation: %s\n", tmp);
|
msg_perr("Invalid chip specified for emulation: %s\n", tmp);
|
||||||
@ -610,6 +647,16 @@ static int emulate_spi_chip_response(unsigned int writecnt,
|
|||||||
if (readcnt > 2)
|
if (readcnt > 2)
|
||||||
readarr[2] = 0x18;
|
readarr[2] = 0x18;
|
||||||
break;
|
break;
|
||||||
|
case EMULATE_VARIABLE_SIZE:
|
||||||
|
if (readcnt > 0)
|
||||||
|
readarr[0] = (PROGMANUF_ID >> 8) & 0xff;
|
||||||
|
if (readcnt > 1)
|
||||||
|
readarr[1] = PROGMANUF_ID & 0xff;
|
||||||
|
if (readcnt > 2)
|
||||||
|
readarr[2] = (PROGDEV_ID >> 8) & 0xff;
|
||||||
|
if (readcnt > 3)
|
||||||
|
readarr[3] = PROGDEV_ID & 0xff;
|
||||||
|
break;
|
||||||
default: /* ignore */
|
default: /* ignore */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -840,6 +887,7 @@ static int dummy_spi_send_command(const struct flashctx *flash, unsigned int wri
|
|||||||
case EMULATE_SST_SST25VF032B:
|
case EMULATE_SST_SST25VF032B:
|
||||||
case EMULATE_MACRONIX_MX25L6436:
|
case EMULATE_MACRONIX_MX25L6436:
|
||||||
case EMULATE_WINBOND_W25Q128FV:
|
case EMULATE_WINBOND_W25Q128FV:
|
||||||
|
case EMULATE_VARIABLE_SIZE:
|
||||||
if (emulate_spi_chip_response(writecnt, readcnt, writearr,
|
if (emulate_spi_chip_response(writecnt, readcnt, writearr,
|
||||||
readarr)) {
|
readarr)) {
|
||||||
msg_pdbg("Invalid command sent to flash chip!\n");
|
msg_pdbg("Invalid command sent to flash chip!\n");
|
||||||
@ -862,3 +910,44 @@ static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsig
|
|||||||
return spi_write_chunked(flash, buf, start, len,
|
return spi_write_chunked(flash, buf, start, len,
|
||||||
spi_write_256_chunksize);
|
spi_write_256_chunksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if EMULATE_CHIP && EMULATE_SPI_CHIP
|
||||||
|
int probe_variable_size(struct flashctx *flash)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Skip the probing if we don't emulate this chip. */
|
||||||
|
if (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
|
||||||
|
* read_flash_to_file()
|
||||||
|
* handle_romentries()
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* Search "total_size * 1024" in code.
|
||||||
|
*/
|
||||||
|
flash->chip->total_size = emu_chip_size / 1024;
|
||||||
|
msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__,
|
||||||
|
flash->chip->total_size);
|
||||||
|
|
||||||
|
/* 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 = emu_chip_size /
|
||||||
|
eraser->eraseblocks[0].size;
|
||||||
|
msg_cdbg("%s: eraser.size=%d, .count=%d\n",
|
||||||
|
__func__, eraser->eraseblocks[0].size,
|
||||||
|
eraser->eraseblocks[0].count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
21
flashchips.c
21
flashchips.c
@ -18757,6 +18757,27 @@ const struct flashchip flashchips[] = {
|
|||||||
.read = NULL,
|
.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,
|
||||||
|
.tested = TEST_OK_PREW,
|
||||||
|
.probe = probe_variable_size,
|
||||||
|
.block_erasers =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.eraseblocks = { {64 * 1024, 1} },
|
||||||
|
.block_erase = spi_block_erase_d8,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.write = spi_chip_write_256,
|
||||||
|
.read = spi_chip_read,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
.vendor = "Generic",
|
.vendor = "Generic",
|
||||||
.name = "unknown SPI chip (RDID)",
|
.name = "unknown SPI chip (RDID)",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user