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 2515b54e7bSVictor 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 }; 4615b54e7bSVictor Chong #else 4715b54e7bSVictor Chong static const io_dev_connector_t *mmap_dev_con; 4815b54e7bSVictor Chong static uintptr_t mmap_dev_handle; 4915b54e7bSVictor Chong static int open_mmap(const uintptr_t spec); 5015b54e7bSVictor Chong 5115b54e7bSVictor Chong static const io_block_spec_t loader_fip_spec = { 5215b54e7bSVictor Chong .offset = FIP_BASE, 5315b54e7bSVictor Chong .length = FIP_SIZE 5415b54e7bSVictor Chong }; 5515b54e7bSVictor Chong #endif 5615b54e7bSVictor Chong 5715b54e7bSVictor Chong static const io_dev_connector_t *fip_dev_con; 5815b54e7bSVictor Chong static uintptr_t fip_dev_handle; 5915b54e7bSVictor 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 73*f3d522beSVictor Chong static const io_uuid_spec_t bl32_extra1_uuid_spec = { 74*f3d522beSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, 75*f3d522beSVictor Chong }; 76*f3d522beSVictor Chong 77*f3d522beSVictor Chong static const io_uuid_spec_t bl32_extra2_uuid_spec = { 78*f3d522beSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, 79*f3d522beSVictor Chong }; 80*f3d522beSVictor Chong 81e35d0edbSJorge Ramirez-Ortiz static const io_uuid_spec_t bl33_uuid_spec = { 82e35d0edbSJorge Ramirez-Ortiz .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 83e35d0edbSJorge Ramirez-Ortiz }; 84e35d0edbSJorge Ramirez-Ortiz 85e35d0edbSJorge Ramirez-Ortiz struct plat_io_policy { 86e35d0edbSJorge Ramirez-Ortiz uintptr_t *dev_handle; 87e35d0edbSJorge Ramirez-Ortiz uintptr_t image_spec; 88e35d0edbSJorge Ramirez-Ortiz int (*check)(const uintptr_t spec); 89e35d0edbSJorge Ramirez-Ortiz }; 90e35d0edbSJorge Ramirez-Ortiz 91e35d0edbSJorge Ramirez-Ortiz static const struct plat_io_policy policies[] = { 9215b54e7bSVictor Chong #if !POPLAR_RECOVERY 93e35d0edbSJorge Ramirez-Ortiz [FIP_IMAGE_ID] = { 9459149bbeSVictor Chong &emmc_dev_handle, 9559149bbeSVictor Chong (uintptr_t)&emmc_fip_spec, 9659149bbeSVictor Chong open_emmc 97e35d0edbSJorge Ramirez-Ortiz }, 9815b54e7bSVictor Chong #else 9915b54e7bSVictor Chong [FIP_IMAGE_ID] = { 10015b54e7bSVictor Chong &mmap_dev_handle, 10115b54e7bSVictor Chong (uintptr_t)&loader_fip_spec, 10215b54e7bSVictor Chong open_mmap 10315b54e7bSVictor Chong }, 10415b54e7bSVictor Chong #endif 105e35d0edbSJorge Ramirez-Ortiz [BL2_IMAGE_ID] = { 106e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle, 107e35d0edbSJorge Ramirez-Ortiz (uintptr_t)&bl2_uuid_spec, 108e35d0edbSJorge Ramirez-Ortiz open_fip 109e35d0edbSJorge Ramirez-Ortiz }, 110e35d0edbSJorge Ramirez-Ortiz [BL31_IMAGE_ID] = { 111e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle, 112e35d0edbSJorge Ramirez-Ortiz (uintptr_t)&bl31_uuid_spec, 113e35d0edbSJorge Ramirez-Ortiz open_fip 114e35d0edbSJorge Ramirez-Ortiz }, 115f336774bSVictor Chong [BL32_IMAGE_ID] = { 116f336774bSVictor Chong &fip_dev_handle, 117f336774bSVictor Chong (uintptr_t)&bl32_uuid_spec, 118f336774bSVictor Chong open_fip 119f336774bSVictor Chong }, 120*f3d522beSVictor Chong [BL32_EXTRA1_IMAGE_ID] = { 121*f3d522beSVictor Chong &fip_dev_handle, 122*f3d522beSVictor Chong (uintptr_t)&bl32_extra1_uuid_spec, 123*f3d522beSVictor Chong open_fip 124*f3d522beSVictor Chong }, 125*f3d522beSVictor Chong [BL32_EXTRA2_IMAGE_ID] = { 126*f3d522beSVictor Chong &fip_dev_handle, 127*f3d522beSVictor Chong (uintptr_t)&bl32_extra2_uuid_spec, 128*f3d522beSVictor Chong open_fip 129*f3d522beSVictor Chong }, 130e35d0edbSJorge Ramirez-Ortiz [BL33_IMAGE_ID] = { 131e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle, 132e35d0edbSJorge Ramirez-Ortiz (uintptr_t)&bl33_uuid_spec, 133e35d0edbSJorge Ramirez-Ortiz open_fip 134e35d0edbSJorge Ramirez-Ortiz }, 135e35d0edbSJorge Ramirez-Ortiz }; 136e35d0edbSJorge Ramirez-Ortiz 13715b54e7bSVictor Chong #if !POPLAR_RECOVERY 13859149bbeSVictor Chong static int open_emmc(const uintptr_t spec) 139e35d0edbSJorge Ramirez-Ortiz { 140e35d0edbSJorge Ramirez-Ortiz int result; 141e35d0edbSJorge Ramirez-Ortiz uintptr_t local_image_handle; 142e35d0edbSJorge Ramirez-Ortiz 14359149bbeSVictor Chong result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL); 144e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 14559149bbeSVictor Chong result = io_open(emmc_dev_handle, spec, &local_image_handle); 146e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 14759149bbeSVictor Chong INFO("Using eMMC\n"); 148e35d0edbSJorge Ramirez-Ortiz io_close(local_image_handle); 14959149bbeSVictor Chong } else { 15059149bbeSVictor Chong ERROR("error opening emmc\n"); 151e35d0edbSJorge Ramirez-Ortiz } 15259149bbeSVictor Chong } else { 15359149bbeSVictor Chong ERROR("error initializing emmc\n"); 154e35d0edbSJorge Ramirez-Ortiz } 15559149bbeSVictor Chong 156e35d0edbSJorge Ramirez-Ortiz return result; 157e35d0edbSJorge Ramirez-Ortiz } 15815b54e7bSVictor Chong #else 15915b54e7bSVictor Chong static int open_mmap(const uintptr_t spec) 16015b54e7bSVictor Chong { 16115b54e7bSVictor Chong int result; 16215b54e7bSVictor Chong uintptr_t local_image_handle; 16315b54e7bSVictor Chong 16415b54e7bSVictor Chong result = io_dev_init(mmap_dev_handle, (uintptr_t)NULL); 16515b54e7bSVictor Chong if (result == 0) { 16615b54e7bSVictor Chong result = io_open(mmap_dev_handle, spec, &local_image_handle); 16715b54e7bSVictor Chong if (result == 0) { 16815b54e7bSVictor Chong INFO("Using mmap\n"); 16915b54e7bSVictor Chong io_close(local_image_handle); 17015b54e7bSVictor Chong } else { 17115b54e7bSVictor Chong ERROR("error opening mmap\n"); 17215b54e7bSVictor Chong } 17315b54e7bSVictor Chong } else { 17415b54e7bSVictor Chong ERROR("error initializing mmap\n"); 17515b54e7bSVictor Chong } 17615b54e7bSVictor Chong 17715b54e7bSVictor Chong return result; 17815b54e7bSVictor Chong } 17915b54e7bSVictor Chong #endif 180e35d0edbSJorge Ramirez-Ortiz 181e35d0edbSJorge Ramirez-Ortiz static int open_fip(const uintptr_t spec) 182e35d0edbSJorge Ramirez-Ortiz { 183e35d0edbSJorge Ramirez-Ortiz uintptr_t local_image_handle; 184e35d0edbSJorge Ramirez-Ortiz int result; 185e35d0edbSJorge Ramirez-Ortiz 186e35d0edbSJorge Ramirez-Ortiz result = io_dev_init(fip_dev_handle, (uintptr_t) FIP_IMAGE_ID); 187e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 188e35d0edbSJorge Ramirez-Ortiz result = io_open(fip_dev_handle, spec, &local_image_handle); 189e35d0edbSJorge Ramirez-Ortiz if (result == 0) { 19059149bbeSVictor Chong INFO("Using FIP\n"); 191e35d0edbSJorge Ramirez-Ortiz io_close(local_image_handle); 192e35d0edbSJorge Ramirez-Ortiz } else { 19359149bbeSVictor Chong ERROR("error opening fip\n"); 194e35d0edbSJorge Ramirez-Ortiz } 195e35d0edbSJorge Ramirez-Ortiz } else { 19659149bbeSVictor Chong ERROR("error initializing fip\n"); 197e35d0edbSJorge Ramirez-Ortiz } 198e35d0edbSJorge Ramirez-Ortiz 199e35d0edbSJorge Ramirez-Ortiz return result; 200e35d0edbSJorge Ramirez-Ortiz } 201e35d0edbSJorge Ramirez-Ortiz 202e35d0edbSJorge Ramirez-Ortiz int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 203e35d0edbSJorge Ramirez-Ortiz uintptr_t *image_spec) 204e35d0edbSJorge Ramirez-Ortiz { 205e35d0edbSJorge Ramirez-Ortiz const struct plat_io_policy *policy; 206e35d0edbSJorge Ramirez-Ortiz int result; 207e35d0edbSJorge Ramirez-Ortiz 208e35d0edbSJorge Ramirez-Ortiz assert(image_id < ARRAY_SIZE(policies)); 209e35d0edbSJorge Ramirez-Ortiz 210e35d0edbSJorge Ramirez-Ortiz policy = &policies[image_id]; 211e35d0edbSJorge Ramirez-Ortiz result = policy->check(policy->image_spec); 212e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 213e35d0edbSJorge Ramirez-Ortiz 214e35d0edbSJorge Ramirez-Ortiz *image_spec = policy->image_spec; 215e35d0edbSJorge Ramirez-Ortiz *dev_handle = *(policy->dev_handle); 216e35d0edbSJorge Ramirez-Ortiz 217e35d0edbSJorge Ramirez-Ortiz return result; 218e35d0edbSJorge Ramirez-Ortiz } 219e35d0edbSJorge Ramirez-Ortiz 220e35d0edbSJorge Ramirez-Ortiz void plat_io_setup(void) 221e35d0edbSJorge Ramirez-Ortiz { 222e35d0edbSJorge Ramirez-Ortiz int result; 223e35d0edbSJorge Ramirez-Ortiz 22415b54e7bSVictor Chong #if !POPLAR_RECOVERY 22559149bbeSVictor Chong result = register_io_dev_block(&emmc_dev_con); 22615b54e7bSVictor Chong #else 22715b54e7bSVictor Chong result = register_io_dev_memmap(&mmap_dev_con); 22815b54e7bSVictor Chong #endif 229e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 230e35d0edbSJorge Ramirez-Ortiz 231e35d0edbSJorge Ramirez-Ortiz result = register_io_dev_fip(&fip_dev_con); 232e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 233e35d0edbSJorge Ramirez-Ortiz 23415b54e7bSVictor Chong #if !POPLAR_RECOVERY 23559149bbeSVictor Chong result = io_dev_open(fip_dev_con, (uintptr_t)NULL, 236e35d0edbSJorge Ramirez-Ortiz &fip_dev_handle); 23715b54e7bSVictor Chong #else 23815b54e7bSVictor Chong result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec, 23915b54e7bSVictor Chong &fip_dev_handle); 24015b54e7bSVictor Chong #endif 241e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 242e35d0edbSJorge Ramirez-Ortiz 24315b54e7bSVictor Chong #if !POPLAR_RECOVERY 24459149bbeSVictor Chong result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec, 24559149bbeSVictor Chong &emmc_dev_handle); 24615b54e7bSVictor Chong #else 24715b54e7bSVictor Chong result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle); 24815b54e7bSVictor Chong #endif 249e35d0edbSJorge Ramirez-Ortiz assert(result == 0); 250e35d0edbSJorge Ramirez-Ortiz 251e35d0edbSJorge Ramirez-Ortiz (void) result; 252e35d0edbSJorge Ramirez-Ortiz } 253