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