summaryrefslogtreecommitdiff
path: root/chip/stm32/bkpdata.c
diff options
context:
space:
mode:
authorCraig Hesling <hesling@chromium.org>2020-01-08 15:41:16 -0800
committerCommit Bot <commit-bot@chromium.org>2020-02-06 06:57:39 +0000
commit127975b6c3efe77b6e92af6b153504c2607d5a07 (patch)
treeeefaa0d3c947c27ff926c9021eb5edb0b955da08 /chip/stm32/bkpdata.c
parent50d7dd999f709669fe965cda68b753c3ee4602e2 (diff)
downloadchrome-ec-127975b6c3efe77b6e92af6b153504c2607d5a07.tar.gz
nocturne_fp: Add fix for legacy reset loop
This patch mitigates an infinite reset loop caused by an RO bug. The reset occurs in RO when hardware write protect (wp_gpio_asserted) is disabled, but software write protect (ro_now) is still enabled. This can be seen by disabling hardware write protect and issuing a soft reset. There is one case where RO will forgo issuing this system reset. That is when it detects a power on reset. Furthermore, it retrieves its reset flags from the main system_get_reset_flags function, which combines hardware reset registers AND a special RTC backup register designed to preserve reset flags. We exploit this reset backup register mechanism to inject a fake power-on flag before resetting. As an added bonus, we also inject an ap-off flag so that we can determine on startup if the power-on flag is real or forged by this mechanism. If we detect that the power-on flag was forged, we print a warning and fix the current reset flags. In order to ensure that a power-on will be forged when a spurious reset happens (exception or pin reset), we keep the backup register loaded with the power-on and ap-off reset flags, when the hardware write protect is disabled. In order to keep the typical code path (HW+SW WP enabled) clear of complexity and false power-on reports, we only forge the power-on flag when hardware write protect is disabled. Thus, we conditionally setup the forge on startup and setup an interrupt handler to catch changes to the hardware write protect status. It is safe to use ap-off flag for our nefarious purposes, since the fingerprint controller has no functionality to control an AP and has no included code that uses this reset flag. Review: * Normal power on reset --> The ap-off flag should be cleared * Forged power on reset --> We set the ap-off flag Scenarios covered: * True power on --> No reset loop and ap-off would not be set * HW reset pulse --> We preloaded ap-off and power-on flags in the reset backup register * Exception/Watchdog --> Same as above * System reboot --> We modified the system_reset function to add ap-off and power-on to reset backup register BRANCH=nocturne,hatch BUG=b:146428434 TEST=make buildall -j TEST=Checked all of the scenarios mentioned above in the [SW-WP off + HW-WP off], [SW-WP on + HW-WP on], and [SW-WP on + HW-WP off] situations using the nucleo-h743zi board (https://crrev.com/c/1994624). TEST=Checked all of the previous using nocturne_fp board on nucleo-h743zi TEST=Checked stable RO+fixed-RW on Kohaku Change-Id: I89361fa95be8eafe78c80c30f5b3195d7a724f81 Signed-off-by: Craig Hesling <hesling@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1992740 Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'chip/stm32/bkpdata.c')
-rw-r--r--chip/stm32/bkpdata.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/chip/stm32/bkpdata.c b/chip/stm32/bkpdata.c
index 51ca4f4a6e..2b26ace7ea 100644
--- a/chip/stm32/bkpdata.c
+++ b/chip/stm32/bkpdata.c
@@ -3,6 +3,8 @@
* found in the LICENSE file.
*/
+#include <assert.h>
+
#include "bkpdata.h"
#include "registers.h"
#include "system.h" /* enum system_bbram_idx */
@@ -67,3 +69,25 @@ int bkpdata_index_lookup(enum system_bbram_idx idx, int *msb)
#endif
return -1;
}
+
+uint32_t bkpdata_read_reset_flags()
+{
+ uint32_t flags = bkpdata_read(BKPDATA_INDEX_SAVED_RESET_FLAGS);
+#ifdef CONFIG_STM32_RESET_FLAGS_EXTENDED
+ flags |= bkpdata_read(BKPDATA_INDEX_SAVED_RESET_FLAGS_2) << 16;
+#endif
+ return flags;
+}
+
+__overridable
+void bkpdata_write_reset_flags(uint32_t save_flags)
+{
+#ifdef CONFIG_STM32_RESET_FLAGS_EXTENDED
+ bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags & 0xffff);
+ bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS_2, save_flags >> 16);
+#else
+ /* Reset flags are 32-bits, but BBRAM entry is only 16 bits. */
+ ASSERT(!(save_flags >> 16));
+ bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags);
+#endif
+}