2 * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+
9 #include <asm/system.h>
10 #include <asm/arch/clock.h>
11 #include <asm/arch/sys_proto.h>
12 #include <asm/arch/hab.h>
14 HAB_FUNC(entry, enum hab_status)
15 HAB_FUNC(exit, enum hab_status)
16 HAB_FUNC5(authenticate_image, void *, uint8_t, size_t, void **, size_t *, hab_loader_callback_f_t)
17 //HAB_FUNC1(run_dcd, enum hab_status, const uint8_t *)
18 HAB_FUNC2(run_csf, enum hab_status, const uint8_t *, uint8_t)
19 HAB_FUNC2(report_status, enum hab_status, enum hab_config *, enum hab_state *)
20 HAB_FUNC4(report_event, enum hab_status, enum hab_status, uint32_t, uint8_t *, size_t *)
21 HAB_FUNC3(check_target, enum hab_status, uint8_t, const void *, size_t)
22 HAB_FUNC3(assert, enum hab_status, uint8_t, const void *, size_t)
24 #define MAX_RECORD_BYTES (8 * 1024)
27 uint8_t tag; /* Tag */
28 uint8_t len[2]; /* Length */
29 uint8_t par; /* Version */
30 uint8_t contents[MAX_RECORD_BYTES];/* Record Data */
35 "RSN = HAB_RSN_ANY (0x00)\n",
36 "RSN = HAB_ENG_FAIL (0x30)\n",
37 "RSN = HAB_INV_ADDRESS (0x22)\n",
38 "RSN = HAB_INV_ASSERTION (0x0C)\n",
39 "RSN = HAB_INV_CALL (0x28)\n",
40 "RSN = HAB_INV_CERTIFICATE (0x21)\n",
41 "RSN = HAB_INV_COMMAND (0x06)\n",
42 "RSN = HAB_INV_CSF (0x11)\n",
43 "RSN = HAB_INV_DCD (0x27)\n",
44 "RSN = HAB_INV_INDEX (0x0F)\n",
45 "RSN = HAB_INV_IVT (0x05)\n",
46 "RSN = HAB_INV_KEY (0x1D)\n",
47 "RSN = HAB_INV_RETURN (0x1E)\n",
48 "RSN = HAB_INV_SIGNATURE (0x18)\n",
49 "RSN = HAB_INV_SIZE (0x17)\n",
50 "RSN = HAB_MEM_FAIL (0x2E)\n",
51 "RSN = HAB_OVR_COUNT (0x2B)\n",
52 "RSN = HAB_OVR_STORAGE (0x2D)\n",
53 "RSN = HAB_UNS_ALGORITHM (0x12)\n",
54 "RSN = HAB_UNS_COMMAND (0x03)\n",
55 "RSN = HAB_UNS_ENGINE (0x0A)\n",
56 "RSN = HAB_UNS_ITEM (0x24)\n",
57 "RSN = HAB_UNS_KEY (0x1B)\n",
58 "RSN = HAB_UNS_PROTOCOL (0x14)\n",
59 "RSN = HAB_UNS_STATE (0x09)\n",
64 "STS = HAB_STS_ANY (0x00)\n",
65 "STS = HAB_FAILURE (0x33)\n",
66 "STS = HAB_WARNING (0x69)\n",
67 "STS = HAB_SUCCESS (0xF0)\n",
72 "ENG = HAB_ENG_ANY (0x00)\n",
73 "ENG = HAB_ENG_SCC (0x03)\n",
74 "ENG = HAB_ENG_RTIC (0x05)\n",
75 "ENG = HAB_ENG_SAHARA (0x06)\n",
76 "ENG = HAB_ENG_CSU (0x0A)\n",
77 "ENG = HAB_ENG_SRTC (0x0C)\n",
78 "ENG = HAB_ENG_DCP (0x1B)\n",
79 "ENG = HAB_ENG_CAAM (0x1D)\n",
80 "ENG = HAB_ENG_SNVS (0x1E)\n",
81 "ENG = HAB_ENG_OCOTP (0x21)\n",
82 "ENG = HAB_ENG_DTCP (0x22)\n",
83 "ENG = HAB_ENG_ROM (0x36)\n",
84 "ENG = HAB_ENG_HDCP (0x24)\n",
85 "ENG = HAB_ENG_RTL (0x77)\n",
86 "ENG = HAB_ENG_SW (0xFF)\n",
91 "CTX = HAB_CTX_ANY(0x00)\n",
92 "CTX = HAB_CTX_FAB (0xFF)\n",
93 "CTX = HAB_CTX_ENTRY (0xE1)\n",
94 "CTX = HAB_CTX_TARGET (0x33)\n",
95 "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
96 "CTX = HAB_CTX_DCD (0xDD)\n",
97 "CTX = HAB_CTX_CSF (0xCF)\n",
98 "CTX = HAB_CTX_COMMAND (0xC0)\n",
99 "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
100 "CTX = HAB_CTX_ASSERT (0xA0)\n",
101 "CTX = HAB_CTX_EXIT (0xEE)\n",
105 uint8_t hab_statuses[ARRAY_SIZE(sts_str)] = {
113 uint8_t hab_reasons[ARRAY_SIZE(rsn_str)] = {
142 uint8_t hab_contexts[ARRAY_SIZE(ctx_str)] = {
147 HAB_CTX_AUTHENTICATE,
157 uint8_t hab_engines[ARRAY_SIZE(eng_str)] = {
176 bool is_hab_enabled(void)
178 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
179 struct fuse_bank *bank = &ocotp->bank[0];
180 struct fuse_bank0_regs *fuse =
181 (struct fuse_bank0_regs *)bank->fuse_regs;
182 uint32_t reg = readl(&fuse->cfg5);
183 static int first = 1;
186 debug("rvt_base=%p\n", hab_rvt_base());
187 debug("hab_rvt_entry=%p\n", hab_rvt_entry_p);
188 debug("hab_rvt_exit=%p\n", hab_rvt_exit_p);
189 debug("hab_rvt_check_target=%p\n", hab_rvt_check_target_p);
190 debug("hab_rvt_authenticate_image=%p\n", hab_rvt_authenticate_image_p);
191 debug("hab_rvt_report_event=%p\n", hab_rvt_report_event_p);
192 debug("hab_rvt_report_status=%p\n", hab_rvt_report_status_p);
193 debug("hab_rvt_assert=%p\n", hab_rvt_assert_p);
196 return (reg & 0x2) == 0x2;
199 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
202 uint8_t element = list[idx];
203 while (element != -1) {
206 element = list[++idx];
211 void process_event_record(uint8_t *event_data, size_t bytes)
213 struct record *rec = (struct record *)event_data;
215 printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
216 printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
217 printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
218 printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
221 void display_event(uint8_t *event_data, size_t bytes)
225 if (!(event_data && bytes > 0))
228 for (i = 0; i < bytes; i++) {
230 printf("\t0x%02x", event_data[i]);
231 else if ((i % 8) == 0)
232 printf("\n\t0x%02x", event_data[i]);
234 printf(" 0x%02x", event_data[i]);
237 process_event_record(event_data, bytes);
240 int get_hab_status(void)
242 static uint32_t last_hab_event __attribute__((section(".data")));
243 uint32_t index = last_hab_event; /* Loop index */
244 uint8_t event_data[128]; /* Event data buffer */
245 size_t bytes = sizeof(event_data); /* Event size in bytes */
246 enum hab_config config;
247 enum hab_state state;
250 if (is_hab_enabled())
251 puts("Secure boot enabled\n");
253 puts("Secure boot disabled\n");
255 /* Check HAB status */
256 config = state = 0; /* ROM code assumes short enums! */
257 ret = hab_rvt_report_status(&config, &state);
258 printf("HAB Configuration: 0x%02x, HAB State: 0x%02x\n",
260 if (ret != HAB_SUCCESS) {
261 /* Display HAB Error events */
262 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
263 &bytes) == HAB_SUCCESS) {
265 printf("--------- HAB Event %d -----------------\n",
267 puts("event data:\n");
268 display_event(event_data, bytes);
270 bytes = sizeof(event_data);
273 ret = index - last_hab_event;
274 last_hab_event = index;
276 /* Display message if no HAB events are found */
277 puts("No HAB Events Found!\n");
283 static inline enum hab_status hab_init(void)
287 if (!is_hab_enabled()) {
288 puts("hab fuse not enabled\n");
292 hab_caam_clock_enable(1);
294 ret = hab_rvt_entry();
295 debug("hab_rvt_entry() returned %02x\n", ret);
296 if (ret != HAB_SUCCESS) {
297 printf("hab entry function failed: %02x\n", ret);
298 hab_caam_clock_enable(0);
304 static inline enum hab_status hab_exit(void)
308 ret = hab_rvt_exit();
309 if (ret != HAB_SUCCESS)
310 printf("hab exit function failed: %02x\n", ret);
312 hab_caam_clock_enable(0);
317 static enum hab_status hab_check_target(enum hab_target type, uint32_t addr, size_t len)
322 if (ret != HAB_SUCCESS)
325 ret = hab_rvt_check_target(type, (void *)addr, len);
326 if (ret != HAB_SUCCESS) {
327 printf("check_target(0x%08x, 0x%08x) failed: %d\n",
333 if (ret == HAB_SUCCESS && get_hab_status() > 0) {
339 static enum hab_status hab_assert(uint32_t type, uint32_t addr, size_t len)
344 if (ret != HAB_SUCCESS)
347 ret = hab_rvt_assert(type, (void *)addr, len);
348 if (ret != HAB_SUCCESS) {
349 printf("assert(0x%08x, 0x%08x) failed: %d\n",
355 if (ret == HAB_SUCCESS && get_hab_status() > 0) {
361 static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
365 return CMD_RET_USAGE;
369 return CMD_RET_SUCCESS;
372 static int do_hab_check_target(cmd_tbl_t *cmdtp, int flag, int argc,
375 enum hab_target type = HAB_TGT_ANY;
380 return CMD_RET_USAGE;
382 addr = simple_strtoul(argv[1], NULL, 16);
383 len = simple_strtoul(argv[2], NULL, 16);
385 switch (argv[3][0]) {
388 type = HAB_TGT_PERIPHERAL;
392 type = HAB_TGT_MEMORY;
398 printf("Invalid type '%s'\n", argv[3]);
399 return CMD_RET_USAGE;
402 if (hab_check_target(type, addr, len) != HAB_SUCCESS)
403 return CMD_RET_FAILURE;
405 return CMD_RET_SUCCESS;
408 static int do_hab_assert(cmd_tbl_t *cmdtp, int flag, int argc,
416 return CMD_RET_USAGE;
418 addr = simple_strtoul(argv[1], NULL, 16);
419 len = simple_strtoul(argv[2], NULL, 16);
421 type = simple_strtoul(argv[3], NULL, 16);
424 if (hab_assert(type, addr, len) != HAB_SUCCESS)
425 return CMD_RET_FAILURE;
427 return CMD_RET_SUCCESS;
431 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
432 "display HAB status",
437 hab_check_target, 4, 0, do_hab_check_target,
438 "verify an address range via HAB",
440 "\t\taddr -\taddress to verify\n"
441 "\t\tlen -\tlength of addr range to verify\n"
445 hab_assert, 4, 0, do_hab_assert,
446 "Test an assertion against the HAB audit log",
448 "\t\taddr -\taddress to verify\n"
449 "\t\tlen -\tlength of addr range to verify\n"