Author: stefanct
Date: Sun Oct 19 09:53:45 2014
New Revision: 1851
URL: http://flashrom.org/trac/flashrom/changeset/1851

Log:
Make read before write configurable (infrastructure part).

 - Introduce a variable in doit() that allows to influence
   read-before-write and its consequences.
 - Modify build_new_image so that it still works even if the old content
   is not read before.
 - Add copy_old_content() to ease the pain for future patches.

Signed-off-by: Stefan Tauner <[email protected]>
Signed-off-by: Carl-Daniel Hailfinger <[email protected]>
Acked-by: Stefan Tauner <[email protected]>

Modified:
   trunk/flash.h
   trunk/flashrom.c
   trunk/layout.c

Modified: trunk/flash.h
==============================================================================
--- trunk/flash.h       Wed Sep 10 01:03:32 2014        (r1850)
+++ trunk/flash.h       Sun Oct 19 09:53:45 2014        (r1851)
@@ -341,7 +341,7 @@
 int process_include_args(void);
 int read_romlayout(const char *name);
 int normalize_romentries(const struct flashctx *flash);
-int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, 
uint8_t *newcontents);
+int build_new_image(struct flashctx *flash, bool oldcontents_valid, uint8_t 
*oldcontents, uint8_t *newcontents);
 void layout_cleanup(void);
 
 /* spi.c */

Modified: trunk/flashrom.c
==============================================================================
--- trunk/flashrom.c    Wed Sep 10 01:03:32 2014        (r1850)
+++ trunk/flashrom.c    Sun Oct 19 09:53:45 2014        (r1851)
@@ -1906,6 +1906,7 @@
        uint8_t *newcontents;
        int ret = 0;
        unsigned long size = flash->chip->total_size * 1024;
+       int read_all_first = 1; /* FIXME: Make this configurable. */
 
        if (chip_safety_check(flash, force, read_it, write_it, erase_it, 
verify_it)) {
                msg_cerr("Aborting.\n");
@@ -1983,26 +1984,33 @@
 
        /* Read the whole chip to be able to check whether regions need to be
         * erased and to give better diagnostics in case write fails.
-        * The alternative would be to read only the regions which are to be
+        * The alternative is to read only the regions which are to be
         * preserved, but in that case we might perform unneeded erase which
         * takes time as well.
         */
-       msg_cinfo("Reading old flash chip contents... ");
-       if (flash->chip->read(flash, oldcontents, 0, size)) {
-               ret = 1;
-               msg_cinfo("FAILED.\n");
-               goto out;
+       if (read_all_first) {
+               msg_cinfo("Reading old flash chip contents... ");
+               if (flash->chip->read(flash, oldcontents, 0, size)) {
+                       ret = 1;
+                       msg_cinfo("FAILED.\n");
+                       goto out;
+               }
        }
        msg_cinfo("done.\n");
 
        /* Build a new image taking the given layout into account. */
-       build_new_image(flash, oldcontents, newcontents);
+       if (build_new_image(flash, read_all_first, oldcontents, newcontents)) {
+               msg_gerr("Could not prepare the data to be written, 
aborting.\n");
+               ret = 1;
+               goto out;
+       }
 
        // ////////////////////////////////////////////////////////////
 
-       if (write_it) {
-               if (erase_and_write_flash(flash, oldcontents, newcontents)) {
-                       msg_cerr("Uh oh. Erase/write failed. Checking if 
anything has changed.\n");
+       if (write_it && erase_and_write_flash(flash, oldcontents, newcontents)) 
{
+               msg_cerr("Uh oh. Erase/write failed.");
+               if (read_all_first) {
+                       msg_cerr("Checking if anything has changed.\n");
                        msg_cinfo("Reading current flash chip contents... ");
                        if (!flash->chip->read(flash, newcontents, 0, size)) {
                                msg_cinfo("done.\n");
@@ -2017,7 +2025,11 @@
                        emergency_help_message();
                        ret = 1;
                        goto out;
-               }
+               } else
+                       msg_cerr("\n");
+               emergency_help_message();
+               ret = 1;
+               goto out;
        }
 
        /* Verify only if we either did not try to write (verify operation) or 
actually changed something. */

Modified: trunk/layout.c
==============================================================================
--- trunk/layout.c      Wed Sep 10 01:03:32 2014        (r1850)
+++ trunk/layout.c      Sun Oct 19 09:53:45 2014        (r1851)
@@ -257,7 +257,28 @@
        return ret;
 }
 
-int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, 
uint8_t *newcontents)
+static int copy_old_content(struct flashctx *flash, int oldcontents_valid, 
uint8_t *oldcontents, uint8_t *newcontents, unsigned int start, unsigned int 
size)
+{
+       if (!oldcontents_valid) {
+               /* oldcontents is a zero-filled buffer. By reading the current 
data into oldcontents here, we
+                * avoid a rewrite of identical regions even if an initial full 
chip read didn't happen. */
+               msg_gdbg2("Read a chunk starting at 0x%06x (len=0x%06x).\n", 
start, size);
+               int ret = flash->chip->read(flash, oldcontents + start, start, 
size);
+               if (ret != 0) {
+                       msg_gerr("Failed to read chunk 0x%06x-0x%06x.\n", 
start, start + size - 1);
+                       return 1;
+               }
+       }
+       memcpy(newcontents + start, oldcontents + start, size);
+       return 0;
+}
+
+/**
+ * Modify @newcontents so that it contains the data that should be on the chip 
eventually. In the case the user
+ * wants to update only parts of it, copy the chunks to be preserved from 
@oldcontents to @newcontents. If
+ * @oldcontents is not valid, we need to fetch the current data from the chip 
first.
+ */
+int build_new_image(struct flashctx *flash, bool oldcontents_valid, uint8_t 
*oldcontents, uint8_t *newcontents)
 {
        unsigned int start = 0;
        romentry_t *entry;
@@ -276,14 +297,14 @@
                entry = get_next_included_romentry(start);
                /* No more romentries for remaining region? */
                if (!entry) {
-                       memcpy(newcontents + start, oldcontents + start,
-                              size - start);
+                       copy_old_content(flash, oldcontents_valid, oldcontents, 
newcontents, start,
+                                        size - start);
                        break;
                }
                /* For non-included region, copy from old content. */
                if (entry->start > start)
-                       memcpy(newcontents + start, oldcontents + start,
-                              entry->start - start);
+                       copy_old_content(flash, oldcontents_valid, oldcontents, 
newcontents, start,
+                                        entry->start - start);
                /* Skip to location after current romentry. */
                start = entry->end + 1;
                /* Catch overflow. */

_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to