[coreboot] flashrom patch for partial flash read

Stephan GUILLOUX stephan.guilloux at free.fr
Sat Nov 29 04:30:38 CET 2008


The goal for this patch is to allow flashrom to read some part of the flash.
flashrom arguments are --chunk-start --chunk-size.
the result is stored in a chunk-size file.

The design intends to provide start and size arguments to the xxx_read 
functions,
so that each can read only <size> bytes from <start> address.
Actually, for the READ part, there are still 2 or 3 to modify. If this 
design is agreed,
I'll modify the others too.

The same kind of design could be used for the VERIFY and WRITE (more 
difficult)
parts too.

I added a generic_read() function to carry out some tests on arguments :
    int generic_read(struct flashchip *flash, uint8_t *buf, uint32_t 
start, uint32_t size)
    {
       /* some tests here */

       if (flash-read == NULL) {
          memcpy(...);
          return (0);
       } else {
          return (flash->read(...));
       }
    }

The design keeps the current buffer size to total_size bytes. This allows
exclude_start/end to be applied too.

Any comment is welcome.

    Stephan.


Also in attachment for GMail users.

Signed-off-by: Stephan Guilloux <mailto:stephan.guilloux at free.fr>

Index: flashrom/flash.h
===================================================================
--- flashrom/flash.h    (revision 3781)
+++ flashrom/flash.h    (working copy)
@@ -74,7 +74,7 @@
     int (*probe) (struct flashchip *flash);
     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, uint32_t start, 
uint32_t size);
 
     /* Some flash devices have an additional register space. */
     volatile uint8_t *virtual_memory;
@@ -464,7 +464,7 @@
 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(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, uint32_t 
start, uint32_t size);
 uint8_t spi_read_status_register();
 int spi_disable_blockprotect(void);
 void spi_byte_program(int address, uint8_t byte);
@@ -488,7 +488,7 @@
 /* ichspi.c */
 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, uint32_t 
start, uint32_t size);
 int ich_spi_write(struct flashchip *flash, uint8_t * buf);
 
 /* it87spi.c */
Index: flashrom/spi.c
===================================================================
--- flashrom/spi.c    (revision 3781)
+++ flashrom/spi.c    (working copy)
@@ -544,17 +544,27 @@
     return spi_command(sizeof(cmd), len, cmd, bytes);
 }
 
