12f2abcf4SHaojian Zhuang /* 2d2128731SHaojian Zhuang * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 32f2abcf4SHaojian Zhuang * 42f2abcf4SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 52f2abcf4SHaojian Zhuang */ 62f2abcf4SHaojian Zhuang 72f2abcf4SHaojian Zhuang #include <arch_helpers.h> 82f2abcf4SHaojian Zhuang #include <assert.h> 92f2abcf4SHaojian Zhuang #include <debug.h> 102f2abcf4SHaojian Zhuang #include <errno.h> 112f2abcf4SHaojian Zhuang #include <firmware_image_package.h> 122f2abcf4SHaojian Zhuang #include <io_block.h> 132f2abcf4SHaojian Zhuang #include <io_driver.h> 142f2abcf4SHaojian Zhuang #include <io_fip.h> 152f2abcf4SHaojian Zhuang #include <io_memmap.h> 162f2abcf4SHaojian Zhuang #include <io_storage.h> 172f2abcf4SHaojian Zhuang #include <mmio.h> 182f2abcf4SHaojian Zhuang #include <platform_def.h> 192f2abcf4SHaojian Zhuang #include <semihosting.h> /* For FOPEN_MODE_... */ 202f2abcf4SHaojian Zhuang #include <string.h> 212f2abcf4SHaojian Zhuang #include <ufs.h> 222f2abcf4SHaojian Zhuang 232f2abcf4SHaojian Zhuang struct plat_io_policy { 242f2abcf4SHaojian Zhuang uintptr_t *dev_handle; 252f2abcf4SHaojian Zhuang uintptr_t image_spec; 262f2abcf4SHaojian Zhuang int (*check)(const uintptr_t spec); 272f2abcf4SHaojian Zhuang }; 282f2abcf4SHaojian Zhuang 292f2abcf4SHaojian Zhuang static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; 302f2abcf4SHaojian Zhuang static uintptr_t ufs_dev_handle, fip_dev_handle; 312f2abcf4SHaojian Zhuang 322f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec); 332f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec); 342f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); 352f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); 362f2abcf4SHaojian Zhuang 372f2abcf4SHaojian Zhuang static const io_block_spec_t ufs_fip_spec = { 382f2abcf4SHaojian Zhuang .offset = HIKEY960_FIP_BASE, 392f2abcf4SHaojian Zhuang .length = HIKEY960_FIP_MAX_SIZE, 402f2abcf4SHaojian Zhuang }; 412f2abcf4SHaojian Zhuang 422f2abcf4SHaojian Zhuang static const io_block_dev_spec_t ufs_dev_spec = { 432f2abcf4SHaojian Zhuang /* It's used as temp buffer in block driver. */ 442f2abcf4SHaojian Zhuang .buffer = { 452f2abcf4SHaojian Zhuang .offset = HIKEY960_UFS_DATA_BASE, 462f2abcf4SHaojian Zhuang .length = HIKEY960_UFS_DATA_SIZE, 472f2abcf4SHaojian Zhuang }, 482f2abcf4SHaojian Zhuang .ops = { 492f2abcf4SHaojian Zhuang .read = ufs_read_lun3_blks, 502f2abcf4SHaojian Zhuang .write = ufs_write_lun3_blks, 512f2abcf4SHaojian Zhuang }, 522f2abcf4SHaojian Zhuang .block_size = UFS_BLOCK_SIZE, 532f2abcf4SHaojian Zhuang }; 542f2abcf4SHaojian Zhuang 552f2abcf4SHaojian Zhuang static const io_uuid_spec_t scp_bl2_uuid_spec = { 562f2abcf4SHaojian Zhuang .uuid = UUID_SCP_FIRMWARE_SCP_BL2, 572f2abcf4SHaojian Zhuang }; 582f2abcf4SHaojian Zhuang 592f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl31_uuid_spec = { 602f2abcf4SHaojian Zhuang .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 612f2abcf4SHaojian Zhuang }; 622f2abcf4SHaojian Zhuang 635e3325e7SVictor Chong static const io_uuid_spec_t bl32_uuid_spec = { 645e3325e7SVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32, 655e3325e7SVictor Chong }; 665e3325e7SVictor Chong 67b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra1_uuid_spec = { 68b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, 69b16bb16eSVictor Chong }; 70b16bb16eSVictor Chong 71b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra2_uuid_spec = { 72b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, 73b16bb16eSVictor Chong }; 74b16bb16eSVictor Chong 752f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = { 762f2abcf4SHaojian Zhuang .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 772f2abcf4SHaojian Zhuang }; 782f2abcf4SHaojian Zhuang 79*745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT 80*745d8a82STeddy Reed static const io_uuid_spec_t trusted_key_cert_uuid_spec = { 81*745d8a82STeddy Reed .uuid = UUID_TRUSTED_KEY_CERT, 82*745d8a82STeddy Reed }; 83*745d8a82STeddy Reed 84*745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { 85*745d8a82STeddy Reed .uuid = UUID_SCP_FW_KEY_CERT, 86*745d8a82STeddy Reed }; 87*745d8a82STeddy Reed 88*745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { 89*745d8a82STeddy Reed .uuid = UUID_SOC_FW_KEY_CERT, 90*745d8a82STeddy Reed }; 91*745d8a82STeddy Reed 92*745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { 93*745d8a82STeddy Reed .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, 94*745d8a82STeddy Reed }; 95*745d8a82STeddy Reed 96*745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { 97*745d8a82STeddy Reed .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, 98*745d8a82STeddy Reed }; 99*745d8a82STeddy Reed 100*745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_cert_uuid_spec = { 101*745d8a82STeddy Reed .uuid = UUID_SCP_FW_CONTENT_CERT, 102*745d8a82STeddy Reed }; 103*745d8a82STeddy Reed 104*745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_cert_uuid_spec = { 105*745d8a82STeddy Reed .uuid = UUID_SOC_FW_CONTENT_CERT, 106*745d8a82STeddy Reed }; 107*745d8a82STeddy Reed 108*745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_cert_uuid_spec = { 109*745d8a82STeddy Reed .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, 110*745d8a82STeddy Reed }; 111*745d8a82STeddy Reed 112*745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_cert_uuid_spec = { 113*745d8a82STeddy Reed .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, 114*745d8a82STeddy Reed }; 115*745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */ 116*745d8a82STeddy Reed 1172f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = { 1182f2abcf4SHaojian Zhuang [FIP_IMAGE_ID] = { 1192f2abcf4SHaojian Zhuang &ufs_dev_handle, 1202f2abcf4SHaojian Zhuang (uintptr_t)&ufs_fip_spec, 1212f2abcf4SHaojian Zhuang check_ufs 1222f2abcf4SHaojian Zhuang }, 1232f2abcf4SHaojian Zhuang [SCP_BL2_IMAGE_ID] = { 1242f2abcf4SHaojian Zhuang &fip_dev_handle, 1252f2abcf4SHaojian Zhuang (uintptr_t)&scp_bl2_uuid_spec, 1262f2abcf4SHaojian Zhuang check_fip 1272f2abcf4SHaojian Zhuang }, 1282f2abcf4SHaojian Zhuang [BL31_IMAGE_ID] = { 1292f2abcf4SHaojian Zhuang &fip_dev_handle, 1302f2abcf4SHaojian Zhuang (uintptr_t)&bl31_uuid_spec, 1312f2abcf4SHaojian Zhuang check_fip 1322f2abcf4SHaojian Zhuang }, 1335e3325e7SVictor Chong [BL32_IMAGE_ID] = { 1345e3325e7SVictor Chong &fip_dev_handle, 1355e3325e7SVictor Chong (uintptr_t)&bl32_uuid_spec, 1365e3325e7SVictor Chong check_fip 1375e3325e7SVictor Chong }, 138b16bb16eSVictor Chong [BL32_EXTRA1_IMAGE_ID] = { 139b16bb16eSVictor Chong &fip_dev_handle, 140b16bb16eSVictor Chong (uintptr_t)&bl32_extra1_uuid_spec, 141b16bb16eSVictor Chong check_fip 142b16bb16eSVictor Chong }, 143b16bb16eSVictor Chong [BL32_EXTRA2_IMAGE_ID] = { 144b16bb16eSVictor Chong &fip_dev_handle, 145b16bb16eSVictor Chong (uintptr_t)&bl32_extra2_uuid_spec, 146b16bb16eSVictor Chong check_fip 147b16bb16eSVictor Chong }, 1482f2abcf4SHaojian Zhuang [BL33_IMAGE_ID] = { 1492f2abcf4SHaojian Zhuang &fip_dev_handle, 1502f2abcf4SHaojian Zhuang (uintptr_t)&bl33_uuid_spec, 1512f2abcf4SHaojian Zhuang check_fip 152*745d8a82STeddy Reed }, 153*745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT 154*745d8a82STeddy Reed [TRUSTED_KEY_CERT_ID] = { 155*745d8a82STeddy Reed &fip_dev_handle, 156*745d8a82STeddy Reed (uintptr_t)&trusted_key_cert_uuid_spec, 157*745d8a82STeddy Reed check_fip 158*745d8a82STeddy Reed }, 159*745d8a82STeddy Reed [SCP_FW_KEY_CERT_ID] = { 160*745d8a82STeddy Reed &fip_dev_handle, 161*745d8a82STeddy Reed (uintptr_t)&scp_fw_key_cert_uuid_spec, 162*745d8a82STeddy Reed check_fip 163*745d8a82STeddy Reed }, 164*745d8a82STeddy Reed [SOC_FW_KEY_CERT_ID] = { 165*745d8a82STeddy Reed &fip_dev_handle, 166*745d8a82STeddy Reed (uintptr_t)&soc_fw_key_cert_uuid_spec, 167*745d8a82STeddy Reed check_fip 168*745d8a82STeddy Reed }, 169*745d8a82STeddy Reed [TRUSTED_OS_FW_KEY_CERT_ID] = { 170*745d8a82STeddy Reed &fip_dev_handle, 171*745d8a82STeddy Reed (uintptr_t)&tos_fw_key_cert_uuid_spec, 172*745d8a82STeddy Reed check_fip 173*745d8a82STeddy Reed }, 174*745d8a82STeddy Reed [NON_TRUSTED_FW_KEY_CERT_ID] = { 175*745d8a82STeddy Reed &fip_dev_handle, 176*745d8a82STeddy Reed (uintptr_t)&nt_fw_key_cert_uuid_spec, 177*745d8a82STeddy Reed check_fip 178*745d8a82STeddy Reed }, 179*745d8a82STeddy Reed [SCP_FW_CONTENT_CERT_ID] = { 180*745d8a82STeddy Reed &fip_dev_handle, 181*745d8a82STeddy Reed (uintptr_t)&scp_fw_cert_uuid_spec, 182*745d8a82STeddy Reed check_fip 183*745d8a82STeddy Reed }, 184*745d8a82STeddy Reed [SOC_FW_CONTENT_CERT_ID] = { 185*745d8a82STeddy Reed &fip_dev_handle, 186*745d8a82STeddy Reed (uintptr_t)&soc_fw_cert_uuid_spec, 187*745d8a82STeddy Reed check_fip 188*745d8a82STeddy Reed }, 189*745d8a82STeddy Reed [TRUSTED_OS_FW_CONTENT_CERT_ID] = { 190*745d8a82STeddy Reed &fip_dev_handle, 191*745d8a82STeddy Reed (uintptr_t)&tos_fw_cert_uuid_spec, 192*745d8a82STeddy Reed check_fip 193*745d8a82STeddy Reed }, 194*745d8a82STeddy Reed [NON_TRUSTED_FW_CONTENT_CERT_ID] = { 195*745d8a82STeddy Reed &fip_dev_handle, 196*745d8a82STeddy Reed (uintptr_t)&nt_fw_cert_uuid_spec, 197*745d8a82STeddy Reed check_fip 198*745d8a82STeddy Reed }, 199*745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */ 2002f2abcf4SHaojian Zhuang }; 2012f2abcf4SHaojian Zhuang 2022f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec) 2032f2abcf4SHaojian Zhuang { 2042f2abcf4SHaojian Zhuang int result; 2052f2abcf4SHaojian Zhuang uintptr_t local_handle; 2062f2abcf4SHaojian Zhuang 2072f2abcf4SHaojian Zhuang result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); 2082f2abcf4SHaojian Zhuang if (result == 0) { 2092f2abcf4SHaojian Zhuang result = io_open(ufs_dev_handle, spec, &local_handle); 2102f2abcf4SHaojian Zhuang if (result == 0) 2112f2abcf4SHaojian Zhuang io_close(local_handle); 2122f2abcf4SHaojian Zhuang } 2132f2abcf4SHaojian Zhuang return result; 2142f2abcf4SHaojian Zhuang } 2152f2abcf4SHaojian Zhuang 2162f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec) 2172f2abcf4SHaojian Zhuang { 2182f2abcf4SHaojian Zhuang int result; 2192f2abcf4SHaojian Zhuang uintptr_t local_image_handle; 2202f2abcf4SHaojian Zhuang 2212f2abcf4SHaojian Zhuang /* See if a Firmware Image Package is available */ 2222f2abcf4SHaojian Zhuang result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 2232f2abcf4SHaojian Zhuang if (result == 0) { 2242f2abcf4SHaojian Zhuang result = io_open(fip_dev_handle, spec, &local_image_handle); 2252f2abcf4SHaojian Zhuang if (result == 0) { 2262f2abcf4SHaojian Zhuang VERBOSE("Using FIP\n"); 2272f2abcf4SHaojian Zhuang io_close(local_image_handle); 2282f2abcf4SHaojian Zhuang } 2292f2abcf4SHaojian Zhuang } 2302f2abcf4SHaojian Zhuang return result; 2312f2abcf4SHaojian Zhuang } 2322f2abcf4SHaojian Zhuang 2332f2abcf4SHaojian Zhuang void hikey960_io_setup(void) 2342f2abcf4SHaojian Zhuang { 2352f2abcf4SHaojian Zhuang int result; 2362f2abcf4SHaojian Zhuang 2372f2abcf4SHaojian Zhuang result = register_io_dev_block(&ufs_dev_con); 2382f2abcf4SHaojian Zhuang assert(result == 0); 2392f2abcf4SHaojian Zhuang 2402f2abcf4SHaojian Zhuang result = register_io_dev_fip(&fip_dev_con); 2412f2abcf4SHaojian Zhuang assert(result == 0); 2422f2abcf4SHaojian Zhuang 2432f2abcf4SHaojian Zhuang result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, 2442f2abcf4SHaojian Zhuang &ufs_dev_handle); 2452f2abcf4SHaojian Zhuang assert(result == 0); 2462f2abcf4SHaojian Zhuang 2472f2abcf4SHaojian Zhuang result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 2482f2abcf4SHaojian Zhuang assert(result == 0); 2492f2abcf4SHaojian Zhuang 2502f2abcf4SHaojian Zhuang /* Ignore improbable errors in release builds */ 2512f2abcf4SHaojian Zhuang (void)result; 2522f2abcf4SHaojian Zhuang } 2532f2abcf4SHaojian Zhuang 2542f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access 2552f2abcf4SHaojian Zhuang * an image. Use this to enforce platform load policy 2562f2abcf4SHaojian Zhuang */ 2572f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 2582f2abcf4SHaojian Zhuang uintptr_t *image_spec) 2592f2abcf4SHaojian Zhuang { 2602f2abcf4SHaojian Zhuang int result; 2612f2abcf4SHaojian Zhuang const struct plat_io_policy *policy; 2622f2abcf4SHaojian Zhuang 2632f2abcf4SHaojian Zhuang assert(image_id < ARRAY_SIZE(policies)); 2642f2abcf4SHaojian Zhuang 2652f2abcf4SHaojian Zhuang policy = &policies[image_id]; 2662f2abcf4SHaojian Zhuang result = policy->check(policy->image_spec); 2672f2abcf4SHaojian Zhuang assert(result == 0); 2682f2abcf4SHaojian Zhuang 2692f2abcf4SHaojian Zhuang *image_spec = policy->image_spec; 2702f2abcf4SHaojian Zhuang *dev_handle = *(policy->dev_handle); 2712f2abcf4SHaojian Zhuang 2722f2abcf4SHaojian Zhuang return result; 2732f2abcf4SHaojian Zhuang } 2742f2abcf4SHaojian Zhuang 2752f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) 2762f2abcf4SHaojian Zhuang { 2772f2abcf4SHaojian Zhuang return ufs_read_blocks(3, lba, buf, size); 2782f2abcf4SHaojian Zhuang } 2792f2abcf4SHaojian Zhuang 2802f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) 2812f2abcf4SHaojian Zhuang { 2822f2abcf4SHaojian Zhuang return ufs_write_blocks(3, lba, buf, size); 2832f2abcf4SHaojian Zhuang } 284