1*2ddb5575SBiju Das /* 2*2ddb5575SBiju Das * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. 3*2ddb5575SBiju Das * 4*2ddb5575SBiju Das * SPDX-License-Identifier: BSD-3-Clause 5*2ddb5575SBiju Das */ 6*2ddb5575SBiju Das 7*2ddb5575SBiju Das #include <errno.h> 8*2ddb5575SBiju Das #include <stdint.h> 9*2ddb5575SBiju Das #include <string.h> 10*2ddb5575SBiju Das 11*2ddb5575SBiju Das #include <arch_helpers.h> 12*2ddb5575SBiju Das #include <common/bl_common.h> 13*2ddb5575SBiju Das #include <common/debug.h> 14*2ddb5575SBiju Das #include <drivers/auth/auth_mod.h> 15*2ddb5575SBiju Das #include <drivers/io/io_driver.h> 16*2ddb5575SBiju Das #include <drivers/io/io_storage.h> 17*2ddb5575SBiju Das #include <lib/mmio.h> 18*2ddb5575SBiju Das #include <plat/common/platform.h> 19*2ddb5575SBiju Das #include <tools_share/firmware_image_package.h> 20*2ddb5575SBiju Das #include <tools_share/uuid.h> 21*2ddb5575SBiju Das 22*2ddb5575SBiju Das #include "io_rcar.h" 23*2ddb5575SBiju Das #include "io_common.h" 24*2ddb5575SBiju Das #include "io_private.h" 25*2ddb5575SBiju Das #include <platform_def.h> 26*2ddb5575SBiju Das 27*2ddb5575SBiju Das extern int32_t plat_get_drv_source(uint32_t id, uintptr_t *dev, 28*2ddb5575SBiju Das uintptr_t *image_spec); 29*2ddb5575SBiju Das 30*2ddb5575SBiju Das static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), 31*2ddb5575SBiju Das io_dev_info_t **dev_info); 32*2ddb5575SBiju Das static int32_t rcar_dev_close(io_dev_info_t *dev_info); 33*2ddb5575SBiju Das 34*2ddb5575SBiju Das typedef struct { 35*2ddb5575SBiju Das const int32_t name; 36*2ddb5575SBiju Das const uint32_t offset; 37*2ddb5575SBiju Das const uint32_t attr; 38*2ddb5575SBiju Das } plat_rcar_name_offset_t; 39*2ddb5575SBiju Das 40*2ddb5575SBiju Das typedef struct { 41*2ddb5575SBiju Das /* 42*2ddb5575SBiju Das * Put position above the struct to allow {0} on static init. 43*2ddb5575SBiju Das * It is a workaround for a known bug in GCC 44*2ddb5575SBiju Das * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 45*2ddb5575SBiju Das */ 46*2ddb5575SBiju Das uint32_t position; 47*2ddb5575SBiju Das uint32_t no_load; 48*2ddb5575SBiju Das uintptr_t offset; 49*2ddb5575SBiju Das uint32_t size; 50*2ddb5575SBiju Das uintptr_t dst; 51*2ddb5575SBiju Das uintptr_t partition; /* for eMMC */ 52*2ddb5575SBiju Das /* RCAR_EMMC_PARTITION_BOOT_0 */ 53*2ddb5575SBiju Das /* RCAR_EMMC_PARTITION_BOOT_1 */ 54*2ddb5575SBiju Das /* RCAR_EMMC_PARTITION_USER */ 55*2ddb5575SBiju Das } file_state_t; 56*2ddb5575SBiju Das 57*2ddb5575SBiju Das #define RCAR_GET_FLASH_ADR(a, b) ((uint32_t)((0x40000U * (a)) + (b))) 58*2ddb5575SBiju Das #define RCAR_ATTR_SET_CALCADDR(a) ((a) & 0xF) 59*2ddb5575SBiju Das #define RCAR_ATTR_SET_ISNOLOAD(a) (((a) & 0x1) << 16U) 60*2ddb5575SBiju Das #define RCAR_ATTR_SET_CERTOFF(a) (((a) & 0xF) << 8U) 61*2ddb5575SBiju Das #define RCAR_ATTR_SET_ALL(a, b, c) ((uint32_t)(RCAR_ATTR_SET_CALCADDR(a) |\ 62*2ddb5575SBiju Das RCAR_ATTR_SET_ISNOLOAD(b) |\ 63*2ddb5575SBiju Das RCAR_ATTR_SET_CERTOFF(c))) 64*2ddb5575SBiju Das 65*2ddb5575SBiju Das #define RCAR_ATTR_GET_CALCADDR(a) ((a) & 0xFU) 66*2ddb5575SBiju Das #define RCAR_ATTR_GET_ISNOLOAD(a) (((a) >> 16) & 0x1U) 67*2ddb5575SBiju Das #define RCAR_ATTR_GET_CERTOFF(a) ((uint32_t)(((a) >> 8) & 0xFU)) 68*2ddb5575SBiju Das 69*2ddb5575SBiju Das #define RCAR_MAX_BL3X_IMAGE (8U) 70*2ddb5575SBiju Das #define RCAR_SECTOR6_CERT_OFFSET (0x400U) 71*2ddb5575SBiju Das #define RCAR_SDRAM_certESS (0x43F00000U) 72*2ddb5575SBiju Das #define RCAR_CERT_SIZE (0x800U) 73*2ddb5575SBiju Das #define RCAR_CERT_INFO_SIZE_OFFSET (0x264U) 74*2ddb5575SBiju Das #define RCAR_CERT_INFO_DST_OFFSET (0x154U) 75*2ddb5575SBiju Das #define RCAR_CERT_INFO_SIZE_OFFSET1 (0x364U) 76*2ddb5575SBiju Das #define RCAR_CERT_INFO_DST_OFFSET1 (0x1D4U) 77*2ddb5575SBiju Das #define RCAR_CERT_INFO_SIZE_OFFSET2 (0x464U) 78*2ddb5575SBiju Das #define RCAR_CERT_INFO_DST_OFFSET2 (0x254U) 79*2ddb5575SBiju Das #define RCAR_CERT_LOAD (1U) 80*2ddb5575SBiju Das 81*2ddb5575SBiju Das #define RCAR_FLASH_CERT_HEADER RCAR_GET_FLASH_ADR(6U, 0U) 82*2ddb5575SBiju Das #define RCAR_EMMC_CERT_HEADER (0x00030000U) 83*2ddb5575SBiju Das 84*2ddb5575SBiju Das #define RCAR_COUNT_LOAD_BL33 (2U) 85*2ddb5575SBiju Das #define RCAR_COUNT_LOAD_BL33X (3U) 86*2ddb5575SBiju Das 87*2ddb5575SBiju Das static const plat_rcar_name_offset_t name_offset[] = { 88*2ddb5575SBiju Das {BL31_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(0, 0, 0)}, 89*2ddb5575SBiju Das 90*2ddb5575SBiju Das /* BL3-2 is optional in the platform */ 91*2ddb5575SBiju Das {BL32_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(1, 0, 1)}, 92*2ddb5575SBiju Das {BL33_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(2, 0, 2)}, 93*2ddb5575SBiju Das {BL332_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(3, 0, 3)}, 94*2ddb5575SBiju Das {BL333_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(4, 0, 4)}, 95*2ddb5575SBiju Das {BL334_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(5, 0, 5)}, 96*2ddb5575SBiju Das {BL335_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(6, 0, 6)}, 97*2ddb5575SBiju Das {BL336_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(7, 0, 7)}, 98*2ddb5575SBiju Das {BL337_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(8, 0, 8)}, 99*2ddb5575SBiju Das {BL338_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(9, 0, 9)}, 100*2ddb5575SBiju Das }; 101*2ddb5575SBiju Das 102*2ddb5575SBiju Das #if TRUSTED_BOARD_BOOT 103*2ddb5575SBiju Das static const plat_rcar_name_offset_t cert_offset[] = { 104*2ddb5575SBiju Das /* Certificates */ 105*2ddb5575SBiju Das {TRUSTED_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, 106*2ddb5575SBiju Das {SOC_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, 107*2ddb5575SBiju Das {TRUSTED_OS_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, 108*2ddb5575SBiju Das {NON_TRUSTED_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, 109*2ddb5575SBiju Das {SOC_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, 110*2ddb5575SBiju Das {TRUSTED_OS_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 1)}, 111*2ddb5575SBiju Das {NON_TRUSTED_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 2)}, 112*2ddb5575SBiju Das {BL332_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 3)}, 113*2ddb5575SBiju Das {BL333_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 4)}, 114*2ddb5575SBiju Das {BL334_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 5)}, 115*2ddb5575SBiju Das {BL335_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 6)}, 116*2ddb5575SBiju Das {BL336_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 7)}, 117*2ddb5575SBiju Das {BL337_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 8)}, 118*2ddb5575SBiju Das {BL338_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 9)}, 119*2ddb5575SBiju Das }; 120*2ddb5575SBiju Das #endif /* TRUSTED_BOARD_BOOT */ 121*2ddb5575SBiju Das 122*2ddb5575SBiju Das static file_state_t current_file = { 0 }; 123*2ddb5575SBiju Das 124*2ddb5575SBiju Das static uintptr_t rcar_handle, rcar_spec; 125*2ddb5575SBiju Das static uint64_t rcar_image_header[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; 126*2ddb5575SBiju Das static uint64_t rcar_image_header_prttn[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; 127*2ddb5575SBiju Das static uint64_t rcar_image_number = { 0U }; 128*2ddb5575SBiju Das static uint32_t rcar_cert_load = { 0U }; 129*2ddb5575SBiju Das 130*2ddb5575SBiju Das static io_type_t device_type_rcar(void) 131*2ddb5575SBiju Das { 132*2ddb5575SBiju Das return IO_TYPE_FIRMWARE_IMAGE_PACKAGE; 133*2ddb5575SBiju Das } 134*2ddb5575SBiju Das 135*2ddb5575SBiju Das int32_t rcar_get_certificate(const int32_t name, uint32_t *cert) 136*2ddb5575SBiju Das { 137*2ddb5575SBiju Das #if TRUSTED_BOARD_BOOT 138*2ddb5575SBiju Das int32_t i; 139*2ddb5575SBiju Das 140*2ddb5575SBiju Das for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { 141*2ddb5575SBiju Das if (name != cert_offset[i].name) { 142*2ddb5575SBiju Das continue; 143*2ddb5575SBiju Das } 144*2ddb5575SBiju Das 145*2ddb5575SBiju Das *cert = RCAR_CERT_SIZE; 146*2ddb5575SBiju Das *cert *= RCAR_ATTR_GET_CERTOFF(cert_offset[i].attr); 147*2ddb5575SBiju Das *cert += RCAR_SDRAM_certESS; 148*2ddb5575SBiju Das return 0; 149*2ddb5575SBiju Das } 150*2ddb5575SBiju Das #endif 151*2ddb5575SBiju Das return -EINVAL; 152*2ddb5575SBiju Das } 153*2ddb5575SBiju Das 154*2ddb5575SBiju Das static int32_t file_to_offset(const int32_t name, uintptr_t *offset, 155*2ddb5575SBiju Das uint32_t *cert, uint32_t *no_load, 156*2ddb5575SBiju Das uintptr_t *partition) 157*2ddb5575SBiju Das { 158*2ddb5575SBiju Das uint32_t addr; 159*2ddb5575SBiju Das int32_t i; 160*2ddb5575SBiju Das 161*2ddb5575SBiju Das for (i = 0; i < ARRAY_SIZE(name_offset); i++) { 162*2ddb5575SBiju Das if (name != name_offset[i].name) { 163*2ddb5575SBiju Das continue; 164*2ddb5575SBiju Das } 165*2ddb5575SBiju Das 166*2ddb5575SBiju Das addr = RCAR_ATTR_GET_CALCADDR(name_offset[i].attr); 167*2ddb5575SBiju Das if (rcar_image_number + 2U < addr) { 168*2ddb5575SBiju Das continue; 169*2ddb5575SBiju Das } 170*2ddb5575SBiju Das 171*2ddb5575SBiju Das *offset = rcar_image_header[addr]; 172*2ddb5575SBiju Das *cert = RCAR_CERT_SIZE; 173*2ddb5575SBiju Das *cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr); 174*2ddb5575SBiju Das *cert += RCAR_SDRAM_certESS; 175*2ddb5575SBiju Das *no_load = RCAR_ATTR_GET_ISNOLOAD(name_offset[i].attr); 176*2ddb5575SBiju Das *partition = rcar_image_header_prttn[addr]; 177*2ddb5575SBiju Das return IO_SUCCESS; 178*2ddb5575SBiju Das } 179*2ddb5575SBiju Das 180*2ddb5575SBiju Das #if TRUSTED_BOARD_BOOT 181*2ddb5575SBiju Das for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { 182*2ddb5575SBiju Das if (name != cert_offset[i].name) { 183*2ddb5575SBiju Das continue; 184*2ddb5575SBiju Das } 185*2ddb5575SBiju Das 186*2ddb5575SBiju Das *no_load = RCAR_ATTR_GET_ISNOLOAD(cert_offset[i].attr); 187*2ddb5575SBiju Das *partition = 0U; 188*2ddb5575SBiju Das *offset = 0U; 189*2ddb5575SBiju Das *cert = 0U; 190*2ddb5575SBiju Das return IO_SUCCESS; 191*2ddb5575SBiju Das } 192*2ddb5575SBiju Das #endif 193*2ddb5575SBiju Das return -EINVAL; 194*2ddb5575SBiju Das } 195*2ddb5575SBiju Das 196*2ddb5575SBiju Das #define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U) 197*2ddb5575SBiju Das #define RCAR_CERT_MAGIC_NUM (0xE291F358U) 198*2ddb5575SBiju Das 199*2ddb5575SBiju Das void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *dst) 200*2ddb5575SBiju Das { 201*2ddb5575SBiju Das uint32_t seed, val, info_1, info_2; 202*2ddb5575SBiju Das uintptr_t size, dsth, dstl; 203*2ddb5575SBiju Das 204*2ddb5575SBiju Das cert &= 0xFFFFFFFFU; 205*2ddb5575SBiju Das 206*2ddb5575SBiju Das seed = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW); 207*2ddb5575SBiju Das val = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW + 0xC); 208*2ddb5575SBiju Das info_1 = (val >> 18) & 0x3U; 209*2ddb5575SBiju Das val = mmio_read_32(cert + 0xC); 210*2ddb5575SBiju Das info_2 = (val >> 21) & 0x3; 211*2ddb5575SBiju Das 212*2ddb5575SBiju Das if (seed == RCAR_CERT_MAGIC_NUM) { 213*2ddb5575SBiju Das if (info_1 != 1) { 214*2ddb5575SBiju Das ERROR("BL2: Cert is invalid.\n"); 215*2ddb5575SBiju Das *dst = 0; 216*2ddb5575SBiju Das *len = 0; 217*2ddb5575SBiju Das return; 218*2ddb5575SBiju Das } 219*2ddb5575SBiju Das 220*2ddb5575SBiju Das if (info_2 > 2) { 221*2ddb5575SBiju Das ERROR("BL2: Cert is invalid.\n"); 222*2ddb5575SBiju Das *dst = 0; 223*2ddb5575SBiju Das *len = 0; 224*2ddb5575SBiju Das return; 225*2ddb5575SBiju Das } 226*2ddb5575SBiju Das 227*2ddb5575SBiju Das switch (info_2) { 228*2ddb5575SBiju Das case 2: 229*2ddb5575SBiju Das size = cert + RCAR_CERT_INFO_SIZE_OFFSET2; 230*2ddb5575SBiju Das dstl = cert + RCAR_CERT_INFO_DST_OFFSET2; 231*2ddb5575SBiju Das break; 232*2ddb5575SBiju Das case 1: 233*2ddb5575SBiju Das size = cert + RCAR_CERT_INFO_SIZE_OFFSET1; 234*2ddb5575SBiju Das dstl = cert + RCAR_CERT_INFO_DST_OFFSET1; 235*2ddb5575SBiju Das break; 236*2ddb5575SBiju Das case 0: 237*2ddb5575SBiju Das size = cert + RCAR_CERT_INFO_SIZE_OFFSET; 238*2ddb5575SBiju Das dstl = cert + RCAR_CERT_INFO_DST_OFFSET; 239*2ddb5575SBiju Das break; 240*2ddb5575SBiju Das } 241*2ddb5575SBiju Das 242*2ddb5575SBiju Das *len = mmio_read_32(size) * 4U; 243*2ddb5575SBiju Das dsth = dstl + 4U; 244*2ddb5575SBiju Das *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + 245*2ddb5575SBiju Das ((uintptr_t) mmio_read_32(dstl)); 246*2ddb5575SBiju Das return; 247*2ddb5575SBiju Das } 248*2ddb5575SBiju Das 249*2ddb5575SBiju Das size = cert + RCAR_CERT_INFO_SIZE_OFFSET; 250*2ddb5575SBiju Das *len = mmio_read_32(size) * 4U; 251*2ddb5575SBiju Das dstl = cert + RCAR_CERT_INFO_DST_OFFSET; 252*2ddb5575SBiju Das dsth = dstl + 4U; 253*2ddb5575SBiju Das *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + 254*2ddb5575SBiju Das ((uintptr_t) mmio_read_32(dstl)); 255*2ddb5575SBiju Das } 256*2ddb5575SBiju Das 257*2ddb5575SBiju Das static int32_t check_load_area(uintptr_t dst, uintptr_t len) 258*2ddb5575SBiju Das { 259*2ddb5575SBiju Das uint32_t legacy = dst + len <= UINT32_MAX - 1 ? 1 : 0; 260*2ddb5575SBiju Das uintptr_t dram_start, dram_end; 261*2ddb5575SBiju Das uintptr_t prot_start, prot_end; 262*2ddb5575SBiju Das int32_t result = IO_SUCCESS; 263*2ddb5575SBiju Das 264*2ddb5575SBiju Das dram_start = legacy ? DRAM1_BASE : DRAM_40BIT_BASE; 265*2ddb5575SBiju Das 266*2ddb5575SBiju Das dram_end = legacy ? DRAM1_BASE + DRAM1_SIZE : 267*2ddb5575SBiju Das DRAM_40BIT_BASE + DRAM_40BIT_SIZE; 268*2ddb5575SBiju Das 269*2ddb5575SBiju Das prot_start = legacy ? DRAM_PROTECTED_BASE : DRAM_40BIT_PROTECTED_BASE; 270*2ddb5575SBiju Das 271*2ddb5575SBiju Das prot_end = prot_start + DRAM_PROTECTED_SIZE; 272*2ddb5575SBiju Das 273*2ddb5575SBiju Das if (dst < dram_start || dst > dram_end - len) { 274*2ddb5575SBiju Das ERROR("BL2: dst address is on the protected area.\n"); 275*2ddb5575SBiju Das result = IO_FAIL; 276*2ddb5575SBiju Das goto done; 277*2ddb5575SBiju Das } 278*2ddb5575SBiju Das 279*2ddb5575SBiju Das /* load image is within SDRAM protected area */ 280*2ddb5575SBiju Das if (dst >= prot_start && dst < prot_end) { 281*2ddb5575SBiju Das ERROR("BL2: dst address is on the protected area.\n"); 282*2ddb5575SBiju Das result = IO_FAIL; 283*2ddb5575SBiju Das } 284*2ddb5575SBiju Das 285*2ddb5575SBiju Das if (dst < prot_start && dst > prot_start - len) { 286*2ddb5575SBiju Das ERROR("BL2: loaded data is on the protected area.\n"); 287*2ddb5575SBiju Das result = IO_FAIL; 288*2ddb5575SBiju Das } 289*2ddb5575SBiju Das done: 290*2ddb5575SBiju Das if (result == IO_FAIL) { 291*2ddb5575SBiju Das ERROR("BL2: Out of range : dst=0x%lx len=0x%lx\n", dst, len); 292*2ddb5575SBiju Das } 293*2ddb5575SBiju Das 294*2ddb5575SBiju Das return result; 295*2ddb5575SBiju Das } 296*2ddb5575SBiju Das 297*2ddb5575SBiju Das static int32_t load_bl33x(void) 298*2ddb5575SBiju Das { 299*2ddb5575SBiju Das static int32_t loaded = IO_NOT_SUPPORTED; 300*2ddb5575SBiju Das uintptr_t dst, partition, handle; 301*2ddb5575SBiju Das uint32_t noload, cert, len, i; 302*2ddb5575SBiju Das uintptr_t offset; 303*2ddb5575SBiju Das int32_t rc; 304*2ddb5575SBiju Das size_t cnt; 305*2ddb5575SBiju Das const int32_t img[] = { 306*2ddb5575SBiju Das BL33_IMAGE_ID, 307*2ddb5575SBiju Das BL332_IMAGE_ID, 308*2ddb5575SBiju Das BL333_IMAGE_ID, 309*2ddb5575SBiju Das BL334_IMAGE_ID, 310*2ddb5575SBiju Das BL335_IMAGE_ID, 311*2ddb5575SBiju Das BL336_IMAGE_ID, 312*2ddb5575SBiju Das BL337_IMAGE_ID, 313*2ddb5575SBiju Das BL338_IMAGE_ID 314*2ddb5575SBiju Das }; 315*2ddb5575SBiju Das 316*2ddb5575SBiju Das if (loaded != IO_NOT_SUPPORTED) { 317*2ddb5575SBiju Das return loaded; 318*2ddb5575SBiju Das } 319*2ddb5575SBiju Das 320*2ddb5575SBiju Das for (i = 1; i < rcar_image_number; i++) { 321*2ddb5575SBiju Das rc = file_to_offset(img[i], &offset, &cert, &noload, 322*2ddb5575SBiju Das &partition); 323*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 324*2ddb5575SBiju Das WARN("%s: failed to get offset\n", __func__); 325*2ddb5575SBiju Das loaded = IO_FAIL; 326*2ddb5575SBiju Das return loaded; 327*2ddb5575SBiju Das } 328*2ddb5575SBiju Das 329*2ddb5575SBiju Das rcar_read_certificate((uint64_t) cert, &len, &dst); 330*2ddb5575SBiju Das ((io_drv_spec_t *) rcar_spec)->partition = partition; 331*2ddb5575SBiju Das 332*2ddb5575SBiju Das rc = io_open(rcar_handle, rcar_spec, &handle); 333*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 334*2ddb5575SBiju Das WARN("%s: Failed to open FIP (%i)\n", __func__, rc); 335*2ddb5575SBiju Das loaded = IO_FAIL; 336*2ddb5575SBiju Das return loaded; 337*2ddb5575SBiju Das } 338*2ddb5575SBiju Das 339*2ddb5575SBiju Das rc = io_seek(handle, IO_SEEK_SET, offset); 340*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 341*2ddb5575SBiju Das WARN("%s: failed to seek\n", __func__); 342*2ddb5575SBiju Das loaded = IO_FAIL; 343*2ddb5575SBiju Das return loaded; 344*2ddb5575SBiju Das } 345*2ddb5575SBiju Das 346*2ddb5575SBiju Das rc = check_load_area(dst, len); 347*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 348*2ddb5575SBiju Das WARN("%s: check load area\n", __func__); 349*2ddb5575SBiju Das loaded = IO_FAIL; 350*2ddb5575SBiju Das return loaded; 351*2ddb5575SBiju Das } 352*2ddb5575SBiju Das 353*2ddb5575SBiju Das rc = io_read(handle, dst, len, &cnt); 354*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 355*2ddb5575SBiju Das WARN("%s: failed to read\n", __func__); 356*2ddb5575SBiju Das loaded = IO_FAIL; 357*2ddb5575SBiju Das return loaded; 358*2ddb5575SBiju Das } 359*2ddb5575SBiju Das #if TRUSTED_BOARD_BOOT 360*2ddb5575SBiju Das rc = auth_mod_verify_img(img[i], (void *)dst, len); 361*2ddb5575SBiju Das if (rc != 0) { 362*2ddb5575SBiju Das memset((void *)dst, 0x00, len); 363*2ddb5575SBiju Das loaded = IO_FAIL; 364*2ddb5575SBiju Das return loaded; 365*2ddb5575SBiju Das } 366*2ddb5575SBiju Das #endif 367*2ddb5575SBiju Das io_close(handle); 368*2ddb5575SBiju Das } 369*2ddb5575SBiju Das 370*2ddb5575SBiju Das loaded = IO_SUCCESS; 371*2ddb5575SBiju Das 372*2ddb5575SBiju Das return loaded; 373*2ddb5575SBiju Das } 374*2ddb5575SBiju Das 375*2ddb5575SBiju Das static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) 376*2ddb5575SBiju Das { 377*2ddb5575SBiju Das uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {0UL}; 378*2ddb5575SBiju Das uintptr_t handle; 379*2ddb5575SBiju Das ssize_t offset; 380*2ddb5575SBiju Das uint32_t i; 381*2ddb5575SBiju Das int32_t rc; 382*2ddb5575SBiju Das size_t cnt; 383*2ddb5575SBiju Das 384*2ddb5575SBiju Das /* Obtain a reference to the image by querying the platform layer */ 385*2ddb5575SBiju Das rc = plat_get_drv_source(name, &rcar_handle, &rcar_spec); 386*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 387*2ddb5575SBiju Das WARN("Failed to obtain reference to img %ld (%i)\n", name, rc); 388*2ddb5575SBiju Das return IO_FAIL; 389*2ddb5575SBiju Das } 390*2ddb5575SBiju Das 391*2ddb5575SBiju Das if (rcar_cert_load == RCAR_CERT_LOAD) { 392*2ddb5575SBiju Das return IO_SUCCESS; 393*2ddb5575SBiju Das } 394*2ddb5575SBiju Das 395*2ddb5575SBiju Das rc = io_open(rcar_handle, rcar_spec, &handle); 396*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 397*2ddb5575SBiju Das WARN("Failed to access img %ld (%i)\n", name, rc); 398*2ddb5575SBiju Das return IO_FAIL; 399*2ddb5575SBiju Das } 400*2ddb5575SBiju Das 401*2ddb5575SBiju Das /* 402*2ddb5575SBiju Das * get start address list 403*2ddb5575SBiju Das * [0] address num 404*2ddb5575SBiju Das * [1] BL33-1 image address 405*2ddb5575SBiju Das * [2] BL33-2 image address 406*2ddb5575SBiju Das * [3] BL33-3 image address 407*2ddb5575SBiju Das * [4] BL33-4 image address 408*2ddb5575SBiju Das * [5] BL33-5 image address 409*2ddb5575SBiju Das * [6] BL33-6 image address 410*2ddb5575SBiju Das * [7] BL33-7 image address 411*2ddb5575SBiju Das * [8] BL33-8 image address 412*2ddb5575SBiju Das */ 413*2ddb5575SBiju Das offset = name == EMMC_DEV_ID ? RCAR_EMMC_CERT_HEADER : 414*2ddb5575SBiju Das RCAR_FLASH_CERT_HEADER; 415*2ddb5575SBiju Das rc = io_seek(handle, IO_SEEK_SET, offset); 416*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 417*2ddb5575SBiju Das WARN("Firmware Image Package header failed to seek\n"); 418*2ddb5575SBiju Das goto error; 419*2ddb5575SBiju Das } 420*2ddb5575SBiju Das #if RCAR_BL2_DCACHE == 1 421*2ddb5575SBiju Das inv_dcache_range((uint64_t) header, sizeof(header)); 422*2ddb5575SBiju Das #endif 423*2ddb5575SBiju Das rc = io_read(handle, (uintptr_t) &header, sizeof(header), &cnt); 424*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 425*2ddb5575SBiju Das WARN("Firmware Image Package header failed to read\n"); 426*2ddb5575SBiju Das goto error; 427*2ddb5575SBiju Das } 428*2ddb5575SBiju Das 429*2ddb5575SBiju Das rcar_image_number = header[0]; 430*2ddb5575SBiju Das for (i = 0; i < rcar_image_number + 2; i++) { 431*2ddb5575SBiju Das rcar_image_header[i] = header[i * 2 + 1]; 432*2ddb5575SBiju Das rcar_image_header_prttn[i] = header[i * 2 + 2]; 433*2ddb5575SBiju Das } 434*2ddb5575SBiju Das 435*2ddb5575SBiju Das if (rcar_image_number == 0 || rcar_image_number > RCAR_MAX_BL3X_IMAGE) { 436*2ddb5575SBiju Das WARN("Firmware Image Package header check failed.\n"); 437*2ddb5575SBiju Das goto error; 438*2ddb5575SBiju Das } 439*2ddb5575SBiju Das 440*2ddb5575SBiju Das rc = io_seek(handle, IO_SEEK_SET, offset + RCAR_SECTOR6_CERT_OFFSET); 441*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 442*2ddb5575SBiju Das WARN("Firmware Image Package header failed to seek cert\n"); 443*2ddb5575SBiju Das goto error; 444*2ddb5575SBiju Das } 445*2ddb5575SBiju Das #if RCAR_BL2_DCACHE == 1 446*2ddb5575SBiju Das inv_dcache_range(RCAR_SDRAM_certESS, 447*2ddb5575SBiju Das RCAR_CERT_SIZE * (2 + rcar_image_number)); 448*2ddb5575SBiju Das #endif 449*2ddb5575SBiju Das rc = io_read(handle, RCAR_SDRAM_certESS, 450*2ddb5575SBiju Das RCAR_CERT_SIZE * (2 + rcar_image_number), &cnt); 451*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 452*2ddb5575SBiju Das WARN("cert file read error.\n"); 453*2ddb5575SBiju Das goto error; 454*2ddb5575SBiju Das } 455*2ddb5575SBiju Das 456*2ddb5575SBiju Das rcar_cert_load = RCAR_CERT_LOAD; 457*2ddb5575SBiju Das error: 458*2ddb5575SBiju Das 459*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 460*2ddb5575SBiju Das rc = IO_FAIL; 461*2ddb5575SBiju Das } 462*2ddb5575SBiju Das 463*2ddb5575SBiju Das io_close(handle); 464*2ddb5575SBiju Das 465*2ddb5575SBiju Das return rc; 466*2ddb5575SBiju Das 467*2ddb5575SBiju Das } 468*2ddb5575SBiju Das 469*2ddb5575SBiju Das static int32_t rcar_file_open(io_dev_info_t *info, const uintptr_t file_spec, 470*2ddb5575SBiju Das io_entity_t *entity) 471*2ddb5575SBiju Das { 472*2ddb5575SBiju Das const io_drv_spec_t *spec = (io_drv_spec_t *) file_spec; 473*2ddb5575SBiju Das uintptr_t partition, offset, dst; 474*2ddb5575SBiju Das uint32_t noload, cert, len; 475*2ddb5575SBiju Das int32_t rc; 476*2ddb5575SBiju Das 477*2ddb5575SBiju Das /* 478*2ddb5575SBiju Das * Only one file open at a time. We need to track state (ie, file 479*2ddb5575SBiju Das * cursor position). Since the header lives at offset zero, this entry 480*2ddb5575SBiju Das * should never be zero in an active file. 481*2ddb5575SBiju Das * Once the system supports dynamic memory allocation we will allow more 482*2ddb5575SBiju Das * than one open file at a time. 483*2ddb5575SBiju Das */ 484*2ddb5575SBiju Das if (current_file.offset != 0U) { 485*2ddb5575SBiju Das WARN("%s: Only one open file at a time.\n", __func__); 486*2ddb5575SBiju Das return IO_RESOURCES_EXHAUSTED; 487*2ddb5575SBiju Das } 488*2ddb5575SBiju Das 489*2ddb5575SBiju Das rc = file_to_offset(spec->offset, &offset, &cert, &noload, &partition); 490*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 491*2ddb5575SBiju Das WARN("Failed to open file name %ld (%i)\n", spec->offset, rc); 492*2ddb5575SBiju Das return IO_FAIL; 493*2ddb5575SBiju Das } 494*2ddb5575SBiju Das 495*2ddb5575SBiju Das if (noload != 0U) { 496*2ddb5575SBiju Das current_file.offset = 1; 497*2ddb5575SBiju Das current_file.dst = 0; 498*2ddb5575SBiju Das current_file.size = 1; 499*2ddb5575SBiju Das current_file.position = 0; 500*2ddb5575SBiju Das current_file.no_load = noload; 501*2ddb5575SBiju Das current_file.partition = 0; 502*2ddb5575SBiju Das entity->info = (uintptr_t) ¤t_file; 503*2ddb5575SBiju Das 504*2ddb5575SBiju Das return IO_SUCCESS; 505*2ddb5575SBiju Das } 506*2ddb5575SBiju Das 507*2ddb5575SBiju Das rcar_read_certificate((uint64_t) cert, &len, &dst); 508*2ddb5575SBiju Das 509*2ddb5575SBiju Das /* Baylibre: HACK */ 510*2ddb5575SBiju Das if (spec->offset == BL31_IMAGE_ID && len < RCAR_TRUSTED_SRAM_SIZE) { 511*2ddb5575SBiju Das WARN("%s,%s\n", "r-car ignoring the BL31 size from certificate", 512*2ddb5575SBiju Das "using RCAR_TRUSTED_SRAM_SIZE instead"); 513*2ddb5575SBiju Das len = RCAR_TRUSTED_SRAM_SIZE; 514*2ddb5575SBiju Das } 515*2ddb5575SBiju Das 516*2ddb5575SBiju Das current_file.partition = partition; 517*2ddb5575SBiju Das current_file.no_load = noload; 518*2ddb5575SBiju Das current_file.offset = offset; 519*2ddb5575SBiju Das current_file.position = 0; 520*2ddb5575SBiju Das current_file.size = len; 521*2ddb5575SBiju Das current_file.dst = dst; 522*2ddb5575SBiju Das entity->info = (uintptr_t) ¤t_file; 523*2ddb5575SBiju Das 524*2ddb5575SBiju Das return IO_SUCCESS; 525*2ddb5575SBiju Das } 526*2ddb5575SBiju Das 527*2ddb5575SBiju Das static int32_t rcar_file_len(io_entity_t *entity, size_t *length) 528*2ddb5575SBiju Das { 529*2ddb5575SBiju Das *length = ((file_state_t *) entity->info)->size; 530*2ddb5575SBiju Das 531*2ddb5575SBiju Das NOTICE("%s: len: 0x%08lx\n", __func__, *length); 532*2ddb5575SBiju Das 533*2ddb5575SBiju Das return IO_SUCCESS; 534*2ddb5575SBiju Das } 535*2ddb5575SBiju Das 536*2ddb5575SBiju Das static int32_t rcar_file_read(io_entity_t *entity, uintptr_t buffer, 537*2ddb5575SBiju Das size_t length, size_t *cnt) 538*2ddb5575SBiju Das { 539*2ddb5575SBiju Das file_state_t *fp = (file_state_t *) entity->info; 540*2ddb5575SBiju Das ssize_t offset = fp->offset + fp->position; 541*2ddb5575SBiju Das uintptr_t handle; 542*2ddb5575SBiju Das int32_t rc; 543*2ddb5575SBiju Das 544*2ddb5575SBiju Das #ifdef SPD_NONE 545*2ddb5575SBiju Das static uint32_t load_bl33x_counter = 1; 546*2ddb5575SBiju Das #else 547*2ddb5575SBiju Das static uint32_t load_bl33x_counter; 548*2ddb5575SBiju Das #endif 549*2ddb5575SBiju Das if (current_file.no_load != 0U) { 550*2ddb5575SBiju Das *cnt = length; 551*2ddb5575SBiju Das return IO_SUCCESS; 552*2ddb5575SBiju Das } 553*2ddb5575SBiju Das 554*2ddb5575SBiju Das ((io_drv_spec_t *) rcar_spec)->partition = fp->partition; 555*2ddb5575SBiju Das 556*2ddb5575SBiju Das rc = io_open(rcar_handle, rcar_spec, &handle); 557*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 558*2ddb5575SBiju Das WARN("Failed to open FIP (%i)\n", rc); 559*2ddb5575SBiju Das return IO_FAIL; 560*2ddb5575SBiju Das } 561*2ddb5575SBiju Das 562*2ddb5575SBiju Das rc = io_seek(handle, IO_SEEK_SET, offset); 563*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 564*2ddb5575SBiju Das WARN("%s: failed to seek\n", __func__); 565*2ddb5575SBiju Das goto error; 566*2ddb5575SBiju Das } 567*2ddb5575SBiju Das 568*2ddb5575SBiju Das if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33) { 569*2ddb5575SBiju Das rc = check_load_area(buffer, length); 570*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 571*2ddb5575SBiju Das WARN("%s: load area err\n", __func__); 572*2ddb5575SBiju Das goto error; 573*2ddb5575SBiju Das } 574*2ddb5575SBiju Das } 575*2ddb5575SBiju Das 576*2ddb5575SBiju Das rc = io_read(handle, buffer, length, cnt); 577*2ddb5575SBiju Das if (rc != IO_SUCCESS) { 578*2ddb5575SBiju Das WARN("Failed to read payload (%i)\n", rc); 579*2ddb5575SBiju Das goto error; 580*2ddb5575SBiju Das } 581*2ddb5575SBiju Das 582*2ddb5575SBiju Das fp->position += *cnt; 583*2ddb5575SBiju Das io_close(handle); 584*2ddb5575SBiju Das 585*2ddb5575SBiju Das load_bl33x_counter += 1; 586*2ddb5575SBiju Das if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33X) { 587*2ddb5575SBiju Das return load_bl33x(); 588*2ddb5575SBiju Das } 589*2ddb5575SBiju Das 590*2ddb5575SBiju Das return IO_SUCCESS; 591*2ddb5575SBiju Das error: 592*2ddb5575SBiju Das io_close(handle); 593*2ddb5575SBiju Das return IO_FAIL; 594*2ddb5575SBiju Das } 595*2ddb5575SBiju Das 596*2ddb5575SBiju Das static int32_t rcar_file_close(io_entity_t *entity) 597*2ddb5575SBiju Das { 598*2ddb5575SBiju Das if (current_file.offset != 0U) { 599*2ddb5575SBiju Das memset(¤t_file, 0, sizeof(current_file)); 600*2ddb5575SBiju Das } 601*2ddb5575SBiju Das 602*2ddb5575SBiju Das entity->info = 0U; 603*2ddb5575SBiju Das 604*2ddb5575SBiju Das return IO_SUCCESS; 605*2ddb5575SBiju Das } 606*2ddb5575SBiju Das 607*2ddb5575SBiju Das static const io_dev_funcs_t rcar_dev_funcs = { 608*2ddb5575SBiju Das .type = &device_type_rcar, 609*2ddb5575SBiju Das .open = &rcar_file_open, 610*2ddb5575SBiju Das .seek = NULL, 611*2ddb5575SBiju Das .size = &rcar_file_len, 612*2ddb5575SBiju Das .read = &rcar_file_read, 613*2ddb5575SBiju Das .write = NULL, 614*2ddb5575SBiju Das .close = &rcar_file_close, 615*2ddb5575SBiju Das .dev_init = &rcar_dev_init, 616*2ddb5575SBiju Das .dev_close = &rcar_dev_close, 617*2ddb5575SBiju Das }; 618*2ddb5575SBiju Das 619*2ddb5575SBiju Das static const io_dev_info_t rcar_dev_info = { 620*2ddb5575SBiju Das .funcs = &rcar_dev_funcs, 621*2ddb5575SBiju Das .info = (uintptr_t) 0 622*2ddb5575SBiju Das }; 623*2ddb5575SBiju Das 624*2ddb5575SBiju Das static const io_dev_connector_t rcar_dev_connector = { 625*2ddb5575SBiju Das .dev_open = &rcar_dev_open 626*2ddb5575SBiju Das }; 627*2ddb5575SBiju Das 628*2ddb5575SBiju Das static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), 629*2ddb5575SBiju Das io_dev_info_t **dev_info) 630*2ddb5575SBiju Das { 631*2ddb5575SBiju Das *dev_info = (io_dev_info_t *) &rcar_dev_info; 632*2ddb5575SBiju Das 633*2ddb5575SBiju Das return IO_SUCCESS; 634*2ddb5575SBiju Das } 635*2ddb5575SBiju Das 636*2ddb5575SBiju Das static int32_t rcar_dev_close(io_dev_info_t *dev_info) 637*2ddb5575SBiju Das { 638*2ddb5575SBiju Das rcar_handle = 0; 639*2ddb5575SBiju Das rcar_spec = 0; 640*2ddb5575SBiju Das 641*2ddb5575SBiju Das return IO_SUCCESS; 642*2ddb5575SBiju Das } 643*2ddb5575SBiju Das 644*2ddb5575SBiju Das int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con) 645*2ddb5575SBiju Das { 646*2ddb5575SBiju Das int32_t result; 647*2ddb5575SBiju Das 648*2ddb5575SBiju Das result = io_register_device(&rcar_dev_info); 649*2ddb5575SBiju Das if (result == IO_SUCCESS) { 650*2ddb5575SBiju Das *dev_con = &rcar_dev_connector; 651*2ddb5575SBiju Das } 652*2ddb5575SBiju Das 653*2ddb5575SBiju Das return result; 654*2ddb5575SBiju Das } 655