summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2023-03-23 12:51:34 -0500
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-04-17 22:07:28 +0000
commit53a6bef971baa7110b6c2367554acf8b77331fb6 (patch)
tree109db372cf4af7c4bb1d3ef1bf9a35267f88f2fa
parent058ae2bf2a86fd45abe219a443619035f8fdcfdc (diff)
downloadchrome-ec-53a6bef971baa7110b6c2367554acf8b77331fb6.tar.gz
cr50: add fwmp wp policy
BUG=b:268352167 TEST=see bug Change-Id: I3a4f2ae746cbc2e64df535c4c91b16cdbd7f292a Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4367525 Reviewed-by: Andrey Pronin <apronin@chromium.org>
-rw-r--r--board/cr50/scratch_reg1.h5
-rw-r--r--board/cr50/wp.c78
-rw-r--r--include/tpm_vendor_cmds.h1
3 files changed, 76 insertions, 8 deletions
diff --git a/board/cr50/scratch_reg1.h b/board/cr50/scratch_reg1.h
index 31a3b541d7..7967c50de6 100644
--- a/board/cr50/scratch_reg1.h
+++ b/board/cr50/scratch_reg1.h
@@ -105,6 +105,11 @@
#define BOARD_USE_DIOM4 BIT(24)
/*
+ * The FWMP settings force WP enable.
+ */
+#define BOARD_FWMP_FORCE_WP_EN BIT(25)
+
+/*
* Indicates successful completion of FIPS power up
* tests earlier. Reduces wake up time after sleep.
* Stored in PWRDN_SCRATCH22 and use multiple bits to harden against
diff --git a/board/cr50/wp.c b/board/cr50/wp.c
index 54dc17318c..c6dbf15779 100644
--- a/board/cr50/wp.c
+++ b/board/cr50/wp.c
@@ -40,6 +40,14 @@ int board_battery_is_present(void)
}
/**
+ * Return non-zero if the FWMP is enabling write protect.
+ */
+static int board_fwmp_force_wp_en(void)
+{
+ return !!(GREG32(PMU, LONG_LIFE_SCRATCH1) & BOARD_FWMP_FORCE_WP_EN);
+}
+
+/**
* Return non-zero if the wp state is being overridden.
*/
static int board_forcing_wp(void)
@@ -54,6 +62,11 @@ static int board_forcing_wp(void)
*/
static void set_wp_state(int asserted)
{
+ /* This shouldn't be possible. Ensure nothing can disable wp. */
+ if (board_fwmp_force_wp_en() && !asserted) {
+ CPRINTS("FWMP: WP ovrd");
+ asserted = 1;
+ }
/* Enable writing to the long life register */
GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 1);
@@ -85,7 +98,7 @@ static void check_wp_battery_presence(void)
int bp = board_battery_is_present();
/* If we're forcing WP, ignore battery detect */
- if (board_forcing_wp())
+ if (board_fwmp_force_wp_en() || board_forcing_wp())
return;
/* Otherwise, mirror battery */
@@ -148,6 +161,17 @@ static enum vendor_cmd_rc vc_set_wp(enum vendor_cmd_cc code,
}
/* Get current wp settings */
+ if (board_fwmp_force_wp_en()) {
+ response |= WPV_FWMP_FORCE_WP_EN;
+ /*
+ * Setting WPV_ATBOOT_SET and WPV_ATBOOT_ENABLE isn't completely
+ * necessary. It just makes cr50 more compatible with old
+ * gsctool versions. These flags show WP is enabled at boot
+ * which is essentially what the FWMP override does.
+ */
+ response |= WPV_ATBOOT_SET;
+ response |= WPV_ATBOOT_ENABLE;
+ }
if (board_forcing_wp())
response |= WPV_FORCE;
if (wp_is_asserted())
@@ -220,6 +244,11 @@ static int command_wp(int argc, char **argv)
if (!ccd_is_cap_enabled(CCD_CAP_OVERRIDE_WP))
return EC_ERROR_ACCESS_DENIED;
+ /* It's not possible to change WP when the FWMP enables it. */
+ if (board_fwmp_force_wp_en()) {
+ ccprintf("FWMP enabled WP\n");
+ return EC_ERROR_ACCESS_DENIED;
+ }
/* Update WP */
if (!strncasecmp(argv[1], "follow", 6))
forced = 0;
@@ -237,10 +266,14 @@ static int command_wp(int argc, char **argv)
}
}
- ccprintf("Flash WP: %s%sabled\n", board_forcing_wp() ? "forced " : "",
- wp_is_asserted() ? "en" : "dis");
+ ccprintf("Flash WP: %s%s%sabled\n",
+ board_fwmp_force_wp_en() ? "fwmp " : "",
+ board_forcing_wp() ? "forced " : "",
+ wp_is_asserted() ? "en" : "dis");
ccprintf(" at boot: ");
- if (ccd_get_flag(CCD_FLAG_OVERRIDE_WP_AT_BOOT))
+ if (board_fwmp_force_wp_en())
+ ccprintf("fwmp enabled\n");
+ else if (ccd_get_flag(CCD_FLAG_OVERRIDE_WP_AT_BOOT))
ccprintf("forced %sabled\n",
ccd_get_flag(CCD_FLAG_OVERRIDE_WP_STATE_ENABLED)
? "en" : "dis");
@@ -267,7 +300,9 @@ void set_bp_follow_ccd_config(void)
static void set_wp_follow_ccd_config(void)
{
- if (ccd_get_flag(CCD_FLAG_OVERRIDE_WP_AT_BOOT)) {
+ if (board_fwmp_force_wp_en()) {
+ force_write_protect(1, 1);
+ } else if (ccd_get_flag(CCD_FLAG_OVERRIDE_WP_AT_BOOT)) {
/* Reset to at-boot state specified by CCD */
force_write_protect(1, ccd_get_flag
(CCD_FLAG_OVERRIDE_WP_STATE_ENABLED));
@@ -289,6 +324,24 @@ void board_wp_follow_ccd_config(void)
set_wp_follow_ccd_config();
}
+static int board_fwmp_check_wp_policy(void)
+{
+ int fwmp_force_wp = !board_fwmp_allows_unlock();
+ int update_brdprop = fwmp_force_wp != board_fwmp_force_wp_en();
+
+ if (update_brdprop) {
+ CPRINTS("%s", __func__);
+ board_write_prop(BOARD_FWMP_FORCE_WP_EN, fwmp_force_wp);
+ }
+
+ if (fwmp_force_wp && (!wp_is_asserted() || update_brdprop)) {
+ CPRINTS("%s: force en", __func__);
+ force_write_protect(1, 1);
+ return 0;
+ }
+ return update_brdprop;
+}
+
void init_wp_state(void)
{
/*
@@ -297,6 +350,16 @@ void init_wp_state(void)
*/
set_bp_follow_ccd_config();
+ /*
+ * If the FWMP is forcing WP, enable write protect. It overrides other
+ * configs.
+ */
+ board_fwmp_check_wp_policy();
+ if (board_fwmp_force_wp_en()) {
+ set_wp_state(1);
+ return;
+ }
+
/* Check system reset flags after CCD config is initially loaded */
if ((system_get_reset_flags() & EC_RESET_FLAG_HIBERNATE) &&
!system_rollback_detected()) {
@@ -498,9 +561,8 @@ int board_fwmp_allows_boot_policy_update(void)
void board_fwmp_update_policies(void)
{
-#ifdef CR50_DEV
- CPRINTS("Update fwmp policies.");
-#endif
+ if (board_fwmp_check_wp_policy())
+ set_wp_follow_ccd_config();
}
int board_vboot_dev_mode_enabled(void)
diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h
index ba8c1a208c..943fafd1a2 100644
--- a/include/tpm_vendor_cmds.h
+++ b/include/tpm_vendor_cmds.h
@@ -346,5 +346,6 @@ struct vendor_cc_spi_hash_request {
#define WPV_FORCE BIT(2)
#define WPV_ATBOOT_SET BIT(3)
#define WPV_ATBOOT_ENABLE BIT(4)
+#define WPV_FWMP_FORCE_WP_EN BIT(5)
#endif /* __INCLUDE_TPM_VENDOR_CMDS_H */