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
21DECLARE_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
37static 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
45static 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
70static volatile gd_t *gd_save;
71#endif
72
73static inline void save_gd(void)
74{
75#ifdef CONFIG_ARM64
76	gd_save = gd;
77#endif
78}
79
80static 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
91enum 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
116enum 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
139enum 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
161enum 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
183void 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
201enum 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
225void *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
253struct 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
261static 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
291static char *sts_str[] = {
292			  "STS = HAB_STS_ANY (0x00)\n",
293			  "STS = HAB_FAILURE (0x33)\n",
294			  "STS = HAB_WARNING (0x69)\n",
295			  "STS = HAB_SUCCESS (0xF0)\n",
296			  "STS = INVALID\n",
297			  NULL
298};
299
300static char *eng_str[] = {
301			  "ENG = HAB_ENG_ANY (0x00)\n",
302			  "ENG = HAB_ENG_SCC (0x03)\n",
303			  "ENG = HAB_ENG_RTIC (0x05)\n",
304			  "ENG = HAB_ENG_SAHARA (0x06)\n",
305			  "ENG = HAB_ENG_CSU (0x0A)\n",
306			  "ENG = HAB_ENG_SRTC (0x0C)\n",
307			  "ENG = HAB_ENG_DCP (0x1B)\n",
308			  "ENG = HAB_ENG_CAAM (0x1D)\n",
309			  "ENG = HAB_ENG_SNVS (0x1E)\n",
310			  "ENG = HAB_ENG_OCOTP (0x21)\n",
311			  "ENG = HAB_ENG_DTCP (0x22)\n",
312			  "ENG = HAB_ENG_ROM (0x36)\n",
313			  "ENG = HAB_ENG_HDCP (0x24)\n",
314			  "ENG = HAB_ENG_RTL (0x77)\n",
315			  "ENG = HAB_ENG_SW (0xFF)\n",
316			  "ENG = INVALID\n",
317			  NULL
318};
319
320static char *ctx_str[] = {
321			  "CTX = HAB_CTX_ANY(0x00)\n",
322			  "CTX = HAB_CTX_FAB (0xFF)\n",
323			  "CTX = HAB_CTX_ENTRY (0xE1)\n",
324			  "CTX = HAB_CTX_TARGET (0x33)\n",
325			  "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
326			  "CTX = HAB_CTX_DCD (0xDD)\n",
327			  "CTX = HAB_CTX_CSF (0xCF)\n",
328			  "CTX = HAB_CTX_COMMAND (0xC0)\n",
329			  "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
330			  "CTX = HAB_CTX_ASSERT (0xA0)\n",
331			  "CTX = HAB_CTX_EXIT (0xEE)\n",
332			  "CTX = INVALID\n",
333			  NULL
334};
335
336static uint8_t hab_statuses[5] = {
337	HAB_STS_ANY,
338	HAB_FAILURE,
339	HAB_WARNING,
340	HAB_SUCCESS
341};
342
343static 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};
370
371static uint8_t hab_contexts[12] = {
372	HAB_CTX_ANY,
373	HAB_CTX_FAB,
374	HAB_CTX_ENTRY,
375	HAB_CTX_TARGET,
376	HAB_CTX_AUTHENTICATE,
377	HAB_CTX_DCD,
378	HAB_CTX_CSF,
379	HAB_CTX_COMMAND,
380	HAB_CTX_AUT_DAT,
381	HAB_CTX_ASSERT,
382	HAB_CTX_EXIT
383};
384
385static uint8_t hab_engines[16] = {
386	HAB_ENG_ANY,
387	HAB_ENG_SCC,
388	HAB_ENG_RTIC,
389	HAB_ENG_SAHARA,
390	HAB_ENG_CSU,
391	HAB_ENG_SRTC,
392	HAB_ENG_DCP,
393	HAB_ENG_CAAM,
394	HAB_ENG_SNVS,
395	HAB_ENG_OCOTP,
396	HAB_ENG_DTCP,
397	HAB_ENG_ROM,
398	HAB_ENG_HDCP,
399	HAB_ENG_RTL,
400	HAB_ENG_SW
401};
402
403static inline u32 get_idx(u8 *list, u8 tgt, u32 size)
404{
405	u32 idx = 0;
406	u8 element;
407
408	while (idx < size) {
409		element = list[idx];
410		if (element == tgt)
411			return idx;
412		++idx;
413	}
414	return idx;
415}
416
417static void process_event_record(uint8_t *event_data, size_t bytes)
418{
419	struct record *rec = (struct record *)event_data;
420
421	printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0],
422	       ARRAY_SIZE(hab_statuses))]);
423	printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1],
424	       ARRAY_SIZE(hab_reasons))]);
425	printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2],
426	       ARRAY_SIZE(hab_contexts))]);
427	printf("%s", eng_str[get_idx(hab_engines, rec->contents[3],
428	       ARRAY_SIZE(hab_engines))]);
429}
430
431static void display_event(uint8_t *event_data, size_t bytes)
432{
433	uint32_t i;
434
435	if (!(event_data && bytes > 0))
436		return;
437
438	for (i = 0; i < bytes; i++) {
439		if (i == 0)
440			printf("\t0x%02x", event_data[i]);
441		else if ((i % 8) == 0)
442			printf("\n\t0x%02x", event_data[i]);
443		else
444			printf(" 0x%02x", event_data[i]);
445	}
446
447	process_event_record(event_data, bytes);
448}
449
450static int get_hab_status(void)
451{
452	uint32_t index = 0; /* Loop index */
453	uint8_t event_data[128]; /* Event data buffer */
454	size_t bytes = sizeof(event_data); /* Event size in bytes */
455	enum hab_config config = 0;
456	enum hab_state state = 0;
457
458	if (imx_hab_is_enabled())
459		puts("\nSecure boot enabled\n");
460	else
461		puts("\nSecure boot disabled\n");
462
463	/* Check HAB status */
464	if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) {
465		printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
466		       config, state);
467
468		/* Display HAB events */
469		while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
470					&bytes) == HAB_SUCCESS) {
471			puts("\n");
472			printf("--------- HAB Event %d -----------------\n",
473			       index + 1);
474			puts("event data:\n");
475			display_event(event_data, bytes);
476			puts("\n");
477			bytes = sizeof(event_data);
478			index++;
479		}
480	}
481	/* Display message if no HAB events are found */
482	else {
483		printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
484		       config, state);
485		puts("No HAB Events Found!\n\n");
486	}
487	return 0;
488}
489
490#ifdef CONFIG_MX7ULP
491
492static int get_record_len(struct record *rec)
493{
494	return (size_t)((rec->len[0] << 8) + (rec->len[1]));
495}
496
497static int get_hab_status_m4(void)
498{
499	unsigned int index = 0;
500	uint8_t event_data[128];
501	size_t record_len, offset = 0;
502	enum hab_config config = 0;
503	enum hab_state state = 0;
504
505	if (imx_hab_is_enabled())
506		puts("\nSecure boot enabled\n");
507	else
508		puts("\nSecure boot disabled\n");
509
510	/*
511	 * HAB in both A7 and M4 gather the security state
512	 * and configuration of the chip from
513	 * shared SNVS module
514	 */
515	hab_rvt_report_status(&config, &state);
516	printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
517	       config, state);
518
519	struct record *rec = (struct record *)(HAB_M4_PERSISTENT_START);
520
521	record_len = get_record_len(rec);
522
523	/* Check if HAB persistent memory is valid */
524	if (rec->tag != HAB_TAG_EVT_DEF ||
525	    record_len != sizeof(struct evt_def) ||
526	    (rec->par & HAB_MAJ_MASK) != HAB_MAJ_VER) {
527		puts("\nERROR: Invalid HAB persistent memory\n");
528		return 1;
529	}
530
531	/* Parse events in HAB M4 persistent memory region */
532	while (offset < HAB_M4_PERSISTENT_BYTES) {
533		rec = (struct record *)(HAB_M4_PERSISTENT_START + offset);
534
535		record_len = get_record_len(rec);
536
537		if (rec->tag == HAB_TAG_EVT) {
538			memcpy(&event_data, rec, record_len);
539			puts("\n");
540			printf("--------- HAB Event %d -----------------\n",
541			       index + 1);
542			puts("event data:\n");
543			display_event(event_data, record_len);
544			puts("\n");
545			index++;
546		}
547
548		offset += record_len;
549
550		/* Ensure all records start on a word boundary */
551		if ((offset % 4) != 0)
552			offset =  offset + (4 - (offset % 4));
553	}
554
555	if (!index)
556		puts("No HAB Events Found!\n\n");
557
558	return 0;
559}
560#endif
561
562static int do_hab_status(struct cmd_tbl *cmdtp, int flag, int argc,
563			 char *const argv[])
564{
565#ifdef CONFIG_MX7ULP
566	if ((argc > 2)) {
567		cmd_usage(cmdtp);
568		return 1;
569	}
570
571	if (strcmp("m4", argv[1]) == 0)
572		get_hab_status_m4();
573	else
574		get_hab_status();
575#else
576	if ((argc != 1)) {
577		cmd_usage(cmdtp);
578		return 1;
579	}
580
581	get_hab_status();
582#endif
583
584	return 0;
585}
586
587static ulong get_image_ivt_offset(ulong img_addr)
588{
589	const void *buf;
590
591	buf = map_sysmem(img_addr, 0);
592	switch (genimg_get_format(buf)) {
593#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
594	case IMAGE_FORMAT_LEGACY:
595		return (image_get_image_size((struct legacy_img_hdr *)img_addr)
596			+ 0x1000 - 1)  & ~(0x1000 - 1);
597#endif
598#if CONFIG_IS_ENABLED(FIT)
599	case IMAGE_FORMAT_FIT:
600		return (fit_get_size(buf) + 0x1000 - 1)  & ~(0x1000 - 1);
601#endif
602	default:
603		return 0;
604	}
605}
606
607static int do_authenticate_image(struct cmd_tbl *cmdtp, int flag, int argc,
608				 char *const argv[])
609{
610	ulong	addr, length, ivt_offset;
611	int	rcode = 0;
612
613	if (argc < 3)
614		return CMD_RET_USAGE;
615
616	addr = hextoul(argv[1], NULL);
617	length = hextoul(argv[2], NULL);
618	if (argc == 3)
619		ivt_offset = get_image_ivt_offset(addr);
620	else
621		ivt_offset = hextoul(argv[3], NULL);
622
623	rcode = imx_hab_authenticate_image(addr, length, ivt_offset);
624	if (rcode == 0)
625		rcode = CMD_RET_SUCCESS;
626	else
627		rcode = CMD_RET_FAILURE;
628
629	return rcode;
630}
631
632static int do_hab_failsafe(struct cmd_tbl *cmdtp, int flag, int argc,
633			   char *const argv[])
634{
635	if (argc != 1) {
636		cmd_usage(cmdtp);
637		return 1;
638	}
639
640	hab_rvt_failsafe();
641
642	return 0;
643}
644
645static int do_hab_version(struct cmd_tbl *cmdtp, int flag, int argc,
646			  char *const argv[])
647{
648	struct hab_hdr *hdr = (struct hab_hdr *)HAB_RVT_BASE;
649
650	if (hdr->tag != HAB_TAG_RVT) {
651		printf("Unexpected header tag: %x\n", hdr->tag);
652		return CMD_RET_FAILURE;
653	}
654
655	printf("HAB version: %d.%d\n", hdr->par >> 4, hdr->par & 0xf);
656
657	return 0;
658}
659
660static int do_authenticate_image_or_failover(struct cmd_tbl *cmdtp, int flag,
661					     int argc, char *const argv[])
662{
663	int ret = CMD_RET_FAILURE;
664
665	if (argc < 3) {
666		ret = CMD_RET_USAGE;
667		goto error;
668	}
669
670	if (!imx_hab_is_enabled()) {
671		printf("error: secure boot disabled\n");
672		goto error;
673	}
674
675	if (do_authenticate_image(NULL, flag, argc, argv) != CMD_RET_SUCCESS) {
676		fprintf(stderr, "authentication fail -> %s %s %s %s\n",
677			argv[0], argv[1], argv[2], argv[3]);
678		do_hab_failsafe(0, 0, 1, NULL);
679	};
680	ret = CMD_RET_SUCCESS;
681error:
682	return ret;
683}
684
685#ifdef CONFIG_MX7ULP
686U_BOOT_CMD(
687		hab_status, CONFIG_SYS_MAXARGS, 2, do_hab_status,
688		"display HAB status and events",
689		"hab_status - A7 HAB event and status\n"
690		"hab_status m4 - M4 HAB event and status"
691	  );
692#else
693U_BOOT_CMD(
694		hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
695		"display HAB status",
696		""
697	  );
698#endif
699
700U_BOOT_CMD(
701		hab_auth_img, 4, 0, do_authenticate_image,
702		"authenticate image via HAB",
703		"addr length ivt_offset\n"
704		"addr - image hex address\n"
705		"length - image hex length\n"
706		"ivt_offset - hex offset of IVT in the image (optional)"
707	  );
708
709U_BOOT_CMD(
710		hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe,
711		"run BootROM failsafe routine",
712		""
713	  );
714
715U_BOOT_CMD(
716		hab_auth_img_or_fail, 4, 0,
717		do_authenticate_image_or_failover,
718		"authenticate image via HAB. Switch to USB BootROM mode on failure",
719		"addr length ivt_offset\n"
720		"addr - image hex address\n"
721		"length - image hex length\n"
722		"ivt_offset - hex offset of IVT in the image (optional)"
723	  );
724
725U_BOOT_CMD(
726		hab_version, 1, 0, do_hab_version,
727		"print HAB major/minor version",
728		""
729	  );
730
731#endif /* !defined(CONFIG_SPL_BUILD) */
732
733/* Get CSF Header length */
734static int get_hab_hdr_len(struct hab_hdr *hdr)
735{
736	return (size_t)((hdr->len[0] << 8) + (hdr->len[1]));
737}
738
739/* Check whether addr lies between start and
740 * end and is within the length of the image
741 */
742static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end)
743{
744	size_t csf_size = (size_t)((end + 1) - addr);
745
746	return (addr && (addr >= start) && (addr <= end) &&
747		(csf_size >= bytes));
748}
749
750/* Get Length of each command in CSF */
751static int get_csf_cmd_hdr_len(u8 *csf_hdr)
752{
753	if (*csf_hdr == HAB_CMD_HDR)
754		return sizeof(struct hab_hdr);
755
756	return get_hab_hdr_len((struct hab_hdr *)csf_hdr);
757}
758
759/* Check if CSF is valid */
760static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes)
761{
762	u8 *start = (u8 *)start_addr;
763	u8 *csf_hdr;
764	u8 *end;
765
766	size_t csf_hdr_len;
767	size_t cmd_hdr_len;
768	size_t offset = 0;
769
770	if (bytes != 0)
771		end = start + bytes - 1;
772	else
773		end = start;
774
775	/* Verify if CSF pointer content is zero */
776	if (!ivt->csf) {
777		puts("Error: CSF pointer is NULL\n");
778		return false;
779	}
780
781	csf_hdr = (u8 *)(ulong)ivt->csf;
782
783	/* Verify if CSF Header exist */
784	if (*csf_hdr != HAB_CMD_HDR) {
785		puts("Error: CSF header command not found\n");
786		return false;
787	}
788
789	csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr);
790
791	/* Check if the CSF lies within the image bounds */
792	if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) {
793		puts("Error: CSF lies outside the image bounds\n");
794		return false;
795	}
796
797	do {
798		struct hab_hdr *cmd;
799
800		cmd = (struct hab_hdr *)&csf_hdr[offset];
801
802		switch (cmd->tag) {
803		case (HAB_CMD_WRT_DAT):
804			puts("Error: Deprecated write command found\n");
805			return false;
806		case (HAB_CMD_CHK_DAT):
807			puts("Error: Deprecated check command found\n");
808			return false;
809		case (HAB_CMD_SET):
810			if (cmd->par == HAB_PAR_MID) {
811				puts("Error: Deprecated Set MID command found\n");
812				return false;
813			}
814		default:
815			break;
816		}
817
818		cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]);
819		if (!cmd_hdr_len) {
820			puts("Error: Invalid command length\n");
821			return false;
822		}
823		offset += cmd_hdr_len;
824
825	} while (offset < csf_hdr_len);
826
827	return true;
828}
829
830/*
831 * Validate IVT structure of the image being authenticated
832 */
833static int validate_ivt(struct ivt *ivt_initial)
834{
835	struct ivt_header *ivt_hdr = &ivt_initial->hdr;
836
837	if ((ulong)ivt_initial & 0x3) {
838		puts("Error: Image's start address is not 4 byte aligned\n");
839		return 0;
840	}
841
842	/* Check IVT fields before allowing authentication */
843	if ((!verify_ivt_header(ivt_hdr)) && \
844	    (ivt_initial->entry != 0x0) && \
845	    (ivt_initial->reserved1 == 0x0) && \
846	    (ivt_initial->self == \
847		   (uint32_t)((ulong)ivt_initial & 0xffffffff)) && \
848	    (ivt_initial->csf != 0x0) && \
849	    (ivt_initial->reserved2 == 0x0)) {
850		/* Report boot failure if DCD pointer is found in IVT */
851		if (ivt_initial->dcd != 0x0)
852			puts("Error: DCD pointer must be 0\n");
853		else
854			return 1;
855	}
856
857	puts("Error: Invalid IVT structure\n");
858	debug("\nAllowed IVT structure:\n");
859	debug("IVT HDR       = 0x4X2000D1\n");
860	debug("IVT ENTRY     = 0xXXXXXXXX\n");
861	debug("IVT RSV1      = 0x0\n");
862	debug("IVT DCD       = 0x0\n");		/* Recommended */
863	debug("IVT BOOT_DATA = 0xXXXXXXXX\n");	/* Commonly 0x0 */
864	debug("IVT SELF      = 0xXXXXXXXX\n");	/* = ddr_start + ivt_offset */
865	debug("IVT CSF       = 0xXXXXXXXX\n");
866	debug("IVT RSV2      = 0x0\n");
867
868	/* Invalid IVT structure */
869	return 0;
870}
871
872bool imx_hab_is_enabled(void)
873{
874	struct imx_sec_config_fuse_t *fuse =
875		(struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
876	uint32_t reg;
877	int ret;
878
879	ret = fuse_read(fuse->bank, fuse->word, &reg);
880	if (ret) {
881		puts("\nSecure boot fuse read error\n");
882		return ret;
883	}
884
885	return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
886}
887
888int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
889			       uint32_t ivt_offset)
890{
891	ulong load_addr = 0;
892	size_t bytes;
893	ulong ivt_addr = 0;
894	int result = 1;
895	ulong start;
896	struct ivt *ivt;
897	enum hab_status status;
898
899	if (!imx_hab_is_enabled())
900		puts("hab fuse not enabled\n");
901
902	printf("\nAuthenticate image from DDR location 0x%x...\n",
903	       ddr_start);
904
905	hab_caam_clock_enable(1);
906
907	/* Calculate IVT address header */
908	ivt_addr = (ulong) (ddr_start + ivt_offset);
909	ivt = (struct ivt *)ivt_addr;
910
911	/* Verify IVT header bugging out on error */
912	if (!validate_ivt(ivt))
913		goto hab_authentication_exit;
914
915	start = ddr_start;
916	bytes = image_size;
917
918	/* Verify CSF */
919	if (!csf_is_valid(ivt, start, bytes))
920		goto hab_authentication_exit;
921
922	if (hab_rvt_entry() != HAB_SUCCESS) {
923		puts("hab entry function fail\n");
924		goto hab_exit_failure_print_status;
925	}
926
927	status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes);
928	if (status != HAB_SUCCESS) {
929		printf("HAB check target 0x%08x-0x%08lx fail\n",
930		       ddr_start, ddr_start + (ulong)bytes);
931		goto hab_exit_failure_print_status;
932	}
933#ifdef DEBUG
934	printf("\nivt_offset = 0x%x, ivt addr = 0x%lx\n", ivt_offset, ivt_addr);
935	printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry,
936	       ivt->dcd, ivt->csf);
937	puts("Dumping IVT\n");
938	print_buffer(ivt_addr, (void *)(uintptr_t)(ivt_addr), 4, 0x8, 0);
939
940	puts("Dumping CSF Header\n");
941	print_buffer(ivt->csf, (void *)(uintptr_t)(ivt->csf), 4, 0x10, 0);
942
943#if  !defined(CONFIG_SPL_BUILD)
944	get_hab_status();
945#endif
946
947	puts("\nCalling authenticate_image in ROM\n");
948	printf("\tivt_offset = 0x%x\n", ivt_offset);
949	printf("\tstart = 0x%08lx\n", start);
950	printf("\tbytes = 0x%lx\n", (ulong)bytes);
951#endif
952
953#ifndef CONFIG_ARM64
954	/*
955	 * If the MMU is enabled, we have to notify the ROM
956	 * code, or it won't flush the caches when needed.
957	 * This is done, by setting the "pu_irom_mmu_enabled"
958	 * word to 1. You can find its address by looking in
959	 * the ROM map. This is critical for
960	 * authenticate_image(). If MMU is enabled, without
961	 * setting this bit, authentication will fail and may
962	 * crash.
963	 */
964	/* Check MMU enabled */
965	if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
966		if (is_mx6dq()) {
967			/*
968			 * This won't work on Rev 1.0.0 of
969			 * i.MX6Q/D, since their ROM doesn't
970			 * do cache flushes. don't think any
971			 * exist, so we ignore them.
972			 */
973			if (!is_mx6dqp())
974				writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
975		} else if (is_mx6sdl()) {
976			writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
977		} else if (is_mx6sl()) {
978			writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
979		}
980	}
981#endif
982
983	load_addr = (ulong)hab_rvt_authenticate_image(
984			HAB_CID_UBOOT,
985			ivt_offset, (void **)&start,
986			(size_t *)&bytes, NULL);
987	if (hab_rvt_exit() != HAB_SUCCESS) {
988		puts("hab exit function fail\n");
989		load_addr = 0;
990	}
991
992hab_exit_failure_print_status:
993#if !defined(CONFIG_SPL_BUILD)
994	get_hab_status();
995#endif
996
997hab_authentication_exit:
998
999	if (load_addr != 0 || !imx_hab_is_enabled())
1000		result = 0;
1001
1002	return result;
1003}
1004
1005int authenticate_image(u32 ddr_start, u32 raw_image_size)
1006{
1007	u32 ivt_offset;
1008	size_t bytes;
1009
1010	ivt_offset = (raw_image_size + ALIGN_SIZE - 1) &
1011					~(ALIGN_SIZE - 1);
1012	bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
1013
1014	return imx_hab_authenticate_image(ddr_start, bytes, ivt_offset);
1015}
1016