[coreboot] [PATCH] flashrom: Partial read support

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Sat Jun 13 16:27:51 CEST 2009


On 13.06.2009 01:48, Carl-Daniel Hailfinger wrote:
> With this patch it is possible to read arbitarary chip ranges on a byte
> boundary.
> 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.
>
> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
>   

Updated patch to apply against svn HEAD and fixed some SPI issues.

This patch gives us arbitrary range reads for every single chip
supported by flashrom.

Tests appreciated. Please check if the result of a read with and without
the patch is identical. (sha1sum etc. work fine)

I need testers with external programmers and testers with onboard chips,
with Parallel, LPC, FWH and SPI bus.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: flashrom-partial_read/flash.h
===================================================================
--- flashrom-partial_read/flash.h	(Revision 589)
+++ flashrom-partial_read/flash.h	(Arbeitskopie)
@@ -166,7 +166,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;
@@ -720,8 +720,9 @@
 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);
 extern char *pcidev_bdf;
 
 /* layout.c */
@@ -763,13 +764,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);
 
@@ -792,7 +793,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 */
@@ -803,14 +804,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;
@@ -910,7 +911,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 */
Index: flashrom-partial_read/it87spi.c
===================================================================
--- flashrom-partial_read/it87spi.c	(Revision 589)
+++ flashrom-partial_read/it87spi.c	(Arbeitskopie)
@@ -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;
Index: flashrom-partial_read/spi.c
===================================================================
--- flashrom-partial_read/spi.c	(Revision 589)
+++ flashrom-partial_read/spi.c	(Arbeitskopie)
@@ -677,19 +677,32 @@
  * 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 = max(start, i * page_size);
+		/* Length of bytes in the range in this page. */
+		lenhere = min(start + len, (i + 1) * page_size) - starthere;
+		/* starthere is an offset to the base address of the chip. */
+		spi_nbyte_read(start, buf + starthere - start, lenhere);
+		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;
 		}
@@ -700,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",
Index: flashrom-partial_read/wbsio_spi.c
===================================================================
--- flashrom-partial_read/wbsio_spi.c	(Revision 589)
+++ flashrom-partial_read/wbsio_spi.c	(Arbeitskopie)
@@ -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;
 }
 
Index: flashrom-partial_read/sb600spi.c
===================================================================
--- flashrom-partial_read/sb600spi.c	(Revision 589)
+++ flashrom-partial_read/sb600spi.c	(Arbeitskopie)
@@ -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)
Index: flashrom-partial_read/flashrom.c
===================================================================
--- flashrom-partial_read/flashrom.c	(Revision 589)
+++ flashrom-partial_read/flashrom.c	(Arbeitskopie)
@@ -193,9 +193,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;
 }
@@ -205,6 +205,11 @@
 	return (a < b) ? a : b;
 }
 
+int max(int a, int b)
+{
+	return (a > b) ? a : b;
+}
+
 char *strcat_realloc(char *dest, const char *src)
 {
 	dest = realloc(dest, strlen(dest) + strlen(src) + 1);
@@ -307,7 +312,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... ");
 
@@ -360,7 +365,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,
@@ -393,7 +398,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]) {
@@ -826,6 +831,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,
Index: flashrom-partial_read/ichspi.c
===================================================================
--- flashrom-partial_read/ichspi.c	(Revision 589)
+++ flashrom-partial_read/ichspi.c	(Arbeitskopie)
@@ -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)


-- 
http://www.hailfinger.org/

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: flashrom_partial_read01.diff
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20090613/e3788c6a/attachment.ksh>


More information about the coreboot mailing list