12f2abcf4SHaojian Zhuang /* 22f2abcf4SHaojian Zhuang * Copyright (c) 2017, 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_spec_t ufs_data_spec = { 432f2abcf4SHaojian Zhuang .offset = 0, 442f2abcf4SHaojian Zhuang .length = 256 << 20, 452f2abcf4SHaojian Zhuang }; 462f2abcf4SHaojian Zhuang 472f2abcf4SHaojian Zhuang static const io_block_dev_spec_t ufs_dev_spec = { 482f2abcf4SHaojian Zhuang /* It's used as temp buffer in block driver. */ 492f2abcf4SHaojian Zhuang .buffer = { 502f2abcf4SHaojian Zhuang .offset = HIKEY960_UFS_DATA_BASE, 512f2abcf4SHaojian Zhuang .length = HIKEY960_UFS_DATA_SIZE, 522f2abcf4SHaojian Zhuang }, 532f2abcf4SHaojian Zhuang .ops = { 542f2abcf4SHaojian Zhuang .read = ufs_read_lun3_blks, 552f2abcf4SHaojian Zhuang .write = ufs_write_lun3_blks, 562f2abcf4SHaojian Zhuang }, 572f2abcf4SHaojian Zhuang .block_size = UFS_BLOCK_SIZE, 582f2abcf4SHaojian Zhuang }; 592f2abcf4SHaojian Zhuang 602f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl2_uuid_spec = { 612f2abcf4SHaojian Zhuang .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, 622f2abcf4SHaojian Zhuang }; 632f2abcf4SHaojian Zhuang 642f2abcf4SHaojian Zhuang static const io_uuid_spec_t scp_bl2_uuid_spec = { 652f2abcf4SHaojian Zhuang .uuid = UUID_SCP_FIRMWARE_SCP_BL2, 662f2abcf4SHaojian Zhuang }; 672f2abcf4SHaojian Zhuang 682f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl31_uuid_spec = { 692f2abcf4SHaojian Zhuang .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 702f2abcf4SHaojian Zhuang }; 712f2abcf4SHaojian Zhuang 725e3325e7SVictor Chong static const io_uuid_spec_t bl32_uuid_spec = { 735e3325e7SVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32, 745e3325e7SVictor Chong }; 755e3325e7SVictor Chong 76*b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra1_uuid_spec = { 77*b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, 78*b16bb16eSVictor Chong }; 79*b16bb16eSVictor Chong 80*b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra2_uuid_spec = { 81*b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, 82*b16bb16eSVictor Chong }; 83*b16bb16eSVictor Chong 842f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = { 852f2abcf4SHaojian Zhuang .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 862f2abcf4SHaojian Zhuang }; 872f2abcf4SHaojian Zhuang 882f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = { 892f2abcf4SHaojian Zhuang [FIP_IMAGE_ID] = { 902f2abcf4SHaojian Zhuang &ufs_dev_handle, 912f2abcf4SHaojian Zhuang (uintptr_t)&ufs_fip_spec, 922f2abcf4SHaojian Zhuang check_ufs 932f2abcf4SHaojian Zhuang }, 942f2abcf4SHaojian Zhuang [BL2_IMAGE_ID] = { 952f2abcf4SHaojian Zhuang &fip_dev_handle, 962f2abcf4SHaojian Zhuang (uintptr_t)&bl2_uuid_spec, 972f2abcf4SHaojian Zhuang check_fip 982f2abcf4SHaojian Zhuang }, 992f2abcf4SHaojian Zhuang [SCP_BL2_IMAGE_ID] = { 1002f2abcf4SHaojian Zhuang &fip_dev_handle, 1012f2abcf4SHaojian Zhuang (uintptr_t)&scp_bl2_uuid_spec, 1022f2abcf4SHaojian Zhuang check_fip 1032f2abcf4SHaojian Zhuang }, 1042f2abcf4SHaojian Zhuang [BL31_IMAGE_ID] = { 1052f2abcf4SHaojian Zhuang &fip_dev_handle, 1062f2abcf4SHaojian Zhuang (uintptr_t)&bl31_uuid_spec, 1072f2abcf4SHaojian Zhuang check_fip 1082f2abcf4SHaojian Zhuang }, 1095e3325e7SVictor Chong [BL32_IMAGE_ID] = { 1105e3325e7SVictor Chong &fip_dev_handle, 1115e3325e7SVictor Chong (uintptr_t)&bl32_uuid_spec, 1125e3325e7SVictor Chong check_fip 1135e3325e7SVictor Chong }, 114*b16bb16eSVictor Chong [BL32_EXTRA1_IMAGE_ID] = { 115*b16bb16eSVictor Chong &fip_dev_handle, 116*b16bb16eSVictor Chong (uintptr_t)&bl32_extra1_uuid_spec, 117*b16bb16eSVictor Chong check_fip 118*b16bb16eSVictor Chong }, 119*b16bb16eSVictor Chong [BL32_EXTRA2_IMAGE_ID] = { 120*b16bb16eSVictor Chong &fip_dev_handle, 121*b16bb16eSVictor Chong (uintptr_t)&bl32_extra2_uuid_spec, 122*b16bb16eSVictor Chong check_fip 123*b16bb16eSVictor Chong }, 1242f2abcf4SHaojian Zhuang [BL33_IMAGE_ID] = { 1252f2abcf4SHaojian Zhuang &fip_dev_handle, 1262f2abcf4SHaojian Zhuang (uintptr_t)&bl33_uuid_spec, 1272f2abcf4SHaojian Zhuang check_fip 1282f2abcf4SHaojian Zhuang }, 1292f2abcf4SHaojian Zhuang [BL2U_IMAGE_ID] = { 1302f2abcf4SHaojian Zhuang &ufs_dev_handle, 1312f2abcf4SHaojian Zhuang (uintptr_t)&ufs_data_spec, 1322f2abcf4SHaojian Zhuang check_ufs 1332f2abcf4SHaojian Zhuang } 1342f2abcf4SHaojian Zhuang }; 1352f2abcf4SHaojian Zhuang 1362f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec) 1372f2abcf4SHaojian Zhuang { 1382f2abcf4SHaojian Zhuang int result; 1392f2abcf4SHaojian Zhuang uintptr_t local_handle; 1402f2abcf4SHaojian Zhuang 1412f2abcf4SHaojian Zhuang result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); 1422f2abcf4SHaojian Zhuang if (result == 0) { 1432f2abcf4SHaojian Zhuang result = io_open(ufs_dev_handle, spec, &local_handle); 1442f2abcf4SHaojian Zhuang if (result == 0) 1452f2abcf4SHaojian Zhuang io_close(local_handle); 1462f2abcf4SHaojian Zhuang } 1472f2abcf4SHaojian Zhuang return result; 1482f2abcf4SHaojian Zhuang } 1492f2abcf4SHaojian Zhuang 1502f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec) 1512f2abcf4SHaojian Zhuang { 1522f2abcf4SHaojian Zhuang int result; 1532f2abcf4SHaojian Zhuang uintptr_t local_image_handle; 1542f2abcf4SHaojian Zhuang 1552f2abcf4SHaojian Zhuang /* See if a Firmware Image Package is available */ 1562f2abcf4SHaojian Zhuang result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 1572f2abcf4SHaojian Zhuang if (result == 0) { 1582f2abcf4SHaojian Zhuang result = io_open(fip_dev_handle, spec, &local_image_handle); 1592f2abcf4SHaojian Zhuang if (result == 0) { 1602f2abcf4SHaojian Zhuang VERBOSE("Using FIP\n"); 1612f2abcf4SHaojian Zhuang io_close(local_image_handle); 1622f2abcf4SHaojian Zhuang } 1632f2abcf4SHaojian Zhuang } 1642f2abcf4SHaojian Zhuang return result; 1652f2abcf4SHaojian Zhuang } 1662f2abcf4SHaojian Zhuang 1672f2abcf4SHaojian Zhuang void hikey960_io_setup(void) 1682f2abcf4SHaojian Zhuang { 1692f2abcf4SHaojian Zhuang int result; 1702f2abcf4SHaojian Zhuang 1712f2abcf4SHaojian Zhuang result = register_io_dev_block(&ufs_dev_con); 1722f2abcf4SHaojian Zhuang assert(result == 0); 1732f2abcf4SHaojian Zhuang 1742f2abcf4SHaojian Zhuang result = register_io_dev_fip(&fip_dev_con); 1752f2abcf4SHaojian Zhuang assert(result == 0); 1762f2abcf4SHaojian Zhuang 1772f2abcf4SHaojian Zhuang result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, 1782f2abcf4SHaojian Zhuang &ufs_dev_handle); 1792f2abcf4SHaojian Zhuang assert(result == 0); 1802f2abcf4SHaojian Zhuang 1812f2abcf4SHaojian Zhuang result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 1822f2abcf4SHaojian Zhuang assert(result == 0); 1832f2abcf4SHaojian Zhuang 1842f2abcf4SHaojian Zhuang /* Ignore improbable errors in release builds */ 1852f2abcf4SHaojian Zhuang (void)result; 1862f2abcf4SHaojian Zhuang } 1872f2abcf4SHaojian Zhuang 1882f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access 1892f2abcf4SHaojian Zhuang * an image. Use this to enforce platform load policy 1902f2abcf4SHaojian Zhuang */ 1912f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 1922f2abcf4SHaojian Zhuang uintptr_t *image_spec) 1932f2abcf4SHaojian Zhuang { 1942f2abcf4SHaojian Zhuang int result; 1952f2abcf4SHaojian Zhuang const struct plat_io_policy *policy; 1962f2abcf4SHaojian Zhuang 1972f2abcf4SHaojian Zhuang assert(image_id < ARRAY_SIZE(policies)); 1982f2abcf4SHaojian Zhuang 1992f2abcf4SHaojian Zhuang policy = &policies[image_id]; 2002f2abcf4SHaojian Zhuang result = policy->check(policy->image_spec); 2012f2abcf4SHaojian Zhuang assert(result == 0); 2022f2abcf4SHaojian Zhuang 2032f2abcf4SHaojian Zhuang *image_spec = policy->image_spec; 2042f2abcf4SHaojian Zhuang *dev_handle = *(policy->dev_handle); 2052f2abcf4SHaojian Zhuang 2062f2abcf4SHaojian Zhuang return result; 2072f2abcf4SHaojian Zhuang } 2082f2abcf4SHaojian Zhuang 2092f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) 2102f2abcf4SHaojian Zhuang { 2112f2abcf4SHaojian Zhuang return ufs_read_blocks(3, lba, buf, size); 2122f2abcf4SHaojian Zhuang } 2132f2abcf4SHaojian Zhuang 2142f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) 2152f2abcf4SHaojian Zhuang { 2162f2abcf4SHaojian Zhuang return ufs_write_blocks(3, lba, buf, size); 2172f2abcf4SHaojian Zhuang } 218