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 <assert.h> 82f2abcf4SHaojian Zhuang #include <errno.h> 92f2abcf4SHaojian Zhuang #include <string.h> 1009d40e0eSAntonio Nino Diaz 1109d40e0eSAntonio Nino Diaz #include <platform_def.h> 1209d40e0eSAntonio Nino Diaz 1309d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1409d40e0eSAntonio Nino Diaz #include <common/debug.h> 1509d40e0eSAntonio Nino Diaz #include <drivers/ufs.h> 1609d40e0eSAntonio Nino Diaz #include <drivers/io/io_block.h> 1709d40e0eSAntonio Nino Diaz #include <drivers/io/io_driver.h> 1809d40e0eSAntonio Nino Diaz #include <drivers/io/io_fip.h> 1909d40e0eSAntonio Nino Diaz #include <drivers/io/io_memmap.h> 2009d40e0eSAntonio Nino Diaz #include <drivers/io/io_storage.h> 21*c61cf58fSHaojian Zhuang #include <drivers/partition/partition.h> 2209d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 2309d40e0eSAntonio Nino Diaz #include <lib/semihosting.h> 2409d40e0eSAntonio Nino Diaz #include <tools_share/firmware_image_package.h> 252f2abcf4SHaojian Zhuang 262f2abcf4SHaojian Zhuang struct plat_io_policy { 272f2abcf4SHaojian Zhuang uintptr_t *dev_handle; 282f2abcf4SHaojian Zhuang uintptr_t image_spec; 292f2abcf4SHaojian Zhuang int (*check)(const uintptr_t spec); 302f2abcf4SHaojian Zhuang }; 312f2abcf4SHaojian Zhuang 322f2abcf4SHaojian Zhuang static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; 332f2abcf4SHaojian Zhuang static uintptr_t ufs_dev_handle, fip_dev_handle; 342f2abcf4SHaojian Zhuang 352f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec); 362f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec); 372f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); 382f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); 392f2abcf4SHaojian Zhuang 40*c61cf58fSHaojian Zhuang static io_block_spec_t ufs_fip_spec; 41*c61cf58fSHaojian Zhuang 42*c61cf58fSHaojian Zhuang static const io_block_spec_t ufs_gpt_spec = { 43*c61cf58fSHaojian Zhuang .offset = 0, 44*c61cf58fSHaojian Zhuang .length = PLAT_PARTITION_BLOCK_SIZE * 45*c61cf58fSHaojian Zhuang (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), 462f2abcf4SHaojian Zhuang }; 472f2abcf4SHaojian Zhuang 482f2abcf4SHaojian Zhuang static const io_block_dev_spec_t ufs_dev_spec = { 492f2abcf4SHaojian Zhuang /* It's used as temp buffer in block driver. */ 502f2abcf4SHaojian Zhuang .buffer = { 512f2abcf4SHaojian Zhuang .offset = HIKEY960_UFS_DATA_BASE, 522f2abcf4SHaojian Zhuang .length = HIKEY960_UFS_DATA_SIZE, 532f2abcf4SHaojian Zhuang }, 542f2abcf4SHaojian Zhuang .ops = { 552f2abcf4SHaojian Zhuang .read = ufs_read_lun3_blks, 562f2abcf4SHaojian Zhuang .write = ufs_write_lun3_blks, 572f2abcf4SHaojian Zhuang }, 582f2abcf4SHaojian Zhuang .block_size = UFS_BLOCK_SIZE, 592f2abcf4SHaojian Zhuang }; 602f2abcf4SHaojian Zhuang 612f2abcf4SHaojian Zhuang static const io_uuid_spec_t scp_bl2_uuid_spec = { 622f2abcf4SHaojian Zhuang .uuid = UUID_SCP_FIRMWARE_SCP_BL2, 632f2abcf4SHaojian Zhuang }; 642f2abcf4SHaojian Zhuang 652f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl31_uuid_spec = { 662f2abcf4SHaojian Zhuang .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 672f2abcf4SHaojian Zhuang }; 682f2abcf4SHaojian Zhuang 695e3325e7SVictor Chong static const io_uuid_spec_t bl32_uuid_spec = { 705e3325e7SVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32, 715e3325e7SVictor Chong }; 725e3325e7SVictor Chong 73b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra1_uuid_spec = { 74b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, 75b16bb16eSVictor Chong }; 76b16bb16eSVictor Chong 77b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra2_uuid_spec = { 78b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, 79b16bb16eSVictor Chong }; 80b16bb16eSVictor Chong 812f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = { 822f2abcf4SHaojian Zhuang .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 832f2abcf4SHaojian Zhuang }; 842f2abcf4SHaojian Zhuang 85745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT 86745d8a82STeddy Reed static const io_uuid_spec_t trusted_key_cert_uuid_spec = { 87745d8a82STeddy Reed .uuid = UUID_TRUSTED_KEY_CERT, 88745d8a82STeddy Reed }; 89745d8a82STeddy Reed 90745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { 91745d8a82STeddy Reed .uuid = UUID_SCP_FW_KEY_CERT, 92745d8a82STeddy Reed }; 93745d8a82STeddy Reed 94745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { 95745d8a82STeddy Reed .uuid = UUID_SOC_FW_KEY_CERT, 96745d8a82STeddy Reed }; 97745d8a82STeddy Reed 98745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { 99745d8a82STeddy Reed .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, 100745d8a82STeddy Reed }; 101745d8a82STeddy Reed 102745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { 103745d8a82STeddy Reed .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, 104745d8a82STeddy Reed }; 105745d8a82STeddy Reed 106745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_cert_uuid_spec = { 107745d8a82STeddy Reed .uuid = UUID_SCP_FW_CONTENT_CERT, 108745d8a82STeddy Reed }; 109745d8a82STeddy Reed 110745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_cert_uuid_spec = { 111745d8a82STeddy Reed .uuid = UUID_SOC_FW_CONTENT_CERT, 112745d8a82STeddy Reed }; 113745d8a82STeddy Reed 114745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_cert_uuid_spec = { 115745d8a82STeddy Reed .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, 116745d8a82STeddy Reed }; 117745d8a82STeddy Reed 118745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_cert_uuid_spec = { 119745d8a82STeddy Reed .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, 120745d8a82STeddy Reed }; 121745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */ 122745d8a82STeddy Reed 1232f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = { 1242f2abcf4SHaojian Zhuang [FIP_IMAGE_ID] = { 1252f2abcf4SHaojian Zhuang &ufs_dev_handle, 1262f2abcf4SHaojian Zhuang (uintptr_t)&ufs_fip_spec, 1272f2abcf4SHaojian Zhuang check_ufs 1282f2abcf4SHaojian Zhuang }, 1292f2abcf4SHaojian Zhuang [SCP_BL2_IMAGE_ID] = { 1302f2abcf4SHaojian Zhuang &fip_dev_handle, 1312f2abcf4SHaojian Zhuang (uintptr_t)&scp_bl2_uuid_spec, 1322f2abcf4SHaojian Zhuang check_fip 1332f2abcf4SHaojian Zhuang }, 1342f2abcf4SHaojian Zhuang [BL31_IMAGE_ID] = { 1352f2abcf4SHaojian Zhuang &fip_dev_handle, 1362f2abcf4SHaojian Zhuang (uintptr_t)&bl31_uuid_spec, 1372f2abcf4SHaojian Zhuang check_fip 1382f2abcf4SHaojian Zhuang }, 1395e3325e7SVictor Chong [BL32_IMAGE_ID] = { 1405e3325e7SVictor Chong &fip_dev_handle, 1415e3325e7SVictor Chong (uintptr_t)&bl32_uuid_spec, 1425e3325e7SVictor Chong check_fip 1435e3325e7SVictor Chong }, 144b16bb16eSVictor Chong [BL32_EXTRA1_IMAGE_ID] = { 145b16bb16eSVictor Chong &fip_dev_handle, 146b16bb16eSVictor Chong (uintptr_t)&bl32_extra1_uuid_spec, 147b16bb16eSVictor Chong check_fip 148b16bb16eSVictor Chong }, 149b16bb16eSVictor Chong [BL32_EXTRA2_IMAGE_ID] = { 150b16bb16eSVictor Chong &fip_dev_handle, 151b16bb16eSVictor Chong (uintptr_t)&bl32_extra2_uuid_spec, 152b16bb16eSVictor Chong check_fip 153b16bb16eSVictor Chong }, 1542f2abcf4SHaojian Zhuang [BL33_IMAGE_ID] = { 1552f2abcf4SHaojian Zhuang &fip_dev_handle, 1562f2abcf4SHaojian Zhuang (uintptr_t)&bl33_uuid_spec, 1572f2abcf4SHaojian Zhuang check_fip 158745d8a82STeddy Reed }, 159745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT 160745d8a82STeddy Reed [TRUSTED_KEY_CERT_ID] = { 161745d8a82STeddy Reed &fip_dev_handle, 162745d8a82STeddy Reed (uintptr_t)&trusted_key_cert_uuid_spec, 163745d8a82STeddy Reed check_fip 164745d8a82STeddy Reed }, 165745d8a82STeddy Reed [SCP_FW_KEY_CERT_ID] = { 166745d8a82STeddy Reed &fip_dev_handle, 167745d8a82STeddy Reed (uintptr_t)&scp_fw_key_cert_uuid_spec, 168745d8a82STeddy Reed check_fip 169745d8a82STeddy Reed }, 170745d8a82STeddy Reed [SOC_FW_KEY_CERT_ID] = { 171745d8a82STeddy Reed &fip_dev_handle, 172745d8a82STeddy Reed (uintptr_t)&soc_fw_key_cert_uuid_spec, 173745d8a82STeddy Reed check_fip 174745d8a82STeddy Reed }, 175745d8a82STeddy Reed [TRUSTED_OS_FW_KEY_CERT_ID] = { 176745d8a82STeddy Reed &fip_dev_handle, 177745d8a82STeddy Reed (uintptr_t)&tos_fw_key_cert_uuid_spec, 178745d8a82STeddy Reed check_fip 179745d8a82STeddy Reed }, 180745d8a82STeddy Reed [NON_TRUSTED_FW_KEY_CERT_ID] = { 181745d8a82STeddy Reed &fip_dev_handle, 182745d8a82STeddy Reed (uintptr_t)&nt_fw_key_cert_uuid_spec, 183745d8a82STeddy Reed check_fip 184745d8a82STeddy Reed }, 185745d8a82STeddy Reed [SCP_FW_CONTENT_CERT_ID] = { 186745d8a82STeddy Reed &fip_dev_handle, 187745d8a82STeddy Reed (uintptr_t)&scp_fw_cert_uuid_spec, 188745d8a82STeddy Reed check_fip 189745d8a82STeddy Reed }, 190745d8a82STeddy Reed [SOC_FW_CONTENT_CERT_ID] = { 191745d8a82STeddy Reed &fip_dev_handle, 192745d8a82STeddy Reed (uintptr_t)&soc_fw_cert_uuid_spec, 193745d8a82STeddy Reed check_fip 194745d8a82STeddy Reed }, 195745d8a82STeddy Reed [TRUSTED_OS_FW_CONTENT_CERT_ID] = { 196745d8a82STeddy Reed &fip_dev_handle, 197745d8a82STeddy Reed (uintptr_t)&tos_fw_cert_uuid_spec, 198745d8a82STeddy Reed check_fip 199745d8a82STeddy Reed }, 200745d8a82STeddy Reed [NON_TRUSTED_FW_CONTENT_CERT_ID] = { 201745d8a82STeddy Reed &fip_dev_handle, 202745d8a82STeddy Reed (uintptr_t)&nt_fw_cert_uuid_spec, 203745d8a82STeddy Reed check_fip 204745d8a82STeddy Reed }, 205745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */ 206*c61cf58fSHaojian Zhuang [GPT_IMAGE_ID] = { 207*c61cf58fSHaojian Zhuang &ufs_dev_handle, 208*c61cf58fSHaojian Zhuang (uintptr_t)&ufs_gpt_spec, 209*c61cf58fSHaojian Zhuang check_ufs 210*c61cf58fSHaojian Zhuang }, 2112f2abcf4SHaojian Zhuang }; 2122f2abcf4SHaojian Zhuang 2132f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec) 2142f2abcf4SHaojian Zhuang { 2152f2abcf4SHaojian Zhuang int result; 2162f2abcf4SHaojian Zhuang uintptr_t local_handle; 2172f2abcf4SHaojian Zhuang 2182f2abcf4SHaojian Zhuang result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); 2192f2abcf4SHaojian Zhuang if (result == 0) { 2202f2abcf4SHaojian Zhuang result = io_open(ufs_dev_handle, spec, &local_handle); 2212f2abcf4SHaojian Zhuang if (result == 0) 2222f2abcf4SHaojian Zhuang io_close(local_handle); 2232f2abcf4SHaojian Zhuang } 2242f2abcf4SHaojian Zhuang return result; 2252f2abcf4SHaojian Zhuang } 2262f2abcf4SHaojian Zhuang 2272f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec) 2282f2abcf4SHaojian Zhuang { 2292f2abcf4SHaojian Zhuang int result; 2302f2abcf4SHaojian Zhuang uintptr_t local_image_handle; 2312f2abcf4SHaojian Zhuang 2322f2abcf4SHaojian Zhuang /* See if a Firmware Image Package is available */ 2332f2abcf4SHaojian Zhuang result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 2342f2abcf4SHaojian Zhuang if (result == 0) { 2352f2abcf4SHaojian Zhuang result = io_open(fip_dev_handle, spec, &local_image_handle); 2362f2abcf4SHaojian Zhuang if (result == 0) { 2372f2abcf4SHaojian Zhuang VERBOSE("Using FIP\n"); 2382f2abcf4SHaojian Zhuang io_close(local_image_handle); 2392f2abcf4SHaojian Zhuang } 2402f2abcf4SHaojian Zhuang } 2412f2abcf4SHaojian Zhuang return result; 2422f2abcf4SHaojian Zhuang } 2432f2abcf4SHaojian Zhuang 2442f2abcf4SHaojian Zhuang void hikey960_io_setup(void) 2452f2abcf4SHaojian Zhuang { 2462f2abcf4SHaojian Zhuang int result; 2472f2abcf4SHaojian Zhuang 2482f2abcf4SHaojian Zhuang result = register_io_dev_block(&ufs_dev_con); 2492f2abcf4SHaojian Zhuang assert(result == 0); 2502f2abcf4SHaojian Zhuang 2512f2abcf4SHaojian Zhuang result = register_io_dev_fip(&fip_dev_con); 2522f2abcf4SHaojian Zhuang assert(result == 0); 2532f2abcf4SHaojian Zhuang 2542f2abcf4SHaojian Zhuang result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, 2552f2abcf4SHaojian Zhuang &ufs_dev_handle); 2562f2abcf4SHaojian Zhuang assert(result == 0); 2572f2abcf4SHaojian Zhuang 2582f2abcf4SHaojian Zhuang result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 2592f2abcf4SHaojian Zhuang assert(result == 0); 2602f2abcf4SHaojian Zhuang 2612f2abcf4SHaojian Zhuang /* Ignore improbable errors in release builds */ 2622f2abcf4SHaojian Zhuang (void)result; 2632f2abcf4SHaojian Zhuang } 2642f2abcf4SHaojian Zhuang 265*c61cf58fSHaojian Zhuang int hikey960_set_fip_addr(unsigned int image_id, const char *name) 266*c61cf58fSHaojian Zhuang { 267*c61cf58fSHaojian Zhuang const partition_entry_t *entry; 268*c61cf58fSHaojian Zhuang 269*c61cf58fSHaojian Zhuang if (ufs_fip_spec.length == 0) { 270*c61cf58fSHaojian Zhuang partition_init(GPT_IMAGE_ID); 271*c61cf58fSHaojian Zhuang entry = get_partition_entry(name); 272*c61cf58fSHaojian Zhuang if (entry == NULL) { 273*c61cf58fSHaojian Zhuang ERROR("Could NOT find the %s partition!\n", name); 274*c61cf58fSHaojian Zhuang return -ENOENT; 275*c61cf58fSHaojian Zhuang } 276*c61cf58fSHaojian Zhuang ufs_fip_spec.offset = entry->start; 277*c61cf58fSHaojian Zhuang ufs_fip_spec.length = entry->length; 278*c61cf58fSHaojian Zhuang } 279*c61cf58fSHaojian Zhuang return 0; 280*c61cf58fSHaojian Zhuang } 281*c61cf58fSHaojian Zhuang 2822f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access 2832f2abcf4SHaojian Zhuang * an image. Use this to enforce platform load policy 2842f2abcf4SHaojian Zhuang */ 2852f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 2862f2abcf4SHaojian Zhuang uintptr_t *image_spec) 2872f2abcf4SHaojian Zhuang { 2882f2abcf4SHaojian Zhuang int result; 2892f2abcf4SHaojian Zhuang const struct plat_io_policy *policy; 2902f2abcf4SHaojian Zhuang 2912f2abcf4SHaojian Zhuang assert(image_id < ARRAY_SIZE(policies)); 2922f2abcf4SHaojian Zhuang 2932f2abcf4SHaojian Zhuang policy = &policies[image_id]; 2942f2abcf4SHaojian Zhuang result = policy->check(policy->image_spec); 2952f2abcf4SHaojian Zhuang assert(result == 0); 2962f2abcf4SHaojian Zhuang 2972f2abcf4SHaojian Zhuang *image_spec = policy->image_spec; 2982f2abcf4SHaojian Zhuang *dev_handle = *(policy->dev_handle); 2992f2abcf4SHaojian Zhuang 3002f2abcf4SHaojian Zhuang return result; 3012f2abcf4SHaojian Zhuang } 3022f2abcf4SHaojian Zhuang 3032f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) 3042f2abcf4SHaojian Zhuang { 3052f2abcf4SHaojian Zhuang return ufs_read_blocks(3, lba, buf, size); 3062f2abcf4SHaojian Zhuang } 3072f2abcf4SHaojian Zhuang 3082f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) 3092f2abcf4SHaojian Zhuang { 3102f2abcf4SHaojian Zhuang return ufs_write_blocks(3, lba, buf, size); 3112f2abcf4SHaojian Zhuang } 312