1 /* 2 * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2019, Intel Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <arch_helpers.h> 9 #include <assert.h> 10 #include <common/debug.h> 11 #include <common/tbbr/tbbr_img_def.h> 12 #include <drivers/io/io_block.h> 13 #include <drivers/io/io_driver.h> 14 #include <drivers/io/io_fip.h> 15 #include <drivers/io/io_memmap.h> 16 #include <drivers/io/io_storage.h> 17 #include <drivers/mmc.h> 18 #include <drivers/partition/partition.h> 19 #include <lib/mmio.h> 20 #include <tools_share/firmware_image_package.h> 21 22 #include "socfpga_private.h" 23 24 #define PLAT_FIP_BASE (0) 25 #define PLAT_FIP_MAX_SIZE (0x1000000) 26 #define PLAT_MMC_DATA_BASE (0xffe3c000) 27 #define PLAT_MMC_DATA_SIZE (0x2000) 28 #define PLAT_QSPI_DATA_BASE (0x3C00000) 29 #define PLAT_QSPI_DATA_SIZE (0x1000000) 30 31 32 static const io_dev_connector_t *fip_dev_con; 33 static const io_dev_connector_t *boot_dev_con; 34 35 static uintptr_t fip_dev_handle; 36 static uintptr_t boot_dev_handle; 37 38 static const io_uuid_spec_t bl2_uuid_spec = { 39 .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, 40 }; 41 42 static const io_uuid_spec_t bl31_uuid_spec = { 43 .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 44 }; 45 46 static const io_uuid_spec_t bl33_uuid_spec = { 47 .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 48 }; 49 50 uintptr_t a2_lba_offset; 51 const char a2[] = {0xa2, 0x0}; 52 53 static const io_block_spec_t gpt_block_spec = { 54 .offset = 0, 55 .length = MMC_BLOCK_SIZE 56 }; 57 58 static int check_fip(const uintptr_t spec); 59 static int check_dev(const uintptr_t spec); 60 61 static io_block_dev_spec_t boot_dev_spec; 62 static int (*register_io_dev)(const io_dev_connector_t **); 63 64 static io_block_spec_t fip_spec = { 65 .offset = PLAT_FIP_BASE, 66 .length = PLAT_FIP_MAX_SIZE, 67 }; 68 69 struct plat_io_policy { 70 uintptr_t *dev_handle; 71 uintptr_t image_spec; 72 int (*check)(const uintptr_t spec); 73 }; 74 75 static const struct plat_io_policy policies[] = { 76 [FIP_IMAGE_ID] = { 77 &boot_dev_handle, 78 (uintptr_t)&fip_spec, 79 check_dev 80 }, 81 [BL2_IMAGE_ID] = { 82 &fip_dev_handle, 83 (uintptr_t)&bl2_uuid_spec, 84 check_fip 85 }, 86 [BL31_IMAGE_ID] = { 87 &fip_dev_handle, 88 (uintptr_t)&bl31_uuid_spec, 89 check_fip 90 }, 91 [BL33_IMAGE_ID] = { 92 &fip_dev_handle, 93 (uintptr_t) &bl33_uuid_spec, 94 check_fip 95 }, 96 [GPT_IMAGE_ID] = { 97 &boot_dev_handle, 98 (uintptr_t) &gpt_block_spec, 99 check_dev 100 }, 101 }; 102 103 static int check_dev(const uintptr_t spec) 104 { 105 int result; 106 uintptr_t local_handle; 107 108 result = io_dev_init(boot_dev_handle, (uintptr_t)NULL); 109 if (result == 0) { 110 result = io_open(boot_dev_handle, spec, &local_handle); 111 if (result == 0) 112 io_close(local_handle); 113 } 114 return result; 115 } 116 117 static int check_fip(const uintptr_t spec) 118 { 119 int result; 120 uintptr_t local_image_handle; 121 122 result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 123 if (result == 0) { 124 result = io_open(fip_dev_handle, spec, &local_image_handle); 125 if (result == 0) 126 io_close(local_image_handle); 127 } 128 return result; 129 } 130 131 void socfpga_io_setup(int boot_source) 132 { 133 int result; 134 135 switch (boot_source) { 136 case BOOT_SOURCE_SDMMC: 137 register_io_dev = ®ister_io_dev_block; 138 boot_dev_spec.buffer.offset = PLAT_MMC_DATA_BASE; 139 boot_dev_spec.buffer.length = MMC_BLOCK_SIZE; 140 boot_dev_spec.ops.read = mmc_read_blocks; 141 boot_dev_spec.ops.write = mmc_write_blocks; 142 boot_dev_spec.block_size = MMC_BLOCK_SIZE; 143 break; 144 145 case BOOT_SOURCE_QSPI: 146 register_io_dev = ®ister_io_dev_memmap; 147 fip_spec.offset = fip_spec.offset + PLAT_QSPI_DATA_BASE; 148 break; 149 150 default: 151 ERROR("Unsupported boot source\n"); 152 panic(); 153 break; 154 } 155 156 result = (*register_io_dev)(&boot_dev_con); 157 assert(result == 0); 158 159 result = register_io_dev_fip(&fip_dev_con); 160 assert(result == 0); 161 162 result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec, 163 &boot_dev_handle); 164 assert(result == 0); 165 166 result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 167 assert(result == 0); 168 169 if (boot_source == BOOT_SOURCE_SDMMC) { 170 partition_init(GPT_IMAGE_ID); 171 fip_spec.offset = get_partition_entry(a2)->start; 172 } 173 174 (void)result; 175 } 176 177 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 178 uintptr_t *image_spec) 179 { 180 int result; 181 const struct plat_io_policy *policy; 182 183 assert(image_id < ARRAY_SIZE(policies)); 184 185 policy = &policies[image_id]; 186 result = policy->check(policy->image_spec); 187 assert(result == 0); 188 189 *image_spec = policy->image_spec; 190 *dev_handle = *(policy->dev_handle); 191 192 return result; 193 } 194