1 /* 2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <assert.h> 9 #include <debug.h> 10 #include <errno.h> 11 #include <firmware_image_package.h> 12 #include <io_block.h> 13 #include <io_driver.h> 14 #include <io_fip.h> 15 #include <io_memmap.h> 16 #include <io_storage.h> 17 #include <mmio.h> 18 #include <platform_def.h> 19 #include <semihosting.h> /* For FOPEN_MODE_... */ 20 #include <string.h> 21 #include <ufs.h> 22 23 struct plat_io_policy { 24 uintptr_t *dev_handle; 25 uintptr_t image_spec; 26 int (*check)(const uintptr_t spec); 27 }; 28 29 static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; 30 static uintptr_t ufs_dev_handle, fip_dev_handle; 31 32 static int check_ufs(const uintptr_t spec); 33 static int check_fip(const uintptr_t spec); 34 size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); 35 size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); 36 37 static const io_block_spec_t ufs_fip_spec = { 38 .offset = HIKEY960_FIP_BASE, 39 .length = HIKEY960_FIP_MAX_SIZE, 40 }; 41 42 static const io_block_dev_spec_t ufs_dev_spec = { 43 /* It's used as temp buffer in block driver. */ 44 .buffer = { 45 .offset = HIKEY960_UFS_DATA_BASE, 46 .length = HIKEY960_UFS_DATA_SIZE, 47 }, 48 .ops = { 49 .read = ufs_read_lun3_blks, 50 .write = ufs_write_lun3_blks, 51 }, 52 .block_size = UFS_BLOCK_SIZE, 53 }; 54 55 static const io_uuid_spec_t scp_bl2_uuid_spec = { 56 .uuid = UUID_SCP_FIRMWARE_SCP_BL2, 57 }; 58 59 static const io_uuid_spec_t bl31_uuid_spec = { 60 .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 61 }; 62 63 static const io_uuid_spec_t bl32_uuid_spec = { 64 .uuid = UUID_SECURE_PAYLOAD_BL32, 65 }; 66 67 static const io_uuid_spec_t bl32_extra1_uuid_spec = { 68 .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, 69 }; 70 71 static const io_uuid_spec_t bl32_extra2_uuid_spec = { 72 .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, 73 }; 74 75 static const io_uuid_spec_t bl33_uuid_spec = { 76 .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 77 }; 78 79 static const struct plat_io_policy policies[] = { 80 [FIP_IMAGE_ID] = { 81 &ufs_dev_handle, 82 (uintptr_t)&ufs_fip_spec, 83 check_ufs 84 }, 85 [SCP_BL2_IMAGE_ID] = { 86 &fip_dev_handle, 87 (uintptr_t)&scp_bl2_uuid_spec, 88 check_fip 89 }, 90 [BL31_IMAGE_ID] = { 91 &fip_dev_handle, 92 (uintptr_t)&bl31_uuid_spec, 93 check_fip 94 }, 95 [BL32_IMAGE_ID] = { 96 &fip_dev_handle, 97 (uintptr_t)&bl32_uuid_spec, 98 check_fip 99 }, 100 [BL32_EXTRA1_IMAGE_ID] = { 101 &fip_dev_handle, 102 (uintptr_t)&bl32_extra1_uuid_spec, 103 check_fip 104 }, 105 [BL32_EXTRA2_IMAGE_ID] = { 106 &fip_dev_handle, 107 (uintptr_t)&bl32_extra2_uuid_spec, 108 check_fip 109 }, 110 [BL33_IMAGE_ID] = { 111 &fip_dev_handle, 112 (uintptr_t)&bl33_uuid_spec, 113 check_fip 114 } 115 }; 116 117 static int check_ufs(const uintptr_t spec) 118 { 119 int result; 120 uintptr_t local_handle; 121 122 result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); 123 if (result == 0) { 124 result = io_open(ufs_dev_handle, spec, &local_handle); 125 if (result == 0) 126 io_close(local_handle); 127 } 128 return result; 129 } 130 131 static int check_fip(const uintptr_t spec) 132 { 133 int result; 134 uintptr_t local_image_handle; 135 136 /* See if a Firmware Image Package is available */ 137 result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 138 if (result == 0) { 139 result = io_open(fip_dev_handle, spec, &local_image_handle); 140 if (result == 0) { 141 VERBOSE("Using FIP\n"); 142 io_close(local_image_handle); 143 } 144 } 145 return result; 146 } 147 148 void hikey960_io_setup(void) 149 { 150 int result; 151 152 result = register_io_dev_block(&ufs_dev_con); 153 assert(result == 0); 154 155 result = register_io_dev_fip(&fip_dev_con); 156 assert(result == 0); 157 158 result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, 159 &ufs_dev_handle); 160 assert(result == 0); 161 162 result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 163 assert(result == 0); 164 165 /* Ignore improbable errors in release builds */ 166 (void)result; 167 } 168 169 /* Return an IO device handle and specification which can be used to access 170 * an image. Use this to enforce platform load policy 171 */ 172 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 173 uintptr_t *image_spec) 174 { 175 int result; 176 const struct plat_io_policy *policy; 177 178 assert(image_id < ARRAY_SIZE(policies)); 179 180 policy = &policies[image_id]; 181 result = policy->check(policy->image_spec); 182 assert(result == 0); 183 184 *image_spec = policy->image_spec; 185 *dev_handle = *(policy->dev_handle); 186 187 return result; 188 } 189 190 size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) 191 { 192 return ufs_read_blocks(3, lba, buf, size); 193 } 194 195 size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) 196 { 197 return ufs_write_blocks(3, lba, buf, size); 198 } 199