CHROMIUM: cros_ec.c: Avoid sysjumps where possible
Avoid unconditional sysjumps to allow software sync to do
its job.
BUG=b:278652302,b:152925812
BRANCH=none
TEST=`futility update --quirks=ec_partial_recovery` does not sysjump from RW for EC.
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Change-Id: I3313a540b98d8e87f84ab6fc25b1e0f4d703dbff
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+/4445816
Reviewed-by: Sam McNally <sammc@chromium.org>
Commit-Queue: Edward O'Callaghan <quasisec@chromium.org>
Tested-by: Sam McNally <sammc@chromium.org>
Auto-Submit: Edward O'Callaghan <quasisec@chromium.org>
Tested-by: Edward O'Callaghan <quasisec@chromium.org>
diff --git a/cros_ec.c b/cros_ec.c
index 3595b14..89b39d8 100644
--- a/cros_ec.c
+++ b/cros_ec.c
@@ -406,6 +406,7 @@
const struct fmap_area *fa = &fmap->areas[i];
for (unsigned int j = EC_IMAGE_RO; j < ARRAY_SIZE(sections); j++) {
+ /* skip fmap sections unrelated to cros_ec sections. */
if (strcmp(sections[j], (const char *) fa->name))
continue;
@@ -417,6 +418,30 @@
free(fmap);
}
+/**
+ * iff layout region is one of the supported cros_ec
+ * sections then modify the region_type bit-feild.
+ * 00 - no RO or RW.
+ * 01 - RO found.
+ * 10 - RW found.
+ * 11 - RO+RW found.
+ */
+static enum ec_current_image parse_layout(const struct flashrom_layout *const layout)
+{
+ enum ec_current_image region_type = EC_IMAGE_UNKNOWN; /* no RO or RW found yet. */
+ const struct romentry *entry = NULL;
+
+ while ((entry = layout_next_included(layout, entry))) {
+ const struct flash_region *region = &entry->region;
+ if (!strcmp("WP_RO", (const char *) region->name))
+ region_type |= EC_IMAGE_RO;
+ if (!strcmp(sections[EC_IMAGE_RW], (const char *) region->name))
+ region_type |= EC_IMAGE_RW;
+ }
+ /* iff neither RO or RW was found in the layout then assume a full image of both. */
+ return region_type == EC_IMAGE_UNKNOWN ? (EC_IMAGE_RO | EC_IMAGE_RW) : region_type;
+}
+
/*
* Prepare EC for update:
* - Disable soft WP if needed.
@@ -437,13 +462,33 @@
return 1;
parse_fmap(image, flash_size);
+ /* check layout to determine what sysjumps we are required to do. */
+ const struct flashrom_layout *const layout = get_layout(flash);
+ const enum ec_current_image region_typ = parse_layout(layout);
+ const uint8_t ec_subtype = cros_ec_priv->subtype; /* non-zero denotes non-ec path. */
if (ec_check_features(EC_FEATURE_EXEC_IN_RAM) <= 0) {
/* Warning: before update, we jump the EC to RO copy. If you
* want to change this behavior, please also check the
* cros_ec_finish().
*/
- msg_pwarn("EXEC_IN_RAM unsupported - jumping to RO\n");
+ msg_pwarn("EXEC_IN_RAM unsupported..");
+
+ if (ec_subtype) {
+ msg_pwarn(" legacy component, unconditional jump to RO.\n");
+ return cros_ec_jump_copy(EC_IMAGE_RO);
+ }
+
+ if (!(region_typ & EC_IMAGE_RO) && cros_ec_get_current_image() == EC_IMAGE_RO) {
+ msg_pwarn(" image contains RW and already in RO, skipping jump.\n");
+ return 0;
+ }
+ if (!(region_typ & EC_IMAGE_RW) && cros_ec_get_current_image() == EC_IMAGE_RW) {
+ msg_pwarn(" image contains RO and already in RW, skipping jump.\n");
+ return 0;
+ }
+
+ msg_pwarn(" unconditional jump to RO.\n");
return cros_ec_jump_copy(EC_IMAGE_RO);
}
msg_pwarn("EXEC_IN_RAM supported - skip jumping to RO\n");
@@ -483,19 +528,23 @@
}
-/* Returns 0 for success.
- *
+/**
+ * Returns 0 for success.
* Try latest firmware: B > A > RO
- *
- * This function assumes the EC jumps to RO at cros_ec_prepare() so that
- * the fwcopy[RO].flags is old (0) and A/B are new. Please also refine
- * this code logic if you change the cros_ec_prepare() behavior.
*/
int cros_ec_finish(void)
{
if (!(cros_ec_priv && cros_ec_priv->detected))
return 0;
+ /*
+ * Check that the EC had jumped to RO at cros_ec_prepare() so that
+ * the fwcopy[RO].flags is old (0) and A/B are new otherwise return.
+ */
+ const uint8_t ec_subtype = cros_ec_priv->subtype; /* non-zero denotes non-ec path. */
+ if (cros_ec_get_current_image() != EC_IMAGE_RO && !ec_subtype)
+ return 0;
+
/* For EC with RWSIG enabled. We need a cold reboot to enable
* EC_FLASH_PROTECT_ALL_NOW and make sure RWSIG check is performed.
*/
diff --git a/cros_ec.h b/cros_ec.h
index 787af26..65f2f7d 100644
--- a/cros_ec.h
+++ b/cros_ec.h
@@ -40,6 +40,9 @@
*/
const char* dev;
+ /* technical debt to deal with non-EC components (pd, tp, fp). */
+ uint8_t subtype;
+
/*
* Some CrOS ECs support page write mode for their flash memory. This
* represents the ideal size of a data payload to write to flash.
diff --git a/cros_ec_dev.c b/cros_ec_dev.c
index 11ebf58..90378c7 100644
--- a/cros_ec_dev.c
+++ b/cros_ec_dev.c
@@ -430,6 +430,7 @@
priv->dev = ec_type[index];
if (!strcmp(priv->dev, "fp"))
msg_perr("\t\033[31;1;5;7m >> The fp subtype is deprecated! Remove call site NOW as this WILL be deleted! <<\033[0m\n");
+ priv->subtype = index;
msg_pdbg("Target %s used\n", priv->dev);
}
free(p);
@@ -515,6 +516,7 @@
.region = NULL,
.ec_command = cros_ec_command_dev,
.dev = "ec",
+ .subtype = 0,
.ideal_write_size = 0,
.erase_block_size = 0,
.max_response_size = 0