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