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