global: Move remaining CONFIG_SYS_* to CFG_SYS_*
[platform/kernel/u-boot.git] / arch / arm / mach-imx / hab.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
4  */
5
6 #include <common.h>
7 #include <command.h>
8 #include <config.h>
9 #include <display_options.h>
10 #include <fuse.h>
11 #include <mapmem.h>
12 #include <image.h>
13 #include <asm/io.h>
14 #include <asm/global_data.h>
15 #include <asm/system.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/sys_proto.h>
18 #include <asm/mach-imx/hab.h>
19 #include <linux/arm-smccc.h>
20
21 DECLARE_GLOBAL_DATA_PTR;
22
23 #define ALIGN_SIZE              0x1000
24 #define MX6DQ_PU_IROM_MMU_EN_VAR        0x009024a8
25 #define MX6DLS_PU_IROM_MMU_EN_VAR       0x00901dd0
26 #define MX6SL_PU_IROM_MMU_EN_VAR        0x00901c60
27 #define IS_HAB_ENABLED_BIT \
28         (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 :     \
29          ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M)) ? 0x2000000 : 0x2))
30
31 #ifdef CONFIG_MX7ULP
32 #define HAB_M4_PERSISTENT_START ((soc_rev() >= CHIP_REV_2_0) ? 0x20008040 : \
33                                   0x20008180)
34 #define HAB_M4_PERSISTENT_BYTES         0xB80
35 #endif
36
37 static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
38 {
39         printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str,
40                ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version);
41
42         return 1;
43 }
44
45 static int verify_ivt_header(struct ivt_header *ivt_hdr)
46 {
47         int result = 0;
48
49         if (ivt_hdr->magic != IVT_HEADER_MAGIC)
50                 result = ivt_header_error("bad magic", ivt_hdr);
51
52         if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH)
53                 result = ivt_header_error("bad length", ivt_hdr);
54
55         if ((ivt_hdr->version & HAB_MAJ_MASK) != HAB_MAJ_VER)
56                 result = ivt_header_error("bad version", ivt_hdr);
57
58         return result;
59 }
60
61 #ifdef CONFIG_ARM64
62 #define FSL_SIP_HAB             0xC2000007
63 #define FSL_SIP_HAB_AUTHENTICATE        0x00
64 #define FSL_SIP_HAB_ENTRY               0x01
65 #define FSL_SIP_HAB_EXIT                0x02
66 #define FSL_SIP_HAB_REPORT_EVENT        0x03
67 #define FSL_SIP_HAB_REPORT_STATUS       0x04
68 #define FSL_SIP_HAB_FAILSAFE            0x05
69 #define FSL_SIP_HAB_CHECK_TARGET        0x06
70 static volatile gd_t *gd_save;
71 #endif
72
73 static inline void save_gd(void)
74 {
75 #ifdef CONFIG_ARM64
76         gd_save = gd;
77 #endif
78 }
79
80 static inline void restore_gd(void)
81 {
82 #ifdef CONFIG_ARM64
83         /*
84          * Make will already error that reserving x18 is not supported at the
85          * time of writing, clang: error: unknown argument: '-ffixed-x18'
86          */
87         __asm__ volatile("mov x18, %0\n" : : "r" (gd_save));
88 #endif
89 }
90
91 enum hab_status hab_rvt_report_event(enum hab_status status, u32 index,
92                                      u8 *event, size_t *bytes)
93 {
94         enum hab_status ret;
95         hab_rvt_report_event_t *hab_rvt_report_event_func;
96         struct arm_smccc_res res __maybe_unused;
97
98         hab_rvt_report_event_func =  (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
99 #if defined(CONFIG_ARM64)
100         if (current_el() != 3) {
101                 /* call sip */
102                 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index,
103                               (unsigned long)event, (unsigned long)bytes, 0, 0, 0, &res);
104                 return (enum hab_status)res.a0;
105         }
106 #endif
107
108         save_gd();
109         ret = hab_rvt_report_event_func(status, index, event, bytes);
110         restore_gd();
111
112         return ret;
113
114 }
115
116 enum hab_status hab_rvt_report_status(enum hab_config *config, enum hab_state *state)
117 {
118         enum hab_status ret;
119         hab_rvt_report_status_t *hab_rvt_report_status_func;
120         struct arm_smccc_res res __maybe_unused;
121
122         hab_rvt_report_status_func = (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
123 #if defined(CONFIG_ARM64)
124         if (current_el() != 3) {
125                 /* call sip */
126                 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_STATUS, (unsigned long)config,
127                               (unsigned long)state, 0, 0, 0, 0, &res);
128                 return (enum hab_status)res.a0;
129         }
130 #endif
131
132         save_gd();
133         ret = hab_rvt_report_status_func(config, state);
134         restore_gd();
135
136         return ret;
137 }
138
139 enum hab_status hab_rvt_entry(void)
140 {
141         enum hab_status ret;
142         hab_rvt_entry_t *hab_rvt_entry_func;
143         struct arm_smccc_res res __maybe_unused;
144
145         hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
146 #if defined(CONFIG_ARM64)
147         if (current_el() != 3) {
148                 /* call sip */
149                 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_ENTRY, 0, 0, 0, 0, 0, 0, &res);
150                 return (enum hab_status)res.a0;
151         }
152 #endif
153
154         save_gd();
155         ret = hab_rvt_entry_func();
156         restore_gd();
157
158         return ret;
159 }
160
161 enum hab_status hab_rvt_exit(void)
162 {
163         enum hab_status ret;
164         hab_rvt_exit_t *hab_rvt_exit_func;
165         struct arm_smccc_res res __maybe_unused;
166
167         hab_rvt_exit_func =  (hab_rvt_exit_t *)HAB_RVT_EXIT;
168 #if defined(CONFIG_ARM64)
169         if (current_el() != 3) {
170                 /* call sip */
171                 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_EXIT, 0, 0, 0, 0, 0, 0, &res);
172                 return (enum hab_status)res.a0;
173         }
174 #endif
175
176         save_gd();
177         ret = hab_rvt_exit_func();
178         restore_gd();
179
180         return ret;
181 }
182
183 void hab_rvt_failsafe(void)
184 {
185         hab_rvt_failsafe_t *hab_rvt_failsafe_func;
186
187         hab_rvt_failsafe_func = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE;
188 #if defined(CONFIG_ARM64)
189         if (current_el() != 3) {
190                 /* call sip */
191                 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_FAILSAFE, 0, 0, 0, 0, 0, 0, NULL);
192                 return;
193         }
194 #endif
195
196         save_gd();
197         hab_rvt_failsafe_func();
198         restore_gd();
199 }
200
201 enum hab_status hab_rvt_check_target(enum hab_target type, const void *start,
202                                                size_t bytes)
203 {
204         enum hab_status ret;
205         hab_rvt_check_target_t *hab_rvt_check_target_func;
206         struct arm_smccc_res res __maybe_unused;
207
208         hab_rvt_check_target_func =  (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET;
209 #if defined(CONFIG_ARM64)
210         if (current_el() != 3) {
211                 /* call sip */
212                 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_CHECK_TARGET, (unsigned long)type,
213                               (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
214                 return (enum hab_status)res.a0;
215         }
216 #endif
217
218         save_gd();
219         ret = hab_rvt_check_target_func(type, start, bytes);
220         restore_gd();
221
222         return ret;
223 }
224
225 void *hab_rvt_authenticate_image(uint8_t cid, ptrdiff_t ivt_offset,
226                                  void **start, size_t *bytes, hab_loader_callback_f_t loader)
227 {
228         void *ret;
229         hab_rvt_authenticate_image_t *hab_rvt_authenticate_image_func;
230         struct arm_smccc_res res __maybe_unused;
231
232         hab_rvt_authenticate_image_func = (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
233 #if defined(CONFIG_ARM64)
234         if (current_el() != 3) {
235                 /* call sip */
236                 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset,
237                               (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
238                 return (void *)res.a0;
239         }
240 #endif
241
242         save_gd();
243         ret = hab_rvt_authenticate_image_func(cid, ivt_offset, start, bytes, loader);
244         restore_gd();
245
246         return ret;
247 }
248
249 #if !defined(CONFIG_SPL_BUILD)
250
251 #define MAX_RECORD_BYTES     (8*1024) /* 4 kbytes */
252
253 struct record {
254         uint8_t  tag;                                           /* Tag */
255         uint8_t  len[2];                                        /* Length */
256         uint8_t  par;                                           /* Version */
257         uint8_t  contents[MAX_RECORD_BYTES];/* Record Data */
258         bool     any_rec_flag;
259 };
260
261 static char *rsn_str[] = {
262                           "RSN = HAB_RSN_ANY (0x00)\n",
263                           "RSN = HAB_ENG_FAIL (0x30)\n",
264                           "RSN = HAB_INV_ADDRESS (0x22)\n",
265                           "RSN = HAB_INV_ASSERTION (0x0C)\n",
266                           "RSN = HAB_INV_CALL (0x28)\n",
267                           "RSN = HAB_INV_CERTIFICATE (0x21)\n",
268                           "RSN = HAB_INV_COMMAND (0x06)\n",
269                           "RSN = HAB_INV_CSF (0x11)\n",
270                           "RSN = HAB_INV_DCD (0x27)\n",
271                           "RSN = HAB_INV_INDEX (0x0F)\n",
272                           "RSN = HAB_INV_IVT (0x05)\n",
273                           "RSN = HAB_INV_KEY (0x1D)\n",
274                           "RSN = HAB_INV_RETURN (0x1E)\n",
275                           "RSN = HAB_INV_SIGNATURE (0x18)\n",
276                           "RSN = HAB_INV_SIZE (0x17)\n",
277                           "RSN = HAB_MEM_FAIL (0x2E)\n",
278                           "RSN = HAB_OVR_COUNT (0x2B)\n",
279                           "RSN = HAB_OVR_STORAGE (0x2D)\n",
280                           "RSN = HAB_UNS_ALGORITHM (0x12)\n",
281                           "RSN = HAB_UNS_COMMAND (0x03)\n",
282                           "RSN = HAB_UNS_ENGINE (0x0A)\n",
283                           "RSN = HAB_UNS_ITEM (0x24)\n",
284                           "RSN = HAB_UNS_KEY (0x1B)\n",
285                           "RSN = HAB_UNS_PROTOCOL (0x14)\n",
286                           "RSN = HAB_UNS_STATE (0x09)\n",
287                           "RSN = INVALID\n",
288                           NULL
289 };
290
291 static char *sts_str[] = {
292                           "STS = HAB_SUCCESS (0xF0)\n",
293                           "STS = HAB_FAILURE (0x33)\n",
294                           "STS = HAB_WARNING (0x69)\n",
295                           "STS = INVALID\n",
296                           NULL
297 };
298
299 static char *eng_str[] = {
300                           "ENG = HAB_ENG_ANY (0x00)\n",
301                           "ENG = HAB_ENG_SCC (0x03)\n",
302                           "ENG = HAB_ENG_RTIC (0x05)\n",
303                           "ENG = HAB_ENG_SAHARA (0x06)\n",
304                           "ENG = HAB_ENG_CSU (0x0A)\n",
305                           "ENG = HAB_ENG_SRTC (0x0C)\n",
306                           "ENG = HAB_ENG_DCP (0x1B)\n",
307                           "ENG = HAB_ENG_CAAM (0x1D)\n",
308                           "ENG = HAB_ENG_SNVS (0x1E)\n",
309                           "ENG = HAB_ENG_OCOTP (0x21)\n",
310                           "ENG = HAB_ENG_DTCP (0x22)\n",
311                           "ENG = HAB_ENG_ROM (0x36)\n",
312                           "ENG = HAB_ENG_HDCP (0x24)\n",
313                           "ENG = HAB_ENG_RTL (0x77)\n",
314                           "ENG = HAB_ENG_SW (0xFF)\n",
315                           "ENG = INVALID\n",
316                           NULL
317 };
318
319 static char *ctx_str[] = {
320                           "CTX = HAB_CTX_ANY(0x00)\n",
321                           "CTX = HAB_CTX_FAB (0xFF)\n",
322                           "CTX = HAB_CTX_ENTRY (0xE1)\n",
323                           "CTX = HAB_CTX_TARGET (0x33)\n",
324                           "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
325                           "CTX = HAB_CTX_DCD (0xDD)\n",
326                           "CTX = HAB_CTX_CSF (0xCF)\n",
327                           "CTX = HAB_CTX_COMMAND (0xC0)\n",
328                           "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
329                           "CTX = HAB_CTX_ASSERT (0xA0)\n",
330                           "CTX = HAB_CTX_EXIT (0xEE)\n",
331                           "CTX = INVALID\n",
332                           NULL
333 };
334
335 static uint8_t hab_statuses[5] = {
336         HAB_STS_ANY,
337         HAB_FAILURE,
338         HAB_WARNING,
339         HAB_SUCCESS,
340         -1
341 };
342
343 static uint8_t hab_reasons[26] = {
344         HAB_RSN_ANY,
345         HAB_ENG_FAIL,
346         HAB_INV_ADDRESS,
347         HAB_INV_ASSERTION,
348         HAB_INV_CALL,
349         HAB_INV_CERTIFICATE,
350         HAB_INV_COMMAND,
351         HAB_INV_CSF,
352         HAB_INV_DCD,
353         HAB_INV_INDEX,
354         HAB_INV_IVT,
355         HAB_INV_KEY,
356         HAB_INV_RETURN,
357         HAB_INV_SIGNATURE,
358         HAB_INV_SIZE,
359         HAB_MEM_FAIL,
360         HAB_OVR_COUNT,
361         HAB_OVR_STORAGE,
362         HAB_UNS_ALGORITHM,
363         HAB_UNS_COMMAND,
364         HAB_UNS_ENGINE,
365         HAB_UNS_ITEM,
366         HAB_UNS_KEY,
367         HAB_UNS_PROTOCOL,
368         HAB_UNS_STATE,
369         -1
370 };
371
372 static uint8_t hab_contexts[12] = {
373         HAB_CTX_ANY,
374         HAB_CTX_FAB,
375         HAB_CTX_ENTRY,
376         HAB_CTX_TARGET,
377         HAB_CTX_AUTHENTICATE,
378         HAB_CTX_DCD,
379         HAB_CTX_CSF,
380         HAB_CTX_COMMAND,
381         HAB_CTX_AUT_DAT,
382         HAB_CTX_ASSERT,
383         HAB_CTX_EXIT,
384         -1
385 };
386
387 static uint8_t hab_engines[16] = {
388         HAB_ENG_ANY,
389         HAB_ENG_SCC,
390         HAB_ENG_RTIC,
391         HAB_ENG_SAHARA,
392         HAB_ENG_CSU,
393         HAB_ENG_SRTC,
394         HAB_ENG_DCP,
395         HAB_ENG_CAAM,
396         HAB_ENG_SNVS,
397         HAB_ENG_OCOTP,
398         HAB_ENG_DTCP,
399         HAB_ENG_ROM,
400         HAB_ENG_HDCP,
401         HAB_ENG_RTL,
402         HAB_ENG_SW,
403         -1
404 };
405
406 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
407 {
408         uint8_t idx = 0;
409         uint8_t element = list[idx];
410         while (element != -1) {
411                 if (element == tgt)
412                         return idx;
413                 element = list[++idx];
414         }
415         return -1;
416 }
417
418 static void process_event_record(uint8_t *event_data, size_t bytes)
419 {
420         struct record *rec = (struct record *)event_data;
421
422         printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
423         printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
424         printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
425         printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
426 }
427
428 static void display_event(uint8_t *event_data, size_t bytes)
429 {
430         uint32_t i;
431
432         if (!(event_data && bytes > 0))
433                 return;
434
435         for (i = 0; i < bytes; i++) {
436                 if (i == 0)
437                         printf("\t0x%02x", event_data[i]);
438                 else if ((i % 8) == 0)
439                         printf("\n\t0x%02x", event_data[i]);
440                 else
441                         printf(" 0x%02x", event_data[i]);
442         }
443
444         process_event_record(event_data, bytes);
445 }
446
447 static int get_hab_status(void)
448 {
449         uint32_t index = 0; /* Loop index */
450         uint8_t event_data[128]; /* Event data buffer */
451         size_t bytes = sizeof(event_data); /* Event size in bytes */
452         enum hab_config config = 0;
453         enum hab_state state = 0;
454
455         if (imx_hab_is_enabled())
456                 puts("\nSecure boot enabled\n");
457         else
458                 puts("\nSecure boot disabled\n");
459
460         /* Check HAB status */
461         if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) {
462                 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
463                        config, state);
464
465                 /* Display HAB events */
466                 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
467                                         &bytes) == HAB_SUCCESS) {
468                         puts("\n");
469                         printf("--------- HAB Event %d -----------------\n",
470                                index + 1);
471                         puts("event data:\n");
472                         display_event(event_data, bytes);
473                         puts("\n");
474                         bytes = sizeof(event_data);
475                         index++;
476                 }
477         }
478         /* Display message if no HAB events are found */
479         else {
480                 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
481                        config, state);
482                 puts("No HAB Events Found!\n\n");
483         }
484         return 0;
485 }
486
487 #ifdef CONFIG_MX7ULP
488
489 static int get_record_len(struct record *rec)
490 {
491         return (size_t)((rec->len[0] << 8) + (rec->len[1]));
492 }
493
494 static int get_hab_status_m4(void)
495 {
496         unsigned int index = 0;
497         uint8_t event_data[128];
498         size_t record_len, offset = 0;
499         enum hab_config config = 0;
500         enum hab_state state = 0;
501
502         if (imx_hab_is_enabled())
503                 puts("\nSecure boot enabled\n");
504         else
505                 puts("\nSecure boot disabled\n");
506
507         /*
508          * HAB in both A7 and M4 gather the security state
509          * and configuration of the chip from
510          * shared SNVS module
511          */
512         hab_rvt_report_status(&config, &state);
513         printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
514                config, state);
515
516         struct record *rec = (struct record *)(HAB_M4_PERSISTENT_START);
517
518         record_len = get_record_len(rec);
519
520         /* Check if HAB persistent memory is valid */
521         if (rec->tag != HAB_TAG_EVT_DEF ||
522             record_len != sizeof(struct evt_def) ||
523             (rec->par & HAB_MAJ_MASK) != HAB_MAJ_VER) {
524                 puts("\nERROR: Invalid HAB persistent memory\n");
525                 return 1;
526         }
527
528         /* Parse events in HAB M4 persistent memory region */
529         while (offset < HAB_M4_PERSISTENT_BYTES) {
530                 rec = (struct record *)(HAB_M4_PERSISTENT_START + offset);
531
532                 record_len = get_record_len(rec);
533
534                 if (rec->tag == HAB_TAG_EVT) {
535                         memcpy(&event_data, rec, record_len);
536                         puts("\n");
537                         printf("--------- HAB Event %d -----------------\n",
538                                index + 1);
539                         puts("event data:\n");
540                         display_event(event_data, record_len);
541                         puts("\n");
542                         index++;
543                 }
544
545                 offset += record_len;
546
547                 /* Ensure all records start on a word boundary */
548                 if ((offset % 4) != 0)
549                         offset =  offset + (4 - (offset % 4));
550         }
551
552         if (!index)
553                 puts("No HAB Events Found!\n\n");
554
555         return 0;
556 }
557 #endif
558
559 static int do_hab_status(struct cmd_tbl *cmdtp, int flag, int argc,
560                          char *const argv[])
561 {
562 #ifdef CONFIG_MX7ULP
563         if ((argc > 2)) {
564                 cmd_usage(cmdtp);
565                 return 1;
566         }
567
568         if (strcmp("m4", argv[1]) == 0)
569                 get_hab_status_m4();
570         else
571                 get_hab_status();
572 #else
573         if ((argc != 1)) {
574                 cmd_usage(cmdtp);
575                 return 1;
576         }
577
578         get_hab_status();
579 #endif
580
581         return 0;
582 }
583
584 static ulong get_image_ivt_offset(ulong img_addr)
585 {
586         const void *buf;
587
588         buf = map_sysmem(img_addr, 0);
589         switch (genimg_get_format(buf)) {
590 #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
591         case IMAGE_FORMAT_LEGACY:
592                 return (image_get_image_size((struct legacy_img_hdr *)img_addr)
593                         + 0x1000 - 1)  & ~(0x1000 - 1);
594 #endif
595 #if CONFIG_IS_ENABLED(FIT)
596         case IMAGE_FORMAT_FIT:
597                 return (fit_get_size(buf) + 0x1000 - 1)  & ~(0x1000 - 1);
598 #endif
599         default:
600                 return 0;
601         }
602 }
603
604 static int do_authenticate_image(struct cmd_tbl *cmdtp, int flag, int argc,
605                                  char *const argv[])
606 {
607         ulong   addr, length, ivt_offset;
608         int     rcode = 0;
609
610         if (argc < 3)
611                 return CMD_RET_USAGE;
612
613         addr = hextoul(argv[1], NULL);
614         length = hextoul(argv[2], NULL);
615         if (argc == 3)
616                 ivt_offset = get_image_ivt_offset(addr);
617         else
618                 ivt_offset = hextoul(argv[3], NULL);
619
620         rcode = imx_hab_authenticate_image(addr, length, ivt_offset);
621         if (rcode == 0)
622                 rcode = CMD_RET_SUCCESS;
623         else
624                 rcode = CMD_RET_FAILURE;
625
626         return rcode;
627 }
628
629 static int do_hab_failsafe(struct cmd_tbl *cmdtp, int flag, int argc,
630                            char *const argv[])
631 {
632         if (argc != 1) {
633                 cmd_usage(cmdtp);
634                 return 1;
635         }
636
637         hab_rvt_failsafe();
638
639         return 0;
640 }
641
642 static int do_hab_version(struct cmd_tbl *cmdtp, int flag, int argc,
643                           char *const argv[])
644 {
645         struct hab_hdr *hdr = (struct hab_hdr *)HAB_RVT_BASE;
646
647         if (hdr->tag != HAB_TAG_RVT) {
648                 printf("Unexpected header tag: %x\n", hdr->tag);
649                 return CMD_RET_FAILURE;
650         }
651
652         printf("HAB version: %d.%d\n", hdr->par >> 4, hdr->par & 0xf);
653
654         return 0;
655 }
656
657 static int do_authenticate_image_or_failover(struct cmd_tbl *cmdtp, int flag,
658                                              int argc, char *const argv[])
659 {
660         int ret = CMD_RET_FAILURE;
661
662         if (argc != 4) {
663                 ret = CMD_RET_USAGE;
664                 goto error;
665         }
666
667         if (!imx_hab_is_enabled()) {
668                 printf("error: secure boot disabled\n");
669                 goto error;
670         }
671
672         if (do_authenticate_image(NULL, flag, argc, argv) != CMD_RET_SUCCESS) {
673                 fprintf(stderr, "authentication fail -> %s %s %s %s\n",
674                         argv[0], argv[1], argv[2], argv[3]);
675                 do_hab_failsafe(0, 0, 1, NULL);
676         };
677         ret = CMD_RET_SUCCESS;
678 error:
679         return ret;
680 }
681
682 #ifdef CONFIG_MX7ULP
683 U_BOOT_CMD(
684                 hab_status, CONFIG_SYS_MAXARGS, 2, do_hab_status,
685                 "display HAB status and events",
686                 "hab_status - A7 HAB event and status\n"
687                 "hab_status m4 - M4 HAB event and status"
688           );
689 #else
690 U_BOOT_CMD(
691                 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
692                 "display HAB status",
693                 ""
694           );
695 #endif
696
697 U_BOOT_CMD(
698                 hab_auth_img, 4, 0, do_authenticate_image,
699                 "authenticate image via HAB",
700                 "addr length ivt_offset\n"
701                 "addr - image hex address\n"
702                 "length - image hex length\n"
703                 "ivt_offset - hex offset of IVT in the image"
704           );
705
706 U_BOOT_CMD(
707                 hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe,
708                 "run BootROM failsafe routine",
709                 ""
710           );
711
712 U_BOOT_CMD(
713                 hab_auth_img_or_fail, 4, 0,
714                 do_authenticate_image_or_failover,
715                 "authenticate image via HAB on failure drop to USB BootROM mode",
716                 "addr length ivt_offset\n"
717                 "addr - image hex address\n"
718                 "length - image hex length\n"
719                 "ivt_offset - hex offset of IVT in the image"
720           );
721
722 U_BOOT_CMD(
723                 hab_version, 1, 0, do_hab_version,
724                 "print HAB major/minor version",
725                 ""
726           );
727
728 #endif /* !defined(CONFIG_SPL_BUILD) */
729
730 /* Get CSF Header length */
731 static int get_hab_hdr_len(struct hab_hdr *hdr)
732 {
733         return (size_t)((hdr->len[0] << 8) + (hdr->len[1]));
734 }
735
736 /* Check whether addr lies between start and
737  * end and is within the length of the image
738  */
739 static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end)
740 {
741         size_t csf_size = (size_t)((end + 1) - addr);
742
743         return (addr && (addr >= start) && (addr <= end) &&
744                 (csf_size >= bytes));
745 }
746
747 /* Get Length of each command in CSF */
748 static int get_csf_cmd_hdr_len(u8 *csf_hdr)
749 {
750         if (*csf_hdr == HAB_CMD_HDR)
751                 return sizeof(struct hab_hdr);
752
753         return get_hab_hdr_len((struct hab_hdr *)csf_hdr);
754 }
755
756 /* Check if CSF is valid */
757 static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes)
758 {
759         u8 *start = (u8 *)start_addr;
760         u8 *csf_hdr;
761         u8 *end;
762
763         size_t csf_hdr_len;
764         size_t cmd_hdr_len;
765         size_t offset = 0;
766
767         if (bytes != 0)
768                 end = start + bytes - 1;
769         else
770                 end = start;
771
772         /* Verify if CSF pointer content is zero */
773         if (!ivt->csf) {
774                 puts("Error: CSF pointer is NULL\n");
775                 return false;
776         }
777
778         csf_hdr = (u8 *)(ulong)ivt->csf;
779
780         /* Verify if CSF Header exist */
781         if (*csf_hdr != HAB_CMD_HDR) {
782                 puts("Error: CSF header command not found\n");
783                 return false;
784         }
785
786         csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr);
787
788         /* Check if the CSF lies within the image bounds */
789         if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) {
790                 puts("Error: CSF lies outside the image bounds\n");
791                 return false;
792         }
793
794         do {
795                 struct hab_hdr *cmd;
796
797                 cmd = (struct hab_hdr *)&csf_hdr[offset];
798
799                 switch (cmd->tag) {
800                 case (HAB_CMD_WRT_DAT):
801                         puts("Error: Deprecated write command found\n");
802                         return false;
803                 case (HAB_CMD_CHK_DAT):
804                         puts("Error: Deprecated check command found\n");
805                         return false;
806                 case (HAB_CMD_SET):
807                         if (cmd->par == HAB_PAR_MID) {
808                                 puts("Error: Deprecated Set MID command found\n");
809                                 return false;
810                         }
811                 default:
812                         break;
813                 }
814
815                 cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]);
816                 if (!cmd_hdr_len) {
817                         puts("Error: Invalid command length\n");
818                         return false;
819                 }
820                 offset += cmd_hdr_len;
821
822         } while (offset < csf_hdr_len);
823
824         return true;
825 }
826
827 /*
828  * Validate IVT structure of the image being authenticated
829  */
830 static int validate_ivt(struct ivt *ivt_initial)
831 {
832         struct ivt_header *ivt_hdr = &ivt_initial->hdr;
833
834         if ((ulong)ivt_initial & 0x3) {
835                 puts("Error: Image's start address is not 4 byte aligned\n");
836                 return 0;
837         }
838
839         /* Check IVT fields before allowing authentication */
840         if ((!verify_ivt_header(ivt_hdr)) && \
841             (ivt_initial->entry != 0x0) && \
842             (ivt_initial->reserved1 == 0x0) && \
843             (ivt_initial->self == \
844                    (uint32_t)((ulong)ivt_initial & 0xffffffff)) && \
845             (ivt_initial->csf != 0x0) && \
846             (ivt_initial->reserved2 == 0x0)) {
847                 /* Report boot failure if DCD pointer is found in IVT */
848                 if (ivt_initial->dcd != 0x0)
849                         puts("Error: DCD pointer must be 0\n");
850                 else
851                         return 1;
852         }
853
854         puts("Error: Invalid IVT structure\n");
855         debug("\nAllowed IVT structure:\n");
856         debug("IVT HDR       = 0x4X2000D1\n");
857         debug("IVT ENTRY     = 0xXXXXXXXX\n");
858         debug("IVT RSV1      = 0x0\n");
859         debug("IVT DCD       = 0x0\n");         /* Recommended */
860         debug("IVT BOOT_DATA = 0xXXXXXXXX\n");  /* Commonly 0x0 */
861         debug("IVT SELF      = 0xXXXXXXXX\n");  /* = ddr_start + ivt_offset */
862         debug("IVT CSF       = 0xXXXXXXXX\n");
863         debug("IVT RSV2      = 0x0\n");
864
865         /* Invalid IVT structure */
866         return 0;
867 }
868
869 bool imx_hab_is_enabled(void)
870 {
871         struct imx_sec_config_fuse_t *fuse =
872                 (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
873         uint32_t reg;
874         int ret;
875
876         ret = fuse_read(fuse->bank, fuse->word, &reg);
877         if (ret) {
878                 puts("\nSecure boot fuse read error\n");
879                 return ret;
880         }
881
882         return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
883 }
884
885 int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
886                                uint32_t ivt_offset)
887 {
888         ulong load_addr = 0;
889         size_t bytes;
890         ulong ivt_addr = 0;
891         int result = 1;
892         ulong start;
893         struct ivt *ivt;
894         enum hab_status status;
895
896         if (!imx_hab_is_enabled())
897                 puts("hab fuse not enabled\n");
898
899         printf("\nAuthenticate image from DDR location 0x%x...\n",
900                ddr_start);
901
902         hab_caam_clock_enable(1);
903
904         /* Calculate IVT address header */
905         ivt_addr = (ulong) (ddr_start + ivt_offset);
906         ivt = (struct ivt *)ivt_addr;
907
908         /* Verify IVT header bugging out on error */
909         if (!validate_ivt(ivt))
910                 goto hab_authentication_exit;
911
912         start = ddr_start;
913         bytes = image_size;
914
915         /* Verify CSF */
916         if (!csf_is_valid(ivt, start, bytes))
917                 goto hab_authentication_exit;
918
919         if (hab_rvt_entry() != HAB_SUCCESS) {
920                 puts("hab entry function fail\n");
921                 goto hab_exit_failure_print_status;
922         }
923
924         status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes);
925         if (status != HAB_SUCCESS) {
926                 printf("HAB check target 0x%08x-0x%08lx fail\n",
927                        ddr_start, ddr_start + (ulong)bytes);
928                 goto hab_exit_failure_print_status;
929         }
930 #ifdef DEBUG
931         printf("\nivt_offset = 0x%x, ivt addr = 0x%lx\n", ivt_offset, ivt_addr);
932         printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry,
933                ivt->dcd, ivt->csf);
934         puts("Dumping IVT\n");
935         print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0);
936
937         puts("Dumping CSF Header\n");
938         print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0);
939
940 #if  !defined(CONFIG_SPL_BUILD)
941         get_hab_status();
942 #endif
943
944         puts("\nCalling authenticate_image in ROM\n");
945         printf("\tivt_offset = 0x%x\n", ivt_offset);
946         printf("\tstart = 0x%08lx\n", start);
947         printf("\tbytes = 0x%x\n", bytes);
948 #endif
949
950 #ifndef CONFIG_ARM64
951         /*
952          * If the MMU is enabled, we have to notify the ROM
953          * code, or it won't flush the caches when needed.
954          * This is done, by setting the "pu_irom_mmu_enabled"
955          * word to 1. You can find its address by looking in
956          * the ROM map. This is critical for
957          * authenticate_image(). If MMU is enabled, without
958          * setting this bit, authentication will fail and may
959          * crash.
960          */
961         /* Check MMU enabled */
962         if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
963                 if (is_mx6dq()) {
964                         /*
965                          * This won't work on Rev 1.0.0 of
966                          * i.MX6Q/D, since their ROM doesn't
967                          * do cache flushes. don't think any
968                          * exist, so we ignore them.
969                          */
970                         if (!is_mx6dqp())
971                                 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
972                 } else if (is_mx6sdl()) {
973                         writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
974                 } else if (is_mx6sl()) {
975                         writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
976                 }
977         }
978 #endif
979
980         load_addr = (ulong)hab_rvt_authenticate_image(
981                         HAB_CID_UBOOT,
982                         ivt_offset, (void **)&start,
983                         (size_t *)&bytes, NULL);
984         if (hab_rvt_exit() != HAB_SUCCESS) {
985                 puts("hab exit function fail\n");
986                 load_addr = 0;
987         }
988
989 hab_exit_failure_print_status:
990 #if !defined(CONFIG_SPL_BUILD)
991         get_hab_status();
992 #endif
993
994 hab_authentication_exit:
995
996         if (load_addr != 0 || !imx_hab_is_enabled())
997                 result = 0;
998
999         return result;
1000 }
1001
1002 int authenticate_image(u32 ddr_start, u32 raw_image_size)
1003 {
1004         u32 ivt_offset;
1005         size_t bytes;
1006
1007         ivt_offset = (raw_image_size + ALIGN_SIZE - 1) &
1008                                         ~(ALIGN_SIZE - 1);
1009         bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
1010
1011         return imx_hab_authenticate_image(ddr_start, bytes, ivt_offset);
1012 }