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