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);
}