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 --- flash.h | 16 ++++++++-------- flashrom.c | 11 ++++++----- ichspi.c | 4 ++-- it87spi.c | 6 +++--- sb600spi.c | 4 ++-- spi.c | 38 +++++++++++++++++++++++++------------- wbsio_spi.c | 4 ++-- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/flash.h b/flash.h index 97e0778..be95bf9 100644 --- a/flash.h +++ b/flash.h @@ -167,7 +167,7 @@ struct flashchip { 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 struct pcidev_status satas_sii[]; 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_52(const struct flashchip *flash, unsigned long addr); 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 write_en29f002a(struct flashchip *flash, uint8_t *buf); 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 it87spi_init(void); 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 write_49f002(struct flashchip *flash, uint8_t *buf); 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 @@ void map_flash_registers(struct flashchip *flash) 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 @@ int verify_flash(struct flashchip *flash, uint8_t *buf) 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 @@ int read_flash(struct flashchip *flash, char *filename, unsigned int exclude_sta 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 @@ int erase_flash(struct flashchip *flash) 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 @@ int main(int argc, char *argv[]) * 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 @@ static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes, 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 @@ int it8716f_spi_chip_write_1(struct flashchip *flash, uint8_t *buf) * 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 { 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 @@ 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", 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 @@ int wbsio_spi_command(unsigned int writecnt, unsigned int readcnt, 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 @@ int wbsio_spi_read(struct flashchip *flash, uint8_t *buf) return 1; } - read_memmapped(flash, buf); + read_memmapped(flash, buf, start, len); return 0; } -- cgit v1.1