1 /* 2 * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <config.h> 9 #include <fuse.h> 10 #include <asm/io.h> 11 #include <asm/system.h> 12 #include <asm/arch/clock.h> 13 #include <asm/arch/sys_proto.h> 14 #include <asm/mach-imx/hab.h> 15 16 /* -------- start of HAB API updates ------------*/ 17 18 #define hab_rvt_report_event_p \ 19 ( \ 20 (is_mx6dqp()) ? \ 21 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ 22 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 23 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ 24 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 25 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ 26 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT) \ 27 ) 28 29 #define hab_rvt_report_status_p \ 30 ( \ 31 (is_mx6dqp()) ? \ 32 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\ 33 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 34 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\ 35 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 36 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\ 37 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS) \ 38 ) 39 40 #define hab_rvt_authenticate_image_p \ 41 ( \ 42 (is_mx6dqp()) ? \ 43 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \ 44 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 45 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \ 46 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 47 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \ 48 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE) \ 49 ) 50 51 #define hab_rvt_entry_p \ 52 ( \ 53 (is_mx6dqp()) ? \ 54 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ 55 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 56 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ 57 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 58 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ 59 ((hab_rvt_entry_t *)HAB_RVT_ENTRY) \ 60 ) 61 62 #define hab_rvt_exit_p \ 63 ( \ 64 (is_mx6dqp()) ? \ 65 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ 66 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 67 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ 68 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 69 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ 70 ((hab_rvt_exit_t *)HAB_RVT_EXIT) \ 71 ) 72 73 #define IVT_SIZE 0x20 74 #define ALIGN_SIZE 0x1000 75 #define CSF_PAD_SIZE 0x2000 76 #define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8 77 #define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0 78 #define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18 79 #define IS_HAB_ENABLED_BIT \ 80 (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \ 81 (is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2)) 82 83 /* 84 * +------------+ 0x0 (DDR_UIMAGE_START) - 85 * | Header | | 86 * +------------+ 0x40 | 87 * | | | 88 * | | | 89 * | | | 90 * | | | 91 * | Image Data | | 92 * . | | 93 * . | > Stuff to be authenticated ----+ 94 * . | | | 95 * | | | | 96 * | | | | 97 * +------------+ | | 98 * | | | | 99 * | Fill Data | | | 100 * | | | | 101 * +------------+ Align to ALIGN_SIZE | | 102 * | IVT | | | 103 * +------------+ + IVT_SIZE - | 104 * | | | 105 * | CSF DATA | <---------------------------------------------------------+ 106 * | | 107 * +------------+ 108 * | | 109 * | Fill Data | 110 * | | 111 * +------------+ + CSF_PAD_SIZE 112 */ 113 114 static bool is_hab_enabled(void); 115 116 #if !defined(CONFIG_SPL_BUILD) 117 118 #define MAX_RECORD_BYTES (8*1024) /* 4 kbytes */ 119 120 struct record { 121 uint8_t tag; /* Tag */ 122 uint8_t len[2]; /* Length */ 123 uint8_t par; /* Version */ 124 uint8_t contents[MAX_RECORD_BYTES];/* Record Data */ 125 bool any_rec_flag; 126 }; 127 128 char *rsn_str[] = {"RSN = HAB_RSN_ANY (0x00)\n", 129 "RSN = HAB_ENG_FAIL (0x30)\n", 130 "RSN = HAB_INV_ADDRESS (0x22)\n", 131 "RSN = HAB_INV_ASSERTION (0x0C)\n", 132 "RSN = HAB_INV_CALL (0x28)\n", 133 "RSN = HAB_INV_CERTIFICATE (0x21)\n", 134 "RSN = HAB_INV_COMMAND (0x06)\n", 135 "RSN = HAB_INV_CSF (0x11)\n", 136 "RSN = HAB_INV_DCD (0x27)\n", 137 "RSN = HAB_INV_INDEX (0x0F)\n", 138 "RSN = HAB_INV_IVT (0x05)\n", 139 "RSN = HAB_INV_KEY (0x1D)\n", 140 "RSN = HAB_INV_RETURN (0x1E)\n", 141 "RSN = HAB_INV_SIGNATURE (0x18)\n", 142 "RSN = HAB_INV_SIZE (0x17)\n", 143 "RSN = HAB_MEM_FAIL (0x2E)\n", 144 "RSN = HAB_OVR_COUNT (0x2B)\n", 145 "RSN = HAB_OVR_STORAGE (0x2D)\n", 146 "RSN = HAB_UNS_ALGORITHM (0x12)\n", 147 "RSN = HAB_UNS_COMMAND (0x03)\n", 148 "RSN = HAB_UNS_ENGINE (0x0A)\n", 149 "RSN = HAB_UNS_ITEM (0x24)\n", 150 "RSN = HAB_UNS_KEY (0x1B)\n", 151 "RSN = HAB_UNS_PROTOCOL (0x14)\n", 152 "RSN = HAB_UNS_STATE (0x09)\n", 153 "RSN = INVALID\n", 154 NULL}; 155 156 char *sts_str[] = {"STS = HAB_SUCCESS (0xF0)\n", 157 "STS = HAB_FAILURE (0x33)\n", 158 "STS = HAB_WARNING (0x69)\n", 159 "STS = INVALID\n", 160 NULL}; 161 162 char *eng_str[] = {"ENG = HAB_ENG_ANY (0x00)\n", 163 "ENG = HAB_ENG_SCC (0x03)\n", 164 "ENG = HAB_ENG_RTIC (0x05)\n", 165 "ENG = HAB_ENG_SAHARA (0x06)\n", 166 "ENG = HAB_ENG_CSU (0x0A)\n", 167 "ENG = HAB_ENG_SRTC (0x0C)\n", 168 "ENG = HAB_ENG_DCP (0x1B)\n", 169 "ENG = HAB_ENG_CAAM (0x1D)\n", 170 "ENG = HAB_ENG_SNVS (0x1E)\n", 171 "ENG = HAB_ENG_OCOTP (0x21)\n", 172 "ENG = HAB_ENG_DTCP (0x22)\n", 173 "ENG = HAB_ENG_ROM (0x36)\n", 174 "ENG = HAB_ENG_HDCP (0x24)\n", 175 "ENG = HAB_ENG_RTL (0x77)\n", 176 "ENG = HAB_ENG_SW (0xFF)\n", 177 "ENG = INVALID\n", 178 NULL}; 179 180 char *ctx_str[] = {"CTX = HAB_CTX_ANY(0x00)\n", 181 "CTX = HAB_CTX_FAB (0xFF)\n", 182 "CTX = HAB_CTX_ENTRY (0xE1)\n", 183 "CTX = HAB_CTX_TARGET (0x33)\n", 184 "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n", 185 "CTX = HAB_CTX_DCD (0xDD)\n", 186 "CTX = HAB_CTX_CSF (0xCF)\n", 187 "CTX = HAB_CTX_COMMAND (0xC0)\n", 188 "CTX = HAB_CTX_AUT_DAT (0xDB)\n", 189 "CTX = HAB_CTX_ASSERT (0xA0)\n", 190 "CTX = HAB_CTX_EXIT (0xEE)\n", 191 "CTX = INVALID\n", 192 NULL}; 193 194 uint8_t hab_statuses[5] = { 195 HAB_STS_ANY, 196 HAB_FAILURE, 197 HAB_WARNING, 198 HAB_SUCCESS, 199 -1 200 }; 201 202 uint8_t hab_reasons[26] = { 203 HAB_RSN_ANY, 204 HAB_ENG_FAIL, 205 HAB_INV_ADDRESS, 206 HAB_INV_ASSERTION, 207 HAB_INV_CALL, 208 HAB_INV_CERTIFICATE, 209 HAB_INV_COMMAND, 210 HAB_INV_CSF, 211 HAB_INV_DCD, 212 HAB_INV_INDEX, 213 HAB_INV_IVT, 214 HAB_INV_KEY, 215 HAB_INV_RETURN, 216 HAB_INV_SIGNATURE, 217 HAB_INV_SIZE, 218 HAB_MEM_FAIL, 219 HAB_OVR_COUNT, 220 HAB_OVR_STORAGE, 221 HAB_UNS_ALGORITHM, 222 HAB_UNS_COMMAND, 223 HAB_UNS_ENGINE, 224 HAB_UNS_ITEM, 225 HAB_UNS_KEY, 226 HAB_UNS_PROTOCOL, 227 HAB_UNS_STATE, 228 -1 229 }; 230 231 uint8_t hab_contexts[12] = { 232 HAB_CTX_ANY, 233 HAB_CTX_FAB, 234 HAB_CTX_ENTRY, 235 HAB_CTX_TARGET, 236 HAB_CTX_AUTHENTICATE, 237 HAB_CTX_DCD, 238 HAB_CTX_CSF, 239 HAB_CTX_COMMAND, 240 HAB_CTX_AUT_DAT, 241 HAB_CTX_ASSERT, 242 HAB_CTX_EXIT, 243 -1 244 }; 245 246 uint8_t hab_engines[16] = { 247 HAB_ENG_ANY, 248 HAB_ENG_SCC, 249 HAB_ENG_RTIC, 250 HAB_ENG_SAHARA, 251 HAB_ENG_CSU, 252 HAB_ENG_SRTC, 253 HAB_ENG_DCP, 254 HAB_ENG_CAAM, 255 HAB_ENG_SNVS, 256 HAB_ENG_OCOTP, 257 HAB_ENG_DTCP, 258 HAB_ENG_ROM, 259 HAB_ENG_HDCP, 260 HAB_ENG_RTL, 261 HAB_ENG_SW, 262 -1 263 }; 264 265 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt) 266 { 267 uint8_t idx = 0; 268 uint8_t element = list[idx]; 269 while (element != -1) { 270 if (element == tgt) 271 return idx; 272 element = list[++idx]; 273 } 274 return -1; 275 } 276 277 void process_event_record(uint8_t *event_data, size_t bytes) 278 { 279 struct record *rec = (struct record *)event_data; 280 281 printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]); 282 printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]); 283 printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]); 284 printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]); 285 } 286 287 void display_event(uint8_t *event_data, size_t bytes) 288 { 289 uint32_t i; 290 291 if (!(event_data && bytes > 0)) 292 return; 293 294 for (i = 0; i < bytes; i++) { 295 if (i == 0) 296 printf("\t0x%02x", event_data[i]); 297 else if ((i % 8) == 0) 298 printf("\n\t0x%02x", event_data[i]); 299 else 300 printf(" 0x%02x", event_data[i]); 301 } 302 303 process_event_record(event_data, bytes); 304 } 305 306 int get_hab_status(void) 307 { 308 uint32_t index = 0; /* Loop index */ 309 uint8_t event_data[128]; /* Event data buffer */ 310 size_t bytes = sizeof(event_data); /* Event size in bytes */ 311 enum hab_config config = 0; 312 enum hab_state state = 0; 313 hab_rvt_report_event_t *hab_rvt_report_event; 314 hab_rvt_report_status_t *hab_rvt_report_status; 315 316 hab_rvt_report_event = hab_rvt_report_event_p; 317 hab_rvt_report_status = hab_rvt_report_status_p; 318 319 if (is_hab_enabled()) 320 puts("\nSecure boot enabled\n"); 321 else 322 puts("\nSecure boot disabled\n"); 323 324 /* Check HAB status */ 325 if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) { 326 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", 327 config, state); 328 329 /* Display HAB Error events */ 330 while (hab_rvt_report_event(HAB_FAILURE, index, event_data, 331 &bytes) == HAB_SUCCESS) { 332 puts("\n"); 333 printf("--------- HAB Event %d -----------------\n", 334 index + 1); 335 puts("event data:\n"); 336 display_event(event_data, bytes); 337 puts("\n"); 338 bytes = sizeof(event_data); 339 index++; 340 } 341 } 342 /* Display message if no HAB events are found */ 343 else { 344 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", 345 config, state); 346 puts("No HAB Events Found!\n\n"); 347 } 348 return 0; 349 } 350 351 int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 352 { 353 if ((argc != 1)) { 354 cmd_usage(cmdtp); 355 return 1; 356 } 357 358 get_hab_status(); 359 360 return 0; 361 } 362 363 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc, 364 char * const argv[]) 365 { 366 ulong addr, ivt_offset; 367 int rcode = 0; 368 369 if (argc < 3) 370 return CMD_RET_USAGE; 371 372 addr = simple_strtoul(argv[1], NULL, 16); 373 ivt_offset = simple_strtoul(argv[2], NULL, 16); 374 375 rcode = authenticate_image(addr, ivt_offset); 376 377 return rcode; 378 } 379 380 U_BOOT_CMD( 381 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status, 382 "display HAB status", 383 "" 384 ); 385 386 U_BOOT_CMD( 387 hab_auth_img, 3, 0, do_authenticate_image, 388 "authenticate image via HAB", 389 "addr ivt_offset\n" 390 "addr - image hex address\n" 391 "ivt_offset - hex offset of IVT in the image" 392 ); 393 394 395 #endif /* !defined(CONFIG_SPL_BUILD) */ 396 397 static bool is_hab_enabled(void) 398 { 399 struct imx_sec_config_fuse_t *fuse = 400 (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; 401 uint32_t reg; 402 int ret; 403 404 ret = fuse_read(fuse->bank, fuse->word, ®); 405 if (ret) { 406 puts("\nSecure boot fuse read error\n"); 407 return ret; 408 } 409 410 return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT; 411 } 412 413 uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size) 414 { 415 uint32_t load_addr = 0; 416 size_t bytes; 417 ptrdiff_t ivt_offset = 0; 418 int result = 0; 419 ulong start; 420 hab_rvt_authenticate_image_t *hab_rvt_authenticate_image; 421 hab_rvt_entry_t *hab_rvt_entry; 422 hab_rvt_exit_t *hab_rvt_exit; 423 424 hab_rvt_authenticate_image = hab_rvt_authenticate_image_p; 425 hab_rvt_entry = hab_rvt_entry_p; 426 hab_rvt_exit = hab_rvt_exit_p; 427 428 if (is_hab_enabled()) { 429 printf("\nAuthenticate image from DDR location 0x%x...\n", 430 ddr_start); 431 432 hab_caam_clock_enable(1); 433 434 if (hab_rvt_entry() == HAB_SUCCESS) { 435 /* If not already aligned, Align to ALIGN_SIZE */ 436 ivt_offset = (image_size + ALIGN_SIZE - 1) & 437 ~(ALIGN_SIZE - 1); 438 439 start = ddr_start; 440 bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE; 441 #ifdef DEBUG 442 printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", 443 ivt_offset, ddr_start + ivt_offset); 444 puts("Dumping IVT\n"); 445 print_buffer(ddr_start + ivt_offset, 446 (void *)(ddr_start + ivt_offset), 447 4, 0x8, 0); 448 449 puts("Dumping CSF Header\n"); 450 print_buffer(ddr_start + ivt_offset+IVT_SIZE, 451 (void *)(ddr_start + ivt_offset+IVT_SIZE), 452 4, 0x10, 0); 453 454 #if !defined(CONFIG_SPL_BUILD) 455 get_hab_status(); 456 #endif 457 458 puts("\nCalling authenticate_image in ROM\n"); 459 printf("\tivt_offset = 0x%x\n", ivt_offset); 460 printf("\tstart = 0x%08lx\n", start); 461 printf("\tbytes = 0x%x\n", bytes); 462 #endif 463 /* 464 * If the MMU is enabled, we have to notify the ROM 465 * code, or it won't flush the caches when needed. 466 * This is done, by setting the "pu_irom_mmu_enabled" 467 * word to 1. You can find its address by looking in 468 * the ROM map. This is critical for 469 * authenticate_image(). If MMU is enabled, without 470 * setting this bit, authentication will fail and may 471 * crash. 472 */ 473 /* Check MMU enabled */ 474 if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) { 475 if (is_mx6dq()) { 476 /* 477 * This won't work on Rev 1.0.0 of 478 * i.MX6Q/D, since their ROM doesn't 479 * do cache flushes. don't think any 480 * exist, so we ignore them. 481 */ 482 if (!is_mx6dqp()) 483 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR); 484 } else if (is_mx6sdl()) { 485 writel(1, MX6DLS_PU_IROM_MMU_EN_VAR); 486 } else if (is_mx6sl()) { 487 writel(1, MX6SL_PU_IROM_MMU_EN_VAR); 488 } 489 } 490 491 load_addr = (uint32_t)hab_rvt_authenticate_image( 492 HAB_CID_UBOOT, 493 ivt_offset, (void **)&start, 494 (size_t *)&bytes, NULL); 495 if (hab_rvt_exit() != HAB_SUCCESS) { 496 puts("hab exit function fail\n"); 497 load_addr = 0; 498 } 499 } else { 500 puts("hab entry function fail\n"); 501 } 502 503 hab_caam_clock_enable(0); 504 505 #if !defined(CONFIG_SPL_BUILD) 506 get_hab_status(); 507 #endif 508 } else { 509 puts("hab fuse not enabled\n"); 510 } 511 512 if ((!is_hab_enabled()) || (load_addr != 0)) 513 result = 1; 514 515 return result; 516 } 517