summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli_classic.c20
-rw-r--r--flash.h2
-rw-r--r--flashrom.c63
-rw-r--r--libflashrom.h4
4 files changed, 61 insertions, 28 deletions
diff --git a/cli_classic.c b/cli_classic.c
index 441fc919c..31f7394d4 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -60,6 +60,7 @@ static void cli_classic_usage(const char *name)
" --ifd read layout from an Intel Firmware Descriptor\n"
" -i | --image <name> only flash image <name> from flash layout\n"
" -o | --output <logfile> log output to <logfile>\n"
+ " --flash-contents <ref-file> assume flash contents to be <ref-file>\n"
" -L | --list-supported print supported devices\n"
#if CONFIG_PRINT_WIKI == 1
" -z | --list-supported-wiki print supported devices in wiki syntax\n"
@@ -108,6 +109,10 @@ int main(int argc, char *argv[])
int dont_verify_it = 0, dont_verify_all = 0, list_supported = 0, operation_specified = 0;
struct flashrom_layout *layout = NULL;
enum programmer prog = PROGRAMMER_INVALID;
+ enum {
+ OPTION_IFD = 0x0100,
+ OPTION_FLASH_CONTENTS,
+ };
int ret = 0;
static const char optstring[] = "r:Rw:v:nNVEfc:l:i:p:Lzho:";
@@ -122,8 +127,9 @@ int main(int argc, char *argv[])
{"verbose", 0, NULL, 'V'},
{"force", 0, NULL, 'f'},
{"layout", 1, NULL, 'l'},
- {"ifd", 0, NULL, 0x0100},
+ {"ifd", 0, NULL, OPTION_IFD},
{"image", 1, NULL, 'i'},
+ {"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS},
{"list-supported", 0, NULL, 'L'},
{"list-supported-wiki", 0, NULL, 'z'},
{"programmer", 1, NULL, 'p'},
@@ -134,6 +140,7 @@ int main(int argc, char *argv[])
};
char *filename = NULL;
+ char *referencefile = NULL;
char *layoutfile = NULL;
#ifndef STANDALONE
char *logfile = NULL;
@@ -229,7 +236,7 @@ int main(int argc, char *argv[])
}
layoutfile = strdup(optarg);
break;
- case 0x0100:
+ case OPTION_IFD:
if (layoutfile) {
fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
cli_classic_abort_usage();
@@ -243,6 +250,9 @@ int main(int argc, char *argv[])
cli_classic_abort_usage();
}
break;
+ case OPTION_FLASH_CONTENTS:
+ referencefile = strdup(optarg);
+ break;
case 'L':
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
@@ -354,6 +364,9 @@ int main(int argc, char *argv[])
if (layoutfile && check_filename(layoutfile, "layout")) {
cli_classic_abort_usage();
}
+ if (referencefile && check_filename(referencefile, "reference")) {
+ cli_classic_abort_usage();
+ }
#ifndef STANDALONE
if (logfile && check_filename(logfile, "log"))
@@ -569,7 +582,7 @@ int main(int argc, char *argv[])
else if (erase_it)
ret = do_erase(fill_flash);
else if (write_it)
- ret = do_write(fill_flash, filename);
+ ret = do_write(fill_flash, filename, referencefile);
else if (verify_it)
ret = do_verify(fill_flash, filename);
@@ -583,6 +596,7 @@ out:
layout_cleanup();
free(filename);
+ free(referencefile);
free(layoutfile);
free(pparam);
/* clean up global variables */
diff --git a/flash.h b/flash.h
index 7bf3cc714..a80a9c249 100644
--- a/flash.h
+++ b/flash.h
@@ -329,7 +329,7 @@ int prepare_flash_access(struct flashctx *, bool read_it, bool write_it, bool er
void finalize_flash_access(struct flashctx *);
int do_read(struct flashctx *, const char *filename);
int do_erase(struct flashctx *);
-int do_write(struct flashctx *, const char *const filename);
+int do_write(struct flashctx *, const char *const filename, const char *const referencefile);
int do_verify(struct flashctx *, const char *const filename);
/* Something happened that shouldn't happen, but we can go on. */
diff --git a/flashrom.c b/flashrom.c
index 26b9863c8..d87a43171 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -2345,13 +2345,15 @@ static void combine_image_by_layout(const struct flashctx *const flashctx,
* @param flashctx The context of the flash chip.
* @param buffer Source buffer to read image from (may be altered for full verification).
* @param buffer_len Size of source buffer in bytes.
+ * @param refbuffer If given, assume flash chip contains same data as `refbuffer`.
* @return 0 on success,
* 4 if buffer_len doesn't match the size of the flash chip,
* 3 if write was tried but nothing has changed,
* 2 if write failed and flash contents changed,
* or 1 on any other failure.
*/
-int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, const size_t buffer_len)
+int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, const size_t buffer_len,
+ const void *const refbuffer)
{
const size_t flash_size = flashctx->chip->total_size * 1024;
const bool verify_all = flashctx->flags.verify_whole_chip;
@@ -2363,6 +2365,7 @@ int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, co
int ret = 1;
uint8_t *const newcontents = buffer;
+ const uint8_t *const refcontents = refbuffer;
uint8_t *const curcontents = malloc(flash_size);
uint8_t *oldcontents = NULL;
if (verify_all)
@@ -2387,27 +2390,35 @@ int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, co
if (prepare_flash_access(flashctx, false, true, false, verify))
goto _free_ret;
- /*
- * 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 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 (verify_all) {
- if (flashctx->chip->read(flashctx, oldcontents, 0, flash_size)) {
- msg_cinfo("FAILED.\n");
- goto _finalize_ret;
- }
- memcpy(curcontents, oldcontents, flash_size);
+ /* If given, assume flash chip contains same data as `refcontents`. */
+ if (refcontents) {
+ msg_cinfo("Assuming old flash chip contents as ref-file...\n");
+ memcpy(curcontents, refcontents, flash_size);
+ if (oldcontents)
+ memcpy(oldcontents, refcontents, flash_size);
} else {
- if (read_by_layout(flashctx, curcontents)) {
- msg_cinfo("FAILED.\n");
- goto _finalize_ret;
+ /*
+ * 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 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 (verify_all) {
+ if (flashctx->chip->read(flashctx, oldcontents, 0, flash_size)) {
+ msg_cinfo("FAILED.\n");
+ goto _finalize_ret;
+ }
+ memcpy(curcontents, oldcontents, flash_size);
+ } else {
+ if (read_by_layout(flashctx, curcontents)) {
+ msg_cinfo("FAILED.\n");
+ goto _finalize_ret;
+ }
}
+ msg_cinfo("done.\n");
}
- msg_cinfo("done.\n");
if (write_by_layout(flashctx, curcontents, newcontents)) {
msg_cerr("Uh oh. Erase/write failed. ");
@@ -2542,13 +2553,15 @@ int do_erase(struct flashctx *const flash)
return ret;
}
-int do_write(struct flashctx *const flash, const char *const filename)
+int do_write(struct flashctx *const flash, const char *const filename, const char *const referencefile)
{
const size_t flash_size = flash->chip->total_size * 1024;
int ret = 1;
uint8_t *const newcontents = malloc(flash_size);
- if (!newcontents) {
+ uint8_t *const refcontents = referencefile ? malloc(flash_size) : NULL;
+
+ if (!newcontents || (referencefile && !refcontents)) {
msg_gerr("Out of memory!\n");
goto _free_ret;
}
@@ -2556,9 +2569,15 @@ int do_write(struct flashctx *const flash, const char *const filename)
if (read_buf_from_file(newcontents, flash_size, filename))
goto _free_ret;
- ret = flashrom_image_write(flash, newcontents, flash_size);
+ if (referencefile) {
+ if (read_buf_from_file(refcontents, flash_size, referencefile))
+ goto _free_ret;
+ }
+
+ ret = flashrom_image_write(flash, newcontents, flash_size, refcontents);
_free_ret:
+ free(refcontents);
free(newcontents);
return ret;
}
diff --git a/libflashrom.h b/libflashrom.h
index d3f3dedcf..786147b2d 100644
--- a/libflashrom.h
+++ b/libflashrom.h
@@ -60,7 +60,7 @@ void flashrom_flag_set(struct flashrom_flashctx *, enum flashrom_flag, bool valu
bool flashrom_flag_get(const struct flashrom_flashctx *, enum flashrom_flag);
int flashrom_image_read(struct flashrom_flashctx *, void *buffer, size_t buffer_len);
-int flashrom_image_write(struct flashrom_flashctx *, void *buffer, size_t buffer_len);
+int flashrom_image_write(struct flashrom_flashctx *, void *buffer, size_t buffer_len, const void *refbuffer);
int flashrom_image_verify(struct flashrom_flashctx *, const void *buffer, size_t buffer_len);
struct flashrom_layout;
@@ -69,4 +69,4 @@ int flashrom_layout_include_region(struct flashrom_layout *, const char *name);
void flashrom_layout_release(struct flashrom_layout *);
void flashrom_layout_set(struct flashrom_flashctx *, const struct flashrom_layout *);
-#endif /* !__LIBFLASHROM_H__ */
+#endif /* !__LIBFLASHROM_H__ */ \ No newline at end of file