int flash_pre_init(void) { uint32_t reset_flags = system_get_reset_flags(); uint32_t prot_flags = flash_get_protect(); int need_reset = 0; /* * If we have already jumped between images, an earlier image could * have applied write protection. Nothing additional needs to be done. */ if (reset_flags & RESET_FLAG_SYSJUMP) return EC_SUCCESS; if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { 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. */ flash_protect_at_boot(FLASH_WP_RO); need_reset = 1; } if (prot_flags & EC_FLASH_PROTECT_ERROR_INCONSISTENT) { /* * Write protect register was in an inconsistent state. * Set it back to a good state and reboot. */ flash_protect_at_boot( (prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) ? FLASH_WP_RO : FLASH_WP_NONE); need_reset = 1; } } else if (prot_flags & (EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ERROR_INCONSISTENT)) { /* * Write protect pin unasserted but some section is * protected. Drop it and reboot. */ unlock(STM32_FLASH_PECR_OPT_LOCK); write_optb_wrp(0); lock(); need_reset = 1; } if (need_reset) system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS); return EC_SUCCESS; }
int flash_pre_init(void) { uint32_t reset_flags = system_get_reset_flags(); uint32_t prot_flags = flash_get_protect(); int need_reset = 0; if (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 & RESET_FLAG_SYSJUMP) return EC_SUCCESS; if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { 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. */ flash_physical_protect_at_boot(FLASH_WP_RO); 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. */ flash_protect_at_boot( (prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) ? FLASH_WP_RO : FLASH_WP_NONE); 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 ((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; } if (need_reset) system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS); return EC_SUCCESS; }
int flash_set_protect(uint32_t mask, uint32_t flags) { int retval = EC_SUCCESS; int rv; enum flash_wp_range range = FLASH_WP_NONE; int need_set_protect = 0; /* * Process flags we can set. Track the most recent error, but process * all flags before returning. */ /* * AT_BOOT flags are trickier than NOW flags, as they can be set * when HW write protection is disabled and can be unset without * a reboot. * * If we are only setting/clearing RO_AT_BOOT, things are simple. * Setting ALL_AT_BOOT is processed only if HW write protection is * enabled and RO_AT_BOOT is set, so it's also simple. * * The most tricky one is when we want to clear ALL_AT_BOOT. We need * to determine whether to clear protection for the entire flash or * leave RO protected. There are two cases that we want to keep RO * protected: * 1. RO_AT_BOOT was already set before flash_set_protect() is * called. * 2. RO_AT_BOOT was not set, but it's requested to be set by * the caller of flash_set_protect(). */ if (mask & EC_FLASH_PROTECT_RO_AT_BOOT) { range = (flags & EC_FLASH_PROTECT_RO_AT_BOOT) ? FLASH_WP_RO : FLASH_WP_NONE; need_set_protect = 1; } if ((mask & EC_FLASH_PROTECT_ALL_AT_BOOT) && !(flags & EC_FLASH_PROTECT_ALL_AT_BOOT)) { if (flash_get_protect() & EC_FLASH_PROTECT_RO_AT_BOOT) range = FLASH_WP_RO; need_set_protect = 1; } if (need_set_protect) { rv = flash_protect_at_boot(range); if (rv) retval = rv; } /* * All subsequent flags only work if write protect is enabled (that is, * hardware WP flag) *and* RO is protected at boot (software WP flag). */ if ((~flash_get_protect()) & (EC_FLASH_PROTECT_GPIO_ASSERTED | EC_FLASH_PROTECT_RO_AT_BOOT)) return retval; if ((mask & EC_FLASH_PROTECT_ALL_AT_BOOT) && (flags & EC_FLASH_PROTECT_ALL_AT_BOOT)) { rv = flash_protect_at_boot(FLASH_WP_ALL); if (rv) retval = rv; } if ((mask & EC_FLASH_PROTECT_RO_NOW) && (flags & EC_FLASH_PROTECT_RO_NOW)) { rv = flash_physical_protect_now(0); if (rv) retval = rv; } if ((mask & EC_FLASH_PROTECT_ALL_NOW) && (flags & EC_FLASH_PROTECT_ALL_NOW)) { rv = flash_physical_protect_now(1); if (rv) retval = rv; } return retval; }