mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 23:22:37 +02:00
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>
This commit is contained in:
parent
30f7cb2f3c
commit
cbf563cbde
16
flash.h
16
flash.h
@ -167,7 +167,7 @@ struct flashchip {
|
|||||||
int probe_timing;
|
int probe_timing;
|
||||||
int (*erase) (struct flashchip *flash);
|
int (*erase) (struct flashchip *flash);
|
||||||
int (*write) (struct flashchip *flash, uint8_t *buf);
|
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. */
|
/* Some flash devices have an additional register space. */
|
||||||
chipaddr virtual_memory;
|
chipaddr virtual_memory;
|
||||||
@ -362,7 +362,7 @@ extern struct pcidev_status satas_sii[];
|
|||||||
extern int verbose;
|
extern int verbose;
|
||||||
#define printf_debug(x...) { if (verbose) printf(x); }
|
#define printf_debug(x...) { if (verbose) printf(x); }
|
||||||
void map_flash_registers(struct flashchip *flash);
|
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 min(int a, int b);
|
||||||
int max(int a, int b);
|
int max(int a, int b);
|
||||||
int check_erased_range(struct flashchip *flash, int start, int len);
|
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_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_1(struct flashchip *flash, uint8_t *buf);
|
||||||
int spi_chip_write_256(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);
|
uint8_t spi_read_status_register(void);
|
||||||
int spi_disable_blockprotect(void);
|
int spi_disable_blockprotect(void);
|
||||||
void spi_byte_program(int address, uint8_t byte);
|
void spi_byte_program(int address, uint8_t byte);
|
||||||
int spi_nbyte_program(int address, uint8_t *bytes, int len);
|
int spi_nbyte_program(int address, uint8_t *bytes, int len);
|
||||||
int spi_nbyte_read(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);
|
int spi_aai_write(struct flashchip *flash, uint8_t *buf);
|
||||||
uint32_t spi_get_valid_read_addr(void);
|
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_init_opcodes(void);
|
||||||
int ich_spi_command(unsigned int writecnt, unsigned int readcnt,
|
int ich_spi_command(unsigned int writecnt, unsigned int readcnt,
|
||||||
const unsigned char *writearr, unsigned char *readarr);
|
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);
|
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf);
|
||||||
|
|
||||||
/* it87spi.c */
|
/* it87spi.c */
|
||||||
@ -451,14 +451,14 @@ int it87spi_init(void);
|
|||||||
int it87xx_probe_spi_flash(const char *name);
|
int it87xx_probe_spi_flash(const char *name);
|
||||||
int it8716f_spi_command(unsigned int writecnt, unsigned int readcnt,
|
int it8716f_spi_command(unsigned int writecnt, unsigned int readcnt,
|
||||||
const unsigned char *writearr, unsigned char *readarr);
|
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_1(struct flashchip *flash, uint8_t *buf);
|
||||||
int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf);
|
int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf);
|
||||||
|
|
||||||
/* sb600spi.c */
|
/* sb600spi.c */
|
||||||
int sb600_spi_command(unsigned int writecnt, unsigned int readcnt,
|
int sb600_spi_command(unsigned int writecnt, unsigned int readcnt,
|
||||||
const unsigned char *writearr, unsigned char *readarr);
|
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);
|
int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf);
|
||||||
uint8_t sb600_read_status_register(void);
|
uint8_t sb600_read_status_register(void);
|
||||||
extern uint8_t *sb600_spibar;
|
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_check_for_spi(const char *name);
|
||||||
int wbsio_spi_command(unsigned int writecnt, unsigned int readcnt,
|
int wbsio_spi_command(unsigned int writecnt, unsigned int readcnt,
|
||||||
const unsigned char *writearr, unsigned char *readarr);
|
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);
|
int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf);
|
||||||
|
|
||||||
/* stm50flw0x0x.c */
|
/* stm50flw0x0x.c */
|
||||||
|
11
flashrom.c
11
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);
|
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;
|
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");
|
fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
} else
|
||||||
flash->read(flash, buf2);
|
flash->read(flash, buf2, 0, total_size);
|
||||||
|
|
||||||
printf("Verifying flash... ");
|
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");
|
fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
} else
|
||||||
flash->read(flash, buf);
|
flash->read(flash, buf, 0, size);
|
||||||
|
|
||||||
if (exclude_end_position - exclude_start_position > 0)
|
if (exclude_end_position - exclude_start_position > 0)
|
||||||
memset(buf + 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");
|
fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
} else
|
||||||
flash->read(flash, buf);
|
flash->read(flash, buf, 0, size);
|
||||||
|
|
||||||
for (erasedbytes = 0; erasedbytes < size; erasedbytes++)
|
for (erasedbytes = 0; erasedbytes < size; erasedbytes++)
|
||||||
if (0xff != buf[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
|
* 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)
|
if (exclude_end_position - exclude_start_position > 0)
|
||||||
chip_readn(buf + exclude_start_position,
|
chip_readn(buf + exclude_start_position,
|
||||||
|
4
ichspi.c
4
ichspi.c
@ -647,14 +647,14 @@ static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
|
|||||||
return 0;
|
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;
|
int maxdata = 64;
|
||||||
|
|
||||||
if (spi_controller == SPI_CONTROLLER_VIA)
|
if (spi_controller == SPI_CONTROLLER_VIA)
|
||||||
maxdata = 16;
|
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)
|
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf)
|
||||||
|
@ -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
|
* 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.
|
* 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;
|
int total_size = 1024 * flash->total_size;
|
||||||
fast_spi = 0;
|
fast_spi = 0;
|
||||||
|
|
||||||
if ((programmer == PROGRAMMER_IT87SPI) || (total_size > 512 * 1024)) {
|
if ((programmer == PROGRAMMER_IT87SPI) || (total_size > 512 * 1024)) {
|
||||||
spi_read_chunked(flash, buf, 3);
|
spi_read_chunked(flash, buf, start, len, 3);
|
||||||
} else {
|
} else {
|
||||||
read_memmapped(flash, buf);
|
read_memmapped(flash, buf, start, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -39,10 +39,10 @@ struct sb600_spi_controller {
|
|||||||
struct sb600_spi_controller *spi_bar = NULL;
|
struct sb600_spi_controller *spi_bar = NULL;
|
||||||
uint8_t *sb600_spibar;
|
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. */
|
/* 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)
|
uint8_t sb600_read_status_register(void)
|
||||||
|
38
spi.c
38
spi.c
@ -678,19 +678,31 @@ int spi_nbyte_read(int address, uint8_t *bytes, int len)
|
|||||||
* Read a complete flash chip.
|
* Read a complete flash chip.
|
||||||
* Each page is read separately in chunks with a maximum size of chunksize.
|
* 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 rc = 0;
|
||||||
int i, j;
|
int i, j, starthere, lenhere;
|
||||||
int total_size = flash->total_size * 1024;
|
|
||||||
int page_size = flash->page_size;
|
int page_size = flash->page_size;
|
||||||
int toread;
|
int toread;
|
||||||
|
|
||||||
for (j = 0; j < total_size / page_size; j++) {
|
/* Warning: This loop has a very unusual condition and body.
|
||||||
for (i = 0; i < page_size; i += chunksize) {
|
* The loop needs to go through each page with at least one affected
|
||||||
toread = min(chunksize, page_size - i);
|
* byte. The lowest page number is (start / page_size) since that
|
||||||
rc = spi_nbyte_read(j * page_size + i,
|
* division rounds down. The highest page number we want is the page
|
||||||
buf + j * page_size + i, toread);
|
* 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)
|
if (rc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -701,19 +713,19 @@ int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int chunksize)
|
|||||||
return rc;
|
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) {
|
switch (spi_controller) {
|
||||||
case SPI_CONTROLLER_IT87XX:
|
case SPI_CONTROLLER_IT87XX:
|
||||||
return it8716f_spi_chip_read(flash, buf);
|
return it8716f_spi_chip_read(flash, buf, start, len);
|
||||||
case SPI_CONTROLLER_SB600:
|
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_ICH7:
|
||||||
case SPI_CONTROLLER_ICH9:
|
case SPI_CONTROLLER_ICH9:
|
||||||
case SPI_CONTROLLER_VIA:
|
case SPI_CONTROLLER_VIA:
|
||||||
return ich_spi_read(flash, buf);
|
return ich_spi_read(flash, buf, start, len);
|
||||||
case SPI_CONTROLLER_WBSIO:
|
case SPI_CONTROLLER_WBSIO:
|
||||||
return wbsio_spi_read(flash, buf);
|
return wbsio_spi_read(flash, buf, start, len);
|
||||||
default:
|
default:
|
||||||
printf_debug
|
printf_debug
|
||||||
("%s called, but no SPI chipset/strapping detected\n",
|
("%s called, but no SPI chipset/strapping detected\n",
|
||||||
|
@ -173,7 +173,7 @@ int wbsio_spi_command(unsigned int writecnt, unsigned int readcnt,
|
|||||||
return 0;
|
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;
|
int size = flash->total_size * 1024;
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ int wbsio_spi_read(struct flashchip *flash, uint8_t *buf)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_memmapped(flash, buf);
|
read_memmapped(flash, buf, start, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user