1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2020 Pengutronix 4 * Rouven Czerwinski <entwicklung@pengutronix.de> 5 * Copyright 2022-2023 NXP 6 */ 7 8 #include <drivers/imx_snvs.h> 9 #include <io.h> 10 #include <mm/core_memprot.h> 11 #include <mm/core_mmu.h> 12 #include <stdint.h> 13 #include <tee/tee_fs.h> 14 #include <types_ext.h> 15 #include <trace.h> 16 17 #define SNVS_HPLR 0x00 18 #define SNVS_HPCOMR 0x04 19 #define SNVS_HPSR 0x14 20 #define SNVS_LPLR 0x34 21 #define SNVS_LPCR 0x38 22 #define SNVS_LPMKCR 0x3C 23 24 #define HPSR_SSM_ST_MASK GENMASK_32(11, 8) 25 #define HPSR_SSM_ST_SHIFT 8 26 27 #define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12 28 #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(14, 12) 29 30 #define SNVS_HPSR_OTPMK_SYND GENMASK_32(24, 16) 31 #define SNVS_HPSR_OTPMK_ZERO BIT(27) 32 33 #define SNVS_HPLR_MKS_SL BIT32(9) 34 35 #define SNVS_LPLR_MKS_HL BIT32(9) 36 37 #define SNVS_HPCOMR_MKS_EN BIT32(13) 38 #define SNVS_HPCOMR_NPSWA_EN BIT32(31) 39 40 #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0) 41 42 #define SNVS_LPCR_TOP_MASK BIT(6) 43 #define SNVS_LPCR_DP_EN_MASK BIT(5) 44 #define SNVS_LPCR_SRTC_ENV_MASK BIT(1) 45 46 enum snvs_ssm_mode { 47 SNVS_SSM_MODE_INIT, 48 SNVS_SSM_MODE_HARD_FAIL, 49 SNVS_SSM_MODE_SOFT_FAIL = 3, 50 SNVS_SSM_MODE_INIT_INTERMEDIATE = 8, 51 SNVS_SSM_MODE_CHECK, 52 SNVS_SSM_MODE_NON_SECURE = 11, 53 SNVS_SSM_MODE_TRUSTED = 13, 54 SNVS_SSM_MODE_SECURE = 15, 55 }; 56 57 enum snvs_security_cfg { 58 SNVS_SECURITY_CFG_FAB, 59 SNVS_SECURITY_CFG_OPEN, 60 SNVS_SECURITY_CFG_CLOSED, 61 SNVS_SECURITY_CFG_FIELD_RETURN, 62 }; 63 64 /* 65 * Return true if the master key is OTPMK, false otherwise. 66 */ 67 static bool is_otpmk_selected(void) 68 { 69 uint32_t hp_mks = 0; 70 vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 71 72 hp_mks = io_read32(base + SNVS_HPCOMR); 73 74 /* 75 * The master key selection might be done by the MASTER_KEY_SEL field 76 * of LPMKCR instead. 77 */ 78 if (hp_mks & SNVS_HPCOMR_MKS_EN) { 79 uint32_t lp_mks = io_read32(base + SNVS_LPMKCR); 80 81 if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL) 82 return false; 83 } 84 85 return true; 86 } 87 88 /* 89 * Return true if the master key selection is locked, false otherwise. 90 */ 91 static bool is_mks_locked(void) 92 { 93 vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 94 95 return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL || 96 io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL; 97 } 98 99 /* Set the Master key to use OTPMK and lock it. */ 100 static void set_mks_otpmk(void) 101 { 102 vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 103 104 io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN); 105 io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL); 106 io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL); 107 io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL); 108 } 109 110 /* 111 * Return true if OTPMK is valid, false otherwise. 112 */ 113 static bool is_otpmk_valid(void) 114 { 115 vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 116 uint32_t status = io_read32(base + SNVS_HPSR); 117 118 return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND)); 119 } 120 121 static enum snvs_security_cfg snvs_get_security_cfg(void) 122 { 123 uint32_t val = 0; 124 vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 125 SNVS_SIZE); 126 127 val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >> 128 SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; 129 130 switch (val) { 131 case 0b000: 132 return SNVS_SECURITY_CFG_FAB; 133 case 0b001: 134 return SNVS_SECURITY_CFG_OPEN; 135 case 0b011: 136 return SNVS_SECURITY_CFG_CLOSED; 137 default: 138 return SNVS_SECURITY_CFG_FIELD_RETURN; 139 } 140 } 141 142 bool snvs_is_device_closed(void) 143 { 144 return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED); 145 } 146 147 #ifdef CFG_RPMB_FS 148 static enum snvs_ssm_mode snvs_get_ssm_mode(void) 149 { 150 vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 151 SNVS_HPSR + sizeof(uint32_t)); 152 uint32_t val = 0; 153 154 val = io_read32(snvs + SNVS_HPSR); 155 val &= HPSR_SSM_ST_MASK; 156 val = val >> HPSR_SSM_ST_SHIFT; 157 DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val); 158 return val; 159 } 160 161 bool plat_rpmb_key_is_ready(void) 162 { 163 enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT; 164 bool ssm_secure = false; 165 166 mode = snvs_get_ssm_mode(); 167 ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED || 168 mode == SNVS_SSM_MODE_SECURE); 169 170 /* 171 * On i.MX6SDL and i.MX6DQ, the security cfg always returns 172 * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security 173 * configuration for this SoC. 174 */ 175 if (soc_is_imx6sdl() || soc_is_imx6dq()) 176 return ssm_secure; 177 178 return ssm_secure && snvs_is_device_closed(); 179 } 180 #endif /* CFG_RPMB_FS */ 181 182 TEE_Result imx_snvs_set_master_otpmk(void) 183 { 184 if (!is_otpmk_valid()) 185 return TEE_ERROR_BAD_STATE; 186 187 if (is_mks_locked()) { 188 if (is_otpmk_selected()) 189 return TEE_SUCCESS; 190 191 return TEE_ERROR_BAD_STATE; 192 } 193 194 set_mks_otpmk(); 195 196 return TEE_SUCCESS; 197 } 198 199 void imx_snvs_shutdown(void) 200 { 201 vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 202 203 io_write32(base + SNVS_LPCR, 204 SNVS_LPCR_TOP_MASK | 205 SNVS_LPCR_DP_EN_MASK | 206 SNVS_LPCR_SRTC_ENV_MASK); 207 } 208