summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-07-17 16:11:44 -0700
committerRandall Spangler <rspangler@chromium.org>2012-07-18 18:14:36 -0700
commit1a76325fa8ec6256946598e0e41e17262d8d9198 (patch)
treebf56b46d682e3f7cc3d9234cfcdce7c6cb32fc45
parent2223179cbcd49743b345ca313df99bfa41a57eeb (diff)
downloadchrome-ec-1a76325fa8ec6256946598e0e41e17262d8d9198.tar.gz
Continue refactoring flash write protect
Now properly detects partially-protected flash banks. Also renames 'flashwp lock/unlock' to 'flashwp enable/disable' BUG=chrome-os-partner:11150 TEST=manual ww 0x400fe400 0x7fffffff flashinfo -> ro_now PARTIAL reboot ww 0x400fe404 0x7fffffff flashinfo -> rw_now PARTIAL flashwp now flashinfo -> ro_now rw_now (and NOT partial) Change-Id: I9266a024eee6d75af052cd47e3f54468ad959a12 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/27795
-rw-r--r--common/flash_common.c98
-rw-r--r--common/system_common.c10
-rw-r--r--include/flash.h30
3 files changed, 84 insertions, 54 deletions
diff --git a/common/flash_common.c b/common/flash_common.c
index 5ee966e06a..c011e0ab25 100644
--- a/common/flash_common.c
+++ b/common/flash_common.c
@@ -29,10 +29,15 @@
/ CONFIG_FLASH_BANK_SIZE)
#define RO_BANK_COUNT (CONFIG_SECTION_RO_SIZE / CONFIG_FLASH_BANK_SIZE)
+
+/* Flags for persist_state.flags */
+/* Protect persist state and RO firmware at boot */
+#define PERSIST_FLAG_PROTECT_RO 0x02
+
/* Persistent protection state - emulates a SPI status register for flashrom */
struct persist_state {
uint8_t version; /* Version of this struct */
- uint8_t lock; /* Lock flags */
+ uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
uint8_t reserved[2]; /* Reserved; set 0 */
};
@@ -76,10 +81,6 @@ static int read_pstate(void)
memset(&pstate, 0, sizeof(pstate));
pstate.version = PERSIST_STATE_VERSION;
}
-
- /* Mask off currently-valid flags */
- pstate.lock &= FLASH_PROTECT_LOCK_SET;
-
#endif /* CHIP_stm32 */
return EC_SUCCESS;
}
@@ -128,7 +129,7 @@ static int apply_pstate(void)
return rv;
/* If flash isn't locked, nothing to do */
- if (!(pstate.lock & FLASH_PROTECT_LOCK_SET))
+ if (!(pstate.flags & PERSIST_FLAG_PROTECT_RO))
return EC_SUCCESS;
/* Lock the protection data first */
@@ -140,13 +141,6 @@ static int apply_pstate(void)
return EC_SUCCESS;
}
-/* Return non-zero if pstate block is already write-protected. */
-static int is_pstate_lock_applied(void)
-{
- /* Fail if write protect block is already locked */
- return flash_physical_get_protect(PSTATE_BANK);
-}
-
int flash_dataptr(int offset, int size_req, int align, char **ptrp)
{
if (offset < 0 || size_req < 0 ||
@@ -194,12 +188,12 @@ int flash_protect_until_reboot(void)
return EC_SUCCESS;
}
-int flash_lock_protect(int lock)
+int flash_enable_protect(int enable)
{
int rv;
/* Fail if write protect block is already locked */
- if (is_pstate_lock_applied())
+ if (flash_physical_get_protect(PSTATE_BANK))
return EC_ERROR_UNKNOWN;
/* Read the current persist state from flash */
@@ -208,7 +202,7 @@ int flash_lock_protect(int lock)
return rv;
/* Set the new flag */
- pstate.lock = lock ? FLASH_PROTECT_LOCK_SET : 0;
+ pstate.flags = enable ? PERSIST_FLAG_PROTECT_RO : 0;
/* Write the state back to flash */
rv = write_pstate();
@@ -216,29 +210,49 @@ int flash_lock_protect(int lock)
return rv;
/* If unlocking, done now */
- if (!lock)
+ if (!enable)
return EC_SUCCESS;
- /* Otherwise, we need to apply all locks NOW */
+ /* Otherwise, we need to protect RO code NOW */
return apply_pstate();
}
-int flash_get_protect_lock(void)
+int flash_get_protect(void)
{
- int flags;
+ int flags = 0;
+ int i;
/* Read the current persist state from flash */
read_pstate();
- flags = pstate.lock;
-
- /* Check if lock has been applied */
- if (is_pstate_lock_applied())
- flags |= FLASH_PROTECT_LOCK_APPLIED;
+ if (pstate.flags & PERSIST_FLAG_PROTECT_RO)
+ flags |= FLASH_PROTECT_RO_AT_BOOT;
/* Check if write protect pin is asserted now */
if (wp_pin_asserted())
flags |= FLASH_PROTECT_PIN_ASSERTED;
+ /* Scan flash protection */
+ for (i = 0; i < PHYSICAL_BANKS; i++) {
+ /* Is this bank part of RO? */
+ int is_ro = ((i >= RO_BANK_OFFSET &&
+ i < RO_BANK_OFFSET + RO_BANK_COUNT) ||
+ i == PSTATE_BANK);
+ int bank_flag = (is_ro ? FLASH_PROTECT_RO_NOW :
+ FLASH_PROTECT_RW_NOW);
+
+ if (flash_physical_get_protect(i)) {
+ /* At least one bank in the region is protected */
+ flags |= bank_flag;
+ } else if (flags & bank_flag) {
+ /* But not all banks in the region! */
+ flags |= FLASH_PROTECT_PARTIAL;
+ }
+ }
+
+ /* Check if any banks were stuck locked at boot */
+ if (stuck_locked)
+ flags |= FLASH_PROTECT_STUCK_LOCKED;
+
return flags;
}
@@ -304,18 +318,22 @@ static int command_flash_info(int argc, char **argv)
ccprintf("Erase: %4d B\n", flash_get_erase_block_size());
ccprintf("Protect: %4d B\n", flash_get_protect_block_size());
- i = flash_get_protect_lock();
- ccprintf("Lock: %s",
- (i & FLASH_PROTECT_LOCK_SET) ? "LOCKED" : "unlocked");
- if (i & FLASH_PROTECT_LOCK_APPLIED)
- ccputs(",APPLIED");
- if (stuck_locked)
- ccputs(",STUCK");
+ i = flash_get_protect();
+ ccprintf("Flags: ");
+ if (i & FLASH_PROTECT_PIN_ASSERTED)
+ ccputs(" wp_asserted");
+ if (i & FLASH_PROTECT_RO_AT_BOOT)
+ ccputs(" ro_at_boot");
+ if (i & FLASH_PROTECT_RO_NOW)
+ ccputs(" ro_now");
+ if (i & FLASH_PROTECT_RW_NOW)
+ ccputs(" rw_now");
+ if (i & FLASH_PROTECT_STUCK_LOCKED)
+ ccputs(" STUCK");
+ if (i & FLASH_PROTECT_PARTIAL)
+ ccputs(" PARTIAL");
ccputs("\n");
- ccprintf("WP pin: %sasserted\n",
- (i & FLASH_PROTECT_PIN_ASSERTED) ? "" : "de");
-
ccputs("Protected now:");
for (i = 0; i < PHYSICAL_BANKS; i++) {
if (!(i & 7))
@@ -395,17 +413,17 @@ static int command_flash_wp(int argc, char **argv)
if (argc < 2)
return EC_ERROR_PARAM_COUNT;
- if (!strcasecmp(argv[1], "lock"))
- return flash_lock_protect(1);
- else if (!strcasecmp(argv[1], "unlock"))
- return flash_lock_protect(0);
+ if (!strcasecmp(argv[1], "enable"))
+ return flash_enable_protect(1);
+ else if (!strcasecmp(argv[1], "disable"))
+ return flash_enable_protect(0);
else if (!strcasecmp(argv[1], "now"))
return flash_protect_until_reboot();
else
return EC_ERROR_PARAM1;
}
DECLARE_CONSOLE_COMMAND(flashwp, command_flash_wp,
- "<lock | unlock | now>",
+ "<enable | disable | now>",
"Modify flash write protect",
NULL);
diff --git a/common/system_common.c b/common/system_common.c
index a8224ae69d..83b156743c 100644
--- a/common/system_common.c
+++ b/common/system_common.c
@@ -92,10 +92,12 @@ int system_is_locked(void)
return 0;
#elif defined(BOARD_link) && defined(CONFIG_FLASH)
- /* On link, unlocked if write protect pin deasserted or flash protect
- * lock not applied. */
- if ((FLASH_PROTECT_PIN_ASSERTED | FLASH_PROTECT_LOCK_APPLIED) &
- ~flash_get_protect_lock())
+ /*
+ * On link, unlocked if write protect pin deasserted or read-only
+ * firmware is not protected.
+ */
+ if ((FLASH_PROTECT_PIN_ASSERTED | FLASH_PROTECT_RO_NOW) &
+ ~flash_get_protect())
return 0;
/* If WP pin is asserted and lock is applied, we're locked */
diff --git a/include/flash.h b/include/flash.h
index ec9407d44e..95cafa374d 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -143,13 +143,17 @@ int flash_protect_until_reboot(void);
/* Higher-level APIs to emulate SPI write protect */
-/* Lock or unlock the persistent write protect settings. Once the write
- * protect settings are locked, they will STAY locked until the system is
- * cold-booted with the hardware write protect pin disabled.
+/**
+ * Enable write protect for the read-only code.
+ *
+ * Once write protect is enabled, it will STAY enabled until the system is
+ * hard-rebooted with the hardware write protect pin deasserted. If the write
+ * protect pin is deasserted, the protect setting is ignored, and the entire
+ * flash will be writable.
*
- * If called with lock!=0, this will also immediately protect all
- * persistently-protected blocks. */
-int flash_lock_protect(int lock);
+ * @param enable Enable write protection
+ */
+int flash_enable_protect(int enable);
/* Flags for flash_get_protect_lock() */
/*
@@ -157,16 +161,22 @@ int flash_lock_protect(int lock);
* deasserted at boot time, this simply indicates the state of the lock
* setting, and not whether blocks are actually protected.
*/
-#define FLASH_PROTECT_LOCK_SET 0x01
+#define FLASH_PROTECT_RO_AT_BOOT (1 << 0)
/*
* Flash protection lock has actually been applied. Read-only firmware is
* protected, and flash protection cannot be unlocked.
*/
-#define FLASH_PROTECT_LOCK_APPLIED 0x02
+#define FLASH_PROTECT_RO_NOW (1 << 1)
/* Write protect pin is currently asserted */
-#define FLASH_PROTECT_PIN_ASSERTED 0x04
+#define FLASH_PROTECT_PIN_ASSERTED (1 << 2)
+/* Entire flash is protected until reboot */
+#define FLASH_PROTECT_RW_NOW (1 << 3)
+/* At least one bank of flash is stuck locked, and cannot be unlocked */
+#define FLASH_PROTECT_STUCK_LOCKED (1 << 4)
+/* At least one bank of flash which should be protected is not protected */
+#define FLASH_PROTECT_PARTIAL (1 << 5)
/* Return the flash protect lock status. */
-int flash_get_protect_lock(void);
+int flash_get_protect(void);
#endif /* __CROS_EC_FLASH_H */