diff options
Diffstat (limited to 'chip/stm32/flash-f.c')
-rw-r--r-- | chip/stm32/flash-f.c | 833 |
1 files changed, 0 insertions, 833 deletions
diff --git a/chip/stm32/flash-f.c b/chip/stm32/flash-f.c deleted file mode 100644 index 9e35a2c689..0000000000 --- a/chip/stm32/flash-f.c +++ /dev/null @@ -1,833 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Common flash memory module for STM32F and STM32F0 */ - -#include <stdbool.h> -#include "battery.h" -#include "console.h" -#include "clock.h" -#include "flash.h" -#include "flash-f.h" -#include "hooks.h" -#include "registers.h" -#include "panic.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "watchdog.h" - -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - -/* - * Approximate number of CPU cycles per iteration of the loop when polling - * the flash status - */ -#define CYCLE_PER_FLASH_LOOP 10 - -/* - * While flash write / erase is in progress, the stm32 CPU core is mostly - * non-functional, due to the inability to fetch instructions from flash. - * This may greatly increase interrupt latency. - */ - -/* Flash page programming timeout. This is 2x the datasheet max. */ -#define FLASH_WRITE_TIMEOUT_US 16000 -/* 20ms < tERASE < 40ms on F0/F3, for 1K / 2K sector size. */ -#define FLASH_ERASE_TIMEOUT_US 40000 - -#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE) -#if !defined(CHIP_FAMILY_STM32F4) -#error "CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE should work with all STM32F " -"series chips, but has not been tested" -#endif /* !CHIP_FAMILY_STM32F4 */ -#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */ - -/* Forward declarations */ -#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE) -static enum flash_rdp_level flash_physical_get_rdp_level(void); -static int flash_physical_set_rdp_level(enum flash_rdp_level level); -#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */ - -static inline int calculate_flash_timeout(void) -{ - return (FLASH_WRITE_TIMEOUT_US * - (clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP); -} - -static int wait_busy(void) -{ - int timeout = calculate_flash_timeout(); - while ((STM32_FLASH_SR & FLASH_SR_BUSY) && timeout-- > 0) - udelay(CYCLE_PER_FLASH_LOOP); - return (timeout > 0) ? EC_SUCCESS : EC_ERROR_TIMEOUT; -} - - -void unlock_flash_control_register(void) -{ - STM32_FLASH_KEYR = FLASH_KEYR_KEY1; - STM32_FLASH_KEYR = FLASH_KEYR_KEY2; -} - -void unlock_flash_option_bytes(void) -{ - STM32_FLASH_OPTKEYR = FLASH_OPTKEYR_KEY1; - STM32_FLASH_OPTKEYR = FLASH_OPTKEYR_KEY2; -} - -void disable_flash_option_bytes(void) -{ - ignore_bus_fault(1); - /* - * Writing anything other than the pre-defined keys to the option key - * register results in a bus fault and the register being locked until - * reboot (even with a further correct key write). - */ - STM32_FLASH_OPTKEYR = 0xffffffff; - ignore_bus_fault(0); -} - -void disable_flash_control_register(void) -{ - ignore_bus_fault(1); - /* - * Writing anything other than the pre-defined keys to the key - * register results in a bus fault and the register being locked until - * reboot (even with a further correct key write). - */ - STM32_FLASH_KEYR = 0xffffffff; - ignore_bus_fault(0); -} - -void lock_flash_control_register(void) -{ -#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) - /* FLASH_CR_OPTWRE was set by writing the keys in unlock(). */ - STM32_FLASH_CR &= ~FLASH_CR_OPTWRE; -#endif - STM32_FLASH_CR |= FLASH_CR_LOCK; -} - -void lock_flash_option_bytes(void) -{ -#if !(defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)) - STM32_FLASH_OPTCR |= FLASH_OPTLOCK; -#endif -} - -bool flash_option_bytes_locked(void) -{ - return !!STM32_FLASH_OPT_LOCKED; -} - -bool flash_control_register_locked(void) -{ - return !!(STM32_FLASH_CR & FLASH_CR_LOCK); -} - -/* - * We at least unlock the control register lock. - * We may also unlock other locks. - */ -enum extra_lock_type { - NO_EXTRA_LOCK = 0, - OPT_LOCK = 1, -}; - -static int unlock(int locks) -{ - /* - * We may have already locked the flash module and get a bus fault - * in the attempt to unlock. Need to disable bus fault handler now. - */ - ignore_bus_fault(1); - - /* Always unlock CR if needed */ - if (flash_control_register_locked()) - unlock_flash_control_register(); - - /* unlock option memory if required */ - if ((locks & OPT_LOCK) && flash_option_bytes_locked()) - unlock_flash_option_bytes(); - - /* Re-enable bus fault handler */ - ignore_bus_fault(0); - - if ((locks & OPT_LOCK) && flash_option_bytes_locked()) - return EC_ERROR_UNKNOWN; - if (STM32_FLASH_CR & FLASH_CR_LOCK) - return EC_ERROR_UNKNOWN; - return EC_SUCCESS; -} - -static void lock(void) -{ - lock_flash_control_register(); -} - -#ifdef CHIP_FAMILY_STM32F4 -static int write_optb(uint32_t mask, uint32_t value) -{ - int rv; - - rv = wait_busy(); - if (rv) - return rv; - - /* The target byte is the value we want to write. */ - if ((STM32_FLASH_OPTCR & mask) == value) - return EC_SUCCESS; - - rv = unlock(OPT_LOCK); - if (rv) - return rv; - - STM32_FLASH_OPTCR = (STM32_FLASH_OPTCR & ~mask) | value; - STM32_FLASH_OPTCR |= FLASH_OPTSTRT; - - rv = wait_busy(); - if (rv) - return rv; - lock(); - - return EC_SUCCESS; -} -#else -static int write_optb(int byte, uint8_t value); -/* - * Option byte organization - * - * [31:24] [23:16] [15:8] [7:0] - * - * 0x1FFF_F800 nUSER USER nRDP RDP - * - * 0x1FFF_F804 nData1 Data1 nData0 Data0 - * - * 0x1FFF_F808 nWRP1 WRP1 nWRP0 WRP0 - * - * 0x1FFF_F80C nWRP3 WRP2 nWRP2 WRP2 - * - * Note that the variable with n prefix means the complement. - */ -static uint8_t read_optb(int byte) -{ - return *(uint8_t *)(STM32_OPTB_BASE + byte); -} - -static int erase_optb(void) -{ - int rv; - - rv = wait_busy(); - if (rv) - return rv; - - rv = unlock(OPT_LOCK); - if (rv) - return rv; - - /* Must be set in 2 separate lines. */ - STM32_FLASH_CR |= FLASH_CR_OPTER; - STM32_FLASH_CR |= FLASH_CR_STRT; - - rv = wait_busy(); - - STM32_FLASH_CR &= ~FLASH_CR_OPTER; - - if (rv) - return rv; - lock(); - - return EC_SUCCESS; -} - -static int write_optb(int byte, uint8_t value); -/* - * Since the option byte erase is WHOLE erase, this function is to keep - * rest of bytes, but make this byte 0xff. - * Note that this could make a recursive call to write_optb(). - */ -static int preserve_optb(int byte) -{ - int i, rv; - uint8_t optb[8]; - - /* The byte has been reset, no need to run preserve. */ - if (*(uint16_t *)(STM32_OPTB_BASE + byte) == 0xffff) - return EC_SUCCESS; - - for (i = 0; i < ARRAY_SIZE(optb); ++i) - optb[i] = read_optb(i * 2); - - optb[byte / 2] = 0xff; - - rv = erase_optb(); - if (rv) - return rv; - for (i = 0; i < ARRAY_SIZE(optb); ++i) { - rv = write_optb(i * 2, optb[i]); - if (rv) - return rv; - } - - return EC_SUCCESS; -} - -static int write_optb(int byte, uint8_t value) -{ - volatile int16_t *hword = (uint16_t *)(STM32_OPTB_BASE + byte); - int rv; - - rv = wait_busy(); - if (rv) - return rv; - - /* The target byte is the value we want to write. */ - if (*(uint8_t *)hword == value) - return EC_SUCCESS; - - /* Try to erase that byte back to 0xff. */ - rv = preserve_optb(byte); - if (rv) - return rv; - - /* The value is 0xff after erase. No need to write 0xff again. */ - if (value == 0xff) - return EC_SUCCESS; - - rv = unlock(OPT_LOCK); - if (rv) - return rv; - - /* set OPTPG bit */ - STM32_FLASH_CR |= FLASH_CR_OPTPG; - - *hword = ((~value) << STM32_OPTB_COMPL_SHIFT) | value; - - /* reset OPTPG bit */ - STM32_FLASH_CR &= ~FLASH_CR_OPTPG; - - rv = wait_busy(); - if (rv) - return rv; - lock(); - - return EC_SUCCESS; -} -#endif - -#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE) -/** - * @return true if RDP (read protection) Level 1 or 2 enabled, false otherwise - */ -bool is_flash_rdp_enabled(void) -{ - enum flash_rdp_level level = flash_physical_get_rdp_level(); - - if (level == FLASH_RDP_LEVEL_INVALID) { - CPRINTS("ERROR: unable to read RDP level"); - return false; - } - - return level != FLASH_RDP_LEVEL_0; -} -#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */ - -/*****************************************************************************/ -/* Physical layer APIs */ - -int crec_flash_physical_write(int offset, int size, const char *data) -{ -#if CONFIG_FLASH_WRITE_SIZE == 1 - uint8_t *address = (uint8_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); - uint8_t quantum = 0; -#elif CONFIG_FLASH_WRITE_SIZE == 2 - uint16_t *address = (uint16_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); - uint16_t quantum = 0; -#elif CONFIG_FLASH_WRITE_SIZE == 4 - uint32_t *address = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); - uint32_t quantum = 0; -#else -#error "CONFIG_FLASH_WRITE_SIZE not supported." -#endif - int res = EC_SUCCESS; - int timeout = calculate_flash_timeout(); - - if (unlock(NO_EXTRA_LOCK) != EC_SUCCESS) { - res = EC_ERROR_UNKNOWN; - goto exit_wr; - } - - /* Clear previous error status */ - STM32_FLASH_SR = FLASH_SR_ALL_ERR | FLASH_SR_EOP; - - /* set PG bit */ - STM32_FLASH_CR |= FLASH_CR_PG; - - for (; size > 0; size -= CONFIG_FLASH_WRITE_SIZE) { - int i; - - for (i = CONFIG_FLASH_WRITE_SIZE - 1, quantum = 0; i >= 0; i--) - quantum = (quantum << 8) + data[i]; - data += CONFIG_FLASH_WRITE_SIZE; - /* - * Reload the watchdog timer to avoid watchdog reset when doing - * long writing with interrupt disabled. - */ - watchdog_reload(); - - /* wait to be ready */ - for (i = 0; - (STM32_FLASH_SR & FLASH_SR_BUSY) && - (i < timeout); - i++) - ; - - /* write the data */ - *address++ = quantum; - - /* Wait for writes to complete */ - for (i = 0; - (STM32_FLASH_SR & FLASH_SR_BUSY) && - (i < timeout); - i++) - ; - - if (STM32_FLASH_SR & FLASH_SR_BUSY) { - res = EC_ERROR_TIMEOUT; - goto exit_wr; - } - - /* Check for error conditions - erase failed, voltage error, - * protection error */ - if (STM32_FLASH_SR & FLASH_SR_ALL_ERR) { - res = EC_ERROR_UNKNOWN; - goto exit_wr; - } - } - -exit_wr: - /* Disable PG bit */ - STM32_FLASH_CR &= ~FLASH_CR_PG; - - lock(); - - return res; -} - -int crec_flash_physical_erase(int offset, int size) -{ - int res = EC_SUCCESS; - int sector_size; - int timeout_us; -#ifdef CHIP_FAMILY_STM32F4 - int sector = crec_flash_bank_index(offset); - /* we take advantage of sector_size == erase_size */ - if ((sector < 0) || (crec_flash_bank_index(offset + size) < 0)) - return EC_ERROR_INVAL; /* Invalid range */ -#endif - - if (unlock(NO_EXTRA_LOCK) != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - /* Clear previous error status */ - STM32_FLASH_SR = FLASH_SR_ALL_ERR | FLASH_SR_EOP; - - /* set SER/PER bit */ - STM32_FLASH_CR |= FLASH_CR_PER; - - while (size > 0) { - timestamp_t deadline; -#ifdef CHIP_FAMILY_STM32F4 - sector_size = crec_flash_bank_size(sector); - /* Timeout: from spec, proportional to the size - * inversely proportional to the write size. - */ - timeout_us = sector_size * 4 / CONFIG_FLASH_WRITE_SIZE; -#else - sector_size = CONFIG_FLASH_ERASE_SIZE; - timeout_us = FLASH_ERASE_TIMEOUT_US; -#endif - /* Do nothing if already erased */ - if (crec_flash_is_erased(offset, sector_size)) - goto next_sector; -#ifdef CHIP_FAMILY_STM32F4 - /* select page to erase */ - STM32_FLASH_CR = (STM32_FLASH_CR & ~STM32_FLASH_CR_SNB_MASK) | - (sector << STM32_FLASH_CR_SNB_OFFSET); -#else - /* select page to erase */ - STM32_FLASH_AR = CONFIG_PROGRAM_MEMORY_BASE + offset; -#endif - /* set STRT bit : start erase */ - STM32_FLASH_CR |= FLASH_CR_STRT; - - deadline.val = get_time().val + timeout_us; - /* Wait for erase to complete */ - watchdog_reload(); - while ((STM32_FLASH_SR & FLASH_SR_BUSY) && - (get_time().val < deadline.val)) { - usleep(timeout_us/100); - } - if (STM32_FLASH_SR & FLASH_SR_BUSY) { - res = EC_ERROR_TIMEOUT; - goto exit_er; - } - - /* - * Check for error conditions - erase failed, voltage error, - * protection error - */ - if (STM32_FLASH_SR & FLASH_SR_ALL_ERR) { - res = EC_ERROR_UNKNOWN; - goto exit_er; - } -next_sector: - size -= sector_size; - offset += sector_size; -#ifdef CHIP_FAMILY_STM32F4 - sector++; -#endif - } - -exit_er: - /* reset SER/PER bit */ - STM32_FLASH_CR &= ~FLASH_CR_PER; - - lock(); - - return res; -} - -#ifdef CHIP_FAMILY_STM32F4 -static int flash_physical_get_protect_at_boot(int block) -{ - /* 0: Write protection active on sector i. */ - return !(STM32_OPTB_WP & STM32_OPTB_nWRP(block)); -} - -static int flash_physical_protect_at_boot_update_rdp_pstate(uint32_t new_flags) -{ -#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE) - int rv = EC_SUCCESS; - - bool rdp_enable = (new_flags & EC_FLASH_PROTECT_RO_AT_BOOT) != 0; - - /* - * This is intentionally a one-way latch. Once we have enabled RDP - * Level 1, we will only allow going back to Level 0 using the - * bootloader (e.g., "stm32mon -U") since transitioning from Level 1 to - * Level 0 triggers a mass erase. - */ - if (rdp_enable) - rv = flash_physical_set_rdp_level(FLASH_RDP_LEVEL_1); - - return rv; -#else - return EC_SUCCESS; -#endif -} - -int crec_flash_physical_protect_at_boot(uint32_t new_flags) -{ - int block; - int original_val, val; - - original_val = val = STM32_OPTB_WP & STM32_OPTB_nWRP_ALL; - - for (block = WP_BANK_OFFSET; - block < WP_BANK_OFFSET + PHYSICAL_BANKS; - block++) { - int protect = new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT; - - if (block >= WP_BANK_OFFSET && - block < WP_BANK_OFFSET + WP_BANK_COUNT) - protect |= new_flags & EC_FLASH_PROTECT_RO_AT_BOOT; -#ifdef CONFIG_FLASH_PROTECT_RW - else - protect |= new_flags & EC_FLASH_PROTECT_RW_AT_BOOT; -#endif - - if (protect) - val &= ~BIT(block); - else - val |= 1 << block; - } - if (original_val != val) { - int rv = write_optb(STM32_FLASH_nWRP_ALL, - val << STM32_FLASH_nWRP_OFFSET); - if (rv != EC_SUCCESS) - return rv; - } - - return flash_physical_protect_at_boot_update_rdp_pstate(new_flags); -} - -static void unprotect_all_blocks(void) -{ - write_optb(STM32_FLASH_nWRP_ALL, STM32_FLASH_nWRP_ALL); -} - -#else /* CHIP_FAMILY_STM32F4 */ -static int flash_physical_get_protect_at_boot(int block) -{ - uint8_t val = read_optb(STM32_OPTB_WRP_OFF(block/8)); - return (!(val & (1 << (block % 8)))) ? 1 : 0; -} - -int crec_flash_physical_protect_at_boot(uint32_t new_flags) -{ - int block; - int i; - int original_val[4], val[4]; - - for (i = 0; i < 4; ++i) - original_val[i] = val[i] = read_optb(i * 2 + 8); - - for (block = WP_BANK_OFFSET; - block < WP_BANK_OFFSET + PHYSICAL_BANKS; - block++) { - int protect = new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT; - int byte_off = STM32_OPTB_WRP_OFF(block/8) / 2 - 4; - - if (block >= WP_BANK_OFFSET && - block < WP_BANK_OFFSET + WP_BANK_COUNT) - protect |= new_flags & EC_FLASH_PROTECT_RO_AT_BOOT; -#ifdef CONFIG_ROLLBACK - else if (block >= ROLLBACK_BANK_OFFSET && - block < ROLLBACK_BANK_OFFSET + ROLLBACK_BANK_COUNT) - protect |= new_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; -#endif -#ifdef CONFIG_FLASH_PROTECT_RW - else - protect |= new_flags & EC_FLASH_PROTECT_RW_AT_BOOT; -#endif - - if (protect) - val[byte_off] = val[byte_off] & (~(1 << (block % 8))); - else - val[byte_off] = val[byte_off] | (1 << (block % 8)); - } - - for (i = 0; i < 4; ++i) - if (original_val[i] != val[i]) - write_optb(i * 2 + 8, val[i]); - -#ifdef CONFIG_FLASH_READOUT_PROTECTION - /* - * Set a permanent protection by increasing RDP to level 1, - * trying to unprotected the flash will trigger a full erase. - */ - write_optb(0, 0x11); -#endif - - return EC_SUCCESS; -} - -static void unprotect_all_blocks(void) -{ - int i; - - for (i = 4; i < 8; ++i) - write_optb(i * 2, 0xff); -} -#endif - -/** - * Check if write protect register state is inconsistent with RO_AT_BOOT and - * ALL_AT_BOOT state. - * - * @return zero if consistent, non-zero if inconsistent. - */ -static int registers_need_reset(void) -{ - uint32_t flags = crec_flash_get_protect(); - int i; - int ro_at_boot = (flags & EC_FLASH_PROTECT_RO_AT_BOOT) ? 1 : 0; - int ro_wp_region_start = WP_BANK_OFFSET; - int ro_wp_region_end = WP_BANK_OFFSET + WP_BANK_COUNT; - - for (i = ro_wp_region_start; i < ro_wp_region_end; i++) - if (flash_physical_get_protect_at_boot(i) != ro_at_boot) - return 1; - return 0; -} - -#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE) -/** - * Set Flash RDP (read protection) level. - * - * @note Does not take effect until reset. - * - * @param level new RDP (read protection) level to set - * @return EC_SUCCESS on success, other on failure - */ -int flash_physical_set_rdp_level(enum flash_rdp_level level) -{ - uint32_t reg_level; - - switch (level) { - case FLASH_RDP_LEVEL_0: - /* - * Asserting by default since we don't want to inadvertently - * go from Level 1 to Level 0, which triggers a mass erase. - * Remove assert if you want to use it. - */ - ASSERT(false); - reg_level = FLASH_OPTCR_RDP_LEVEL_0; - break; - case FLASH_RDP_LEVEL_1: - reg_level = FLASH_OPTCR_RDP_LEVEL_1; - break; - case FLASH_RDP_LEVEL_2: - /* - * Asserting by default since it's permanent (there is no - * way to reverse). Remove assert if you want to use it. - */ - ASSERT(false); - reg_level = FLASH_OPTCR_RDP_LEVEL_2; - break; - default: - return EC_ERROR_INVAL; - } - - return write_optb(FLASH_OPTCR_RDP_MASK, reg_level); -} - -/** - * @return On success, current flash read protection level. - * On failure, FLASH_RDP_LEVEL_INVALID - */ -enum flash_rdp_level flash_physical_get_rdp_level(void) -{ - uint32_t level = (STM32_FLASH_OPTCR & FLASH_OPTCR_RDP_MASK); - - switch (level) { - case FLASH_OPTCR_RDP_LEVEL_0: - return FLASH_RDP_LEVEL_0; - case FLASH_OPTCR_RDP_LEVEL_1: - return FLASH_RDP_LEVEL_1; - case FLASH_OPTCR_RDP_LEVEL_2: - return FLASH_RDP_LEVEL_2; - default: - return FLASH_RDP_LEVEL_INVALID; - } -} -#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */ - -/*****************************************************************************/ -/* High-level APIs */ - -int crec_flash_pre_init(void) -{ - uint32_t reset_flags = system_get_reset_flags(); - uint32_t prot_flags = crec_flash_get_protect(); - int need_reset = 0; - - -#ifdef CHIP_FAMILY_STM32F4 - unlock(NO_EXTRA_LOCK); - /* Set the proper write size */ - STM32_FLASH_CR = (STM32_FLASH_CR & ~STM32_FLASH_CR_PSIZE_MASK) | - (31 - __builtin_clz(CONFIG_FLASH_WRITE_SIZE)) << - STM32_FLASH_CR_PSIZE_OFFSET; - lock(); -#endif - if (crec_flash_physical_restore_state()) - return EC_SUCCESS; - - /* - * If we have already jumped between images, an earlier image could - * have applied write protection. Nothing additional needs to be done. - */ - if (reset_flags & EC_RESET_FLAG_SYSJUMP) - return EC_SUCCESS; - - if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { - if (prot_flags & EC_FLASH_PROTECT_RO_NOW) { - /* Enable physical protection for RO (0 means RO). */ - crec_flash_physical_protect_now(0); - } - - if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) && - !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) { - /* - * Pstate wants RO protected at boot, but the write - * protect register wasn't set to protect it. Force an - * update to the write protect register and reboot so - * it takes effect. - */ - crec_flash_physical_protect_at_boot( - EC_FLASH_PROTECT_RO_AT_BOOT); - need_reset = 1; - } - - if (registers_need_reset()) { - /* - * Write protect register was in an inconsistent state. - * Set it back to a good state and reboot. - * - * TODO(crosbug.com/p/23798): this seems really similar - * to the check above. One of them should be able to - * go away. - */ - crec_flash_protect_at_boot( - prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT); - need_reset = 1; - } - } else { - if (prot_flags & EC_FLASH_PROTECT_RO_NOW) { - /* - * Write protect pin unasserted but some section is - * protected. Drop it and reboot. - */ - unprotect_all_blocks(); - need_reset = 1; - } - } - - if ((crec_flash_physical_get_valid_flags() & - EC_FLASH_PROTECT_ALL_AT_BOOT) && - (!!(prot_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) != - !!(prot_flags & EC_FLASH_PROTECT_ALL_NOW))) { - /* - * ALL_AT_BOOT and ALL_NOW should be both set or both unset - * at boot. If they are not, it must be that the chip requires - * OBL_LAUNCH to be set to reload option bytes. Let's reset - * the system with OBL_LAUNCH set. - * This assumes OBL_LAUNCH is used for hard reset in - * chip/stm32/system.c. - */ - need_reset = 1; - } - -#ifdef CONFIG_FLASH_PROTECT_RW - if ((crec_flash_physical_get_valid_flags() & - EC_FLASH_PROTECT_RW_AT_BOOT) && - (!!(prot_flags & EC_FLASH_PROTECT_RW_AT_BOOT) != - !!(prot_flags & EC_FLASH_PROTECT_RW_NOW))) { - /* RW_AT_BOOT and RW_NOW do not match. */ - need_reset = 1; - } -#endif - -#ifdef CONFIG_ROLLBACK - if ((crec_flash_physical_get_valid_flags() & - EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) && - (!!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) != - !!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_NOW))) { - /* ROLLBACK_AT_BOOT and ROLLBACK_NOW do not match. */ - need_reset = 1; - } -#endif - - if (need_reset) - system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS); - - return EC_SUCCESS; -} |