uboot/arch/arm/mach-imx/imx8/ahab.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2018-2019 NXP
   4 */
   5
   6#include <common.h>
   7#include <command.h>
   8#include <errno.h>
   9#include <log.h>
  10#include <asm/global_data.h>
  11#include <asm/io.h>
  12#include <asm/arch/sci/sci.h>
  13#include <asm/mach-imx/sys_proto.h>
  14#include <asm/arch-imx/cpu.h>
  15#include <asm/arch/sys_proto.h>
  16#include <asm/mach-imx/image.h>
  17#include <console.h>
  18#include <cpu_func.h>
  19
  20DECLARE_GLOBAL_DATA_PTR;
  21
  22#define SEC_SECURE_RAM_BASE             (0x31800000UL)
  23#define SEC_SECURE_RAM_END_BASE         (SEC_SECURE_RAM_BASE + 0xFFFFUL)
  24#define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE  (0x60000000UL)
  25
  26#define SECO_PT                 2U
  27
  28static inline bool check_in_dram(ulong addr)
  29{
  30        int i;
  31        struct bd_info *bd = gd->bd;
  32
  33        for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
  34                if (bd->bi_dram[i].size) {
  35                        if (addr >= bd->bi_dram[i].start &&
  36                            addr < (bd->bi_dram[i].start + bd->bi_dram[i].size))
  37                                return true;
  38                }
  39        }
  40
  41        return false;
  42}
  43
  44int authenticate_os_container(ulong addr)
  45{
  46        struct container_hdr *phdr;
  47        int i, ret = 0;
  48        int err;
  49        sc_rm_mr_t mr;
  50        sc_faddr_t start, end;
  51        u16 length;
  52        struct boot_img_t *img;
  53        unsigned long s, e;
  54
  55        if (addr % 4) {
  56                puts("Error: Image's address is not 4 byte aligned\n");
  57                return -EINVAL;
  58        }
  59
  60        if (!check_in_dram(addr)) {
  61                puts("Error: Image's address is invalid\n");
  62                return -EINVAL;
  63        }
  64
  65        phdr = (struct container_hdr *)addr;
  66        if (phdr->tag != 0x87 && phdr->version != 0x0) {
  67                printf("Error: Wrong container header\n");
  68                return -EFAULT;
  69        }
  70
  71        if (!phdr->num_images) {
  72                printf("Error: Wrong container, no image found\n");
  73                return -EFAULT;
  74        }
  75
  76        length = phdr->length_lsb + (phdr->length_msb << 8);
  77
  78        debug("container length %u\n", length);
  79        memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)addr,
  80               ALIGN(length, CONFIG_SYS_CACHELINE_SIZE));
  81
  82        err = sc_seco_authenticate(-1, SC_SECO_AUTH_CONTAINER,
  83                                   SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE);
  84        if (err) {
  85                printf("Authenticate container hdr failed, return %d\n",
  86                       err);
  87                ret = -EIO;
  88                goto exit;
  89        }
  90
  91        /* Copy images to dest address */
  92        for (i = 0; i < phdr->num_images; i++) {
  93                img = (struct boot_img_t *)(addr +
  94                                            sizeof(struct container_hdr) +
  95                                            i * sizeof(struct boot_img_t));
  96
  97                debug("img %d, dst 0x%x, src 0x%lux, size 0x%x\n",
  98                      i, (uint32_t) img->dst, img->offset + addr, img->size);
  99
 100                memcpy((void *)img->dst, (const void *)(img->offset + addr),
 101                       img->size);
 102
 103                s = img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
 104                e = ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1;
 105
 106                flush_dcache_range(s, e);
 107
 108                /* Find the memreg and set permission for seco pt */
 109                err = sc_rm_find_memreg(-1, &mr, s, e);
 110                if (err) {
 111                        printf("Error: can't find memreg for image load address 0x%llx, error %d\n", img->dst, err);
 112                        ret = -ENOMEM;
 113                        goto exit;
 114                }
 115
 116                err = sc_rm_get_memreg_info(-1, mr, &start, &end);
 117                if (!err)
 118                        debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
 119
 120                err = sc_rm_set_memreg_permissions(-1, mr, SECO_PT,
 121                                                   SC_RM_PERM_FULL);
 122                if (err) {
 123                        printf("Set permission failed for img %d, error %d\n",
 124                               i, err);
 125                        ret = -EPERM;
 126                        goto exit;
 127                }
 128
 129                err = sc_seco_authenticate(-1, SC_SECO_VERIFY_IMAGE,
 130                                           (1 << i));
 131                if (err) {
 132                        printf("Authenticate img %d failed, return %d\n",
 133                               i, err);
 134                        ret = -EIO;
 135                }
 136
 137                err = sc_rm_set_memreg_permissions(-1, mr, SECO_PT,
 138                                                   SC_RM_PERM_NONE);
 139                if (err) {
 140                        printf("Remove permission failed for img %d, err %d\n",
 141                               i, err);
 142                        ret = -EPERM;
 143                }
 144
 145                if (ret)
 146                        goto exit;
 147        }
 148
 149exit:
 150        if (sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0) != SC_ERR_NONE)
 151                printf("Error: release container failed!\n");
 152
 153        return ret;
 154}
 155
 156static int do_authenticate(struct cmd_tbl *cmdtp, int flag, int argc,
 157                           char *const argv[])
 158{
 159        ulong addr;
 160
 161        if (argc < 2)
 162                return CMD_RET_USAGE;
 163
 164        addr = hextoul(argv[1], NULL);
 165
 166        printf("Authenticate OS container at 0x%lx\n", addr);
 167
 168        if (authenticate_os_container(addr))
 169                return CMD_RET_FAILURE;
 170
 171        return CMD_RET_SUCCESS;
 172}
 173
 174static void display_life_cycle(u16 lc)
 175{
 176        printf("Lifecycle: 0x%04X, ", lc);
 177        switch (lc) {
 178        case 0x1:
 179                printf("Pristine\n\n");
 180                break;
 181        case 0x2:
 182                printf("Fab\n\n");
 183                break;
 184        case 0x8:
 185                printf("Open\n\n");
 186                break;
 187        case 0x20:
 188                printf("NXP closed\n\n");
 189                break;
 190        case 0x80:
 191                printf("OEM closed\n\n");
 192                break;
 193        case 0x100:
 194                printf("Partial field return\n\n");
 195                break;
 196        case 0x200:
 197                printf("Full field return\n\n");
 198                break;
 199        case 0x400:
 200                printf("No return\n\n");
 201                break;
 202        default:
 203                printf("Unknown\n\n");
 204                break;
 205        }
 206}
 207
 208#define AHAB_AUTH_CONTAINER_REQ 0x87
 209#define AHAB_VERIFY_IMAGE_REQ 0x88
 210
 211#define AHAB_NO_AUTHENTICATION_IND 0xee
 212#define AHAB_BAD_KEY_HASH_IND 0xfa
 213#define AHAB_INVALID_KEY_IND 0xf9
 214#define AHAB_BAD_SIGNATURE_IND 0xf0
 215#define AHAB_BAD_HASH_IND 0xf1
 216
 217static void display_ahab_auth_event(u32 event)
 218{
 219        u8 cmd = (event >> 16) & 0xff;
 220        u8 resp_ind = (event >> 8) & 0xff;
 221
 222        switch (cmd) {
 223        case AHAB_AUTH_CONTAINER_REQ:
 224                printf("\tCMD = AHAB_AUTH_CONTAINER_REQ (0x%02X)\n", cmd);
 225                printf("\tIND = ");
 226                break;
 227        case AHAB_VERIFY_IMAGE_REQ:
 228                printf("\tCMD = AHAB_VERIFY_IMAGE_REQ (0x%02X)\n", cmd);
 229                printf("\tIND = ");
 230                break;
 231        default:
 232                return;
 233        }
 234
 235        switch (resp_ind) {
 236        case AHAB_NO_AUTHENTICATION_IND:
 237                printf("AHAB_NO_AUTHENTICATION_IND (0x%02X)\n\n", resp_ind);
 238                break;
 239        case AHAB_BAD_KEY_HASH_IND:
 240                printf("AHAB_BAD_KEY_HASH_IND (0x%02X)\n\n", resp_ind);
 241                break;
 242        case AHAB_INVALID_KEY_IND:
 243                printf("AHAB_INVALID_KEY_IND (0x%02X)\n\n", resp_ind);
 244                break;
 245        case AHAB_BAD_SIGNATURE_IND:
 246                printf("AHAB_BAD_SIGNATURE_IND (0x%02X)\n\n", resp_ind);
 247                break;
 248        case AHAB_BAD_HASH_IND:
 249                printf("AHAB_BAD_HASH_IND (0x%02X)\n\n", resp_ind);
 250                break;
 251        default:
 252                printf("Unknown Indicator (0x%02X)\n\n", resp_ind);
 253                break;
 254        }
 255}
 256
 257static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc,
 258                          char *const argv[])
 259{
 260        int err;
 261        u8 idx = 0U;
 262        u32 event;
 263        u16 lc;
 264
 265        err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
 266        if (err != SC_ERR_NONE) {
 267                printf("Error in get lifecycle\n");
 268                return -EIO;
 269        }
 270
 271        display_life_cycle(lc);
 272
 273        err = sc_seco_get_event(-1, idx, &event);
 274        while (err == SC_ERR_NONE) {
 275                printf("SECO Event[%u] = 0x%08X\n", idx, event);
 276                display_ahab_auth_event(event);
 277
 278                idx++;
 279                err = sc_seco_get_event(-1, idx, &event);
 280        }
 281
 282        if (idx == 0)
 283                printf("No SECO Events Found!\n\n");
 284
 285        return 0;
 286}
 287
 288static int confirm_close(void)
 289{
 290        puts("Warning: Please ensure your sample is in NXP closed state, "
 291             "OEM SRK hash has been fused, \n"
 292             "         and you are able to boot a signed image successfully "
 293             "without any SECO events reported.\n"
 294             "         If not, your sample will be unrecoverable.\n"
 295             "\nReally perform this operation? <y/N>\n");
 296
 297        if (confirm_yesno())
 298                return 1;
 299
 300        puts("Ahab close aborted\n");
 301        return 0;
 302}
 303
 304static int do_ahab_close(struct cmd_tbl *cmdtp, int flag, int argc,
 305                         char *const argv[])
 306{
 307        int confirmed = argc >= 2 && !strcmp(argv[1], "-y");
 308        int err;
 309        u16 lc;
 310
 311        if (!confirmed && !confirm_close())
 312                return -EACCES;
 313
 314        err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
 315        if (err != SC_ERR_NONE) {
 316                printf("Error in get lifecycle\n");
 317                return -EIO;
 318        }
 319
 320        if (lc != 0x20) {
 321                puts("Current lifecycle is NOT NXP closed, can't move to OEM closed\n");
 322                display_life_cycle(lc);
 323                return -EPERM;
 324        }
 325
 326        err = sc_seco_forward_lifecycle(-1, 16);
 327        if (err != SC_ERR_NONE) {
 328                printf("Error in forward lifecycle to OEM closed\n");
 329                return -EIO;
 330        }
 331
 332        printf("Change to OEM closed successfully\n");
 333
 334        return 0;
 335}
 336
 337U_BOOT_CMD(auth_cntr, CONFIG_SYS_MAXARGS, 1, do_authenticate,
 338           "autenticate OS container via AHAB",
 339           "addr\n"
 340           "addr - OS container hex address\n"
 341);
 342
 343U_BOOT_CMD(ahab_status, CONFIG_SYS_MAXARGS, 1, do_ahab_status,
 344           "display AHAB lifecycle and events from seco",
 345           ""
 346);
 347
 348U_BOOT_CMD(ahab_close, CONFIG_SYS_MAXARGS, 1, do_ahab_close,
 349           "Change AHAB lifecycle to OEM closed",
 350           ""
 351);
 352