1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2021, ARM Limited. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <common/debug.h> 8*91f16700Schasinglulu #include <drivers/fwu/fwu_metadata.h> 9*91f16700Schasinglulu #include <drivers/io/io_driver.h> 10*91f16700Schasinglulu #include <drivers/io/io_fip.h> 11*91f16700Schasinglulu #include <drivers/io/io_memmap.h> 12*91f16700Schasinglulu #include <drivers/io/io_storage.h> 13*91f16700Schasinglulu #include <drivers/partition/partition.h> 14*91f16700Schasinglulu #include <lib/utils.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include <plat/arm/common/arm_fconf_getter.h> 17*91f16700Schasinglulu #include <plat/arm/common/arm_fconf_io_storage.h> 18*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 19*91f16700Schasinglulu #include <plat/common/platform.h> 20*91f16700Schasinglulu #include <platform_def.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* IO devices */ 23*91f16700Schasinglulu static const io_dev_connector_t *fip_dev_con; 24*91f16700Schasinglulu uintptr_t fip_dev_handle; 25*91f16700Schasinglulu static const io_dev_connector_t *memmap_dev_con; 26*91f16700Schasinglulu uintptr_t memmap_dev_handle; 27*91f16700Schasinglulu 28*91f16700Schasinglulu #if ARM_GPT_SUPPORT 29*91f16700Schasinglulu /* fip partition names */ 30*91f16700Schasinglulu static const char * const fip_part_names[] = {"FIP_A", "FIP_B"}; 31*91f16700Schasinglulu CASSERT(sizeof(fip_part_names)/sizeof(char *) == NR_OF_FW_BANKS, 32*91f16700Schasinglulu assert_fip_partition_names_missing); 33*91f16700Schasinglulu #endif /* ARM_GPT_SUPPORT */ 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* Weak definitions may be overridden in specific ARM standard platform */ 36*91f16700Schasinglulu #pragma weak plat_arm_io_setup 37*91f16700Schasinglulu #pragma weak plat_arm_get_alt_image_source 38*91f16700Schasinglulu 39*91f16700Schasinglulu int open_fip(const uintptr_t spec) 40*91f16700Schasinglulu { 41*91f16700Schasinglulu int result; 42*91f16700Schasinglulu uintptr_t local_image_handle; 43*91f16700Schasinglulu 44*91f16700Schasinglulu /* See if a Firmware Image Package is available */ 45*91f16700Schasinglulu result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 46*91f16700Schasinglulu if (result == 0) { 47*91f16700Schasinglulu result = io_open(fip_dev_handle, spec, &local_image_handle); 48*91f16700Schasinglulu if (result == 0) { 49*91f16700Schasinglulu VERBOSE("Using FIP\n"); 50*91f16700Schasinglulu io_close(local_image_handle); 51*91f16700Schasinglulu } 52*91f16700Schasinglulu } 53*91f16700Schasinglulu return result; 54*91f16700Schasinglulu } 55*91f16700Schasinglulu 56*91f16700Schasinglulu int open_memmap(const uintptr_t spec) 57*91f16700Schasinglulu { 58*91f16700Schasinglulu int result; 59*91f16700Schasinglulu uintptr_t local_image_handle; 60*91f16700Schasinglulu 61*91f16700Schasinglulu result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); 62*91f16700Schasinglulu if (result == 0) { 63*91f16700Schasinglulu result = io_open(memmap_dev_handle, spec, &local_image_handle); 64*91f16700Schasinglulu if (result == 0) { 65*91f16700Schasinglulu VERBOSE("Using Memmap\n"); 66*91f16700Schasinglulu io_close(local_image_handle); 67*91f16700Schasinglulu } 68*91f16700Schasinglulu } 69*91f16700Schasinglulu return result; 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu int arm_io_setup(void) 73*91f16700Schasinglulu { 74*91f16700Schasinglulu int io_result; 75*91f16700Schasinglulu 76*91f16700Schasinglulu io_result = register_io_dev_fip(&fip_dev_con); 77*91f16700Schasinglulu if (io_result < 0) { 78*91f16700Schasinglulu return io_result; 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu io_result = register_io_dev_memmap(&memmap_dev_con); 82*91f16700Schasinglulu if (io_result < 0) { 83*91f16700Schasinglulu return io_result; 84*91f16700Schasinglulu } 85*91f16700Schasinglulu 86*91f16700Schasinglulu /* Open connections to devices and cache the handles */ 87*91f16700Schasinglulu io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, 88*91f16700Schasinglulu &fip_dev_handle); 89*91f16700Schasinglulu if (io_result < 0) { 90*91f16700Schasinglulu return io_result; 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, 94*91f16700Schasinglulu &memmap_dev_handle); 95*91f16700Schasinglulu 96*91f16700Schasinglulu return io_result; 97*91f16700Schasinglulu } 98*91f16700Schasinglulu 99*91f16700Schasinglulu void plat_arm_io_setup(void) 100*91f16700Schasinglulu { 101*91f16700Schasinglulu int err; 102*91f16700Schasinglulu 103*91f16700Schasinglulu err = arm_io_setup(); 104*91f16700Schasinglulu if (err < 0) { 105*91f16700Schasinglulu panic(); 106*91f16700Schasinglulu } 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu int plat_arm_get_alt_image_source( 110*91f16700Schasinglulu unsigned int image_id __unused, 111*91f16700Schasinglulu uintptr_t *dev_handle __unused, 112*91f16700Schasinglulu uintptr_t *image_spec __unused) 113*91f16700Schasinglulu { 114*91f16700Schasinglulu /* By default do not try an alternative */ 115*91f16700Schasinglulu return -ENOENT; 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* Return an IO device handle and specification which can be used to access 119*91f16700Schasinglulu * an image. Use this to enforce platform load policy */ 120*91f16700Schasinglulu int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 121*91f16700Schasinglulu uintptr_t *image_spec) 122*91f16700Schasinglulu { 123*91f16700Schasinglulu int result; 124*91f16700Schasinglulu const struct plat_io_policy *policy; 125*91f16700Schasinglulu 126*91f16700Schasinglulu policy = FCONF_GET_PROPERTY(arm, io_policies, image_id); 127*91f16700Schasinglulu result = policy->check(policy->image_spec); 128*91f16700Schasinglulu if (result == 0) { 129*91f16700Schasinglulu *image_spec = policy->image_spec; 130*91f16700Schasinglulu *dev_handle = *(policy->dev_handle); 131*91f16700Schasinglulu } else { 132*91f16700Schasinglulu VERBOSE("Trying alternative IO\n"); 133*91f16700Schasinglulu result = plat_arm_get_alt_image_source(image_id, dev_handle, 134*91f16700Schasinglulu image_spec); 135*91f16700Schasinglulu } 136*91f16700Schasinglulu 137*91f16700Schasinglulu return result; 138*91f16700Schasinglulu } 139*91f16700Schasinglulu 140*91f16700Schasinglulu /* 141*91f16700Schasinglulu * See if a Firmware Image Package is available, 142*91f16700Schasinglulu * by checking if TOC is valid or not. 143*91f16700Schasinglulu */ 144*91f16700Schasinglulu bool arm_io_is_toc_valid(void) 145*91f16700Schasinglulu { 146*91f16700Schasinglulu return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0); 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu #if ARM_GPT_SUPPORT 150*91f16700Schasinglulu /****************************************************************************** 151*91f16700Schasinglulu * Retrieve partition entry details such as offset and length, and set these 152*91f16700Schasinglulu * details in the I/O policy of the requested image. 153*91f16700Schasinglulu * 154*91f16700Schasinglulu * @image_id: image id whose I/O policy to be updated 155*91f16700Schasinglulu * 156*91f16700Schasinglulu * @part_name: partition name whose details to be retrieved 157*91f16700Schasinglulu * 158*91f16700Schasinglulu * Returns 0 on success, error otherwise 159*91f16700Schasinglulu * Alongside, returns device handle and image specification of requested 160*91f16700Schasinglulu * image. 161*91f16700Schasinglulu ******************************************************************************/ 162*91f16700Schasinglulu int arm_set_image_source(unsigned int image_id, const char *part_name, 163*91f16700Schasinglulu uintptr_t *dev_handle, uintptr_t *image_spec) 164*91f16700Schasinglulu { 165*91f16700Schasinglulu const partition_entry_t *entry = get_partition_entry(part_name); 166*91f16700Schasinglulu 167*91f16700Schasinglulu if (entry == NULL) { 168*91f16700Schasinglulu ERROR("Unable to find the %s partition\n", part_name); 169*91f16700Schasinglulu return -ENOENT; 170*91f16700Schasinglulu } 171*91f16700Schasinglulu 172*91f16700Schasinglulu struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm, 173*91f16700Schasinglulu io_policies, 174*91f16700Schasinglulu image_id); 175*91f16700Schasinglulu 176*91f16700Schasinglulu assert(policy != NULL); 177*91f16700Schasinglulu assert(policy->image_spec != 0UL); 178*91f16700Schasinglulu 179*91f16700Schasinglulu io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec; 180*91f16700Schasinglulu /* set offset and length of the image */ 181*91f16700Schasinglulu spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start; 182*91f16700Schasinglulu spec->length = entry->length; 183*91f16700Schasinglulu 184*91f16700Schasinglulu *dev_handle = *(policy->dev_handle); 185*91f16700Schasinglulu *image_spec = policy->image_spec; 186*91f16700Schasinglulu 187*91f16700Schasinglulu return 0; 188*91f16700Schasinglulu } 189*91f16700Schasinglulu 190*91f16700Schasinglulu /******************************************************************************* 191*91f16700Schasinglulu * Set the source offset and length of the FIP image in its I/O policy. 192*91f16700Schasinglulu * 193*91f16700Schasinglulu * @active_fw_bank_idx: active firmware bank index gathered from FWU metadata. 194*91f16700Schasinglulu ******************************************************************************/ 195*91f16700Schasinglulu void arm_set_fip_addr(uint32_t active_fw_bank_idx) 196*91f16700Schasinglulu { 197*91f16700Schasinglulu uintptr_t dev_handle __unused; 198*91f16700Schasinglulu uintptr_t image_spec __unused; 199*91f16700Schasinglulu 200*91f16700Schasinglulu assert(active_fw_bank_idx < NR_OF_FW_BANKS); 201*91f16700Schasinglulu 202*91f16700Schasinglulu INFO("Booting with partition %s\n", fip_part_names[active_fw_bank_idx]); 203*91f16700Schasinglulu 204*91f16700Schasinglulu int result = arm_set_image_source(FIP_IMAGE_ID, 205*91f16700Schasinglulu fip_part_names[active_fw_bank_idx], 206*91f16700Schasinglulu &dev_handle, 207*91f16700Schasinglulu &image_spec); 208*91f16700Schasinglulu if (result != 0) { 209*91f16700Schasinglulu panic(); 210*91f16700Schasinglulu } 211*91f16700Schasinglulu } 212*91f16700Schasinglulu #endif /* ARM_GPT_SUPPORT */ 213*91f16700Schasinglulu 214*91f16700Schasinglulu #if PSA_FWU_SUPPORT 215*91f16700Schasinglulu /******************************************************************************* 216*91f16700Schasinglulu * Read the FIP partition of the GPT image corresponding to the active firmware 217*91f16700Schasinglulu * bank to get its offset and length, and update these details in the I/O policy 218*91f16700Schasinglulu * of the FIP image. 219*91f16700Schasinglulu ******************************************************************************/ 220*91f16700Schasinglulu void plat_fwu_set_images_source(const struct fwu_metadata *metadata) 221*91f16700Schasinglulu { 222*91f16700Schasinglulu arm_set_fip_addr(metadata->active_index); 223*91f16700Schasinglulu } 224*91f16700Schasinglulu 225*91f16700Schasinglulu /******************************************************************************* 226*91f16700Schasinglulu * Read the requested FWU metadata partition of the GPT image to get its offset 227*91f16700Schasinglulu * and length, and update these details in the I/O policy of the requested FWU 228*91f16700Schasinglulu * metadata image. 229*91f16700Schasinglulu ******************************************************************************/ 230*91f16700Schasinglulu int plat_fwu_set_metadata_image_source(unsigned int image_id, 231*91f16700Schasinglulu uintptr_t *dev_handle, 232*91f16700Schasinglulu uintptr_t *image_spec) 233*91f16700Schasinglulu { 234*91f16700Schasinglulu int result = -1; 235*91f16700Schasinglulu 236*91f16700Schasinglulu if (image_id == FWU_METADATA_IMAGE_ID) { 237*91f16700Schasinglulu result = arm_set_image_source(FWU_METADATA_IMAGE_ID, 238*91f16700Schasinglulu "FWU-Metadata", 239*91f16700Schasinglulu dev_handle, 240*91f16700Schasinglulu image_spec); 241*91f16700Schasinglulu } else if (image_id == BKUP_FWU_METADATA_IMAGE_ID) { 242*91f16700Schasinglulu result = arm_set_image_source(BKUP_FWU_METADATA_IMAGE_ID, 243*91f16700Schasinglulu "Bkup-FWU-Metadata", 244*91f16700Schasinglulu dev_handle, 245*91f16700Schasinglulu image_spec); 246*91f16700Schasinglulu } 247*91f16700Schasinglulu 248*91f16700Schasinglulu return result; 249*91f16700Schasinglulu } 250*91f16700Schasinglulu #endif /* PSA_FWU_SUPPORT */ 251