1e35d0edbSJorge Ramirez-Ortiz /* 2e35d0edbSJorge Ramirez-Ortiz * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3e35d0edbSJorge Ramirez-Ortiz * 4e35d0edbSJorge Ramirez-Ortiz * SPDX-License-Identifier: BSD-3-Clause 5e35d0edbSJorge Ramirez-Ortiz */ 6e35d0edbSJorge Ramirez-Ortiz 7e35d0edbSJorge Ramirez-Ortiz #include <arch_helpers.h> 8e35d0edbSJorge Ramirez-Ortiz #include <assert.h> 9e35d0edbSJorge Ramirez-Ortiz #include <debug.h> 1059149bbeSVictor Chong #include <emmc.h> 11e35d0edbSJorge Ramirez-Ortiz #include <firmware_image_package.h> 12e35d0edbSJorge Ramirez-Ortiz #include <io_block.h> 13e35d0edbSJorge Ramirez-Ortiz #include <io_driver.h> 14e35d0edbSJorge Ramirez-Ortiz #include <io_fip.h> 15e35d0edbSJorge Ramirez-Ortiz #include <io_memmap.h> 16e35d0edbSJorge Ramirez-Ortiz #include <io_storage.h> 17e35d0edbSJorge Ramirez-Ortiz #include <mmio.h> 18e35d0edbSJorge Ramirez-Ortiz #include <partition/partition.h> 19e35d0edbSJorge Ramirez-Ortiz #include <semihosting.h> 20e35d0edbSJorge Ramirez-Ortiz #include <string.h> 21e35d0edbSJorge Ramirez-Ortiz #include <tbbr_img_def.h> 22e35d0edbSJorge Ramirez-Ortiz #include <utils.h> 23e35d0edbSJorge Ramirez-Ortiz #include "platform_def.h" 24e35d0edbSJorge Ramirez-Ortiz 25*15b54e7bSVictor Chong #if !POPLAR_RECOVERY 2659149bbeSVictor Chong static const io_dev_connector_t *emmc_dev_con; 2759149bbeSVictor Chong static uintptr_t emmc_dev_handle; 2859149bbeSVictor Chong static int open_emmc(const uintptr_t spec); 29e35d0edbSJorge Ramirez-Ortiz 3059149bbeSVictor Chong static const io_block_spec_t emmc_fip_spec = { 3159149bbeSVictor Chong .offset = FIP_BASE_EMMC, 32e35d0edbSJorge Ramirez-Ortiz .length = FIP_SIZE 33e35d0edbSJorge Ramirez-Ortiz }; 34e35d0edbSJorge Ramirez-Ortiz 3559149bbeSVictor Chong static const io_block_dev_spec_t emmc_dev_spec = { 3659149bbeSVictor Chong .buffer = { 3759149bbeSVictor Chong .offset = POPLAR_EMMC_DATA_BASE, 3859149bbeSVictor Chong .length = POPLAR_EMMC_DATA_SIZE, 3959149bbeSVictor Chong }, 4059149bbeSVictor Chong .ops = { 4159149bbeSVictor Chong .read = emmc_read_blocks, 4259149bbeSVictor Chong .write = emmc_write_blocks, 4359149bbeSVictor Chong }, 4459149bbeSVictor Chong .block_size = EMMC_BLOCK_SIZE, 4559149bbeSVictor Chong }; 46*15b54e7bSVictor Chong #else 47*15b54e7bSVictor Chong static const io_dev_connector_t *mmap_dev_con; 48*15b54e7bSVictor Chong static uintptr_t mmap_dev_handle; 49*15b54e7bSVictor Chong static int open_mmap(const uintptr_t spec); 50*15b54e7bSVictor Chong 51*15b54e7bSVictor Chong static const io_block_spec_t loader_fip_spec = { 52*15b54e7bSVictor Chong .offset = FIP_BASE, 53*15b54e7bSVictor Chong .length = FIP_SIZE 54*15b54e7bSVictor Chong }; 55*15b54e7bSVictor Chong #endif 56*15b54e7bSVictor Chong 57*15b54e7bSVictor Chong static const io_dev_connector_t *fip_dev_con; 58*15b54e7bSVictor Chong static uintptr_t fip_dev_handle; 59*15b54e7bSVictor Chong static int open_fip(const uintptr_t spec); 6059149bbeSVictor Chong 61e35d0edbSJorge Ramirez-Ortiz static const io_uuid_spec_t bl2_uuid_spec = { 62e35d0edbSJorge Ramirez-Ortiz .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, 63e35d0edbSJorge Ramirez-Ortiz }; 64e35d0edbSJorge Ramirez-Ortiz 65e35d0edbSJorge Ramirez-Ortiz static const io_uuid_spec_t bl31_uuid_spec = { 66e35d0edbSJorge Ramirez-Ortiz .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 67e35d0edbSJorge Ramirez-Ortiz }; 68e35d0edbSJorge Ramirez-Ortiz 69f336774bSVictor Chong static const io_uuid_spec_t bl32_uuid_spec = { 70f336774bSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32, 71f336774bSVictor Chong }; 72f336774bSVictor Chong 73e35d0edbSJorge Ramirez-Ortiz static const io_uuid_spec_t bl33_uuid_spec = { 74e35d0edbSJorge Ramirez-Ortiz .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 75e35d0edbSJorge Ramirez-Ortiz }; 76e35d0edbSJorge Ramirez-Ortiz 77e35d0edbSJorge Ramirez-Ortiz struct plat_io_policy { 78e35d0edbSJorge Ramirez-Ortiz uintptr_t *dev_handle; 79e35d0edbSJorge Ramirez-Ortiz uintptr_t image_spec; 80e35d0edbSJorge Ramirez-Ortiz int (*check)(const uintptr_t spec); 81e35d0edbSJorge Ramirez-Ortiz }; 82e35d0edbSJorge Ramirez-Ortiz 83e35d0edbSJorge Ramirez-Ortiz static const struct plat_io_policy policies[] = { 84*15b54e7bSVictor Chong #if !POPLAR_RECOVERY 85e35d0edbSJorge Ramirez-Ortiz [FIP_IMAGE_ID] = { 8659149bbeSVictor Chong &emmc_dev_handle, 8759149bbeSVictor Chong (uintptr_t)&emmc_fip_spec, 8859149bbeSVictor Chong open_emmc 89e35d0edbSJorge Ramirez-Ortiz }, 90*15b54e7bSVictor Chong #else 91*15b54e7bSVictor Chong [FIP_IMAGE_ID] = { 92*15b54e7bSVictor Chong &mmap_dev_handle, 93*15b54e7bSVictor Chong (uintptr_t)&loader_fip_spec, 94*15b54e7bSVictor Chong open_mmap 95*15b54e7bSVictor Chong }, 96*15b54e7bSVictor Chong #endif 97e35d0edbSJorge Ramirez-Ortiz [BL2_IMAGE_ID] = { 98e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle, 99e35d0edbSJorge Ramirez-Ortiz (uintptr_t)&bl2_uuid_spec, 100e35d0edbSJorge Ramirez-Ortiz open_fip 101e35d0edbSJorge Ramirez-Ortiz }, 102e35d0edbSJorge Ramirez-Ortiz [BL31_IMAGE_ID] = { 103e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle, 104e35d0edbSJorge Ramirez-Ortiz (uintptr_t)&bl31_uuid_spec, 105e35d0edbSJorge Ramirez-Ortiz open_fip 106e35d0edbSJorge Ramirez-Ortiz }, 107f336774bSVictor Chong [BL32_IMAGE_ID] = { 108f336774bSVictor Chong &fip_dev_handle, 109f336774bSVictor Chong (uintptr_t)&bl32_uuid_spec, 110f336774bSVictor Chong open_fip 111f336774bSVictor Chong }, 112e35d0edbSJorge Ramirez-Ortiz [BL33_IMAGE_ID] = { 113e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle, 114e35d0edbSJorge Ramirez-Ortiz (uintptr_t)&bl33_uuid_spec, 115e35d0edbSJorge Ramirez-Ortiz open_fip 116e35d0edbSJorge Ramirez-Ortiz }, 117e35d0edbSJorge Ramirez-Ortiz }; 118e35d0edbSJorge Ramirez-Ortiz 119*15b54e7bSVictor Chong #if !POPLAR_RECOVERY 12059149bbeSVictor Chong static int open_emmc(const uintptr_t spec) 121e35d0edbSJorge Ramirez-Ortiz { 122e35d0edbSJorge Ramirez-Ortiz int result; 123e35d0edbSJorge Ramirez-Ortiz uintptr_t local_image_handle; 124e35d0edbSJorge Ramirez-Ortiz 12559149bbeSVictor Chong result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL); 126e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 12759149bbeSVictor Chong result = io_open(emmc_dev_handle, spec, &local_image_handle); 128e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 12959149bbeSVictor Chong INFO("Using eMMC\n"); 130e35d0edbSJorge Ramirez-Ortiz io_close(local_image_handle); 13159149bbeSVictor Chong } else { 13259149bbeSVictor Chong ERROR("error opening emmc\n"); 133e35d0edbSJorge Ramirez-Ortiz } 13459149bbeSVictor Chong } else { 13559149bbeSVictor Chong ERROR("error initializing emmc\n"); 136e35d0edbSJorge Ramirez-Ortiz } 13759149bbeSVictor Chong 138e35d0edbSJorge Ramirez-Ortiz return result; 139e35d0edbSJorge Ramirez-Ortiz } 140*15b54e7bSVictor Chong #else 141*15b54e7bSVictor Chong static int open_mmap(const uintptr_t spec) 142*15b54e7bSVictor Chong { 143*15b54e7bSVictor Chong int result; 144*15b54e7bSVictor Chong uintptr_t local_image_handle; 145*15b54e7bSVictor Chong 146*15b54e7bSVictor Chong result = io_dev_init(mmap_dev_handle, (uintptr_t)NULL); 147*15b54e7bSVictor Chong if (result == 0) { 148*15b54e7bSVictor Chong result = io_open(mmap_dev_handle, spec, &local_image_handle); 149*15b54e7bSVictor Chong if (result == 0) { 150*15b54e7bSVictor Chong INFO("Using mmap\n"); 151*15b54e7bSVictor Chong io_close(local_image_handle); 152*15b54e7bSVictor Chong } else { 153*15b54e7bSVictor Chong ERROR("error opening mmap\n"); 154*15b54e7bSVictor Chong } 155*15b54e7bSVictor Chong } else { 156*15b54e7bSVictor Chong ERROR("error initializing mmap\n"); 157*15b54e7bSVictor Chong } 158*15b54e7bSVictor Chong 159*15b54e7bSVictor Chong return result; 160*15b54e7bSVictor Chong } 161*15b54e7bSVictor Chong #endif 162e35d0edbSJorge Ramirez-Ortiz 163e35d0edbSJorge Ramirez-Ortiz static int open_fip(const uintptr_t spec) 164e35d0edbSJorge Ramirez-Ortiz { 165e35d0edbSJorge Ramirez-Ortiz uintptr_t local_image_handle; 166e35d0edbSJorge Ramirez-Ortiz int result; 167e35d0edbSJorge Ramirez-Ortiz 168e35d0edbSJorge Ramirez-Ortiz result = io_dev_init(fip_dev_handle, (uintptr_t) FIP_IMAGE_ID); 169e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 170e35d0edbSJorge Ramirez-Ortiz result = io_open(fip_dev_handle, spec, &local_image_handle); 171e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 17259149bbeSVictor Chong INFO("Using FIP\n"); 173e35d0edbSJorge Ramirez-Ortiz io_close(local_image_handle); 174e35d0edbSJorge Ramirez-Ortiz } else { 17559149bbeSVictor Chong ERROR("error opening fip\n"); 176e35d0edbSJorge Ramirez-Ortiz } 177e35d0edbSJorge Ramirez-Ortiz } else { 17859149bbeSVictor Chong ERROR("error initializing fip\n"); 179e35d0edbSJorge Ramirez-Ortiz } 180e35d0edbSJorge Ramirez-Ortiz 181e35d0edbSJorge Ramirez-Ortiz return result; 182e35d0edbSJorge Ramirez-Ortiz } 183e35d0edbSJorge Ramirez-Ortiz 184e35d0edbSJorge Ramirez-Ortiz int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 185e35d0edbSJorge Ramirez-Ortiz uintptr_t *image_spec) 186e35d0edbSJorge Ramirez-Ortiz { 187e35d0edbSJorge Ramirez-Ortiz const struct plat_io_policy *policy; 188e35d0edbSJorge Ramirez-Ortiz int result; 189e35d0edbSJorge Ramirez-Ortiz 190e35d0edbSJorge Ramirez-Ortiz assert(image_id < ARRAY_SIZE(policies)); 191e35d0edbSJorge Ramirez-Ortiz 192e35d0edbSJorge Ramirez-Ortiz policy = &policies[image_id]; 193e35d0edbSJorge Ramirez-Ortiz result = policy->check(policy->image_spec); 194e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 195e35d0edbSJorge Ramirez-Ortiz 196e35d0edbSJorge Ramirez-Ortiz *image_spec = policy->image_spec; 197e35d0edbSJorge Ramirez-Ortiz *dev_handle = *(policy->dev_handle); 198e35d0edbSJorge Ramirez-Ortiz 199e35d0edbSJorge Ramirez-Ortiz return result; 200e35d0edbSJorge Ramirez-Ortiz } 201e35d0edbSJorge Ramirez-Ortiz 202e35d0edbSJorge Ramirez-Ortiz void plat_io_setup(void) 203e35d0edbSJorge Ramirez-Ortiz { 204e35d0edbSJorge Ramirez-Ortiz int result; 205e35d0edbSJorge Ramirez-Ortiz 206*15b54e7bSVictor Chong #if !POPLAR_RECOVERY 20759149bbeSVictor Chong result = register_io_dev_block(&emmc_dev_con); 208*15b54e7bSVictor Chong #else 209*15b54e7bSVictor Chong result = register_io_dev_memmap(&mmap_dev_con); 210*15b54e7bSVictor Chong #endif 211e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 212e35d0edbSJorge Ramirez-Ortiz 213e35d0edbSJorge Ramirez-Ortiz result = register_io_dev_fip(&fip_dev_con); 214e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 215e35d0edbSJorge Ramirez-Ortiz 216*15b54e7bSVictor Chong #if !POPLAR_RECOVERY 21759149bbeSVictor Chong result = io_dev_open(fip_dev_con, (uintptr_t)NULL, 218e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle); 219*15b54e7bSVictor Chong #else 220*15b54e7bSVictor Chong result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec, 221*15b54e7bSVictor Chong &fip_dev_handle); 222*15b54e7bSVictor Chong #endif 223e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 224e35d0edbSJorge Ramirez-Ortiz 225*15b54e7bSVictor Chong #if !POPLAR_RECOVERY 22659149bbeSVictor Chong result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec, 22759149bbeSVictor Chong &emmc_dev_handle); 228*15b54e7bSVictor Chong #else 229*15b54e7bSVictor Chong result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle); 230*15b54e7bSVictor Chong #endif 231e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 232e35d0edbSJorge Ramirez-Ortiz 233e35d0edbSJorge Ramirez-Ortiz (void) result; 234e35d0edbSJorge Ramirez-Ortiz } 235