The goal for this patch is to allow flashrom to read some part of the flash. flashrom arguments are --chunk-start --chunk-size. the result is stored in a chunk-size file.
The design intends to provide start and size arguments to the xxx_read functions, so that each can read only <size> bytes from <start> address. Actually, for the READ part, there are still 2 or 3 to modify. If this design is agreed, I'll modify the others too.
The same kind of design could be used for the VERIFY and WRITE (more difficult) parts too.
I added a generic_read() function to carry out some tests on arguments : int generic_read(struct flashchip *flash, uint8_t *buf, uint32_t start, uint32_t size) { /* some tests here */
if (flash-read == NULL) { memcpy(...); return (0); } else { return (flash->read(...)); } }
The design keeps the current buffer size to total_size bytes. This allows exclude_start/end to be applied too.
Any comment is welcome.
Stephan.
Also in attachment for GMail users.
Signed-off-by: Stephan Guilloux mailto:stephan.guilloux@free.fr
Index: flashrom/flash.h =================================================================== --- flashrom/flash.h (revision 3781) +++ flashrom/flash.h (working copy) @@ -74,7 +74,7 @@ int (*probe) (struct flashchip *flash); int (*erase) (struct flashchip *flash); int (*write) (struct flashchip *flash, uint8_t *buf); - int (*read) (struct flashchip *flash, uint8_t *buf); + int (*read) (struct flashchip *flash, uint8_t *buf, uint32_t start, uint32_t size);
/* Some flash devices have an additional register space. */ volatile uint8_t *virtual_memory; @@ -464,7 +464,7 @@ int spi_block_erase_52(const struct flashchip *flash, unsigned long addr); int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr); int spi_chip_write(struct flashchip *flash, uint8_t *buf); -int spi_chip_read(struct flashchip *flash, uint8_t *buf); +int spi_chip_read(struct flashchip *flash, uint8_t *buf, uint32_t start, uint32_t size); uint8_t spi_read_status_register(); int spi_disable_blockprotect(void); void spi_byte_program(int address, uint8_t byte); @@ -488,7 +488,7 @@ /* ichspi.c */ int ich_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); -int ich_spi_read(struct flashchip *flash, uint8_t * buf); +int ich_spi_read(struct flashchip *flash, uint8_t * buf, uint32_t start, uint32_t size); int ich_spi_write(struct flashchip *flash, uint8_t * buf);
/* it87spi.c */ Index: flashrom/spi.c =================================================================== --- flashrom/spi.c (revision 3781) +++ flashrom/spi.c (working copy) @@ -544,17 +544,27 @@ return spi_command(sizeof(cmd), len, cmd, bytes); }
-int spi_chip_read(struct flashchip *flash, uint8_t *buf) +int spi_chip_read(struct flashchip *flash, uint8_t *buf, uint32_t start, uint32_t size) { + unsigned int total_size = flash->total_size * 1024; + switch (flashbus) { case BUS_TYPE_IT87XX_SPI: + if ((start != 0) || (size != total_size)) { + printf ("Error: chunks not supported.\n"); + return (1); + } return it8716f_spi_chip_read(flash, buf); case BUS_TYPE_SB600_SPI: + if ((start != 0) || (size != total_size)) { + printf ("Error: chunks not supported.\n"); + return (1); + } return sb600_spi_read(flash, buf); case BUS_TYPE_ICH7_SPI: case BUS_TYPE_ICH9_SPI: case BUS_TYPE_VIA_SPI: - return ich_spi_read(flash, buf); + return ich_spi_read(flash, buf, start, size); default: printf_debug ("%s called, but no SPI chipset/strapping detected\n", Index: flashrom/flashrom.c =================================================================== --- flashrom/flashrom.c (revision 3781) +++ flashrom/flashrom.c (working copy) @@ -46,6 +46,8 @@ int verbose = 0; int fd_mem;
+#define UNKNOWN_CHUNK_SIZE 0xffffffff + struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device) { struct pci_dev *temp; @@ -171,15 +173,41 @@ return flash; }
+static int generic_read(struct flashchip *flash, uint8_t *buf, uint32_t chk_start, uint32_t chk_size) +{ + int total_size = flash->total_size * 1024; + + if (chk_start > total_size) { + printf ("Error: Invalid chunk start.\n"); + return (1); + } + + if ((chk_size == 0) || (chk_start + chk_size > total_size)) { + printf ("Error: Invalid chunk size.\n"); + return (1); + } + + if (flash->read == NULL) { + memcpy(buf, (const char *)flash->virtual_memory + chk_start, chk_size); + } else { + if (flash->read(flash, buf, chk_start, chk_size)) { + printf ("ERROR : flash read failed\n"); + return (1); + } + } + return (0); +} + int verify_flash(struct flashchip *flash, uint8_t *buf) { int idx; int total_size = flash->total_size * 1024; uint8_t *buf2 = (uint8_t *) calloc(total_size, sizeof(char)); - if (flash->read == NULL) - memcpy(buf2, (const char *)flash->virtual_memory, total_size); - else - flash->read(flash, buf2); + + if (generic_read(flash, buf2, 0, total_size)) { + printf ("ERROR : verification aborted.\n"); + return (1); + }
printf("Verifying flash... ");
@@ -280,6 +308,8 @@ {"force", 0, 0, 'f'}, {"layout", 1, 0, 'l'}, {"image", 1, 0, 'i'}, + {"chunk-start", 1, 0, 'S'}, + {"chunk-size", 1, 0, 'N'}, {"list-supported", 0, 0, 'L'}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'R'}, @@ -288,6 +318,8 @@
char *filename = NULL;
+ unsigned int chunk_start = 0; + unsigned int chunk_size = UNKNOWN_CHUNK_SIZE; unsigned int exclude_start_position = 0, exclude_end_position = 0; // [x,y) char *tempstr = NULL, *tempstr2 = NULL;
@@ -329,6 +361,14 @@ tempstr = strdup(optarg); sscanf(tempstr, "%x", &exclude_end_position); break; + case 'S': + tempstr = strdup(optarg); + sscanf(tempstr, "%x", &chunk_start); + break; + case 'N': + tempstr = strdup(optarg); + sscanf(tempstr, "%x", &chunk_size); + break; case 'm': tempstr = strdup(optarg); strtok(tempstr, ":"); @@ -459,22 +499,25 @@ size = flashes[0]->total_size * 1024; buf = (uint8_t *) calloc(size, sizeof(char));
+ if (chunk_size == UNKNOWN_CHUNK_SIZE) + chunk_size = size - chunk_start; + if ((image = fopen(filename, "w")) == NULL) { perror(filename); exit(1); } printf("Force reading flash... "); - if (!flashes[0]->read) - memcpy(buf, (const char *)flashes[0]->virtual_memory, size); - else - flashes[0]->read(flashes[0], buf); + if (generic_read(flashes[0], buf + chunk_start, chunk_start, chunk_size)) { + fclose(image); + exit (1); + }
if (exclude_end_position - exclude_start_position > 0) memset(buf + exclude_start_position, 0, exclude_end_position - exclude_start_position);
- fwrite(buf, sizeof(char), size, image); + fwrite(buf + chunk_start, sizeof(char), chunk_size, image); fclose(image); printf("done.\n"); free(buf); @@ -546,21 +589,25 @@ printf("done.\n"); exit(0); } else if (read_it) { + printf("Reading flash... "); if ((image = fopen(filename, "w")) == NULL) { perror(filename); exit(1); } - printf("Reading flash... "); - if (flash->read == NULL) - memcpy(buf, (const char *)flash->virtual_memory, size); - else - flash->read(flash, buf);
+ if (chunk_size == UNKNOWN_CHUNK_SIZE) + chunk_size = size - chunk_start; + + if (generic_read(flash, buf + chunk_start, chunk_start, chunk_size)) { + fclose(image); + exit(1); + } + if (exclude_end_position - exclude_start_position > 0) memset(buf + exclude_start_position, 0, exclude_end_position - exclude_start_position);
- fwrite(buf, sizeof(char), size, image); + fwrite(buf + chunk_start, sizeof(char), chunk_size, image); fclose(image); printf("done.\n"); } else { @@ -620,7 +667,7 @@ }
if (verify_it) - ret |= verify_flash(flash, buf); + ret |= verify_flash(flash, buf);
#ifdef __FreeBSD__ close(io_fd); Index: flashrom/ichspi.c =================================================================== --- flashrom/ichspi.c (revision 3781) +++ flashrom/ichspi.c (working copy) @@ -545,18 +545,26 @@ return 0; }
-int ich_spi_read(struct flashchip *flash, uint8_t * buf) +int ich_spi_read(struct flashchip *flash, uint8_t * buf, uint32_t start, uint32_t size) { int i, rc = 0; - int total_size = flash->total_size * 1024; int page_size = flash->page_size; int maxdata = 64; + int page_start; + int page_nbr;
+ if ((start % page_size) || (size % page_size)) { + printf ("Error: start/size must be page aligned (page=%d bytes).\n", page_size); + return (1); + } + page_start = start / page_size; + page_nbr = size / page_size; + if (flashbus == BUS_TYPE_VIA_SPI) { maxdata = 16; }
- for (i = 0; (i < total_size / page_size) && (rc == 0); i++) { + for (i = page_start; (i < page_nbr) && (rc == 0); i++) { rc = ich_spi_read_page(flash, (void *)(buf + i * page_size), i * page_size, maxdata); }