]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/mx6/hab.c
arm: mx6: implement refcounting for the ocotp clock and use 'fuse_read()' rather...
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / mx6 / hab.c
1 /*
2  * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:    GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <fuse.h>
9 #include <asm/io.h>
10 #include <asm/system.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/sys_proto.h>
13 #include <asm/arch/hab.h>
14
15 HAB_FUNC(entry, enum hab_status)
16 HAB_FUNC(exit, enum hab_status)
17 HAB_FUNC5(authenticate_image, void *, uint8_t, size_t, void **, size_t *, hab_loader_callback_f_t)
18 //HAB_FUNC1(run_dcd, enum hab_status, const uint8_t *)
19 HAB_FUNC2(run_csf, enum hab_status, const uint8_t *, uint8_t)
20 HAB_FUNC2(report_status, enum hab_status, enum hab_config *, enum hab_state *)
21 HAB_FUNC4(report_event, enum hab_status, enum hab_status, uint32_t, uint8_t *, size_t *)
22 HAB_FUNC3(check_target, enum hab_status, uint8_t, const void *, size_t)
23 HAB_FUNC3(assert, enum hab_status, uint8_t, const void *, size_t)
24
25 #define MAX_RECORD_BYTES     (8 * 1024)
26
27 struct record {
28         uint8_t  tag;                                           /* Tag */
29         uint8_t  len[2];                                        /* Length */
30         uint8_t  par;                                           /* Version */
31         uint8_t  contents[MAX_RECORD_BYTES];/* Record Data */
32         bool     any_rec_flag;
33 };
34
35 char *rsn_str[] = {
36         "RSN = HAB_RSN_ANY (0x00)\n",
37         "RSN = HAB_ENG_FAIL (0x30)\n",
38         "RSN = HAB_INV_ADDRESS (0x22)\n",
39         "RSN = HAB_INV_ASSERTION (0x0C)\n",
40         "RSN = HAB_INV_CALL (0x28)\n",
41         "RSN = HAB_INV_CERTIFICATE (0x21)\n",
42         "RSN = HAB_INV_COMMAND (0x06)\n",
43         "RSN = HAB_INV_CSF (0x11)\n",
44         "RSN = HAB_INV_DCD (0x27)\n",
45         "RSN = HAB_INV_INDEX (0x0F)\n",
46         "RSN = HAB_INV_IVT (0x05)\n",
47         "RSN = HAB_INV_KEY (0x1D)\n",
48         "RSN = HAB_INV_RETURN (0x1E)\n",
49         "RSN = HAB_INV_SIGNATURE (0x18)\n",
50         "RSN = HAB_INV_SIZE (0x17)\n",
51         "RSN = HAB_MEM_FAIL (0x2E)\n",
52         "RSN = HAB_OVR_COUNT (0x2B)\n",
53         "RSN = HAB_OVR_STORAGE (0x2D)\n",
54         "RSN = HAB_UNS_ALGORITHM (0x12)\n",
55         "RSN = HAB_UNS_COMMAND (0x03)\n",
56         "RSN = HAB_UNS_ENGINE (0x0A)\n",
57         "RSN = HAB_UNS_ITEM (0x24)\n",
58         "RSN = HAB_UNS_KEY (0x1B)\n",
59         "RSN = HAB_UNS_PROTOCOL (0x14)\n",
60         "RSN = HAB_UNS_STATE (0x09)\n",
61         "RSN = INVALID\n",
62 };
63
64 char *sts_str[] = {
65         "STS = HAB_STS_ANY (0x00)\n",
66         "STS = HAB_FAILURE (0x33)\n",
67         "STS = HAB_WARNING (0x69)\n",
68         "STS = HAB_SUCCESS (0xF0)\n",
69         "STS = INVALID\n",
70 };
71
72 char *eng_str[] = {
73         "ENG = HAB_ENG_ANY (0x00)\n",
74         "ENG = HAB_ENG_SCC (0x03)\n",
75         "ENG = HAB_ENG_RTIC (0x05)\n",
76         "ENG = HAB_ENG_SAHARA (0x06)\n",
77         "ENG = HAB_ENG_CSU (0x0A)\n",
78         "ENG = HAB_ENG_SRTC (0x0C)\n",
79         "ENG = HAB_ENG_DCP (0x1B)\n",
80         "ENG = HAB_ENG_CAAM (0x1D)\n",
81         "ENG = HAB_ENG_SNVS (0x1E)\n",
82         "ENG = HAB_ENG_OCOTP (0x21)\n",
83         "ENG = HAB_ENG_DTCP (0x22)\n",
84         "ENG = HAB_ENG_ROM (0x36)\n",
85         "ENG = HAB_ENG_HDCP (0x24)\n",
86         "ENG = HAB_ENG_RTL (0x77)\n",
87         "ENG = HAB_ENG_SW (0xFF)\n",
88         "ENG = INVALID\n",
89 };
90
91 char *ctx_str[] = {
92         "CTX = HAB_CTX_ANY(0x00)\n",
93         "CTX = HAB_CTX_FAB (0xFF)\n",
94         "CTX = HAB_CTX_ENTRY (0xE1)\n",
95         "CTX = HAB_CTX_TARGET (0x33)\n",
96         "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
97         "CTX = HAB_CTX_DCD (0xDD)\n",
98         "CTX = HAB_CTX_CSF (0xCF)\n",
99         "CTX = HAB_CTX_COMMAND (0xC0)\n",
100         "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
101         "CTX = HAB_CTX_ASSERT (0xA0)\n",
102         "CTX = HAB_CTX_EXIT (0xEE)\n",
103         "CTX = INVALID\n",
104 };
105
106 uint8_t hab_statuses[ARRAY_SIZE(sts_str)] = {
107         HAB_STS_ANY,
108         HAB_FAILURE,
109         HAB_WARNING,
110         HAB_SUCCESS,
111         -1
112 };
113
114 uint8_t hab_reasons[ARRAY_SIZE(rsn_str)] = {
115         HAB_RSN_ANY,
116         HAB_ENG_FAIL,
117         HAB_INV_ADDRESS,
118         HAB_INV_ASSERTION,
119         HAB_INV_CALL,
120         HAB_INV_CERTIFICATE,
121         HAB_INV_COMMAND,
122         HAB_INV_CSF,
123         HAB_INV_DCD,
124         HAB_INV_INDEX,
125         HAB_INV_IVT,
126         HAB_INV_KEY,
127         HAB_INV_RETURN,
128         HAB_INV_SIGNATURE,
129         HAB_INV_SIZE,
130         HAB_MEM_FAIL,
131         HAB_OVR_COUNT,
132         HAB_OVR_STORAGE,
133         HAB_UNS_ALGORITHM,
134         HAB_UNS_COMMAND,
135         HAB_UNS_ENGINE,
136         HAB_UNS_ITEM,
137         HAB_UNS_KEY,
138         HAB_UNS_PROTOCOL,
139         HAB_UNS_STATE,
140         -1
141 };
142
143 uint8_t hab_contexts[ARRAY_SIZE(ctx_str)] = {
144         HAB_CTX_ANY,
145         HAB_CTX_FAB,
146         HAB_CTX_ENTRY,
147         HAB_CTX_TARGET,
148         HAB_CTX_AUTHENTICATE,
149         HAB_CTX_DCD,
150         HAB_CTX_CSF,
151         HAB_CTX_COMMAND,
152         HAB_CTX_AUT_DAT,
153         HAB_CTX_ASSERT,
154         HAB_CTX_EXIT,
155         -1
156 };
157
158 uint8_t hab_engines[ARRAY_SIZE(eng_str)] = {
159         HAB_ENG_ANY,
160         HAB_ENG_SCC,
161         HAB_ENG_RTIC,
162         HAB_ENG_SAHARA,
163         HAB_ENG_CSU,
164         HAB_ENG_SRTC,
165         HAB_ENG_DCP,
166         HAB_ENG_CAAM,
167         HAB_ENG_SNVS,
168         HAB_ENG_OCOTP,
169         HAB_ENG_DTCP,
170         HAB_ENG_ROM,
171         HAB_ENG_HDCP,
172         HAB_ENG_RTL,
173         HAB_ENG_SW,
174         -1
175 };
176
177 bool is_hab_enabled(void)
178 {
179         uint32_t reg;
180         static int first = 1;
181
182         if (fuse_read(0, 6, &reg)) {
183                 printf("Failed to read SECURE_BOOT fuse\n");
184                 return 0;
185         }
186
187         if (first) {
188                 debug("rvt_base=%p\n", hab_rvt_base());
189                 debug("hab_rvt_entry=%p\n", hab_rvt_entry_p);
190                 debug("hab_rvt_exit=%p\n", hab_rvt_exit_p);
191                 debug("hab_rvt_check_target=%p\n", hab_rvt_check_target_p);
192                 debug("hab_rvt_authenticate_image=%p\n", hab_rvt_authenticate_image_p);
193                 debug("hab_rvt_report_event=%p\n", hab_rvt_report_event_p);
194                 debug("hab_rvt_report_status=%p\n", hab_rvt_report_status_p);
195                 debug("hab_rvt_assert=%p\n", hab_rvt_assert_p);
196                 first = 0;
197         }
198         return (reg & 0x2) == 0x2;
199 }
200
201 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
202 {
203         uint8_t idx = 0;
204         uint8_t element = list[idx];
205         while (element != -1) {
206                 if (element == tgt)
207                         return idx;
208                 element = list[++idx];
209         }
210         return -1;
211 }
212
213 void process_event_record(uint8_t *event_data, size_t bytes)
214 {
215         struct record *rec = (struct record *)event_data;
216
217         printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
218         printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
219         printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
220         printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
221 }
222
223 void display_event(uint8_t *event_data, size_t bytes)
224 {
225         uint32_t i;
226
227         if (!(event_data && bytes > 0))
228                 return;
229
230         for (i = 0; i < bytes; i++) {
231                 if (i == 0)
232                         printf("\t0x%02x", event_data[i]);
233                 else if ((i % 8) == 0)
234                         printf("\n\t0x%02x", event_data[i]);
235                 else
236                         printf(" 0x%02x", event_data[i]);
237         }
238
239         process_event_record(event_data, bytes);
240 }
241
242 int get_hab_status(void)
243 {
244         static uint32_t last_hab_event __attribute__((section(".data")));
245         uint32_t index = last_hab_event; /* Loop index */
246         uint8_t event_data[128]; /* Event data buffer */
247         size_t bytes = sizeof(event_data); /* Event size in bytes */
248         enum hab_config config;
249         enum hab_state state;
250         int ret;
251
252         if (is_hab_enabled())
253                 puts("Secure boot enabled\n");
254         else
255                 puts("Secure boot disabled\n");
256
257         /* Check HAB status */
258         enable_ocotp_clk(1);
259         config = state = 0; /* ROM code assumes short enums! */
260         ret = hab_rvt_report_status(&config, &state);
261         enable_ocotp_clk(0);
262         printf("HAB Configuration: 0x%02x, HAB State: 0x%02x\n",
263                 config, state);
264         if (ret != HAB_SUCCESS) {
265                 /* Display HAB Error events */
266                 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
267                                         &bytes) == HAB_SUCCESS) {
268                         puts("\n");
269                         printf("--------- HAB Event %d -----------------\n",
270                                index + 1);
271                         puts("event data:\n");
272                         display_event(event_data, bytes);
273                         puts("\n");
274                         bytes = sizeof(event_data);
275                         index++;
276                 }
277                 ret = index - last_hab_event;
278                 last_hab_event = index;
279         } else {
280                 /* Display message if no HAB events are found */
281                 puts("No HAB Events Found!\n");
282                 ret = 0;
283         }
284         return ret;
285 }
286
287 static inline enum hab_status hab_init(void)
288 {
289         enum hab_status ret;
290
291         enable_ocotp_clk(1);
292         if (!is_hab_enabled()) {
293                 puts("hab fuse not enabled\n");
294                 return HAB_FAILURE;
295         }
296
297         hab_caam_clock_enable(1);
298
299         ret = hab_rvt_entry();
300         debug("hab_rvt_entry() returned %02x\n", ret);
301         if (ret != HAB_SUCCESS) {
302                 printf("hab entry function failed: %02x\n", ret);
303                 hab_caam_clock_enable(0);
304         }
305
306         return ret;
307 }
308
309 static inline enum hab_status hab_exit(void)
310 {
311         enum hab_status ret;
312
313         ret = hab_rvt_exit();
314         if (ret != HAB_SUCCESS)
315                 printf("hab exit function failed: %02x\n", ret);
316
317         hab_caam_clock_enable(0);
318         enable_ocotp_clk(0);
319
320         return ret;
321 }
322
323 static enum hab_status hab_check_target(enum hab_target type, uint32_t addr, size_t len)
324 {
325         enum hab_status ret;
326
327         ret = hab_init();
328         if (ret != HAB_SUCCESS)
329                 return ret;
330
331         ret = hab_rvt_check_target(type, (void *)addr, len);
332         if (ret != HAB_SUCCESS) {
333                 printf("check_target(0x%08x, 0x%08x) failed: %d\n",
334                         addr, len, ret);
335                 return ret;
336         }
337         ret = hab_exit();
338
339         if (ret == HAB_SUCCESS && get_hab_status() > 0) {
340                 return HAB_FAILURE;
341         }
342         return ret;
343 }
344
345 static enum hab_status hab_assert(uint32_t type, uint32_t addr, size_t len)
346 {
347         enum hab_status ret;
348
349         ret = hab_init();
350         if (ret != HAB_SUCCESS)
351                 return ret;
352
353         ret = hab_rvt_assert(type, (void *)addr, len);
354         if (ret != HAB_SUCCESS) {
355                 printf("assert(0x%08x, 0x%08x) failed: %d\n",
356                         addr, len, ret);
357                 return ret;
358         }
359         ret = hab_exit();
360
361         if (ret == HAB_SUCCESS && get_hab_status() > 0) {
362                 return HAB_FAILURE;
363         }
364         return ret;
365 }
366
367 static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
368                         char *const argv[])
369 {
370         if (argc != 1)
371                 return CMD_RET_USAGE;
372
373         get_hab_status();
374
375         return CMD_RET_SUCCESS;
376 }
377
378 static int do_hab_check_target(cmd_tbl_t *cmdtp, int flag, int argc,
379                         char *const argv[])
380 {
381         enum hab_target type = HAB_TGT_ANY;
382         uint32_t addr;
383         size_t len;
384
385         if (argc < 3)
386                 return CMD_RET_USAGE;
387
388         addr = simple_strtoul(argv[1], NULL, 16);
389         len = simple_strtoul(argv[2], NULL, 16);
390         if (argc > 3) {
391                 switch (argv[3][0]) {
392                 case 'p':
393                 case 'P':
394                         type = HAB_TGT_PERIPHERAL;
395                         break;
396                 case 'm':
397                 case 'M':
398                         type = HAB_TGT_MEMORY;
399                         break;
400                 case 'a':
401                 case 'A':
402                         break;
403                 default:
404                         printf("Invalid type '%s'\n", argv[3]);
405                         return CMD_RET_USAGE;
406                 }
407         }
408         if (hab_check_target(type, addr, len) != HAB_SUCCESS)
409                 return CMD_RET_FAILURE;
410
411         return CMD_RET_SUCCESS;
412 }
413
414 static int do_hab_assert(cmd_tbl_t *cmdtp, int flag, int argc,
415                         char *const argv[])
416 {
417         uint32_t type = 0;
418         uint32_t addr;
419         size_t len;
420
421         if (argc < 3)
422                 return CMD_RET_USAGE;
423
424         addr = simple_strtoul(argv[1], NULL, 16);
425         len = simple_strtoul(argv[2], NULL, 16);
426         if (argc > 3) {
427                 type = simple_strtoul(argv[3], NULL, 16);
428         }
429
430         if (hab_assert(type, addr, len) != HAB_SUCCESS)
431                 return CMD_RET_FAILURE;
432
433         return CMD_RET_SUCCESS;
434 }
435
436 U_BOOT_CMD(
437                 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
438                 "display HAB status",
439                 ""
440           );
441
442 U_BOOT_CMD(
443                 hab_check_target, 4, 0, do_hab_check_target,
444                 "verify an address range via HAB",
445                 "addr len [type]\n"
446                 "\t\taddr -\taddress to verify\n"
447                 "\t\tlen -\tlength of addr range to verify\n"
448           );
449
450 U_BOOT_CMD(
451                 hab_assert, 4, 0, do_hab_assert,
452                 "Test an assertion against the HAB audit log",
453                 "addr len [type]\n"
454                 "\t\taddr -\taddress to verify\n"
455                 "\t\tlen -\tlength of addr range to verify\n"
456           );