gcc-9: silence 'address-of-packed-member' warning
[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 #define MX6DQ_PU_IROM_MMU_EN_VAR        0x009024a8
28 #define MX6SDL_PU_IROM_MMU_EN_VAR       0x00901dd0
29 #define MX6SL_PU_IROM_MMU_EN_VAR        0x00900a18
30
31 struct record {
32         uint8_t  tag;                           /* Tag */
33         uint8_t  len[2];                        /* Length */
34         uint8_t  par;                           /* Version */
35         uint8_t  contents[MAX_RECORD_BYTES];    /* Record Data */
36         bool     any_rec_flag;
37 };
38
39 char *rsn_str[] = {
40         "RSN = HAB_RSN_ANY (0x00)\n",
41         "RSN = HAB_ENG_FAIL (0x30)\n",
42         "RSN = HAB_INV_ADDRESS (0x22)\n",
43         "RSN = HAB_INV_ASSERTION (0x0C)\n",
44         "RSN = HAB_INV_CALL (0x28)\n",
45         "RSN = HAB_INV_CERTIFICATE (0x21)\n",
46         "RSN = HAB_INV_COMMAND (0x06)\n",
47         "RSN = HAB_INV_CSF (0x11)\n",
48         "RSN = HAB_INV_DCD (0x27)\n",
49         "RSN = HAB_INV_INDEX (0x0F)\n",
50         "RSN = HAB_INV_IVT (0x05)\n",
51         "RSN = HAB_INV_KEY (0x1D)\n",
52         "RSN = HAB_INV_RETURN (0x1E)\n",
53         "RSN = HAB_INV_SIGNATURE (0x18)\n",
54         "RSN = HAB_INV_SIZE (0x17)\n",
55         "RSN = HAB_MEM_FAIL (0x2E)\n",
56         "RSN = HAB_OVR_COUNT (0x2B)\n",
57         "RSN = HAB_OVR_STORAGE (0x2D)\n",
58         "RSN = HAB_UNS_ALGORITHM (0x12)\n",
59         "RSN = HAB_UNS_COMMAND (0x03)\n",
60         "RSN = HAB_UNS_ENGINE (0x0A)\n",
61         "RSN = HAB_UNS_ITEM (0x24)\n",
62         "RSN = HAB_UNS_KEY (0x1B)\n",
63         "RSN = HAB_UNS_PROTOCOL (0x14)\n",
64         "RSN = HAB_UNS_STATE (0x09)\n",
65         "RSN = INVALID\n",
66 };
67
68 char *sts_str[] = {
69         "STS = HAB_STS_ANY (0x00)\n",
70         "STS = HAB_FAILURE (0x33)\n",
71         "STS = HAB_WARNING (0x69)\n",
72         "STS = HAB_SUCCESS (0xF0)\n",
73         "STS = INVALID\n",
74 };
75
76 char *eng_str[] = {
77         "ENG = HAB_ENG_ANY (0x00)\n",
78         "ENG = HAB_ENG_SCC (0x03)\n",
79         "ENG = HAB_ENG_RTIC (0x05)\n",
80         "ENG = HAB_ENG_SAHARA (0x06)\n",
81         "ENG = HAB_ENG_CSU (0x0A)\n",
82         "ENG = HAB_ENG_SRTC (0x0C)\n",
83         "ENG = HAB_ENG_DCP (0x1B)\n",
84         "ENG = HAB_ENG_CAAM (0x1D)\n",
85         "ENG = HAB_ENG_SNVS (0x1E)\n",
86         "ENG = HAB_ENG_OCOTP (0x21)\n",
87         "ENG = HAB_ENG_DTCP (0x22)\n",
88         "ENG = HAB_ENG_ROM (0x36)\n",
89         "ENG = HAB_ENG_HDCP (0x24)\n",
90         "ENG = HAB_ENG_RTL (0x77)\n",
91         "ENG = HAB_ENG_SW (0xFF)\n",
92         "ENG = INVALID\n",
93 };
94
95 char *ctx_str[] = {
96         "CTX = HAB_CTX_ANY(0x00)\n",
97         "CTX = HAB_CTX_FAB (0xFF)\n",
98         "CTX = HAB_CTX_ENTRY (0xE1)\n",
99         "CTX = HAB_CTX_TARGET (0x33)\n",
100         "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
101         "CTX = HAB_CTX_DCD (0xDD)\n",
102         "CTX = HAB_CTX_CSF (0xCF)\n",
103         "CTX = HAB_CTX_COMMAND (0xC0)\n",
104         "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
105         "CTX = HAB_CTX_ASSERT (0xA0)\n",
106         "CTX = HAB_CTX_EXIT (0xEE)\n",
107         "CTX = INVALID\n",
108 };
109
110 uint8_t hab_statuses[ARRAY_SIZE(sts_str)] = {
111         HAB_STS_ANY,
112         HAB_FAILURE,
113         HAB_WARNING,
114         HAB_SUCCESS,
115         -1
116 };
117
118 uint8_t hab_reasons[ARRAY_SIZE(rsn_str)] = {
119         HAB_RSN_ANY,
120         HAB_ENG_FAIL,
121         HAB_INV_ADDRESS,
122         HAB_INV_ASSERTION,
123         HAB_INV_CALL,
124         HAB_INV_CERTIFICATE,
125         HAB_INV_COMMAND,
126         HAB_INV_CSF,
127         HAB_INV_DCD,
128         HAB_INV_INDEX,
129         HAB_INV_IVT,
130         HAB_INV_KEY,
131         HAB_INV_RETURN,
132         HAB_INV_SIGNATURE,
133         HAB_INV_SIZE,
134         HAB_MEM_FAIL,
135         HAB_OVR_COUNT,
136         HAB_OVR_STORAGE,
137         HAB_UNS_ALGORITHM,
138         HAB_UNS_COMMAND,
139         HAB_UNS_ENGINE,
140         HAB_UNS_ITEM,
141         HAB_UNS_KEY,
142         HAB_UNS_PROTOCOL,
143         HAB_UNS_STATE,
144         -1
145 };
146
147 uint8_t hab_contexts[ARRAY_SIZE(ctx_str)] = {
148         HAB_CTX_ANY,
149         HAB_CTX_FAB,
150         HAB_CTX_ENTRY,
151         HAB_CTX_TARGET,
152         HAB_CTX_AUTHENTICATE,
153         HAB_CTX_DCD,
154         HAB_CTX_CSF,
155         HAB_CTX_COMMAND,
156         HAB_CTX_AUT_DAT,
157         HAB_CTX_ASSERT,
158         HAB_CTX_EXIT,
159         -1
160 };
161
162 uint8_t hab_engines[ARRAY_SIZE(eng_str)] = {
163         HAB_ENG_ANY,
164         HAB_ENG_SCC,
165         HAB_ENG_RTIC,
166         HAB_ENG_SAHARA,
167         HAB_ENG_CSU,
168         HAB_ENG_SRTC,
169         HAB_ENG_DCP,
170         HAB_ENG_CAAM,
171         HAB_ENG_SNVS,
172         HAB_ENG_OCOTP,
173         HAB_ENG_DTCP,
174         HAB_ENG_ROM,
175         HAB_ENG_HDCP,
176         HAB_ENG_RTL,
177         HAB_ENG_SW,
178         -1
179 };
180
181 bool is_hab_enabled(void)
182 {
183         uint32_t reg;
184         static int first = 1;
185
186         if (fuse_read(0, 6, &reg)) {
187                 printf("Failed to read SECURE_BOOT fuse\n");
188                 return 0;
189         }
190
191         if (first) {
192                 debug("rvt_base=%p\n", hab_rvt_base());
193                 debug("hab_rvt_entry=%p\n", hab_rvt_entry_p);
194                 debug("hab_rvt_exit=%p\n", hab_rvt_exit_p);
195                 debug("hab_rvt_check_target=%p\n", hab_rvt_check_target_p);
196                 debug("hab_rvt_authenticate_image=%p\n", hab_rvt_authenticate_image_p);
197                 debug("hab_rvt_report_event=%p\n", hab_rvt_report_event_p);
198                 debug("hab_rvt_report_status=%p\n", hab_rvt_report_status_p);
199                 debug("hab_rvt_assert=%p\n", hab_rvt_assert_p);
200                 first = 0;
201         }
202         return (reg & 0x2) == 0x2;
203 }
204
205 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
206 {
207         uint8_t idx = 0;
208         uint8_t element = list[idx];
209         while (element != -1) {
210                 if (element == tgt)
211                         return idx;
212                 element = list[++idx];
213         }
214         return -1;
215 }
216
217 void process_event_record(uint8_t *event_data, size_t bytes)
218 {
219         struct record *rec = (struct record *)event_data;
220
221         printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
222         printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
223         printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
224         printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
225 }
226
227 void display_event(uint8_t *event_data, size_t bytes)
228 {
229         uint32_t i;
230
231         if (!(event_data && bytes > 0))
232                 return;
233
234         for (i = 0; i < bytes; i++) {
235                 if (i == 0)
236                         printf("\t0x%02x", event_data[i]);
237                 else if ((i % 8) == 0)
238                         printf("\n\t0x%02x", event_data[i]);
239                 else
240                         printf(" 0x%02x", event_data[i]);
241         }
242
243         process_event_record(event_data, bytes);
244 }
245
246 static uint32_t last_hab_event __attribute__((section(".data")));
247
248 int get_hab_status(void)
249 {
250         uint32_t index = last_hab_event; /* Loop index */
251         uint8_t event_data[128]; /* Event data buffer */
252         size_t bytes = sizeof(event_data); /* Event size in bytes */
253         enum hab_config config = 0;
254         enum hab_state state = 0;
255         static int first = 1;
256         int ret;
257
258         if (first) {
259                 printf("Secure boot %sabled\n",
260                        is_hab_enabled() ? "en" : "dis");
261         }
262
263         /* Check HAB status */
264         enable_ocotp_clk(1);
265         ret = hab_rvt_report_status(&config, &state);
266         enable_ocotp_clk(0);
267         if (first)
268                 printf("HAB Configuration: 0x%02x, HAB State: 0x%02x\n",
269                        config, state);
270         if (ret != HAB_SUCCESS) {
271                 /* Display HAB Error events */
272                 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
273                                             &bytes) == HAB_SUCCESS) {
274                         puts("\n");
275                         printf("--------- HAB Event %d -----------------\n",
276                                index + 1);
277                         puts("event data:\n");
278                         display_event(event_data, bytes);
279                         puts("\n");
280                         bytes = sizeof(event_data);
281                         index++;
282                 }
283                 ret = index - last_hab_event;
284                 last_hab_event = index;
285         } else {
286                 /* Display message if no HAB events are found */
287                 puts("No HAB Events Found!\n");
288                 ret = 0;
289         }
290         first = 0;
291         return ret;
292 }
293
294 static inline void hab_clear_events(void)
295 {
296         uint32_t index = last_hab_event; /* Loop index */
297         uint8_t event_data[128]; /* Event data buffer */
298         size_t bytes = sizeof(event_data); /* Event size in bytes */
299         enum hab_config config = 0;
300         enum hab_state state = 0;
301         int ret;
302
303         /* Check HAB status */
304         enable_ocotp_clk(1);
305         ret = hab_rvt_report_status(&config, &state);
306         enable_ocotp_clk(0);
307         if (ret != HAB_SUCCESS) {
308                 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
309                                             &bytes) == HAB_SUCCESS) {
310                         index++;
311                 }
312                 last_hab_event = index;
313         }
314 }
315
316 static inline enum hab_status hab_init(void)
317 {
318         enum hab_status ret;
319
320         enable_ocotp_clk(1);
321
322         hab_caam_clock_enable(1);
323
324         ret = hab_rvt_entry();
325         debug("hab_rvt_entry() returned %02x\n", ret);
326         if (ret != HAB_SUCCESS) {
327                 printf("hab entry function failed: %02x\n", ret);
328                 hab_caam_clock_enable(0);
329         }
330
331         return ret;
332 }
333
334 static inline enum hab_status hab_exit(void)
335 {
336         enum hab_status ret;
337
338         ret = hab_rvt_exit();
339         if (ret != HAB_SUCCESS)
340                 printf("hab exit function failed: %02x\n", ret);
341
342         hab_caam_clock_enable(0);
343         enable_ocotp_clk(0);
344
345         return ret;
346 }
347
348 static enum hab_status hab_check_target(enum hab_target type, uint32_t addr, size_t len)
349 {
350         enum hab_status ret;
351
352         ret = hab_init();
353         if (ret != HAB_SUCCESS)
354                 return ret;
355
356         ret = hab_rvt_check_target(type, (void *)addr, len);
357         if (ret != HAB_SUCCESS) {
358                 printf("check_target(0x%08x, 0x%08x) failed: %d\n",
359                         addr, len, ret);
360                 return ret;
361         }
362         ret = hab_exit();
363
364         if (ret == HAB_SUCCESS && get_hab_status() > 0) {
365                 return HAB_FAILURE;
366         }
367         return ret;
368 }
369
370 static enum hab_status hab_assert(uint32_t type, uint32_t addr, size_t len)
371 {
372         enum hab_status ret;
373
374         ret = hab_init();
375         if (ret != HAB_SUCCESS)
376                 return ret;
377
378         ret = hab_rvt_assert(type, (void *)addr, len);
379         if (ret != HAB_SUCCESS) {
380                 printf("assert(0x%08x, 0x%08x) failed: %d\n",
381                         addr, len, ret);
382                 return ret;
383         }
384         ret = hab_exit();
385
386         if (ret == HAB_SUCCESS && get_hab_status() > 0) {
387                 return HAB_FAILURE;
388         }
389         return ret;
390 }
391
392 static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
393                         char *const argv[])
394 {
395         if (argc != 1)
396                 return CMD_RET_USAGE;
397
398         get_hab_status();
399
400         return CMD_RET_SUCCESS;
401 }
402
403 static int do_hab_check_target(cmd_tbl_t *cmdtp, int flag, int argc,
404                         char *const argv[])
405 {
406         enum hab_target type = HAB_TGT_ANY;
407         uint32_t addr;
408         size_t len;
409
410         if (argc < 3)
411                 return CMD_RET_USAGE;
412
413         addr = simple_strtoul(argv[1], NULL, 16);
414         len = simple_strtoul(argv[2], NULL, 16);
415         if (argc > 3) {
416                 switch (argv[3][0]) {
417                 case 'p':
418                 case 'P':
419                         type = HAB_TGT_PERIPHERAL;
420                         break;
421                 case 'm':
422                 case 'M':
423                         type = HAB_TGT_MEMORY;
424                         break;
425                 case 'a':
426                 case 'A':
427                         break;
428                 default:
429                         printf("Invalid type '%s'\n", argv[3]);
430                         return CMD_RET_USAGE;
431                 }
432         }
433         if (hab_check_target(type, addr, len) != HAB_SUCCESS)
434                 return CMD_RET_FAILURE;
435
436         return CMD_RET_SUCCESS;
437 }
438
439 static int do_hab_assert(cmd_tbl_t *cmdtp, int flag, int argc,
440                         char *const argv[])
441 {
442         uint32_t type = 0;
443         uint32_t addr;
444         size_t len;
445
446         if (argc < 3)
447                 return CMD_RET_USAGE;
448
449         addr = simple_strtoul(argv[1], NULL, 16);
450         len = simple_strtoul(argv[2], NULL, 16);
451         if (argc > 3) {
452                 type = simple_strtoul(argv[3], NULL, 16);
453         }
454
455         if (hab_assert(type, addr, len) != HAB_SUCCESS)
456                 return CMD_RET_FAILURE;
457
458         return CMD_RET_SUCCESS;
459 }
460
461 /* Get CSF Header length */
462 static int get_hab_hdr_len(struct hab_hdr *hdr)
463 {
464         return (size_t)((hdr->len[0] << 8) + (hdr->len[1]));
465 }
466
467 /* Check whether addr lies between start and
468  * end and is within the length of the image
469  */
470 static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end)
471 {
472         size_t csf_size = (size_t)((end + 1) - addr);
473
474         return addr && (addr >= start) && (addr <= end) &&
475                 (csf_size >= bytes);
476 }
477
478 /* Get Length of each command in CSF */
479 static int get_csf_cmd_hdr_len(u8 *csf_hdr)
480 {
481         if (*csf_hdr == HAB_CMD_HDR)
482                 return sizeof(struct hab_hdr);
483
484         return get_hab_hdr_len((struct hab_hdr *)csf_hdr);
485 }
486
487 /* Check if CSF is valid */
488 static inline bool csf_is_valid(struct ivt *ivt, void *addr, size_t bytes)
489 {
490         u8 *start = addr;
491         u8 *csf_hdr;
492         u8 *end;
493
494         size_t csf_hdr_len;
495         size_t cmd_hdr_len;
496         size_t offset = 0;
497
498         if (bytes != 0)
499                 end = start + bytes - 1;
500         else
501                 end = start;
502
503         /* Verify if CSF pointer content is zero */
504         if (!ivt->csf) {
505                 puts("Error: CSF pointer is NULL\n");
506                 return false;
507         }
508
509         csf_hdr = (u8 *)(uintptr_t)ivt->csf;
510
511         /* Verify if CSF Header exist */
512         if (*csf_hdr != HAB_CMD_HDR) {
513                 puts("Error: CSF header command not found\n");
514                 return false;
515         }
516
517         csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr);
518
519         /* Check if the CSF lies within the image bounds */
520         if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) {
521                 puts("Error: CSF lies outside the image bounds\n");
522                 return false;
523         }
524
525         do {
526                 struct hab_hdr *cmd;
527
528                 cmd = (struct hab_hdr *)&csf_hdr[offset];
529
530                 switch (cmd->tag) {
531                 case (HAB_CMD_WRT_DAT):
532                         puts("Error: Deprecated write command found\n");
533                         return false;
534                 case (HAB_CMD_CHK_DAT):
535                         puts("Error: Deprecated check command found\n");
536                         return false;
537                 case (HAB_CMD_SET):
538                         if (cmd->par == HAB_PAR_MID) {
539                                 puts("Error: Deprecated Set MID command found\n");
540                                 return false;
541                         }
542                 default:
543                         break;
544                 }
545
546                 cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]);
547                 if (!cmd_hdr_len) {
548                         puts("Error: Invalid command length\n");
549                         return false;
550                 }
551                 offset += cmd_hdr_len;
552
553         } while (offset < csf_hdr_len);
554
555         return true;
556 }
557
558 static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
559 {
560         printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str,
561                ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version);
562
563         return 1;
564 }
565
566 static int verify_ivt_header(struct ivt_header *ivt_hdr)
567 {
568         if (ivt_hdr->magic != IVT_HEADER_MAGIC)
569                 return ivt_header_error("bad IVT magic", ivt_hdr);
570
571         if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH)
572                 return ivt_header_error("bad IVT length", ivt_hdr);
573
574         if (ivt_hdr->version != IVT_HEADER_V1 &&
575             ivt_hdr->version != IVT_HEADER_V2)
576                 return ivt_header_error("bad IVT version", ivt_hdr);
577
578         return 0;
579 }
580
581 /*
582  * Validate IVT structure of the image being authenticated
583  */
584 static int validate_ivt(struct ivt *ivt)
585 {
586         struct ivt_header *ivt_hdr = &ivt->hdr;
587
588         if ((uintptr_t)ivt & 0x3) {
589                 puts("Error: IVT address is not 4 byte aligned\n");
590                 return 0;
591         }
592
593         /* Check IVT fields before allowing authentication */
594         if ((!verify_ivt_header(ivt_hdr)) &&
595             (ivt->entry != 0x0) &&
596             (ivt->reserved1 == 0x0) &&
597             (ivt->self == (uint32_t)ivt) &&
598             (ivt->csf != 0x0) &&
599             (ivt->reserved2 == 0x0) &&
600             (ivt->dcd == 0x0)) {
601                 return 1;
602         }
603
604         puts("Error: Invalid IVT structure\n");
605         if (ivt->entry == 0x0)
606                 printf("entry address must not be NULL\n");
607         if (ivt->reserved1 != 0x0)
608                 printf("reserved word at offset 0x%02x should be NULL\n",
609                        offsetof(struct ivt, reserved1));
610         if (ivt->dcd != 0x0)
611                 puts("Error: DCD pointer must be 0\n");
612         if (ivt->self != (uint32_t)ivt)
613                 printf("SELF pointer does not point to IVT\n");
614         if (ivt->csf == 0x0)
615                 printf("CSF address must not be NULL\n");
616         if (ivt->reserved2 != 0x0)
617                 printf("reserved word at offset 0x%02x should be NULL\n",
618                        offsetof(struct ivt, reserved2));
619         puts("\nAllowed IVT structure:\n");
620         printf("IVT HDR       = 0x4X2000D1 (0x%08x)\n", *((u32 *)&ivt->hdr));
621         printf("IVT ENTRY     = 0xXXXXXXXX (0x%08x)\n", ivt->entry);
622         printf("IVT RSV1      = 0x00000000 (0x%08x)\n", ivt->reserved1);
623         printf("IVT DCD       = 0x00000000 (0x%08x)\n", ivt->dcd);
624         printf("IVT BOOT_DATA = 0xXXXXXXXX (0x%08x)\n", ivt->boot);
625         printf("IVT SELF      = 0xXXXXXXXX (0x%08x)\n", ivt->self);
626         printf("IVT CSF       = 0xXXXXXXXX (0x%08x)\n", ivt->csf);
627         printf("IVT RSV2      = 0x00000000 (0x%08x)\n", ivt->reserved2);
628
629         /* Invalid IVT structure */
630         return 0;
631 }
632
633 bool imx_hab_authenticate_image(void *addr, size_t len, size_t ivt_offset)
634 {
635         struct ivt *ivt;
636         enum hab_status status;
637
638         if (len <= sizeof(ivt)) {
639                 printf("Invalid image size %08x\n", len);
640                 return false;
641         }
642         if (ivt_offset >= len - sizeof(*ivt)) {
643                 printf("IVT offset must be smaller than image size - %u\n",
644                        sizeof(*ivt));
645                 return false;
646         }
647
648         ivt = addr + ivt_offset;
649         /* Verify IVT header bugging out on error */
650         if (!validate_ivt(ivt)) {
651                 print_buffer((ulong)ivt, ivt, 4, 0x8, 0);
652                 return false;
653         }
654
655         if (!csf_is_valid(ivt, addr, len)) {
656                 print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0);
657                 return false;
658         }
659
660         status = hab_init();
661         if (status != HAB_SUCCESS)
662                 goto hab_auth_error;
663
664         hab_clear_events();
665
666         status = hab_rvt_check_target(HAB_TGT_MEMORY, addr, len);
667         if (status != HAB_SUCCESS) {
668                 printf("HAB check target 0x%p-0x%p failed\n",
669                        addr, addr + len);
670                 goto hab_auth_error;
671         }
672         get_hab_status();
673
674         /*
675          * If the MMU is enabled, we have to notify the ROM
676          * code, or it won't flush the caches when needed.
677          * This is done, by setting the "pu_irom_mmu_enabled"
678          * word to 1. You can find its address by looking in
679          * the ROM map. This is critical for
680          * authenticate_image(). If MMU is enabled, without
681          * setting this bit, authentication will fail and may
682          * crash.
683          */
684         /* Check MMU enabled */
685         if (get_cr() & CR_M) {
686                 if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
687                         /*
688                          * This won't work on Rev 1.0.0 of
689                          * i.MX6Q/D, since their ROM doesn't
690                          * do cache flushes. don't think any
691                          * exist, so we ignore them.
692                          */
693                         if (!is_mx6dqp())
694                                 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
695                 } else if (is_cpu_type(MXC_CPU_MX6SOLO) ||
696                            is_cpu_type(MXC_CPU_MX6DL)) {
697                         writel(1, MX6SDL_PU_IROM_MMU_EN_VAR);
698                 } else if (is_cpu_type(MXC_CPU_MX6SL)) {
699                         writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
700                 }
701         }
702
703         hab_rvt_authenticate_image(HAB_CID_UBOOT, ivt_offset, &addr,
704                                    &len, NULL);
705         status = hab_exit();
706         if (status != HAB_SUCCESS)
707                 goto hab_auth_error;
708
709         if (get_hab_status() != 0) {
710                 printf("ERROR: hab_authenticate_image failed\n");
711                 return false;
712         }
713         printf("HAB authentication of image at %p..%p successful\n",
714                addr, addr + len);
715         return true;
716
717  hab_auth_error:
718         printf("ERROR: HAB authentication failure: %02x\n", status);
719         get_hab_status();
720         return false;
721 }
722
723 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
724                                  char *const argv[])
725 {
726         void *addr;
727         size_t ivt_offset, len;
728
729         if (argc < 4)
730                 return CMD_RET_USAGE;
731
732         addr = (void *)simple_strtoul(argv[1], NULL, 16);
733         len = simple_strtoul(argv[2], NULL, 16);
734         ivt_offset = simple_strtoul(argv[3], NULL, 16);
735
736         if (imx_hab_authenticate_image(addr, len, ivt_offset))
737                 return CMD_RET_SUCCESS;
738
739         get_hab_status();
740
741         return CMD_RET_FAILURE;
742 }
743
744 U_BOOT_CMD(
745            hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
746            "display HAB status",
747            ""
748            );
749
750 U_BOOT_CMD(
751            hab_check_target, 4, 0, do_hab_check_target,
752            "verify an address range via HAB",
753            "addr len [type]\n"
754            "\t\taddr -\taddress to verify\n"
755            "\t\tlen -\tlength of addr range to verify\n"
756            );
757
758 U_BOOT_CMD(
759            hab_assert, 4, 0, do_hab_assert,
760            "Test an assertion against the HAB audit log",
761            "addr len [type]\n"
762            "\t\taddr -\taddress to verify\n"
763            "\t\tlen -\tlength of addr range to verify\n"
764            );
765
766 U_BOOT_CMD(
767            hab_auth_img, 4, 0, do_authenticate_image,
768            "authenticate image via HAB",
769            "addr len ivt_offset\n"
770            "addr - image hex address\n"
771            "len - image size (hex)\n"
772            "ivt_offset - hex offset of IVT in the image"
773            );