uboot/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2016 NXP Semiconductor, Inc.
   4 */
   5#include <common.h>
   6#include <log.h>
   7#include <malloc.h>
   8#include <config.h>
   9#include <errno.h>
  10#include <asm/cache.h>
  11#include <asm/global_data.h>
  12#include <asm/system.h>
  13#include <asm/types.h>
  14#include <asm/arch/soc.h>
  15#ifdef CONFIG_FSL_LSCH3
  16#include <asm/arch/immap_lsch3.h>
  17#elif defined(CONFIG_FSL_LSCH2)
  18#include <asm/arch/immap_lsch2.h>
  19#endif
  20#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
  21#include <asm/armv8/sec_firmware.h>
  22#endif
  23#ifdef CONFIG_CHAIN_OF_TRUST
  24#include <fsl_validate.h>
  25#endif
  26
  27#ifdef CONFIG_SYS_LS_PPA_FW_IN_NAND
  28#include <nand.h>
  29#elif defined(CONFIG_SYS_LS_PPA_FW_IN_MMC)
  30#include <mmc.h>
  31#endif
  32
  33DECLARE_GLOBAL_DATA_PTR;
  34
  35int ppa_init(void)
  36{
  37        unsigned int el = current_el();
  38        void *ppa_fit_addr;
  39        u32 *boot_loc_ptr_l, *boot_loc_ptr_h;
  40        u32 *loadable_l, *loadable_h;
  41        int ret;
  42
  43#ifdef CONFIG_CHAIN_OF_TRUST
  44        uintptr_t ppa_esbc_hdr = 0;
  45        uintptr_t ppa_img_addr = 0;
  46#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \
  47        defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
  48        void *ppa_hdr_ddr;
  49#endif
  50#endif
  51
  52        /* Skip if running at lower exception level */
  53        if (el < 3) {
  54                debug("Skipping PPA init, running at EL%d\n", el);
  55                return 0;
  56        }
  57
  58#ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP
  59        ppa_fit_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR;
  60        debug("%s: PPA image load from XIP\n", __func__);
  61#ifdef CONFIG_CHAIN_OF_TRUST
  62        ppa_esbc_hdr = CONFIG_SYS_LS_PPA_ESBC_ADDR;
  63#endif
  64#else /* !CONFIG_SYS_LS_PPA_FW_IN_XIP */
  65        size_t fw_length, fdt_header_len = sizeof(struct fdt_header);
  66
  67        /* Copy PPA image from MMC/SD/NAND to allocated memory */
  68#ifdef CONFIG_SYS_LS_PPA_FW_IN_MMC
  69        struct mmc *mmc;
  70        int dev = CONFIG_SYS_MMC_ENV_DEV;
  71        struct fdt_header *fitp;
  72        u32 cnt;
  73        u32 blk;
  74
  75        debug("%s: PPA image load from eMMC/SD\n", __func__);
  76
  77        ret = mmc_initialize(gd->bd);
  78        if (ret) {
  79                printf("%s: mmc_initialize() failed\n", __func__);
  80                return ret;
  81        }
  82        mmc = find_mmc_device(dev);
  83        if (!mmc) {
  84                printf("PPA: MMC cannot find device for PPA firmware\n");
  85                return -ENODEV;
  86        }
  87
  88        ret = mmc_init(mmc);
  89        if (ret) {
  90                printf("%s: mmc_init() failed\n", __func__);
  91                return ret;
  92        }
  93
  94        fitp = malloc(roundup(fdt_header_len, 512));
  95        if (!fitp) {
  96                printf("PPA: malloc failed for FIT header(size 0x%zx)\n",
  97                       roundup(fdt_header_len, 512));
  98                return -ENOMEM;
  99        }
 100
 101        blk = CONFIG_SYS_LS_PPA_FW_ADDR / 512;
 102        cnt = DIV_ROUND_UP(fdt_header_len, 512);
 103        debug("%s: MMC read PPA FIT header: dev # %u, block # %u, count %u\n",
 104              __func__, dev, blk, cnt);
 105        ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, fitp);
 106        if (ret != cnt) {
 107                free(fitp);
 108                printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n",
 109                       CONFIG_SYS_LS_PPA_FW_ADDR);
 110                return -EIO;
 111        }
 112
 113        ret = fdt_check_header(fitp);
 114        if (ret) {
 115                free(fitp);
 116                printf("%s: fdt_check_header() failed\n", __func__);
 117                return ret;
 118        }
 119
 120#ifdef CONFIG_CHAIN_OF_TRUST
 121        ppa_hdr_ddr = malloc(CONFIG_LS_PPA_ESBC_HDR_SIZE);
 122        if (!ppa_hdr_ddr) {
 123                printf("PPA: malloc failed for PPA header\n");
 124                return -ENOMEM;
 125        }
 126
 127        blk = CONFIG_SYS_LS_PPA_ESBC_ADDR >> 9;
 128        cnt = DIV_ROUND_UP(CONFIG_LS_PPA_ESBC_HDR_SIZE, 512);
 129        ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, ppa_hdr_ddr);
 130        if (ret != cnt) {
 131                free(ppa_hdr_ddr);
 132                printf("MMC/SD read of PPA header failed\n");
 133                return -EIO;
 134        }
 135        debug("Read PPA header to 0x%p\n", ppa_hdr_ddr);
 136
 137        ppa_esbc_hdr = (uintptr_t)ppa_hdr_ddr;
 138#endif
 139
 140        fw_length = fdt_totalsize(fitp);
 141        free(fitp);
 142
 143        fw_length = roundup(fw_length, 512);
 144        ppa_fit_addr = malloc(fw_length);
 145        if (!ppa_fit_addr) {
 146                printf("PPA: malloc failed for PPA image(size 0x%zx)\n",
 147                       fw_length);
 148                return -ENOMEM;
 149        }
 150
 151        blk = CONFIG_SYS_LS_PPA_FW_ADDR / 512;
 152        cnt = DIV_ROUND_UP(fw_length, 512);
 153        debug("%s: MMC read PPA FIT image: dev # %u, block # %u, count %u\n",
 154              __func__, dev, blk, cnt);
 155        ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, ppa_fit_addr);
 156        if (ret != cnt) {
 157                free(ppa_fit_addr);
 158                printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n",
 159                       CONFIG_SYS_LS_PPA_FW_ADDR);
 160                return -EIO;
 161        }
 162
 163#elif defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
 164        struct fdt_header fit;
 165
 166        debug("%s: PPA image load from NAND\n", __func__);
 167
 168        nand_init();
 169        ret = nand_read(get_nand_dev_by_index(0),
 170                        (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
 171                        &fdt_header_len, (u_char *)&fit);
 172        if (ret == -EUCLEAN) {
 173                printf("NAND read of PPA FIT header at offset 0x%x failed\n",
 174                       CONFIG_SYS_LS_PPA_FW_ADDR);
 175                return -EIO;
 176        }
 177
 178        ret = fdt_check_header(&fit);
 179        if (ret) {
 180                printf("%s: fdt_check_header() failed\n", __func__);
 181                return ret;
 182        }
 183
 184#ifdef CONFIG_CHAIN_OF_TRUST
 185        ppa_hdr_ddr = malloc(CONFIG_LS_PPA_ESBC_HDR_SIZE);
 186        if (!ppa_hdr_ddr) {
 187                printf("PPA: malloc failed for PPA header\n");
 188                return -ENOMEM;
 189        }
 190
 191        fw_length = CONFIG_LS_PPA_ESBC_HDR_SIZE;
 192
 193        ret = nand_read(get_nand_dev_by_index(0),
 194                        (loff_t)CONFIG_SYS_LS_PPA_ESBC_ADDR,
 195                        &fw_length, (u_char *)ppa_hdr_ddr);
 196        if (ret == -EUCLEAN) {
 197                free(ppa_hdr_ddr);
 198                printf("NAND read of PPA firmware at offset 0x%x failed\n",
 199                       CONFIG_SYS_LS_PPA_FW_ADDR);
 200                return -EIO;
 201        }
 202        debug("Read PPA header to 0x%p\n", ppa_hdr_ddr);
 203
 204        ppa_esbc_hdr = (uintptr_t)ppa_hdr_ddr;
 205#endif
 206
 207        fw_length = fdt_totalsize(&fit);
 208
 209        ppa_fit_addr = malloc(fw_length);
 210        if (!ppa_fit_addr) {
 211                printf("PPA: malloc failed for PPA image(size 0x%zx)\n",
 212                       fw_length);
 213                return -ENOMEM;
 214        }
 215
 216        ret = nand_read(get_nand_dev_by_index(0),
 217                        (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
 218                        &fw_length, (u_char *)ppa_fit_addr);
 219        if (ret == -EUCLEAN) {
 220                free(ppa_fit_addr);
 221                printf("NAND read of PPA firmware at offset 0x%x failed\n",
 222                       CONFIG_SYS_LS_PPA_FW_ADDR);
 223                return -EIO;
 224        }
 225#else
 226#error "No CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
 227#endif
 228
 229#endif
 230
 231#ifdef CONFIG_CHAIN_OF_TRUST
 232        ppa_img_addr = (uintptr_t)ppa_fit_addr;
 233        if (fsl_check_boot_mode_secure() != 0) {
 234                /*
 235                 * In case of failure in validation, fsl_secboot_validate
 236                 * would not return back in case of Production environment
 237                 * with ITS=1. In Development environment (ITS=0 and
 238                 * SB_EN=1), the function may return back in case of
 239                 * non-fatal failures.
 240                 */
 241                ret = fsl_secboot_validate(ppa_esbc_hdr,
 242                                           PPA_KEY_HASH,
 243                                           &ppa_img_addr);
 244                if (ret != 0)
 245                        printf("SEC firmware(s) validation failed\n");
 246                else
 247                        printf("SEC firmware(s) validation Successful\n");
 248        }
 249#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \
 250        defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
 251        free(ppa_hdr_ddr);
 252#endif
 253#endif
 254
 255#ifdef CONFIG_FSL_LSCH3
 256        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
 257        boot_loc_ptr_l = &gur->bootlocptrl;
 258        boot_loc_ptr_h = &gur->bootlocptrh;
 259
 260        /* Assign addresses to loadable ptrs */
 261        loadable_l = &gur->scratchrw[4];
 262        loadable_h = &gur->scratchrw[5];
 263#elif defined(CONFIG_FSL_LSCH2)
 264        struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR);
 265        boot_loc_ptr_l = &scfg->scratchrw[1];
 266        boot_loc_ptr_h = &scfg->scratchrw[0];
 267
 268        /* Assign addresses to loadable ptrs */
 269        loadable_l = &scfg->scratchrw[2];
 270        loadable_h = &scfg->scratchrw[3];
 271#endif
 272
 273        debug("fsl-ppa: boot_loc_ptr_l = 0x%p, boot_loc_ptr_h =0x%p\n",
 274              boot_loc_ptr_l, boot_loc_ptr_h);
 275        ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h,
 276                                loadable_l, loadable_h);
 277
 278#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \
 279        defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
 280        free(ppa_fit_addr);
 281#endif
 282
 283        return ret;
 284}
 285