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 /* Closed device : bit 6 of OPT0*/
15 #define STM32_OTP_CLOSE_ID		0
16 #define STM32_OTP_CLOSE_MASK		BIT(6)
17 
18 /* HASH of key: 8 OTPs, starting with OTP24) */
19 #define STM32_OTP_HASH_KEY_START	24
20 #define STM32_OTP_HASH_KEY_SIZE		8
21 
get_misc_dev(struct udevice ** dev)22 static int get_misc_dev(struct udevice **dev)
23 {
24 	int ret;
25 
26 	ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(stm32mp_bsec), dev);
27 	if (ret)
28 		log_err("Can't find stm32mp_bsec driver\n");
29 
30 	return ret;
31 }
32 
read_hash_value(u32 addr)33 static void read_hash_value(u32 addr)
34 {
35 	int i;
36 
37 	printf("Read KEY at 0x%x\n", addr);
38 	for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
39 		printf("OTP value %i: %x\n", STM32_OTP_HASH_KEY_START + i,
40 		       __be32_to_cpu(*(u32 *)addr));
41 		addr += 4;
42 	}
43 }
44 
read_hash_otp(bool print,bool * locked,bool * closed)45 static int read_hash_otp(bool print, bool *locked, bool *closed)
46 {
47 	struct udevice *dev;
48 	int i, word, ret;
49 	int nb_invalid = 0, nb_zero = 0, nb_lock = 0;
50 	u32 val, lock;
51 	bool status;
52 
53 	ret = get_misc_dev(&dev);
54 	if (ret)
55 		return ret;
56 
57 	for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++) {
58 		ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4);
59 		if (ret != 4)
60 			val = ~0x0;
61 		ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4);
62 		if (ret != 4)
63 			lock = -1;
64 		if (print)
65 			printf("OTP HASH %i: %x lock : %d\n", word, val, lock);
66 		if (val == ~0x0)
67 			nb_invalid++;
68 		else if (val == 0x0)
69 			nb_zero++;
70 		if (lock == 1)
71 			nb_lock++;
72 	}
73 
74 	word = STM32_OTP_CLOSE_ID;
75 	ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4);
76 	if (ret != 4)
77 		val = 0x0;
78 	ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4);
79 	if (ret != 4)
80 		lock = -1;
81 
82 	status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK;
83 	if (closed)
84 		*closed = status;
85 	if (print)
86 		printf("OTP %d: closed status: %d lock : %d\n", word, status, lock);
87 
88 	status = (nb_lock == STM32_OTP_HASH_KEY_SIZE);
89 	if (locked)
90 		*locked = status;
91 	if (!status && print)
92 		printf("Hash of key is not locked!\n");
93 
94 	if (nb_invalid == STM32_OTP_HASH_KEY_SIZE) {
95 		if (print)
96 			printf("Hash of key is invalid!\n");
97 		return -EINVAL;
98 	}
99 	if (nb_zero == STM32_OTP_HASH_KEY_SIZE) {
100 		if (print)
101 			printf("Hash of key is free!\n");
102 		return -ENOENT;
103 	}
104 
105 	return 0;
106 }
107 
fuse_hash_value(u32 addr,bool print)108 static int fuse_hash_value(u32 addr, bool print)
109 {
110 	struct udevice *dev;
111 	u32 word, val;
112 	int i, ret;
113 
114 	ret = get_misc_dev(&dev);
115 	if (ret)
116 		return ret;
117 
118 	for (i = 0, word = STM32_OTP_HASH_KEY_START;
119 	     i < STM32_OTP_HASH_KEY_SIZE;
120 	     i++, word++, addr += 4) {
121 		val = __be32_to_cpu(*(u32 *)addr);
122 		if (print)
123 			printf("Fuse OTP %i : %x\n", word, val);
124 
125 		ret = misc_write(dev, STM32_BSEC_OTP(word), &val, 4);
126 		if (ret != 4) {
127 			log_err("Fuse OTP %i failed\n", word);
128 			return ret;
129 		}
130 		/* on success, lock the OTP for HASH key */
131 		val = 1;
132 		ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4);
133 		if (ret != 4) {
134 			log_err("Lock OTP %i failed\n", word);
135 			return ret;
136 		}
137 	}
138 
139 	return 0;
140 }
141 
confirm_prog(void)142 static int confirm_prog(void)
143 {
144 	puts("Warning: Programming fuses is an irreversible operation!\n"
145 			"         This may brick your system.\n"
146 			"         Use this command only if you are sure of what you are doing!\n"
147 			"\nReally perform this fuse programming? <y/N>\n");
148 
149 	if (confirm_yesno())
150 		return 1;
151 
152 	puts("Fuse programming aborted\n");
153 	return 0;
154 }
155 
do_stm32key_read(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])156 static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
157 {
158 	u32 addr;
159 
160 	if (argc == 1) {
161 		read_hash_otp(true, NULL, NULL);
162 		return CMD_RET_SUCCESS;
163 	}
164 
165 	addr = hextoul(argv[1], NULL);
166 	if (!addr)
167 		return CMD_RET_USAGE;
168 
169 	read_hash_value(addr);
170 
171 	return CMD_RET_SUCCESS;
172 }
173 
do_stm32key_fuse(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])174 static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
175 {
176 	u32 addr;
177 	bool yes = false, lock, closed;
178 
179 	if (argc < 2)
180 		return CMD_RET_USAGE;
181 
182 	if (argc == 3) {
183 		if (strcmp(argv[1], "-y"))
184 			return CMD_RET_USAGE;
185 		yes = true;
186 	}
187 
188 	addr = hextoul(argv[argc - 1], NULL);
189 	if (!addr)
190 		return CMD_RET_USAGE;
191 
192 	if (read_hash_otp(!yes, &lock, &closed) != -ENOENT) {
193 		printf("Error: can't fuse again the OTP\n");
194 		return CMD_RET_FAILURE;
195 	}
196 
197 	if (lock || closed) {
198 		printf("Error: invalid OTP configuration (lock=%d, closed=%d)\n", lock, closed);
199 		return CMD_RET_FAILURE;
200 	}
201 
202 	if (!yes && !confirm_prog())
203 		return CMD_RET_FAILURE;
204 
205 	if (fuse_hash_value(addr, !yes))
206 		return CMD_RET_FAILURE;
207 
208 	printf("Hash key updated !\n");
209 
210 	return CMD_RET_SUCCESS;
211 }
212 
do_stm32key_close(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])213 static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
214 {
215 	bool yes, lock, closed;
216 	struct udevice *dev;
217 	u32 val;
218 	int ret;
219 
220 	yes = false;
221 	if (argc == 2) {
222 		if (strcmp(argv[1], "-y"))
223 			return CMD_RET_USAGE;
224 		yes = true;
225 	}
226 
227 	ret = read_hash_otp(!yes, &lock, &closed);
228 	if (ret) {
229 		if (ret == -ENOENT)
230 			printf("Error: OTP not programmed!\n");
231 		return CMD_RET_FAILURE;
232 	}
233 
234 	if (closed) {
235 		printf("Error: already closed!\n");
236 		return CMD_RET_FAILURE;
237 	}
238 
239 	if (!lock)
240 		printf("Warning: OTP not locked!\n");
241 
242 	if (!yes && !confirm_prog())
243 		return CMD_RET_FAILURE;
244 
245 	ret = get_misc_dev(&dev);
246 	if (ret)
247 		return CMD_RET_FAILURE;
248 
249 	val = STM32_OTP_CLOSE_MASK;
250 	ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4);
251 	if (ret != 4) {
252 		printf("Error: can't update OTP\n");
253 		return CMD_RET_FAILURE;
254 	}
255 
256 	printf("Device is closed !\n");
257 
258 	return CMD_RET_SUCCESS;
259 }
260 
261 static char stm32key_help_text[] =
262 	"read [<addr>]: Read the hash stored at addr in memory or in OTP\n"
263 	"stm32key fuse [-y] <addr> : Fuse hash stored at addr in OTP\n"
264 	"stm32key close [-y] : Close the device, the hash stored in OTP\n";
265 
266 U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Fuse ST Hash key", stm32key_help_text,
267 	U_BOOT_SUBCMD_MKENT(read, 2, 0, do_stm32key_read),
268 	U_BOOT_SUBCMD_MKENT(fuse, 3, 0, do_stm32key_fuse),
269 	U_BOOT_SUBCMD_MKENT(close, 2, 0, do_stm32key_close));
270