1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 2/* 3 * Copyright (C) 2019, STMicroelectronics - All Rights Reserved 4 */ 5 6#include <common.h> 7#include <command.h> 8#include <console.h> 9#include <log.h> 10#include <misc.h> 11#include <asm/arch/bsec.h> 12#include <dm/device.h> 13#include <dm/uclass.h> 14#include <linux/printk.h> 15 16/* 17 * Closed device: OTP0 18 * STM32MP15x: bit 6 of OPT0 19 * STM32MP13x: 0b111111 = 0x3F for OTP_SECURED closed device 20 */ 21#define STM32_OTP_CLOSE_ID 0 22#define STM32_OTP_STM32MP13X_CLOSE_MASK 0x3F 23#define STM32_OTP_STM32MP15X_CLOSE_MASK BIT(6) 24 25/* PKH is the first element of the key list */ 26#define STM32KEY_PKH 0 27 28struct stm32key { 29 char *name; 30 char *desc; 31 u8 start; 32 u8 size; 33}; 34 35const struct stm32key stm32mp13_list[] = { 36 [STM32KEY_PKH] = { 37 .name = "PKHTH", 38 .desc = "Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm)", 39 .start = 24, 40 .size = 8, 41 }, 42 { 43 .name = "EDMK", 44 .desc = "Encryption/Decryption Master Key", 45 .start = 92, 46 .size = 4, 47 } 48}; 49 50const struct stm32key stm32mp15_list[] = { 51 [STM32KEY_PKH] = { 52 .name = "PKH", 53 .desc = "Hash of the ECC Public Key (ECDSA is the authentication algorithm)", 54 .start = 24, 55 .size = 8, 56 } 57}; 58 59/* index of current selected key in stm32key list, 0 = PKH by default */ 60static u8 stm32key_index; 61 62static u8 get_key_nb(void) 63{ 64 if (IS_ENABLED(CONFIG_STM32MP13X)) 65 return ARRAY_SIZE(stm32mp13_list); 66 67 if (IS_ENABLED(CONFIG_STM32MP15X)) 68 return ARRAY_SIZE(stm32mp15_list); 69} 70 71static const struct stm32key *get_key(u8 index) 72{ 73 if (IS_ENABLED(CONFIG_STM32MP13X)) 74 return &stm32mp13_list[index]; 75 76 if (IS_ENABLED(CONFIG_STM32MP15X)) 77 return &stm32mp15_list[index]; 78} 79 80static u32 get_otp_close_mask(void) 81{ 82 if (IS_ENABLED(CONFIG_STM32MP13X)) 83 return STM32_OTP_STM32MP13X_CLOSE_MASK; 84 85 if (IS_ENABLED(CONFIG_STM32MP15X)) 86 return STM32_OTP_STM32MP15X_CLOSE_MASK; 87} 88 89static int get_misc_dev(struct udevice **dev) 90{ 91 int ret; 92 93 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(stm32mp_bsec), dev); 94 if (ret) 95 log_err("Can't find stm32mp_bsec driver\n"); 96 97 return ret; 98} 99 100static void read_key_value(const struct stm32key *key, u32 addr) 101{ 102 int i; 103 104 for (i = 0; i < key->size; i++) { 105 printf("%s OTP %i: [%08x] %08x\n", key->name, key->start + i, 106 addr, __be32_to_cpu(*(u32 *)addr)); 107 addr += 4; 108 } 109} 110 111static int read_key_otp(struct udevice *dev, const struct stm32key *key, bool print, bool *locked) 112{ 113 int i, word, ret; 114 int nb_invalid = 0, nb_zero = 0, nb_lock = 0, nb_lock_err = 0; 115 u32 val, lock; 116 bool status; 117 118 for (i = 0, word = key->start; i < key->size; i++, word++) { 119 ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); 120 if (ret != 4) 121 val = ~0x0; 122 ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); 123 if (ret != 4) 124 lock = BSEC_LOCK_ERROR; 125 if (print) 126 printf("%s OTP %i: %08x lock : %08x\n", key->name, word, val, lock); 127 if (val == ~0x0) 128 nb_invalid++; 129 else if (val == 0x0) 130 nb_zero++; 131 if (lock & BSEC_LOCK_PERM) 132 nb_lock++; 133 if (lock & BSEC_LOCK_ERROR) 134 nb_lock_err++; 135 } 136 137 status = nb_lock_err || (nb_lock == key->size); 138 if (locked) 139 *locked = status; 140 if (nb_lock_err && print) 141 printf("%s lock is invalid!\n", key->name); 142 else if (!status && print) 143 printf("%s is not locked!\n", key->name); 144 145 if (nb_invalid == key->size) { 146 if (print) 147 printf("%s is invalid!\n", key->name); 148 return -EINVAL; 149 } 150 if (nb_zero == key->size) { 151 if (print) 152 printf("%s is free!\n", key->name); 153 return -ENOENT; 154 } 155 156 return 0; 157} 158 159static int read_close_status(struct udevice *dev, bool print, bool *closed) 160{ 161 int word, ret, result; 162 u32 val, lock, mask; 163 bool status; 164 165 result = 0; 166 word = STM32_OTP_CLOSE_ID; 167 ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); 168 if (ret < 0) 169 result = ret; 170 if (ret != 4) 171 val = 0x0; 172 173 ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); 174 if (ret < 0) 175 result = ret; 176 if (ret != 4) 177 lock = BSEC_LOCK_ERROR; 178 179 mask = get_otp_close_mask(); 180 status = (val & mask) == mask; 181 if (closed) 182 *closed = status; 183 if (print) 184 printf("OTP %d: closed status: %d lock : %08x\n", word, status, lock); 185 186 return result; 187} 188 189static int fuse_key_value(struct udevice *dev, const struct stm32key *key, u32 addr, bool print) 190{ 191 u32 word, val; 192 int i, ret; 193 194 for (i = 0, word = key->start; i < key->size; i++, word++, addr += 4) { 195 val = __be32_to_cpu(*(u32 *)addr); 196 if (print) 197 printf("Fuse %s OTP %i : %08x\n", key->name, word, val); 198 199 ret = misc_write(dev, STM32_BSEC_OTP(word), &val, 4); 200 if (ret != 4) { 201 log_err("Fuse %s OTP %i failed\n", key->name, word); 202 return ret; 203 } 204 /* on success, lock the OTP for the key */ 205 val = BSEC_LOCK_PERM; 206 ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4); 207 if (ret != 4) { 208 log_err("Lock %s OTP %i failed\n", key->name, word); 209 return ret; 210 } 211 } 212 213 return 0; 214} 215 216static int confirm_prog(void) 217{ 218 puts("Warning: Programming fuses is an irreversible operation!\n" 219 " This may brick your system.\n" 220 " Use this command only if you are sure of what you are doing!\n" 221 "\nReally perform this fuse programming? <y/N>\n"); 222 223 if (confirm_yesno()) 224 return 1; 225 226 puts("Fuse programming aborted\n"); 227 return 0; 228} 229 230static void display_key_info(const struct stm32key *key) 231{ 232 printf("%s : %s\n", key->name, key->desc); 233 printf("\tOTP%d..%d\n", key->start, key->start + key->size); 234} 235 236static int do_stm32key_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 237{ 238 int i; 239 240 for (i = 0; i < get_key_nb(); i++) 241 display_key_info(get_key(i)); 242 243 return CMD_RET_SUCCESS; 244} 245 246static int do_stm32key_select(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 247{ 248 const struct stm32key *key; 249 int i; 250 251 if (argc == 1) { 252 printf("Selected key:\n"); 253 key = get_key(stm32key_index); 254 display_key_info(key); 255 return CMD_RET_SUCCESS; 256 } 257 258 for (i = 0; i < get_key_nb(); i++) { 259 key = get_key(i); 260 if (!strcmp(key->name, argv[1])) { 261 printf("%s selected\n", key->name); 262 stm32key_index = i; 263 return CMD_RET_SUCCESS; 264 } 265 } 266 267 printf("Unknown key %s\n", argv[1]); 268 269 return CMD_RET_FAILURE; 270} 271 272static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 273{ 274 const struct stm32key *key; 275 struct udevice *dev; 276 u32 addr; 277 int ret, i; 278 int result; 279 280 ret = get_misc_dev(&dev); 281 282 if (argc == 1) { 283 if (ret) 284 return CMD_RET_FAILURE; 285 key = get_key(stm32key_index); 286 ret = read_key_otp(dev, key, true, NULL); 287 if (ret != -ENOENT) 288 return CMD_RET_FAILURE; 289 return CMD_RET_SUCCESS; 290 } 291 292 if (!strcmp("-a", argv[1])) { 293 if (ret) 294 return CMD_RET_FAILURE; 295 result = CMD_RET_SUCCESS; 296 for (i = 0; i < get_key_nb(); i++) { 297 key = get_key(i); 298 ret = read_key_otp(dev, key, true, NULL); 299 if (ret != -ENOENT) 300 result = CMD_RET_FAILURE; 301 } 302 ret = read_close_status(dev, true, NULL); 303 if (ret) 304 result = CMD_RET_FAILURE; 305 306 return result; 307 } 308 309 addr = hextoul(argv[1], NULL); 310 if (!addr) 311 return CMD_RET_USAGE; 312 313 key = get_key(stm32key_index); 314 printf("Read %s at 0x%08x\n", key->name, addr); 315 read_key_value(key, addr); 316 317 return CMD_RET_SUCCESS; 318} 319 320static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 321{ 322 const struct stm32key *key = get_key(stm32key_index); 323 struct udevice *dev; 324 u32 addr; 325 int ret; 326 bool yes = false, lock; 327 328 if (argc < 2) 329 return CMD_RET_USAGE; 330 331 if (argc == 3) { 332 if (strcmp(argv[1], "-y")) 333 return CMD_RET_USAGE; 334 yes = true; 335 } 336 337 addr = hextoul(argv[argc - 1], NULL); 338 if (!addr) 339 return CMD_RET_USAGE; 340 341 ret = get_misc_dev(&dev); 342 if (ret) 343 return CMD_RET_FAILURE; 344 345 if (read_key_otp(dev, key, !yes, &lock) != -ENOENT) { 346 printf("Error: can't fuse again the OTP\n"); 347 return CMD_RET_FAILURE; 348 } 349 if (lock) { 350 printf("Error: %s is locked\n", key->name); 351 return CMD_RET_FAILURE; 352 } 353 354 if (!yes) { 355 printf("Writing %s with\n", key->name); 356 read_key_value(key, addr); 357 } 358 359 if (!yes && !confirm_prog()) 360 return CMD_RET_FAILURE; 361 362 if (fuse_key_value(dev, key, addr, !yes)) 363 return CMD_RET_FAILURE; 364 365 printf("%s updated !\n", key->name); 366 367 return CMD_RET_SUCCESS; 368} 369 370static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 371{ 372 const struct stm32key *key; 373 bool yes, lock, closed; 374 struct udevice *dev; 375 u32 val; 376 int ret; 377 378 yes = false; 379 if (argc == 2) { 380 if (strcmp(argv[1], "-y")) 381 return CMD_RET_USAGE; 382 yes = true; 383 } 384 385 ret = get_misc_dev(&dev); 386 if (ret) 387 return CMD_RET_FAILURE; 388 389 if (read_close_status(dev, !yes, &closed)) 390 return CMD_RET_FAILURE; 391 392 if (closed) { 393 printf("Error: already closed!\n"); 394 return CMD_RET_FAILURE; 395 } 396 397 /* check PKH status before to close */ 398 key = get_key(STM32KEY_PKH); 399 ret = read_key_otp(dev, key, !yes, &lock); 400 if (ret) { 401 if (ret == -ENOENT) 402 printf("Error: %s not programmed!\n", key->name); 403 return CMD_RET_FAILURE; 404 } 405 if (!lock) 406 printf("Warning: %s not locked!\n", key->name); 407 408 if (!yes && !confirm_prog()) 409 return CMD_RET_FAILURE; 410 411 val = get_otp_close_mask(); 412 ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); 413 if (ret != 4) { 414 printf("Error: can't update OTP %d\n", STM32_OTP_CLOSE_ID); 415 return CMD_RET_FAILURE; 416 } 417 418 printf("Device is closed !\n"); 419 420 return CMD_RET_SUCCESS; 421} 422 423static char stm32key_help_text[] = 424 "list : list the supported key with description\n" 425 "stm32key select [<key>] : Select the key identified by <key> or display the key used for read/fuse command\n" 426 "stm32key read [<addr> | -a ] : Read the curent key at <addr> or current / all (-a) key in OTP\n" 427 "stm32key fuse [-y] <addr> : Fuse the current key at addr in OTP\n" 428 "stm32key close [-y] : Close the device\n"; 429 430U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Manage key on STM32", stm32key_help_text, 431 U_BOOT_SUBCMD_MKENT(list, 1, 0, do_stm32key_list), 432 U_BOOT_SUBCMD_MKENT(select, 2, 0, do_stm32key_select), 433 U_BOOT_SUBCMD_MKENT(read, 2, 0, do_stm32key_read), 434 U_BOOT_SUBCMD_MKENT(fuse, 3, 0, do_stm32key_fuse), 435 U_BOOT_SUBCMD_MKENT(close, 2, 0, do_stm32key_close)); 436