-int spi_chip_read(struct flashchip *flash, uint8_t *buf)
+int spi_chip_read(struct flashchip *flash, uint8_t *buf, uint32_t 
start, uint32_t size)
 {
+    unsigned int total_size = flash->total_size * 1024;
+
     switch (flashbus) {
     case BUS_TYPE_IT87XX_SPI:
+        if ((start != 0) || (size != total_size)) {
+            printf ("Error: chunks not supported.\n");
+            return (1);
+        }
         return it8716f_spi_chip_read(flash, buf);
     case BUS_TYPE_SB600_SPI:
+        if ((start != 0) || (size != total_size)) {
+            printf ("Error: chunks not supported.\n");
+            return (1);
+        }
         return sb600_spi_read(flash, buf);
     case BUS_TYPE_ICH7_SPI:
     case BUS_TYPE_ICH9_SPI:
     case BUS_TYPE_VIA_SPI:
-        return ich_spi_read(flash, buf);
+        return ich_spi_read(flash, buf, start, size);
     default:
         printf_debug
             ("%s called, but no SPI chipset/strapping detected\n",
Index: flashrom/flashrom.c
===================================================================
--- flashrom/flashrom.c    (revision 3781)
+++ flashrom/flashrom.c    (working copy)
@@ -46,6 +46,8 @@
 int verbose = 0;
 int fd_mem;
 
+#define UNKNOWN_CHUNK_SIZE    0xffffffff
+
 struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
 {
     struct pci_dev *temp;
@@ -171,15 +173,41 @@
     return flash;
 }
 
+static int generic_read(struct flashchip *flash, uint8_t *buf, uint32_t 
chk_start, uint32_t chk_size)
+{
+    int total_size = flash->total_size * 1024;
+
+    if (chk_start > total_size) {
+        printf ("Error: Invalid chunk start.\n");
+        return (1);
+    }
+
+    if ((chk_size == 0) || (chk_start + chk_size > total_size)) {
+        printf ("Error: Invalid chunk size.\n");
+        return (1);
+    }
+
+    if (flash->read == NULL) {
+        memcpy(buf, (const char *)flash->virtual_memory + chk_start, 
chk_size);
+    } else {
+        if (flash->read(flash, buf, chk_start, chk_size)) {
+            printf ("ERROR : flash read failed\n");
+            return (1);
+        }
+        }
+    return (0);
+}
+
 int verify_flash(struct flashchip *flash, uint8_t *buf)
 {
     int idx;
     int total_size = flash->total_size * 1024;
     uint8_t *buf2 = (uint8_t *) calloc(total_size, sizeof(char));
-    if (flash->read == NULL)
-        memcpy(buf2, (const char *)flash->virtual_memory, total_size);
-    else
-        flash->read(flash, buf2);
+   
+    if (generic_read(flash, buf2, 0, total_size)) {
+        printf ("ERROR : verification aborted.\n");
+        return (1);
+        }
 
     printf("Verifying flash... ");
 
@@ -280,6 +308,8 @@
         {"force", 0, 0, 'f'},
         {"layout", 1, 0, 'l'},
         {"image", 1, 0, 'i'},
+        {"chunk-start", 1, 0, 'S'},
+        {"chunk-size", 1, 0, 'N'},
         {"list-supported", 0, 0, 'L'},
         {"help", 0, 0, 'h'},
         {"version", 0, 0, 'R'},
@@ -288,6 +318,8 @@
 
     char *filename = NULL;
 
+    unsigned int chunk_start = 0;
+    unsigned int chunk_size = UNKNOWN_CHUNK_SIZE;
     unsigned int exclude_start_position = 0, exclude_end_position = 
0;    // [x,y)
     char *tempstr = NULL, *tempstr2 = NULL;
 
@@ -329,6 +361,14 @@
             tempstr = strdup(optarg);
             sscanf(tempstr, "%x", &exclude_end_position);
             break;
+        case 'S':
+            tempstr = strdup(optarg);
+            sscanf(tempstr, "%x", &chunk_start);
+            break;
+        case 'N':
+            tempstr = strdup(optarg);
+            sscanf(tempstr, "%x", &chunk_size);
+            break;
         case 'm':
             tempstr = strdup(optarg);
             strtok(tempstr, ":");
@@ -459,22 +499,25 @@
             size = flashes[0]->total_size * 1024;
             buf = (uint8_t *) calloc(size, sizeof(char));
 
+            if (chunk_size == UNKNOWN_CHUNK_SIZE)
+                chunk_size = size - chunk_start;
+
             if ((image = fopen(filename, "w")) == NULL) {
                 perror(filename);
                 exit(1);
             }
             printf("Force reading flash... ");
-            if (!flashes[0]->read)
-                memcpy(buf, (const char *)flashes[0]->virtual_memory, 
size);
-            else
-                flashes[0]->read(flashes[0], buf);
+            if (generic_read(flashes[0], buf + chunk_start, 
chunk_start, chunk_size)) {
+                fclose(image);
+                exit (1);
+            }
 
             if (exclude_end_position - exclude_start_position > 0)
                 memset(buf + exclude_start_position, 0,
                        exclude_end_position -
                        exclude_start_position);
 
-            fwrite(buf, sizeof(char), size, image);
+            fwrite(buf + chunk_start, sizeof(char), chunk_size, image);
             fclose(image);
             printf("done.\n");
             free(buf);
@@ -546,21 +589,25 @@
         printf("done.\n");
         exit(0);
     } else if (read_it) {
+        printf("Reading flash... ");
         if ((image = fopen(filename, "w")) == NULL) {
             perror(filename);
             exit(1);
         }
-        printf("Reading flash... ");
-        if (flash->read == NULL)
-            memcpy(buf, (const char *)flash->virtual_memory, size);
-        else
-            flash->read(flash, buf);
 
+        if (chunk_size == UNKNOWN_CHUNK_SIZE)
+            chunk_size = size - chunk_start;
+
+        if (generic_read(flash, buf + chunk_start, chunk_start, 
chunk_size)) {
+            fclose(image);
+            exit(1);
+        }
+
         if (exclude_end_position - exclude_start_position > 0)
             memset(buf + exclude_start_position, 0,
                    exclude_end_position - exclude_start_position);
 
-        fwrite(buf, sizeof(char), size, image);
+        fwrite(buf + chunk_start, sizeof(char), chunk_size, image);
         fclose(image);
         printf("done.\n");
     } else {
@@ -620,7 +667,7 @@
     }
 
     if (verify_it)
-        ret |= verify_flash(flash, buf);
+      ret |= verify_flash(flash, buf);
 
 #ifdef __FreeBSD__
     close(io_fd);
Index: flashrom/ichspi.c
===================================================================
--- flashrom/ichspi.c    (revision 3781)
+++ flashrom/ichspi.c    (working copy)
@@ -545,18 +545,26 @@
     return 0;
 }
 
-int ich_spi_read(struct flashchip *flash, uint8_t * buf)
+int ich_spi_read(struct flashchip *flash, uint8_t * buf, uint32_t 
start, uint32_t size)
 {
     int i, rc = 0;
-    int total_size = flash->total_size * 1024;
     int page_size = flash->page_size;
     int maxdata = 64;
+    int page_start;
+    int page_nbr;
 
+    if ((start % page_size) || (size % page_size)) {
+        printf ("Error: start/size must be page aligned (page=%d 
bytes).\n", page_size);
+        return (1);
+    }
+    page_start = start / page_size;
+    page_nbr = size / page_size;
+
     if (flashbus == BUS_TYPE_VIA_SPI) {
         maxdata = 16;
     }
 
-    for (i = 0; (i < total_size / page_size) && (rc == 0); i++) {
+    for (i = page_start; (i < page_nbr) && (rc == 0); i++) {
         rc = ich_spi_read_page(flash, (void *)(buf + i * page_size),
                        i * page_size, maxdata);
     }







More information about the coreboot mailing list