futility: updater: add new quirk 'extra_retries'
In early bring up, some devices may have problem when flashrom is
reading or writing to the system flash. To unblock dogfood process,
we want to have a special quirk to retry flashing.
BUG=b:213706510
TEST=make; build and run test
BRANCH=None
Change-Id: I58788f620fb32f7c886d1e5638f4a3605ea77953
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3452846
Reviewed-by: YH Lin <yueherngl@chromium.org>
Commit-Queue: YH Lin <yueherngl@chromium.org>
Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
(cherry picked from commit 707b839fadfd600af4300bc451946f8e8ccf840e)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3906634
Commit-Queue: Nick Vaccaro <nvaccaro@google.com>
Tested-by: Nick Vaccaro <nvaccaro@google.com>
diff --git a/futility/updater.c b/futility/updater.c
index 46f8878..5790ace 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -384,6 +384,14 @@
}
/*
+ * Returns the number of retries when reading or writing to flash.
+ */
+static int get_io_retries(struct updater_config *cfg)
+{
+ return 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg);
+}
+
+/*
* Writes a section from given firmware image to system firmware.
* If section_name is NULL, write whole image.
* Returns 0 if success, non-zero if error.
@@ -410,7 +418,7 @@
return write_system_firmware(image, diff_image, section_name,
&cfg->tempfiles, cfg->do_verify,
- cfg->verbosity + 1);
+ get_io_retries(cfg), cfg->verbosity + 1);
}
/*
@@ -1207,9 +1215,10 @@
}
if (!image_from->data) {
int ret;
+
INFO("Loading current system firmware...\n");
ret = load_system_firmware(image_from, &cfg->tempfiles,
- cfg->verbosity);
+ get_io_retries(cfg), cfg->verbosity);
if (ret == IMAGE_PARSE_FAILURE && cfg->force_update) {
WARN("No compatible firmware in system.\n");
cfg->check_platform = 0;
@@ -1392,7 +1401,9 @@
if (!cfg->image_current.data) {
INFO("Loading system firmware for white label...\n");
load_system_firmware(&cfg->image_current,
- &cfg->tempfiles, cfg->verbosity);
+ &cfg->tempfiles,
+ get_io_retries(cfg),
+ cfg->verbosity);
}
tmp_image = get_firmware_image_temp_file(
&cfg->image_current, &cfg->tempfiles);
diff --git a/futility/updater.h b/futility/updater.h
index 2562782..6dda928 100644
--- a/futility/updater.h
+++ b/futility/updater.h
@@ -48,6 +48,7 @@
QUIRK_PRESERVE_ME,
QUIRK_NO_CHECK_PLATFORM,
QUIRK_NO_VERIFY,
+ QUIRK_EXTRA_RETRIES,
QUIRK_MAX,
};
diff --git a/futility/updater_quirks.c b/futility/updater_quirks.c
index 1f7fada..6d6ccf8 100644
--- a/futility/updater_quirks.c
+++ b/futility/updater_quirks.c
@@ -512,6 +512,11 @@
quirks->name = "no_verify";
quirks->help = "Do not verify when flashing.";
quirks->apply = quirk_no_verify;
+
+ quirks = &cfg->quirks[QUIRK_EXTRA_RETRIES];
+ quirks->name = "extra_retries";
+ quirks->help = "Extra retries when writing to system firmware.";
+ quirks->apply = NULL; /* Simple config. */
}
/*
diff --git a/futility/updater_utils.c b/futility/updater_utils.c
index 2221a87..a846ef2 100644
--- a/futility/updater_utils.c
+++ b/futility/updater_utils.c
@@ -523,11 +523,16 @@
* Returns 0 if success, non-zero if error.
*/
int load_system_firmware(struct firmware_image *image,
- struct tempfile *tempfiles, int verbosity)
+ struct tempfile *tempfiles,
+ int retries, int verbosity)
{
- int r;
+ int r, i;
- r = flashrom_read_image(image, NULL, (verbosity + 1));
+ for (i = 1, r = -1; i <= retries && r != 0; i++) {
+ if (i > 1)
+ WARN("Retry reading firmware (%d/%d)...\n", i, retries);
+ r = flashrom_read_image(image, NULL, verbosity + 1);
+ }
if (!r)
r = parse_firmware_image(image);
return r;
@@ -542,10 +547,17 @@
const struct firmware_image *diff_image,
const char *section_name,
struct tempfile *tempfiles,
- int do_verify, int verbosity)
+ int do_verify, int retries, int verbosity)
{
- return flashrom_write_image(image, section_name, diff_image,
- do_verify, (verbosity + 1));
+ int r, i;
+
+ for (i = 1, r = -1; i <= retries && r != 0; i++) {
+ if (i > 1)
+ WARN("Retry writing firmware (%d/%d)...\n", i, retries);
+ r = flashrom_write_image(image, section_name, diff_image,
+ do_verify, verbosity + 1);
+ }
+ return r;
}
/* Helper function to return host software write protection status. */
diff --git a/futility/updater_utils.h b/futility/updater_utils.h
index ae5574f..8ac0683 100644
--- a/futility/updater_utils.h
+++ b/futility/updater_utils.h
@@ -85,7 +85,8 @@
* Returns 0 if success, non-zero if error.
*/
int load_system_firmware(struct firmware_image *image,
- struct tempfile *tempfiles, int verbosity);
+ struct tempfile *tempfiles,
+ int retries, int verbosity);
/* Frees the allocated resource from a firmware image object. */
void free_firmware_image(struct firmware_image *image);
@@ -107,7 +108,7 @@
const struct firmware_image *diff_image,
const char *section_name,
struct tempfile *tempfiles,
- int do_verify, int verbosity);
+ int do_verify, int retries, int verbosity);
struct firmware_section {
uint8_t *data;