[flashrom] [commit] r1851 - trunk
repository service
svn at flashrom.org
Sun Oct 19 09:53:47 CEST 2014
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 <stefan.tauner at student.tuwien.ac.at>
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
Acked-by: Stefan Tauner <stefan.tauner at alumni.tuwien.ac.at>
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. */
More information about the flashrom
mailing list