blob: c6747b257c42b839a30b6c81e839f97e26edf8d3 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Stefano Babic83fd8582013-06-28 00:20:21 +02002/*
Ulises Cardenas8df2acd2015-07-02 21:26:30 -05003 * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
Stefano Babic83fd8582013-06-28 00:20:21 +02004 */
5
6#include <common.h>
Simon Glassed38aef2020-05-10 11:40:03 -06007#include <command.h>
Adrian Alonso1f3029f2015-10-12 13:48:14 -05008#include <config.h>
Simon Glass1ab16922022-07-31 12:28:48 -06009#include <display_options.h>
Adrian Alonso1f3029f2015-10-12 13:48:14 -050010#include <fuse.h>
Parthiban Nallathambi2c88aa62018-11-21 14:50:40 +010011#include <mapmem.h>
12#include <image.h>
Stefano Babic83fd8582013-06-28 00:20:21 +020013#include <asm/io.h>
Peng Fan4f3cf8f2021-03-25 17:30:07 +080014#include <asm/global_data.h>
Nitin Gargb1ce7012014-09-16 13:33:25 -050015#include <asm/system.h>
Nitin Gargb1ce7012014-09-16 13:33:25 -050016#include <asm/arch/clock.h>
Stefano Babic14404422014-06-10 10:26:22 +020017#include <asm/arch/sys_proto.h>
Stefano Babic33731bc2017-06-29 10:16:06 +020018#include <asm/mach-imx/hab.h>
Peng Fan4f3cf8f2021-03-25 17:30:07 +080019#include <linux/arm-smccc.h>
20
21DECLARE_GLOBAL_DATA_PTR;
Stefano Babic83fd8582013-06-28 00:20:21 +020022
Nitin Gargb1ce7012014-09-16 13:33:25 -050023#define ALIGN_SIZE 0x1000
Nitin Gargb1ce7012014-09-16 13:33:25 -050024#define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8
25#define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0
Breno Matheus Lima25d93482019-05-07 20:19:17 +000026#define MX6SL_PU_IROM_MMU_EN_VAR 0x00901c60
Adrian Alonso00a0b562015-10-12 13:48:15 -050027#define IS_HAB_ENABLED_BIT \
Peng Fana26ba6d2017-02-22 16:21:53 +080028 (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \
Peng Fan4f3cf8f2021-03-25 17:30:07 +080029 ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M)) ? 0x2000000 : 0x2))
Nitin Gargb1ce7012014-09-16 13:33:25 -050030
Breno Lima3adb6f02021-03-25 17:30:13 +080031#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
Bryan O'Donoghue5ee19b32018-01-12 12:40:03 +000037static 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
Breno Limad03a4d32021-03-25 17:30:12 +080055 if ((ivt_hdr->version & HAB_MAJ_MASK) != HAB_MAJ_VER)
Bryan O'Donoghue5ee19b32018-01-12 12:40:03 +000056 result = ivt_header_error("bad version", ivt_hdr);
57
58 return result;
59}
60
Peng Fan4f3cf8f2021-03-25 17:30:07 +080061#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
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100249#if !defined(CONFIG_SPL_BUILD)
250
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500251#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
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000261static 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};
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500290
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000291static 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};
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500298
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000299static 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};
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500318
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000319static 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};
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500334
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000335static uint8_t hab_statuses[5] = {
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500336 HAB_STS_ANY,
337 HAB_FAILURE,
338 HAB_WARNING,
339 HAB_SUCCESS,
340 -1
341};
342
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000343static uint8_t hab_reasons[26] = {
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500344 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
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000372static uint8_t hab_contexts[12] = {
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500373 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
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000387static uint8_t hab_engines[16] = {
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500388 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
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500406static 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
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000418static void process_event_record(uint8_t *event_data, size_t bytes)
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500419{
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
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000428static void display_event(uint8_t *event_data, size_t bytes)
Stefano Babic83fd8582013-06-28 00:20:21 +0200429{
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 }
Ulises Cardenas8df2acd2015-07-02 21:26:30 -0500443
444 process_event_record(event_data, bytes);
Stefano Babic83fd8582013-06-28 00:20:21 +0200445}
446
Bryan O'Donoghuee92a5f92018-01-12 12:40:12 +0000447static int get_hab_status(void)
Stefano Babic83fd8582013-06-28 00:20:21 +0200448{
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;
Stefano Babic83fd8582013-06-28 00:20:21 +0200454
Bryan O'Donoghue899cab02018-01-12 12:40:14 +0000455 if (imx_hab_is_enabled())
Stefano Babic83fd8582013-06-28 00:20:21 +0200456 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
Utkarsh Gupta1115bed2021-03-25 17:30:11 +0800465 /* Display HAB events */
466 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
Stefano Babic83fd8582013-06-28 00:20:21 +0200467 &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
Breno Lima3adb6f02021-03-25 17:30:13 +0800487#ifdef CONFIG_MX7ULP
488
489static int get_record_len(struct record *rec)
490{
491 return (size_t)((rec->len[0] << 8) + (rec->len[1]));
492}
493
494static 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
Simon Glassed38aef2020-05-10 11:40:03 -0600559static int do_hab_status(struct cmd_tbl *cmdtp, int flag, int argc,
560 char *const argv[])
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100561{
Breno Lima3adb6f02021-03-25 17:30:13 +0800562#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
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100573 if ((argc != 1)) {
574 cmd_usage(cmdtp);
575 return 1;
576 }
577
578 get_hab_status();
Breno Lima3adb6f02021-03-25 17:30:13 +0800579#endif
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100580
581 return 0;
582}
583
Parthiban Nallathambi2c88aa62018-11-21 14:50:40 +0100584static 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)) {
Tom Rinic220bd92019-05-23 07:14:07 -0400590#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Parthiban Nallathambi2c88aa62018-11-21 14:50:40 +0100591 case IMAGE_FORMAT_LEGACY:
Simon Glassbb7d3bb2022-09-06 20:26:52 -0600592 return (image_get_image_size((struct legacy_img_hdr *)img_addr)
Parthiban Nallathambi2c88aa62018-11-21 14:50:40 +0100593 + 0x1000 - 1) & ~(0x1000 - 1);
594#endif
Simon Glasse719d3b2021-09-25 19:43:20 -0600595#if CONFIG_IS_ENABLED(FIT)
Parthiban Nallathambi2c88aa62018-11-21 14:50:40 +0100596 case IMAGE_FORMAT_FIT:
597 return (fit_get_size(buf) + 0x1000 - 1) & ~(0x1000 - 1);
598#endif
599 default:
600 return 0;
601 }
602}
603
Simon Glassed38aef2020-05-10 11:40:03 -0600604static int do_authenticate_image(struct cmd_tbl *cmdtp, int flag, int argc,
605 char *const argv[])
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100606{
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000607 ulong addr, length, ivt_offset;
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100608 int rcode = 0;
609
Parthiban Nallathambi2c88aa62018-11-21 14:50:40 +0100610 if (argc < 3)
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100611 return CMD_RET_USAGE;
612
Simon Glass3ff49ec2021-07-24 09:03:29 -0600613 addr = hextoul(argv[1], NULL);
614 length = hextoul(argv[2], NULL);
Parthiban Nallathambi2c88aa62018-11-21 14:50:40 +0100615 if (argc == 3)
616 ivt_offset = get_image_ivt_offset(addr);
617 else
Simon Glass3ff49ec2021-07-24 09:03:29 -0600618 ivt_offset = hextoul(argv[3], NULL);
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100619
Bryan O'Donoghue1efba6a2018-01-12 12:40:13 +0000620 rcode = imx_hab_authenticate_image(addr, length, ivt_offset);
Bryan O'Donoghue79987a12018-01-12 12:39:56 +0000621 if (rcode == 0)
622 rcode = CMD_RET_SUCCESS;
623 else
624 rcode = CMD_RET_FAILURE;
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000625
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100626 return rcode;
627}
628
Simon Glassed38aef2020-05-10 11:40:03 -0600629static int do_hab_failsafe(struct cmd_tbl *cmdtp, int flag, int argc,
630 char *const argv[])
Bryan O'Donoghuefaa15022018-01-12 12:40:19 +0000631{
Bryan O'Donoghuefaa15022018-01-12 12:40:19 +0000632 if (argc != 1) {
633 cmd_usage(cmdtp);
634 return 1;
635 }
636
Bryan O'Donoghuefaa15022018-01-12 12:40:19 +0000637 hab_rvt_failsafe();
638
639 return 0;
640}
641
Simon Glassed38aef2020-05-10 11:40:03 -0600642static int do_hab_version(struct cmd_tbl *cmdtp, int flag, int argc,
643 char *const argv[])
Sjoerd Simons27f3fae2019-06-18 23:08:59 +0200644{
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
Simon Glassed38aef2020-05-10 11:40:03 -0600657static int do_authenticate_image_or_failover(struct cmd_tbl *cmdtp, int flag,
658 int argc, char *const argv[])
Bryan O'Donoghue933092f2018-03-26 15:36:46 +0100659{
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;
678error:
679 return ret;
680}
681
Breno Lima3adb6f02021-03-25 17:30:13 +0800682#ifdef CONFIG_MX7ULP
683U_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
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100690U_BOOT_CMD(
691 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
692 "display HAB status",
693 ""
694 );
Breno Lima3adb6f02021-03-25 17:30:13 +0800695#endif
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100696
697U_BOOT_CMD(
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000698 hab_auth_img, 4, 0, do_authenticate_image,
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100699 "authenticate image via HAB",
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000700 "addr length ivt_offset\n"
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100701 "addr - image hex address\n"
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000702 "length - image hex length\n"
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100703 "ivt_offset - hex offset of IVT in the image"
704 );
705
Bryan O'Donoghuefaa15022018-01-12 12:40:19 +0000706U_BOOT_CMD(
707 hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe,
708 "run BootROM failsafe routine",
709 ""
710 );
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100711
Bryan O'Donoghue933092f2018-03-26 15:36:46 +0100712U_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
Sjoerd Simons27f3fae2019-06-18 23:08:59 +0200722U_BOOT_CMD(
723 hab_version, 1, 0, do_hab_version,
724 "print HAB major/minor version",
725 ""
726 );
727
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100728#endif /* !defined(CONFIG_SPL_BUILD) */
729
Utkarsh Gupta2b1f4142018-02-20 01:19:24 +0000730/* Get CSF Header length */
731static 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 */
739static 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 */
748static 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 */
757static 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
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800778 csf_hdr = (u8 *)(ulong)ivt->csf;
Utkarsh Gupta2b1f4142018-02-20 01:19:24 +0000779
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 {
Utkarsh Gupta09af35c2018-02-20 01:19:25 +0000795 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
Utkarsh Gupta2b1f4142018-02-20 01:19:24 +0000815 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
Utkarsh Guptaaac4ab52021-03-25 17:30:08 +0800827/*
828 * Validate IVT structure of the image being authenticated
829 */
830static 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
Bryan O'Donoghue47b3f342018-01-12 12:40:16 +0000869bool imx_hab_is_enabled(void)
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100870{
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
Bryan O'Donoghue1efba6a2018-01-12 12:40:13 +0000885int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
886 uint32_t ivt_offset)
Nitin Gargb1ce7012014-09-16 13:33:25 -0500887{
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800888 ulong load_addr = 0;
Nitin Gargb1ce7012014-09-16 13:33:25 -0500889 size_t bytes;
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800890 ulong ivt_addr = 0;
Bryan O'Donoghue79987a12018-01-12 12:39:56 +0000891 int result = 1;
Nitin Gargb1ce7012014-09-16 13:33:25 -0500892 ulong start;
Bryan O'Donoghue5ee19b32018-01-12 12:40:03 +0000893 struct ivt *ivt;
Bryan O'Donoghue13513252018-01-12 12:40:10 +0000894 enum hab_status status;
Nitin Gargb1ce7012014-09-16 13:33:25 -0500895
Breno Lima5deb9302021-03-25 17:30:10 +0800896 if (!imx_hab_is_enabled())
Bryan O'Donoghue19369c72018-01-12 12:39:57 +0000897 puts("hab fuse not enabled\n");
Nitin Gargb1ce7012014-09-16 13:33:25 -0500898
Bryan O'Donoghue19369c72018-01-12 12:39:57 +0000899 printf("\nAuthenticate image from DDR location 0x%x...\n",
900 ddr_start);
Nitin Gargb1ce7012014-09-16 13:33:25 -0500901
Bryan O'Donoghue19369c72018-01-12 12:39:57 +0000902 hab_caam_clock_enable(1);
Nitin Gargb1ce7012014-09-16 13:33:25 -0500903
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000904 /* Calculate IVT address header */
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800905 ivt_addr = (ulong) (ddr_start + ivt_offset);
Bryan O'Donoghue5ee19b32018-01-12 12:40:03 +0000906 ivt = (struct ivt *)ivt_addr;
Bryan O'Donoghue5ee19b32018-01-12 12:40:03 +0000907
908 /* Verify IVT header bugging out on error */
Utkarsh Guptaaac4ab52021-03-25 17:30:08 +0800909 if (!validate_ivt(ivt))
Breno Lima52d389c2018-02-20 01:19:22 +0000910 goto hab_authentication_exit;
Utkarsh Guptaf79f75e2018-02-20 01:19:23 +0000911
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000912 start = ddr_start;
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000913 bytes = image_size;
Bryan O'Donoghued525a282018-01-12 12:40:05 +0000914
Utkarsh Gupta2b1f4142018-02-20 01:19:24 +0000915 /* Verify CSF */
916 if (!csf_is_valid(ivt, start, bytes))
917 goto hab_authentication_exit;
918
Bryan O'Donoghued525a282018-01-12 12:40:05 +0000919 if (hab_rvt_entry() != HAB_SUCCESS) {
920 puts("hab entry function fail\n");
Bryan O'Donoghue3bf65de2018-01-12 12:40:11 +0000921 goto hab_exit_failure_print_status;
Bryan O'Donoghued525a282018-01-12 12:40:05 +0000922 }
923
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800924 status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes);
Bryan O'Donoghue13513252018-01-12 12:40:10 +0000925 if (status != HAB_SUCCESS) {
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800926 printf("HAB check target 0x%08x-0x%08lx fail\n",
Breno Lima9807f552021-03-25 17:30:14 +0800927 ddr_start, ddr_start + (ulong)bytes);
Bryan O'Donoghue3bf65de2018-01-12 12:40:11 +0000928 goto hab_exit_failure_print_status;
Bryan O'Donoghue13513252018-01-12 12:40:10 +0000929 }
Nitin Gargb1ce7012014-09-16 13:33:25 -0500930#ifdef DEBUG
Breno Lima9807f552021-03-25 17:30:14 +0800931 printf("\nivt_offset = 0x%x, ivt addr = 0x%lx\n", ivt_offset, ivt_addr);
Bryan O'Donoghueeb031502018-01-12 12:40:07 +0000932 printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry,
933 ivt->dcd, ivt->csf);
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000934 puts("Dumping IVT\n");
Bryan O'Donoghue88919962018-01-12 12:40:01 +0000935 print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0);
Nitin Gargb1ce7012014-09-16 13:33:25 -0500936
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000937 puts("Dumping CSF Header\n");
Bryan O'Donoghue6c906ff2018-01-12 12:40:06 +0000938 print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0);
Nitin Gargb1ce7012014-09-16 13:33:25 -0500939
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100940#if !defined(CONFIG_SPL_BUILD)
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000941 get_hab_status();
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100942#endif
Nitin Gargb1ce7012014-09-16 13:33:25 -0500943
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000944 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);
Nitin Gargb1ce7012014-09-16 13:33:25 -0500948#endif
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800949
950#ifndef CONFIG_ARM64
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000951 /*
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);
Bryan O'Donoghue19369c72018-01-12 12:39:57 +0000976 }
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000977 }
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800978#endif
Nitin Gargb1ce7012014-09-16 13:33:25 -0500979
Peng Fan4f3cf8f2021-03-25 17:30:07 +0800980 load_addr = (ulong)hab_rvt_authenticate_image(
Bryan O'Donoghueb8dd7a62018-01-12 12:39:58 +0000981 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;
Bryan O'Donoghue19369c72018-01-12 12:39:57 +0000987 }
Nitin Gargb1ce7012014-09-16 13:33:25 -0500988
Bryan O'Donoghue3bf65de2018-01-12 12:40:11 +0000989hab_exit_failure_print_status:
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100990#if !defined(CONFIG_SPL_BUILD)
Bryan O'Donoghue19369c72018-01-12 12:39:57 +0000991 get_hab_status();
Sven Ebenfeldeba5e332016-11-06 16:37:55 +0100992#endif
Bryan O'Donoghue3bf65de2018-01-12 12:40:11 +0000993
Breno Lima52d389c2018-02-20 01:19:22 +0000994hab_authentication_exit:
Bryan O'Donoghue3bf65de2018-01-12 12:40:11 +0000995
Breno Lima5deb9302021-03-25 17:30:10 +0800996 if (load_addr != 0 || !imx_hab_is_enabled())
Bryan O'Donoghue79987a12018-01-12 12:39:56 +0000997 result = 0;
Nitin Gargb1ce7012014-09-16 13:33:25 -0500998
999 return result;
1000}
Ye Lif66fd7b2021-03-25 17:30:06 +08001001
1002int 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}