From cbf563cbde925dae6971c7df305493a638de51c6 Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Tue, 16 Jun 2009 08:55:44 +0000 Subject: 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 Acked-by: Uwe Hermann --- spi.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'spi.c') diff --git a/spi.c b/spi.c index e9319d7..f625da7 100644 --- a/spi.c +++ b/spi.c @@ -678,19 +678,31 @@ int spi_nbyte_read(int address, uint8_t *bytes, int len) * 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 @@ int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int chunksize) 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", -- cgit v1.1