From 6405d35f324f767c2ab88da12a600cb8e6c25f0e Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Tue, 3 Nov 2020 01:22:53 +0100 Subject: [PATCH] flash/stm32l4x: probe tzen and rdp values introduction of 'enum stm32l4_rdp' enumerating possible RDP levels for devices with and without TrustZone. also in 'stm32l4_flash_bank' structure we added and rdp and tzen members to store read values by the helper 'stm32l4_sync_rdp_tzen' these new members are used to display security and protection status while probing the flash. Change-Id: Icf883189715278a3323fe210d295047678b16592 Signed-off-by: Tarek BOCHKATI Reviewed-on: http://openocd.zylin.com/5541 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/stm32l4x.c | 65 +++++++++++++++++++++++++++++++++++----- src/flash/nor/stm32l4x.h | 6 ++-- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index bfedc8d66d..594bce0393 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -143,6 +143,13 @@ enum stm32l4_flash_reg_index { STM32_FLASH_REG_INDEX_NUM, }; +enum stm32l4_rdp { + RDP_LEVEL_0 = 0xAA, + RDP_LEVEL_0_5 = 0x55, /* for devices with TrustZone enabled */ + RDP_LEVEL_1 = 0x00, + RDP_LEVEL_2 = 0xCC +}; + static const uint32_t stm32l4_flash_regs[STM32_FLASH_REG_INDEX_NUM] = { [STM32_FLASH_ACR_INDEX] = 0x000, [STM32_FLASH_KEYR_INDEX] = 0x008, @@ -199,6 +206,8 @@ struct stm32l4_flash_bank { const struct stm32l4_part_info *part_info; const uint32_t *flash_regs; bool otp_enabled; + enum stm32l4_rdp rdp; + bool tzen; }; enum stm32_bank_id { @@ -610,6 +619,35 @@ static inline bool stm32l4_otp_is_enabled(struct flash_bank *bank) return stm32l4_info->otp_enabled; } +static void stm32l4_sync_rdp_tzen(struct flash_bank *bank, uint32_t optr_value) +{ + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + + bool tzen = false; + + if (stm32l4_info->part_info->flags & F_HAS_TZ) + tzen = (optr_value & FLASH_TZEN) != 0; + + uint32_t rdp = optr_value & FLASH_RDP_MASK; + + /* for devices without TrustZone: + * RDP level 0 and 2 values are to 0xAA and 0xCC + * Any other value corresponds to RDP level 1 + * for devices with TrusZone: + * RDP level 0 and 2 values are 0xAA and 0xCC + * RDP level 0.5 value is 0x55 only if TZEN = 1 + * Any other value corresponds to RDP level 1, including 0x55 if TZEN = 0 + */ + + if (rdp != RDP_LEVEL_0 && rdp != RDP_LEVEL_2) { + if (!tzen || (tzen && rdp != RDP_LEVEL_0_5)) + rdp = RDP_LEVEL_1; + } + + stm32l4_info->tzen = tzen; + stm32l4_info->rdp = rdp; +} + static inline uint32_t stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset) { struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; @@ -1332,6 +1370,22 @@ static int stm32l4_probe(struct flash_bank *bank) LOG_INFO("device idcode = 0x%08" PRIx32 " (%s)", stm32l4_info->idcode, device_info); + /* read flash option register */ + retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_OPTR_INDEX, &options); + if (retval != ERROR_OK) + return retval; + + stm32l4_sync_rdp_tzen(bank, options); + + if (part_info->flags & F_HAS_TZ) + LOG_INFO("TZEN = %d : TrustZone %s by option bytes", + stm32l4_info->tzen, + stm32l4_info->tzen ? "enabled" : "disabled"); + + LOG_INFO("RDP level %s (0x%02X)", + stm32l4_info->rdp == RDP_LEVEL_0 ? "0" : stm32l4_info->rdp == RDP_LEVEL_0_5 ? "0.5" : "1", + stm32l4_info->rdp); + if (stm32l4_is_otp(bank)) { bank->size = part_info->otp_size; @@ -1347,7 +1401,6 @@ static int stm32l4_probe(struct flash_bank *bank) return ERROR_FAIL; } - stm32l4_info->probed = true; return ERROR_OK; } else if (bank->base != STM32_FLASH_BANK_BASE) { @@ -1379,11 +1432,6 @@ static int stm32l4_probe(struct flash_bank *bank) /* did we assign a flash size? */ assert((flash_size_kb != 0xffff) && flash_size_kb); - /* read flash option register */ - retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_OPTR_INDEX, &options); - if (retval != ERROR_OK) - return retval; - stm32l4_info->bank1_sectors = 0; stm32l4_info->hole_sectors = 0; @@ -1783,7 +1831,8 @@ COMMAND_HANDLER(stm32l4_handle_lock_command) /* set readout protection level 1 by erasing the RDP option byte */ struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; - if (stm32l4_write_option(bank, stm32l4_info->flash_regs[STM32_FLASH_OPTR_INDEX], 0, 0x000000FF) != ERROR_OK) { + if (stm32l4_write_option(bank, stm32l4_info->flash_regs[STM32_FLASH_OPTR_INDEX], + RDP_LEVEL_1, FLASH_RDP_MASK) != ERROR_OK) { command_print(CMD, "%s failed to lock device", bank->driver->name); return ERROR_OK; } @@ -1817,7 +1866,7 @@ COMMAND_HANDLER(stm32l4_handle_unlock_command) struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; if (stm32l4_write_option(bank, stm32l4_info->flash_regs[STM32_FLASH_OPTR_INDEX], - RDP_LEVEL_0, 0x000000FF) != ERROR_OK) { + RDP_LEVEL_0, FLASH_RDP_MASK) != ERROR_OK) { command_print(CMD, "%s failed to unlock device", bank->driver->name); return ERROR_OK; } diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 3e810a03ce..41b5ff82d9 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -56,9 +56,9 @@ #define OPTKEY1 0x08192A3B #define OPTKEY2 0x4C5D6E7F -#define RDP_LEVEL_0 0xAA -#define RDP_LEVEL_1 0xBB -#define RDP_LEVEL_2 0xCC +/* FLASH_OPTR register bits */ +#define FLASH_RDP_MASK 0xFF +#define FLASH_TZEN (1 << 31) /* other registers */ #define DBGMCU_IDCODE_G0 0x40015800 -- 2.30.2