Support reads of arbitrary range
That means you can tell flashrom to read exactly bytes 12345-56789
(start 12345, length 44445) and it will not fetch a single byte more.
Uwe tested this on one LPC, one SPI, and one parallel flash board.
Corresponding to flashrom svn r596.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
diff --git a/flash.h b/flash.h
index 97e0778..be95bf9 100644
--- a/flash.h
+++ b/flash.h
@@ -167,7 +167,7 @@
int probe_timing;
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, int start, int len);
/* Some flash devices have an additional register space. */
chipaddr virtual_memory;
@@ -362,7 +362,7 @@
extern int verbose;
#define printf_debug(x...) { if (verbose) printf(x); }
void map_flash_registers(struct flashchip *flash);
-int read_memmapped(struct flashchip *flash, uint8_t *buf);
+int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len);
int min(int a, int b);
int max(int a, int b);
int check_erased_range(struct flashchip *flash, int start, int len);
@@ -408,13 +408,13 @@
int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr);
int spi_chip_write_1(struct flashchip *flash, uint8_t *buf);
int spi_chip_write_256(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, int start, int len);
uint8_t spi_read_status_register(void);
int spi_disable_blockprotect(void);
void spi_byte_program(int address, uint8_t byte);
int spi_nbyte_program(int address, uint8_t *bytes, int len);
int spi_nbyte_read(int address, uint8_t *bytes, int len);
-int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int chunksize);
+int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize);
int spi_aai_write(struct flashchip *flash, uint8_t *buf);
uint32_t spi_get_valid_read_addr(void);
@@ -440,7 +440,7 @@
int ich_init_opcodes(void);
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, int start, int len);
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf);
/* it87spi.c */
@@ -451,14 +451,14 @@
int it87xx_probe_spi_flash(const char *name);
int it8716f_spi_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
-int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf);
+int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len);
int it8716f_spi_chip_write_1(struct flashchip *flash, uint8_t *buf);
int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf);
/* sb600spi.c */
int sb600_spi_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
-int sb600_spi_read(struct flashchip *flash, uint8_t *buf);
+int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf);
uint8_t sb600_read_status_register(void);
extern uint8_t *sb600_spibar;
@@ -557,7 +557,7 @@
int wbsio_check_for_spi(const char *name);
int wbsio_spi_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
-int wbsio_spi_read(struct flashchip *flash, uint8_t *buf);
+int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf);
/* stm50flw0x0x.c */
diff --git a/flashrom.c b/flashrom.c
index fe5826f..5821371 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -194,9 +194,9 @@
flash->virtual_registers = (chipaddr)programmer_map_flash_region("flash chip registers", (0xFFFFFFFF - 0x400000 - size + 1), size);
}
-int read_memmapped(struct flashchip *flash, uint8_t *buf)
+int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len)
{
- chip_readn(buf, flash->virtual_memory, flash->total_size * 1024);
+ chip_readn(buf, flash->virtual_memory + start, len);
return 0;
}
@@ -393,7 +393,7 @@
fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
return 1;
} else
- flash->read(flash, buf2);
+ flash->read(flash, buf2, 0, total_size);
printf("Verifying flash... ");
@@ -446,7 +446,7 @@
fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
return 1;
} else
- flash->read(flash, buf);
+ flash->read(flash, buf, 0, size);
if (exclude_end_position - exclude_start_position > 0)
memset(buf + exclude_start_position, 0,
@@ -482,7 +482,7 @@
fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
return 1;
} else
- flash->read(flash, buf);
+ flash->read(flash, buf, 0, size);
for (erasedbytes = 0; erasedbytes < size; erasedbytes++)
if (0xff != buf[erasedbytes]) {
@@ -915,6 +915,7 @@
* completely once all flash chips can do rom layouts. stepan
*/
+ /* FIXME: This code is totally broken. It treats exclude ranges as include ranges. */
// ////////////////////////////////////////////////////////////
if (exclude_end_position - exclude_start_position > 0)
chip_readn(buf + exclude_start_position,
diff --git a/ichspi.c b/ichspi.c
index e3fb740..9091230 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -647,14 +647,14 @@
return 0;
}
-int ich_spi_read(struct flashchip *flash, uint8_t * buf)
+int ich_spi_read(struct flashchip *flash, uint8_t * buf, int start, int len)
{
int maxdata = 64;
if (spi_controller == SPI_CONTROLLER_VIA)
maxdata = 16;
- return spi_read_chunked(flash, buf, maxdata);
+ return spi_read_chunked(flash, buf, start, len, maxdata);
}
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf)
diff --git a/it87spi.c b/it87spi.c
index ecc1ad8..5183bae 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -257,15 +257,15 @@
* IT8716F only allows maximum of 512 kb SPI mapped to LPC memory cycles
* Need to read this big flash using firmware cycles 3 byte at a time.
*/
-int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf)
+int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
int total_size = 1024 * flash->total_size;
fast_spi = 0;
if ((programmer == PROGRAMMER_IT87SPI) || (total_size > 512 * 1024)) {
- spi_read_chunked(flash, buf, 3);
+ spi_read_chunked(flash, buf, start, len, 3);
} else {
- read_memmapped(flash, buf);
+ read_memmapped(flash, buf, start, len);
}
return 0;
diff --git a/sb600spi.c b/sb600spi.c
index 259ad27..f4f3492 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -39,10 +39,10 @@
struct sb600_spi_controller *spi_bar = NULL;
uint8_t *sb600_spibar;
-int sb600_spi_read(struct flashchip *flash, uint8_t *buf)
+int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
/* Maximum read length is 8 bytes. */
- return spi_read_chunked(flash, buf, 8);
+ return spi_read_chunked(flash, buf, start, len, 8);
}
uint8_t sb600_read_status_register(void)
diff --git a/spi.c b/spi.c
index e9319d7..f625da7 100644
--- a/spi.c
+++ b/spi.c
@@ -678,19 +678,31 @@
* Read a complete flash chip.
* Each page is read separately in chunks with a maximum size of chunksize.
*/
-int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int chunksize)
+int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize)
{
int rc = 0;
- int i, j;
- int total_size = flash->total_size * 1024;
+ int i, j, starthere, lenhere;
int page_size = flash->page_size;
int toread;
- for (j = 0; j < total_size / page_size; j++) {
- for (i = 0; i < page_size; i += chunksize) {
- toread = min(chunksize, page_size - i);
- rc = spi_nbyte_read(j * page_size + i,
- buf + j * page_size + i, toread);
+ /* Warning: This loop has a very unusual condition and body.
+ * The loop needs to go through each page with at least one affected
+ * byte. The lowest page number is (start / page_size) since that
+ * division rounds down. The highest page number we want is the page
+ * where the last byte of the range lives. That last byte has the
+ * address (start + len - 1), thus the highest page number is
+ * (start + len - 1) / page_size. Since we want to include that last
+ * page as well, the loop condition uses <=.
+ */
+ for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
+ /* Byte position of the first byte in the range in this page. */
+ /* starthere is an offset to the base address of the chip. */
+ starthere = max(start, i * page_size);
+ /* Length of bytes in the range in this page. */
+ lenhere = min(start + len, (i + 1) * page_size) - starthere;
+ for (j = 0; j < lenhere; j += chunksize) {
+ toread = min(chunksize, lenhere - j);
+ rc = spi_nbyte_read(starthere + j, buf + starthere - start + j, toread);
if (rc)
break;
}
@@ -701,19 +713,19 @@
return rc;
}
-int spi_chip_read(struct flashchip *flash, uint8_t *buf)
+int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
switch (spi_controller) {
case SPI_CONTROLLER_IT87XX:
- return it8716f_spi_chip_read(flash, buf);
+ return it8716f_spi_chip_read(flash, buf, start, len);
case SPI_CONTROLLER_SB600:
- return sb600_spi_read(flash, buf);
+ return sb600_spi_read(flash, buf, start, len);
case SPI_CONTROLLER_ICH7:
case SPI_CONTROLLER_ICH9:
case SPI_CONTROLLER_VIA:
- return ich_spi_read(flash, buf);
+ return ich_spi_read(flash, buf, start, len);
case SPI_CONTROLLER_WBSIO:
- return wbsio_spi_read(flash, buf);
+ return wbsio_spi_read(flash, buf, start, len);
default:
printf_debug
("%s called, but no SPI chipset/strapping detected\n",
diff --git a/wbsio_spi.c b/wbsio_spi.c
index 8ca0abc..9ac15d1 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -173,7 +173,7 @@
return 0;
}
-int wbsio_spi_read(struct flashchip *flash, uint8_t *buf)
+int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
int size = flash->total_size * 1024;
@@ -182,7 +182,7 @@
return 1;
}
- read_memmapped(flash, buf);
+ read_memmapped(flash, buf, start, len);
return 0;
}