1 /* 2 * Copyright (c) 2025, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 10 #include <drivers/clk.h> 11 #include <drivers/delay_timer.h> 12 #include <drivers/st/stm32_mce.h> 13 #include <lib/mmio.h> 14 #include <lib/mmio_poll.h> 15 #include <libfdt.h> 16 17 #include <platform_def.h> 18 #include <stm32mp_fconf_getter.h> 19 20 /* MCE registers (base relative) */ 21 #define MCE_CR U(0x0000) /* MCE configuration register */ 22 #define MCE_SR U(0x0004) /* MCE status register */ 23 #define MCE_IASR U(0x0008) /* MCE illegal access status register */ 24 #define MCE_IACR U(0x000C) /* MCE illegal access clear register */ 25 #define MCE_IAIER U(0x0010) /* MCE illegal access interrupt enable reg */ 26 #define MCE_PRIVCFGR U(0x001C) /* MCE privileged configuration register */ 27 #define MCE_REGCR U(0x0040) /* MCE region configuration register */ 28 #define MCE_SADDR U(0x0044) /* MCE start address for region register */ 29 #define MCE_EADDR U(0x0048) /* MCE end address for region register */ 30 #define MCE_MKEYR U(0x0200) /* MCE master key register offset */ 31 #define MCE_HWCFGR3 U(0x03E8) /* MCE hardware configuration register 3 */ 32 #define MCE_HWCFGR2 U(0x03EC) /* MCE hardware configuration register 2 */ 33 #define MCE_HWCFGR1 U(0x03F0) /* MCE hardware configuration register 1 */ 34 #define MCE_VERR U(0x03F4) /* MCE version register */ 35 #define MCE_IPIDR U(0x03F8) /* MCE identification register */ 36 #define MCE_SIDR U(0x03FC) /* MCE size ID register */ 37 38 /* MCE configuration register */ 39 #define MCE_CR_GLOCK BIT(0) 40 #define MCE_CR_MKLOCK BIT(1) 41 42 /* MCE status register */ 43 #define MCE_SR_MKVALID BIT(0) 44 #define MCE_SR_ENCDIS BIT(4) 45 46 /* MCE privileged configuration register */ 47 #define MCE_PRIVCFGR_PRIV BIT(0) 48 49 /* MCE region configuration register */ 50 #define MCE_REGCR_BREN BIT(0) 51 #define MCE_REGCR_ENC BIT(15) 52 53 /* MCE start address for region register */ 54 #define MCE_SADDR_BADDSTART_MASK GENMASK(31, 16) 55 56 /* MCE end address for region register */ 57 #define MCE_EADDR_BADDEND_MASK GENMASK(31, 16) 58 59 /* MCE version register */ 60 #define MCE_VERR_MINREV_MASK GENMASK(3, 0) 61 #define MCE_VERR_MINREV_SHIFT 0 62 #define MCE_VERR_MAJREV_MASK GENMASK(7, 4) 63 #define MCE_VERR_MAJREV_SHIFT 4 64 65 /* IP configuration */ 66 #define MCE_MAJREV 1U 67 #define MCE_MINREV 0U 68 #define MCE_IP_ID 0x00170081U 69 #define MCE_SIZE_ID 0xA3C5DD01U 70 #define MCE_ADDR_GRANULARITY 0x10000U 71 72 /* Other definitions */ 73 #define MCE_TIMEOUT_1MS_IN_US 1000U 74 #define DDR_BASE_EXTRA_MASK GENMASK_32(31, 30) 75 #define MCE_REGION_PARAMS 3U 76 77 struct mce_version_s { 78 uint32_t major; 79 uint32_t minor; 80 uint32_t ip_id; 81 uint32_t size_id; 82 }; 83 84 struct mce_dt_id_attr { 85 fdt32_t id_attr[MCE_IP_MAX_REGION_NB]; 86 }; 87 88 /* 89 * @brief Configure privileged access to the MCE registers. 90 * @param privilege: Only privileged (true) or all (false) access are granted. 91 * @retval None. 92 */ 93 static void configure_privilege(bool privilege) 94 { 95 if (privilege) { 96 mmio_setbits_32(MCE_BASE + MCE_PRIVCFGR, MCE_PRIVCFGR_PRIV); 97 } else { 98 mmio_clrbits_32(MCE_BASE + MCE_PRIVCFGR, MCE_PRIVCFGR_PRIV); 99 } 100 } 101 102 /* 103 * @brief Check consistency of region settings. 104 * @param config: Ref to the region configuration structure. 105 * @retval 0 if OK, negative value else. 106 */ 107 static int check_region_settings(struct stm32_mce_region_s *config) 108 { 109 uint32_t end; 110 111 if (config->encrypt_mode > MCE_ENCRYPTION_MODE_MAX) { 112 ERROR("MCE: encryption mode out of range error\n"); 113 return -EINVAL; 114 } 115 116 if ((config->start_address < STM32MP_DDR_BASE) || 117 (config->end_address < STM32MP_DDR_BASE)) { 118 ERROR("MCE: start/end address lower than DDR base\n"); 119 return -EINVAL; 120 } 121 122 end = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U; 123 if ((config->start_address > end) || (config->end_address > end)) { 124 ERROR("MCE: start/end address higher than physical end\n"); 125 return -EINVAL; 126 } 127 128 if (config->start_address >= config->end_address) { 129 ERROR("MCE: start address higher than or equal to end one\n"); 130 return -EINVAL; 131 } 132 133 if (((config->start_address % MCE_ADDR_GRANULARITY) != 0U) || 134 (((config->end_address + 1U) % MCE_ADDR_GRANULARITY) != 0U)) { 135 ERROR("MCE: start/end address granularity not respected\n"); 136 return -EINVAL; 137 } 138 139 return 0; 140 } 141 142 /* 143 * @brief Configure (and enable) the MCE region. 144 * @param index: Region index (first region is 0). 145 * @param config: Ref to the region configuration structure. 146 * @retval 0 if OK, negative value else. 147 */ 148 static int stm32_mce_configure_region(uint32_t index, struct stm32_mce_region_s *config) 149 { 150 int ret; 151 152 if ((index >= MCE_IP_MAX_REGION_NB) || (config == NULL)) { 153 return -EINVAL; 154 } 155 156 ret = check_region_settings(config); 157 if (ret != 0) { 158 return ret; 159 } 160 161 mmio_clrbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_BREN); 162 163 mmio_clrsetbits_32(MCE_BASE + MCE_SADDR, MCE_SADDR_BADDSTART_MASK, 164 config->start_address & MCE_SADDR_BADDSTART_MASK); 165 mmio_clrsetbits_32(MCE_BASE + MCE_EADDR, MCE_EADDR_BADDEND_MASK, 166 config->end_address & MCE_EADDR_BADDEND_MASK); 167 168 if (config->encrypt_mode == MCE_ENCRYPT_MODE) { 169 mmio_setbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_BREN | MCE_REGCR_ENC); 170 171 if (!stm32_mce_is_hw_encryption_functional()) { 172 ERROR("MCE: encryption feature error\n"); 173 return -EIO; 174 } 175 } else { 176 mmio_clrbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_ENC); 177 mmio_setbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_BREN); 178 } 179 180 return 0; 181 } 182 183 /* 184 * @brief Initialize the MCE driver. 185 * @param None. 186 * @retval None. 187 */ 188 void stm32_mce_init(void) 189 { 190 const struct mce_version_s exp_version = { 191 .major = MCE_MAJREV, 192 .minor = MCE_MINREV, 193 .ip_id = MCE_IP_ID, 194 .size_id = MCE_SIZE_ID 195 }; 196 struct mce_version_s version; 197 198 if (clk_enable(MCE) != 0) { 199 panic(); 200 } 201 202 version = (struct mce_version_s) { 203 .major = (mmio_read_32(MCE_BASE + MCE_VERR) & 204 MCE_VERR_MAJREV_MASK) >> MCE_VERR_MAJREV_SHIFT, 205 .minor = (mmio_read_32(MCE_BASE + MCE_VERR) & 206 MCE_VERR_MINREV_MASK) >> MCE_VERR_MINREV_SHIFT, 207 .ip_id = mmio_read_32(MCE_BASE + MCE_IPIDR), 208 .size_id = mmio_read_32(MCE_BASE + MCE_SIDR) 209 }; 210 211 if ((version.major != exp_version.major) || 212 (version.minor != exp_version.minor) || 213 (version.ip_id != exp_version.ip_id) || 214 (version.size_id != exp_version.size_id)) { 215 ERROR("MCE: unexpected IP version { 0x%x, 0x%x, 0x%x, 0x%x }\n", 216 version.major, version.minor, version.ip_id, version.size_id); 217 panic(); 218 } 219 220 configure_privilege(true); 221 } 222 223 /* 224 * @brief Write the MCE master key. 225 * @param mkey: Pointer to the master key buffer. 226 * @retval 0 if OK, negative value else. 227 */ 228 int stm32_mce_write_master_key(uint8_t *mkey) 229 { 230 uint8_t i; 231 uint32_t mce_sr; 232 233 if (mkey == NULL) { 234 return -EINVAL; 235 } 236 237 if ((mmio_read_32(MCE_BASE + MCE_CR) & MCE_CR_MKLOCK) == MCE_CR_MKLOCK) { 238 return -EPERM; 239 } 240 241 for (i = 0U; i < MCE_KEY_SIZE_IN_BYTES; i += sizeof(uint32_t)) { 242 uint32_t key_val = 0U; 243 244 (void)memcpy(&key_val, mkey + i, sizeof(uint32_t)); 245 246 mmio_write_32(MCE_BASE + MCE_MKEYR + i, key_val); 247 } 248 249 return mmio_read_32_poll_timeout((MCE_BASE + MCE_SR), mce_sr, 250 ((mce_sr & MCE_SR_MKVALID) == MCE_SR_MKVALID), 251 MCE_TIMEOUT_1MS_IN_US); 252 } 253 254 /* 255 * @brief Lock the MCE master key. 256 * @param None. 257 * @retval None. 258 */ 259 void stm32_mce_lock_master_key(void) 260 { 261 mmio_setbits_32(MCE_BASE + MCE_CR, MCE_CR_MKLOCK); 262 } 263 264 /* 265 * @brief Get the MCE master key lock state. 266 * @param None. 267 * @retval True if locked, false else. 268 */ 269 bool stm32_mce_is_master_key_locked(void) 270 { 271 return (mmio_read_32(MCE_BASE + MCE_CR) & MCE_CR_MKLOCK) == MCE_CR_MKLOCK; 272 } 273 274 /* 275 * @brief Lock the MCE IP registers. 276 * @param None. 277 * @retval None. 278 */ 279 void stm32_mce_lock_global(void) 280 { 281 mmio_setbits_32(MCE_BASE + MCE_CR, MCE_CR_GLOCK); 282 } 283 284 /* 285 * @brief Get the MCE global lock state. 286 * @param None. 287 * @retval True if locked, false else. 288 */ 289 bool stm32_mce_is_globally_locked(void) 290 { 291 return (mmio_read_32(MCE_BASE + MCE_CR) & MCE_CR_GLOCK) == MCE_CR_GLOCK; 292 } 293 294 /* 295 * @brief Get the MCE encryption HW feature state. 296 * @param None. 297 * @retval True if functional, false else. 298 */ 299 bool stm32_mce_is_hw_encryption_functional(void) 300 { 301 return (mmio_read_32(MCE_BASE + MCE_SR) & MCE_SR_ENCDIS) != MCE_SR_ENCDIS; 302 } 303 304 /* 305 * @brief Get the encryption state of an address. 306 * @param index: Memory address. 307 * @param state: Ref to the encryption state. 308 * @retval 0 if OK, negative value else. 309 */ 310 int stm32_mce_get_address_encryption_state(uint32_t address, uint32_t *state) 311 { 312 struct stm32_mce_region_s config; 313 314 if ((address < STM32MP_DDR_BASE) || 315 (address > (STM32MP_DDR_BASE + dt_get_ddr_size() - 1U)) || 316 (state == NULL)) { 317 return -EINVAL; 318 } 319 320 if ((mmio_read_32(MCE_BASE + MCE_REGCR) & MCE_REGCR_ENC) != MCE_REGCR_ENC) { 321 /* No encrypted region, all DDR area is in plain text */ 322 *state = MCE_BYPASS_MODE; 323 return 0; 324 } 325 326 if (!stm32_mce_is_hw_encryption_functional()) { 327 ERROR("MCE: encryption feature error\n"); 328 return -EIO; 329 } 330 331 /* 332 * When MCE_SADDR and MCE_EADDR are accessed in read, the 2 MSB bits 333 * return zeros. So DDR base address mask has to be ORed. 334 */ 335 config.start_address = mmio_read_32(MCE_BASE + MCE_SADDR) | 336 (STM32MP_DDR_BASE & DDR_BASE_EXTRA_MASK); 337 338 config.end_address = mmio_read_32(MCE_BASE + MCE_EADDR) | 339 (STM32MP_DDR_BASE & DDR_BASE_EXTRA_MASK); 340 341 if ((address >= config.start_address) && (address <= config.end_address)) { 342 *state = MCE_ENCRYPT_MODE; 343 } else { 344 *state = MCE_BYPASS_MODE; 345 } 346 347 return 0; 348 } 349 350 static int fconf_populate_mce(uintptr_t config) 351 { 352 int node, len; 353 unsigned int i; 354 const struct mce_dt_id_attr *conf_list; 355 const void *dtb = (const void *)config; 356 357 /* Check the node offset point to "st,mem-encrypt" compatible property */ 358 const char *compatible_str = "st,mem-encrypt"; 359 360 if ((stm32mp_check_closed_device() == STM32MP_CHIP_SEC_OPEN) && 361 !stm32mp_is_auth_supported()) { 362 return 0; 363 } 364 365 node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); 366 if (node < 0) { 367 ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); 368 return node; 369 } 370 371 conf_list = (const struct mce_dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len); 372 if (conf_list == NULL) { 373 WARN("FCONF: Read cell failed for %s\n", "memory-ranges"); 374 return -1; 375 } 376 377 /* Consider only complete set of values */ 378 len -= len % MCE_REGION_PARAMS; 379 380 /* Locate the memory cells and read all values */ 381 for (i = 0U; i < ((unsigned int)len / (sizeof(uint32_t) * MCE_REGION_PARAMS)); i++) { 382 uint32_t size; 383 struct stm32_mce_region_s region; 384 385 region.start_address = fdt32_to_cpu(conf_list->id_attr[i * MCE_REGION_PARAMS]); 386 size = fdt32_to_cpu(conf_list->id_attr[i * MCE_REGION_PARAMS + 1U]); 387 region.end_address = region.start_address + size - 1U; 388 region.encrypt_mode = fdt32_to_cpu(conf_list->id_attr[i * MCE_REGION_PARAMS + 2U]); 389 390 VERBOSE("FCONF: mce cell found with value = 0x%x 0x%x 0x%x\n", 391 region.start_address, size, region.encrypt_mode); 392 393 if (stm32_mce_configure_region(i, ®ion) != 0) { 394 panic(); 395 } 396 } 397 398 return 0; 399 } 400 401 FCONF_REGISTER_POPULATOR(FW_CONFIG, mce_config, fconf_populate_mce); 402