summaryrefslogtreecommitdiff
path: root/chip/g/system.c
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2016-12-15 14:21:56 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-12-21 00:43:38 -0800
commit4692be2957e102ad937d34c9eeccb76dca06ecff (patch)
tree980423d6b9c4a0a90d57064f35a04d9aa955cb39 /chip/g/system.c
parent167f7e51d8e7693a277077d6c24294d2997e1c55 (diff)
downloadchrome-ec-4692be2957e102ad937d34c9eeccb76dca06ecff.tar.gz
cr50: keep wp and console state through deep sleep
After every reboot, we were resetting the write protect and console lock states back to default. With this change the wp and lock states will be preserved through deep sleep. They will still be reset on any other type of reboot (like Power On reset or panic). The states are also cleared if the system detects a rollback even when booting from the deep sleep. With this patch it is going to be impossible to remove hardware write protection guarding writes into AP and EC firmware flash, unless the cr50 console is unlocked. Locking the console would reinstate hardware write protection automatically even if it was disabled when the console was unlocked. Two long life scratch register 1 bits are used to keep the console and write protect states over resets. To make code cleaner bitmap assignments of the long life scratch register is put in its own include file. BUG=chrome-os-partner:58961 BRANCH=none TEST=manual On prod/dev images verify that the default wp and console lock states are still correct. change the lock and write protect states from the default and verify they are preserved through deep sleep. reboot cr50 and make sure that they are reset. unlock the console and enable flash writes, then set fallback counter on cr50 to the value of 6 (rw 0x40000128 1; rw 0x4000012c 6) and put the AP into deep sleep by hitting Alt-H-VolUp. In five minutes press the power button on the device to bring it back from s5. Observe cr50 fall back to an older image and console lock and wp disabled. Change-Id: Ie7e62cb0b2eda49b04a592ee1d0903e83246b045 Signed-off-by: Mary Ruthven <mruthven@chromium.org> Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/420812 Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'chip/g/system.c')
-rw-r--r--chip/g/system.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/chip/g/system.c b/chip/g/system.c
index 5ab69abda1..a6a67cc5f1 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -310,7 +310,7 @@ static int a_is_newer_than_b(const struct SignedHeader *a,
* apparently failing image from being considered as a candidate to load and
* run on the following reboots.
*/
-static int corrupt_other_header(volatile struct SignedHeader *header)
+static int corrupt_header(volatile struct SignedHeader *header)
{
int rv;
const char zero[4] = {}; /* value to write to magic. */
@@ -344,19 +344,15 @@ static int corrupt_other_header(volatile struct SignedHeader *header)
*/
#define RW_BOOT_MAX_RETRY_COUNT 5
-int system_process_retry_counter(void)
+/*
+ * Check if the current running image is newer. Set the passed in pointer, if
+ * supplied, to point to the newer image in case the running image is the
+ * older one.
+ */
+static int current_image_is_newer(struct SignedHeader **newer_image)
{
- unsigned retry_counter;
struct SignedHeader *me, *other;
- retry_counter = GREG32(PMU, LONG_LIFE_SCRATCH0);
- system_clear_retry_counter();
-
- ccprintf("%s:retry counter %d\n", __func__, retry_counter);
-
- if (retry_counter <= RW_BOOT_MAX_RETRY_COUNT)
- return EC_SUCCESS;
-
if (system_get_image_copy() == SYSTEM_IMAGE_RW) {
me = (struct SignedHeader *)
get_program_memory_addr(SYSTEM_IMAGE_RW);
@@ -369,17 +365,43 @@ int system_process_retry_counter(void)
get_program_memory_addr(SYSTEM_IMAGE_RW);
}
- if (a_is_newer_than_b(me, other)) {
+ if (a_is_newer_than_b(me, other))
+ return 1;
+
+ if (newer_image)
+ *newer_image = other;
+ return 0;
+}
+
+int system_rollback_detected(void)
+{
+ return !current_image_is_newer(NULL);
+}
+
+int system_process_retry_counter(void)
+{
+ unsigned retry_counter;
+ struct SignedHeader *newer_image;
+
+ retry_counter = GREG32(PMU, LONG_LIFE_SCRATCH0);
+ system_clear_retry_counter();
+
+ ccprintf("%s:retry counter %d\n", __func__, retry_counter);
+
+ if (retry_counter <= RW_BOOT_MAX_RETRY_COUNT)
+ return EC_SUCCESS;
+
+ if (current_image_is_newer(&newer_image)) {
ccprintf("%s: "
"this is odd, I am newer, but retry counter was %d\n",
__func__, retry_counter);
return EC_SUCCESS;
}
/*
- * let's corrupt the "other" guy so that the next restart is happening
- * straight into this version.
+ * let's corrupt the newer image so that the next restart is happening
+ * straight into the current version.
*/
- return corrupt_other_header(other);
+ return corrupt_header(newer_image);
}
int system_rolling_reboot_suspected(void)