aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2018-01-15 01:10:36 +0300
committerNico Huber <nico.h@gmx.de>2018-02-11 16:54:14 +0000
commitf701f343117270b4373320eb25ae259b8e513b7d (patch)
tree2749940aec9f2b1dc0ad53069079b78f225d76cf
parent3a826043dbd389b4be2f5783c1b984ba297b8179 (diff)
downloadflashrom-f701f343117270b4373320eb25ae259b8e513b7d.tar.gz
flashrom-f701f343117270b4373320eb25ae259b8e513b7d.tar.bz2
flashrom-f701f343117270b4373320eb25ae259b8e513b7d.zip
Add support for reading the current flash contents from a file
When developing software that has to be flashed to a flash chip to be executed, it often takes a long time to read the current flash contents (for flashrom to know what pages to erase and reprogram) each time when writing the new image. However, when the flash was just reprogrammed, its current state is known to be the previous image that was flashed (assuming it was verified). Thus, it makes sense to provide that image as a file for the flash contents instead of wasting valuable time read the whole flash each time. Change-Id: Idf153b6955f37779ae9bfb228a434ed10c304947 Signed-off-by: Mike Banon <mikebdp2@gmail.com> Signed-off-by: Paul Kocialkowski <contact@paulk.fr> Reviewed-on: https://review.coreboot.org/23263 Reviewed-by: Nico Huber <nico.h@gmx.de> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-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 441fc919..31f7394d 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 7bf3cc71..a80a9c24 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 26b9863c..d87a4317 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 d3f3dedc..786147b2 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