diff options
-rw-r--r-- | chip/lm4/config.h | 2 | ||||
-rw-r--r-- | chip/lm4/flash.c | 10 | ||||
-rw-r--r-- | chip/stm32/config-stm32f100.h | 15 | ||||
-rw-r--r-- | chip/stm32/config-stm32l15x.h | 16 | ||||
-rw-r--r-- | chip/stm32/flash-stm32f100.c | 13 | ||||
-rw-r--r-- | chip/stm32/flash-stm32l15x.c | 13 | ||||
-rw-r--r-- | common/flash_commands.c | 29 | ||||
-rw-r--r-- | common/flash_common.c | 146 | ||||
-rw-r--r-- | include/flash.h | 34 |
9 files changed, 101 insertions, 177 deletions
diff --git a/chip/lm4/config.h b/chip/lm4/config.h index 063132b74a..712b8d8f87 100644 --- a/chip/lm4/config.h +++ b/chip/lm4/config.h @@ -46,7 +46,7 @@ */ #define CONFIG_SECTION_FLASH_PSTATE_SIZE (1 * CONFIG_FLASH_BANK_SIZE) #define CONFIG_SECTION_FLASH_PSTATE_OFF (CONFIG_FLASH_SIZE \ - - CONFIG_FLASH_FLASH_PSTATE_SIZE) + - CONFIG_SECTION_FLASH_PSTATE_SIZE) /* Then there are the two major sections. */ /* TODO: Increase to 128KB, or shrink to 64KB? */ diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c index 20c90793bd..c69538d5bc 100644 --- a/chip/lm4/flash.c +++ b/chip/lm4/flash.c @@ -171,15 +171,17 @@ int flash_physical_erase(int offset, int size) } -int flash_physical_get_protect(int block) +int flash_physical_get_protect(int bank) { - return (LM4_FLASH_FMPPE[F_BANK(block)] & F_BIT(block)) ? 0 : 1; + return (LM4_FLASH_FMPPE[F_BANK(bank)] & F_BIT(bank)) ? 0 : 1; } -void flash_physical_set_protect(int block) +void flash_physical_set_protect(int start_bank, int bank_count) { - LM4_FLASH_FMPPE[F_BANK(block)] &= ~F_BIT(block); + int bank; + for (bank = start_bank; bank < start_bank + bank_count; bank++) + LM4_FLASH_FMPPE[F_BANK(bank)] &= ~F_BIT(bank); } int flash_physical_pre_init(void) diff --git a/chip/stm32/config-stm32f100.h b/chip/stm32/config-stm32f100.h index 2a591e7b1d..831daa62d7 100644 --- a/chip/stm32/config-stm32f100.h +++ b/chip/stm32/config-stm32f100.h @@ -5,7 +5,8 @@ /* Memory mapping */ #define CONFIG_FLASH_BASE 0x08000000 -#define CONFIG_FLASH_SIZE 0x00020000 +#define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000 +#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE #define CONFIG_FLASH_BANK_SIZE 0x1000 #define CONFIG_RAM_BASE 0x20000000 #define CONFIG_RAM_SIZE 0x00002000 @@ -23,11 +24,13 @@ #define CONFIG_SECTION_RW_OFF CONFIG_FW_RW_OFF #define CONFIG_SECTION_RW_SIZE CONFIG_FW_RW_SIZE -/* no keys for now */ -#define CONFIG_VBOOT_ROOTKEY_OFF (CONFIG_FW_RO_OFF + CONFIG_FW_RO_SIZE) -#define CONFIG_VBLOCK_RW_OFF (CONFIG_FW_RW_OFF + CONFIG_FW_RW_SIZE) -#define CONFIG_VBOOT_ROOTKEY_SIZE 0 -#define CONFIG_VBLOCK_SIZE 0 +/* + * The EC uses the top bank of flash to emulate a SPI-like write protect + * register with persistent state. Put that up at the top. + */ +#define CONFIG_SECTION_FLASH_PSTATE_SIZE (1 * CONFIG_FLASH_BANK_SIZE) +#define CONFIG_SECTION_FLASH_PSTATE_OFF (CONFIG_FLASH_SIZE \ + - CONFIG_SECTION_FLASH_PSTATE_SIZE) /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 61 diff --git a/chip/stm32/config-stm32l15x.h b/chip/stm32/config-stm32l15x.h index 15b37eb956..63d9b0d323 100644 --- a/chip/stm32/config-stm32l15x.h +++ b/chip/stm32/config-stm32l15x.h @@ -5,7 +5,8 @@ /* Memory mapping */ #define CONFIG_FLASH_BASE 0x08000000 -#define CONFIG_FLASH_SIZE 0x00020000 +#define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000 +#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE #define CONFIG_FLASH_BANK_SIZE 0x1000 #define CONFIG_RAM_BASE 0x20000000 #define CONFIG_RAM_SIZE 0x00004000 @@ -23,12 +24,13 @@ #define CONFIG_SECTION_RW_OFF CONFIG_FW_RW_OFF #define CONFIG_SECTION_RW_SIZE CONFIG_FW_RW_SIZE -/* no keys for now */ -#define CONFIG_VBOOT_ROOTKEY_OFF (CONFIG_FW_RO_OFF + CONFIG_FW_RO_SIZE) -#define CONFIG_VBLOCK_RW_OFF (CONFIG_FW_RW_OFF + CONFIG_FW_RW_SIZE) -#define CONFIG_VBOOT_ROOTKEY_SIZE 0 -#define CONFIG_VBLOCK_SIZE 0 - +/* + * The EC uses the top bank of flash to emulate a SPI-like write protect + * register with persistent state. Put that up at the top. + */ +#define CONFIG_SECTION_FLASH_PSTATE_SIZE (1 * CONFIG_FLASH_BANK_SIZE) +#define CONFIG_SECTION_FLASH_PSTATE_OFF (CONFIG_FLASH_SIZE \ + - CONFIG_SECTION_FLASH_PSTATE_SIZE) /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 45 diff --git a/chip/stm32/flash-stm32f100.c b/chip/stm32/flash-stm32f100.c index 46dc8336be..2e88f3b511 100644 --- a/chip/stm32/flash-stm32f100.c +++ b/chip/stm32/flash-stm32f100.c @@ -326,12 +326,15 @@ int flash_physical_get_protect(int block) return !(val & (1 << (block % 8))); } - -void flash_physical_set_protect(int block) +void flash_physical_set_protect(int start_bank, int bank_count) { - int byte_off = STM32_OPTB_WRP_OFF(block/8); - uint8_t val = read_optb(byte_off) & ~(1 << (block % 8)); - write_optb(byte_off, val); + int block; + + for (block = start_bank; block < start_bank + bank_count; block++) { + int byte_off = STM32_OPTB_WRP_OFF(block/8); + uint8_t val = read_optb(byte_off) | (1 << (block % 8)); + write_optb(byte_off, val); + } } int flash_physical_pre_init(void) diff --git a/chip/stm32/flash-stm32l15x.c b/chip/stm32/flash-stm32l15x.c index d3e3db5033..2ac9227c2e 100644 --- a/chip/stm32/flash-stm32l15x.c +++ b/chip/stm32/flash-stm32l15x.c @@ -308,13 +308,16 @@ int flash_physical_get_protect(int block) return val & (1 << (block % 8)); } - -void flash_physical_set_protect(int block) +void flash_physical_set_protect(int start_bank, int bank_count) { if (0) { /* TODO: crosbug.com/p/9849 verify WP */ - int byte_off = STM32_OPTB_WRP_OFF(block/8); - uint8_t val = read_optb(byte_off) | (1 << (block % 8)); - write_optb(byte_off, val); + int block; + + for (block = start_bank; block < start_bank + bank_count; block++) { + int byte_off = STM32_OPTB_WRP_OFF(block/8); + uint8_t val = read_optb(byte_off) | (1 << (block % 8)); + write_optb(byte_off, val); + } } } diff --git a/common/flash_commands.c b/common/flash_commands.c index c52f308325..322409cbaf 100644 --- a/common/flash_commands.c +++ b/common/flash_commands.c @@ -74,12 +74,6 @@ static int command_flash_info(int argc, char **argv) ccputs(" "); ccputs(wp[i] & FLASH_PROTECT_UNTIL_REBOOT ? "Y" : "."); } - ccputs("\n Persistent: "); - for (i = 0; i < banks; i++) { - if (!(i & 7)) - ccputs(" "); - ccputs(wp[i] & FLASH_PROTECT_PERSISTENT ? "Y" : "."); - } ccputs("\n"); return EC_SUCCESS; @@ -151,36 +145,21 @@ DECLARE_CONSOLE_COMMAND(flashwrite, command_flash_write, static int command_flash_wp(int argc, char **argv) { - int offset = -1; - int size = flash_get_protect_block_size(); - int rv; - if (argc < 2) return EC_ERROR_PARAM_COUNT; - /* Commands that don't need offset and size */ if (!strcasecmp(argv[1], "lock")) return flash_lock_protect(1); else if (!strcasecmp(argv[1], "unlock")) return flash_lock_protect(0); - - /* All remaining commands need offset and size */ - rv = parse_offset_size(argc, argv, 2, &offset, &size); - if (rv) - return rv; - - if (!strcasecmp(argv[1], "now")) - return flash_protect_until_reboot(offset, size); - else if (!strcasecmp(argv[1], "set")) - return flash_set_protect(offset, size, 1); - else if (!strcasecmp(argv[1], "clear")) - return flash_set_protect(offset, size, 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 | set | clear> offset [size]", - "Print or modify flash write protect", + "<lock | unlock | now>", + "Modify flash write protect", NULL); /*****************************************************************************/ diff --git a/common/flash_common.c b/common/flash_common.c index e7467954f4..c0a769d0c9 100644 --- a/common/flash_common.c +++ b/common/flash_common.c @@ -14,6 +14,16 @@ #define PERSIST_STATE_VERSION 1 #define MAX_BANKS (CONFIG_FLASH_SIZE / CONFIG_FLASH_BANK_SIZE) +/* Persistent protection state flash offset / size / bank */ +#define PSTATE_OFFSET (CONFIG_SECTION_FLASH_PSTATE_OFF - CONFIG_FLASH_BASE) +#define PSTATE_SIZE CONFIG_SECTION_FLASH_PSTATE_SIZE +#define PSTATE_BANK (PSTATE_OFFSET / CONFIG_FLASH_BANK_SIZE) + +/* Read-only firmware offset and size in units of flash banks */ +#define RO_BANK_OFFSET ((CONFIG_SECTION_RO_OFF - CONFIG_FLASH_BASE) \ + / CONFIG_FLASH_BANK_SIZE) +#define RO_BANK_COUNT (CONFIG_SECTION_RO_SIZE / CONFIG_FLASH_BANK_SIZE) + /* Persistent protection state - emulates a SPI status register for flashrom */ struct persist_state { uint8_t version; /* Version of this struct */ @@ -22,7 +32,6 @@ struct persist_state { uint8_t blocks[MAX_BANKS]; /* Per-block flags */ }; -static int usable_flash_size; /* Usable flash size, not counting pstate */ static struct persist_state pstate; /* RAM copy of pstate data */ @@ -41,12 +50,15 @@ static int wp_pin_asserted(void) #endif } - /* Read persistent state into pstate. */ static int read_pstate(void) { +#ifdef CHIP_stm32 + memset(&pstate, 0, sizeof(pstate)); + pstate.version = PERSIST_STATE_VERSION; +#else int i; - int rv = flash_physical_read(usable_flash_size, sizeof(pstate), + int rv = flash_physical_read(PSTATE_OFFSET, sizeof(pstate), (char *)&pstate); if (rv) return rv; @@ -60,42 +72,40 @@ static int read_pstate(void) /* Mask off currently-valid flags */ pstate.lock &= FLASH_PROTECT_LOCK_SET; for (i = 0; i < MAX_BANKS; i++) - pstate.blocks[i] &= FLASH_PROTECT_PERSISTENT; + pstate.blocks[i] = 0; +#endif /* CHIP_stm32 */ return EC_SUCCESS; } - /* Write persistent state from pstate, erasing if necessary. */ static int write_pstate(void) { int rv; - /* Erase top protection block. Assumes pstate size is less than - * erase/protect block size, and protect block size is less than erase - * block size. */ - /* TODO: optimize based on current physical flash contents; we can - * avoid the erase if we're only changing 1's into 0's. */ - rv = flash_physical_erase(usable_flash_size, - flash_get_protect_block_size()); + /* Erase pstate */ + /* + * TODO: optimize based on current physical flash contents; we can + * avoid the erase if we're only changing 1's into 0's. + */ + rv = flash_physical_erase(PSTATE_OFFSET, PSTATE_SIZE); if (rv) return rv; - /* Note that if we lose power in here, we'll lose the pstate contents. + /* + * Note that if we lose power in here, we'll lose the pstate contents. * That's ok, because it's only possible to write the pstate before - * it's protected. */ + * it's protected. + */ /* Rewrite the data */ - return flash_physical_write(usable_flash_size, sizeof(pstate), + return flash_physical_write(PSTATE_OFFSET, sizeof(pstate), (const char *)&pstate); } - /* Apply write protect based on persistent state. */ static int apply_pstate(void) { - int pbsize = flash_get_protect_block_size(); - int banks = usable_flash_size / pbsize; - int rv, i; + int rv; /* If write protect is disabled, nothing to do */ if (!wp_pin_asserted()) @@ -111,47 +121,38 @@ static int apply_pstate(void) return EC_SUCCESS; /* Lock the protection data first */ - flash_physical_set_protect(banks); + flash_physical_set_protect(PSTATE_BANK, 1); - /* Then lock any banks necessary */ - for (i = 0; i < banks; i++) { - if (pstate.blocks[i] & FLASH_PROTECT_PERSISTENT) - flash_physical_set_protect(i); - } + /* Lock the read-only section whenever pstate is locked */ + flash_physical_set_protect(RO_BANK_OFFSET, RO_BANK_COUNT); return EC_SUCCESS; } - /* Return non-zero if pstate block is already write-protected. */ static int is_pstate_lock_applied(void) { - int pstate_block = usable_flash_size / flash_get_protect_block_size(); - /* Fail if write protect block is already locked */ - return flash_physical_get_protect(pstate_block); + return flash_physical_get_protect(PSTATE_BANK); } - int flash_get_size(void) { - return usable_flash_size; + return CONFIG_FLASH_SIZE; } - int flash_dataptr(int offset, int size_req, int align, char **ptrp) { if (offset < 0 || size_req < 0 || - offset + size_req > usable_flash_size || + offset + size_req > CONFIG_FLASH_SIZE || (offset | size_req) & (align - 1)) return -1; /* Invalid range */ if (ptrp) *ptrp = flash_physical_dataptr(offset); - return usable_flash_size - offset; + return CONFIG_FLASH_SIZE - offset; } - int flash_read(int offset, int size, char *data) { if (flash_dataptr(offset, size, 1, NULL) < 0) @@ -160,84 +161,33 @@ int flash_read(int offset, int size, char *data) return flash_physical_read(offset, size, data); } - int flash_write(int offset, int size, const char *data) { if (flash_dataptr(offset, size, flash_get_write_block_size(), NULL) < 0) return EC_ERROR_INVAL; /* Invalid range */ - /* TODO (crosbug.com/p/7478) - safety check - don't allow writing to - * the image we're running from */ - return flash_physical_write(offset, size, data); } - int flash_erase(int offset, int size) { if (flash_dataptr(offset, size, flash_get_erase_block_size(), NULL) < 0) return EC_ERROR_INVAL; /* Invalid range */ - /* TODO (crosbug.com/p/7478) - safety check - don't allow erasing the - * image we're running from */ - return flash_physical_erase(offset, size); } - -int flash_protect_until_reboot(int offset, int size) +int flash_protect_until_reboot(void) { - int pbsize = flash_get_protect_block_size(); - int i; - - if (flash_dataptr(offset, size, pbsize, NULL) < 0) - return EC_ERROR_INVAL; /* Invalid range */ - - /* Convert offset and size to blocks */ - offset /= pbsize; - size /= pbsize; + /* Protect the entire flash */ + flash_physical_set_protect(0, CONFIG_FLASH_PHYSICAL_SIZE / + CONFIG_FLASH_BANK_SIZE); - for (i = 0; i < size; i++) - flash_physical_set_protect(offset + i); return EC_SUCCESS; } - -int flash_set_protect(int offset, int size, int enable) -{ - uint8_t newflag = enable ? FLASH_PROTECT_PERSISTENT : 0; - int pbsize = flash_get_protect_block_size(); - int rv, i; - - if (flash_dataptr(offset, size, pbsize, NULL) < 0) - return EC_ERROR_INVAL; /* Invalid range */ - - /* Fail if write protect block is already locked */ - if (is_pstate_lock_applied()) - return EC_ERROR_UNKNOWN; - - /* Read the current persist state from flash */ - rv = read_pstate(); - if (rv) - return rv; - - /* Convert offset and size to blocks */ - offset /= pbsize; - size /= pbsize; - - /* Set the new state */ - for (i = 0; i < size; i++) { - pstate.blocks[offset + i] &= ~FLASH_PROTECT_PERSISTENT; - pstate.blocks[offset + i] |= newflag; - } - - /* Write the state back to flash */ - return write_pstate(); -} - - int flash_lock_protect(int lock) { int rv; @@ -267,7 +217,6 @@ int flash_lock_protect(int lock) return apply_pstate(); } - const uint8_t *flash_get_protect_array(void) { /* @@ -275,15 +224,13 @@ const uint8_t *flash_get_protect_array(void) * of per-protect-block flags. (This is NOT the actual array, so * attempting to change it will have no effect.) */ - int pbsize = flash_get_protect_block_size(); - int banks = usable_flash_size / pbsize; int i; /* Read the current persist state from flash */ read_pstate(); /* Combine with current block protection state */ - for (i = 0; i < banks; i++) { + for (i = 0; i < MAX_BANKS; i++) { if (flash_physical_get_protect(i)) pstate.blocks[i] |= FLASH_PROTECT_UNTIL_REBOOT; } @@ -292,7 +239,6 @@ const uint8_t *flash_get_protect_array(void) return pstate.blocks; } - int flash_get_protect(int offset, int size) { int pbsize = flash_get_protect_block_size(); @@ -320,7 +266,6 @@ int flash_get_protect(int offset, int size) return minflags; } - int flash_get_protect_lock(void) { int flags; @@ -352,13 +297,6 @@ int flash_pre_init(void) */ flash_physical_pre_init(); - /* - * Calculate usable flash size. Reserve one protection block - * at the top to hold the "pretend SPI" write protect data. - */ - usable_flash_size = flash_physical_size() - - flash_get_protect_block_size(); - - /* Apply write protect to blocks if needed */ + /* Read pstate and apply write protect to blocks if needed */ return apply_pstate(); } diff --git a/include/flash.h b/include/flash.h index 2ad8581440..bd89448c57 100644 --- a/include/flash.h +++ b/include/flash.h @@ -55,11 +55,16 @@ int flash_physical_write(int offset, int size, const char *data); /* Erase <size> bytes of flash at byte offset <offset>. */ int flash_physical_erase(int offset, int size); -/* Return non-zero if block is protected until reboot. */ -int flash_physical_get_protect(int block); +/* Return non-zero if bank is protected until reboot. */ +int flash_physical_get_protect(int bank); -/* Protects the block until reboot. */ -void flash_physical_set_protect(int block); +/** + * Protect the flash banks until reboot. + * + * @param start_bank Start bank to protect + * @param bank_count Number of banks to protect + */ +void flash_physical_set_protect(int start_bank, int bank_count); /*****************************************************************************/ /* High-level interface for use by other modules. */ @@ -131,18 +136,13 @@ int flash_erase(int offset, int size); * the system is rebooted with the write protect pin asserted - at which point, * protection is re-applied. */ -/* Write-protect <size> bytes of flash at byte offset <offset> until next - * reboot. */ -int flash_protect_until_reboot(int offset, int size); +/** + * Protect the entire flash until reboot. + */ +int flash_protect_until_reboot(void); /* Higher-level APIs to emulate SPI write protect */ -/* Set (enable=1) or clear (enable=0) the persistent write protect setting for - * the specified range. This will only succeed if write protect is unlocked. - * This will take effect on the next boot, or when flash_lock_protect(1) is - * called. */ -int flash_set_protect(int offset, int size, int enable); - /* 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. @@ -152,16 +152,10 @@ int flash_set_protect(int offset, int size, int enable); int flash_lock_protect(int lock); /* Flags for flash_get_protect() and flash_get_protect_array(). */ -/* Protected persistently. Note that if the write protect pin was deasserted - * at boot time, a block may have the FLASH_PROTECT_PERSISTENT flag indicating - * the block would be protected on a normal boot, but may not have the - * FLASH_PROTECT_UNTIL_REBOOT flag indicating it's actually protected right - * now. */ -#define FLASH_PROTECT_PERSISTENT 0x01 /* Protected until reboot. This will be set for persistently-protected blocks * as soon as the flash module protects them, and for non-persistent protection * after flash_protect_until_reboot() is called on a block. */ -#define FLASH_PROTECT_UNTIL_REBOOT 0x02 +#define FLASH_PROTECT_UNTIL_REBOOT 0x01 /* Return a copy of the current write protect state. This is an array of * per-protect-block flags. The data is valid until the next call to a flash |