12f2abcf4SHaojian Zhuang /* 26971642dSLukas Hanel * Copyright (c) 2017-2022, 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> 21c61cf58fSHaojian 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 26*c371b83fSArthur Cassegrain #include "hikey960_def.h" 27*c371b83fSArthur Cassegrain #include "hikey960_private.h" 28*c371b83fSArthur Cassegrain 292f2abcf4SHaojian Zhuang struct plat_io_policy { 302f2abcf4SHaojian Zhuang uintptr_t *dev_handle; 312f2abcf4SHaojian Zhuang uintptr_t image_spec; 322f2abcf4SHaojian Zhuang int (*check)(const uintptr_t spec); 332f2abcf4SHaojian Zhuang }; 342f2abcf4SHaojian Zhuang 352f2abcf4SHaojian Zhuang static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; 362f2abcf4SHaojian Zhuang static uintptr_t ufs_dev_handle, fip_dev_handle; 372f2abcf4SHaojian Zhuang 382f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec); 392f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec); 402f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); 412f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); 422f2abcf4SHaojian Zhuang 43c61cf58fSHaojian Zhuang static io_block_spec_t ufs_fip_spec; 44c61cf58fSHaojian Zhuang 45c61cf58fSHaojian Zhuang static const io_block_spec_t ufs_gpt_spec = { 46c61cf58fSHaojian Zhuang .offset = 0, 47c61cf58fSHaojian Zhuang .length = PLAT_PARTITION_BLOCK_SIZE * 48c61cf58fSHaojian Zhuang (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), 492f2abcf4SHaojian Zhuang }; 502f2abcf4SHaojian Zhuang 51*c371b83fSArthur Cassegrain /* Fastboot serial number stored within first UFS device blocks */ 52*c371b83fSArthur Cassegrain static const io_block_spec_t ufs_fastboot_spec = { 53*c371b83fSArthur Cassegrain .offset = UFS_BASE, 54*c371b83fSArthur Cassegrain .length = 1 << 20, 55*c371b83fSArthur Cassegrain }; 56*c371b83fSArthur Cassegrain 572f2abcf4SHaojian Zhuang static const io_block_dev_spec_t ufs_dev_spec = { 582f2abcf4SHaojian Zhuang /* It's used as temp buffer in block driver. */ 592f2abcf4SHaojian Zhuang .buffer = { 602f2abcf4SHaojian Zhuang .offset = HIKEY960_UFS_DATA_BASE, 612f2abcf4SHaojian Zhuang .length = HIKEY960_UFS_DATA_SIZE, 622f2abcf4SHaojian Zhuang }, 632f2abcf4SHaojian Zhuang .ops = { 642f2abcf4SHaojian Zhuang .read = ufs_read_lun3_blks, 652f2abcf4SHaojian Zhuang .write = ufs_write_lun3_blks, 662f2abcf4SHaojian Zhuang }, 672f2abcf4SHaojian Zhuang .block_size = UFS_BLOCK_SIZE, 682f2abcf4SHaojian Zhuang }; 692f2abcf4SHaojian Zhuang 702f2abcf4SHaojian Zhuang static const io_uuid_spec_t scp_bl2_uuid_spec = { 712f2abcf4SHaojian Zhuang .uuid = UUID_SCP_FIRMWARE_SCP_BL2, 722f2abcf4SHaojian Zhuang }; 732f2abcf4SHaojian Zhuang 742f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl31_uuid_spec = { 752f2abcf4SHaojian Zhuang .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 762f2abcf4SHaojian Zhuang }; 772f2abcf4SHaojian Zhuang 785e3325e7SVictor Chong static const io_uuid_spec_t bl32_uuid_spec = { 795e3325e7SVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32, 805e3325e7SVictor Chong }; 815e3325e7SVictor Chong 82b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra1_uuid_spec = { 83b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, 84b16bb16eSVictor Chong }; 85b16bb16eSVictor Chong 86b16bb16eSVictor Chong static const io_uuid_spec_t bl32_extra2_uuid_spec = { 87b16bb16eSVictor Chong .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, 88b16bb16eSVictor Chong }; 89b16bb16eSVictor Chong 906971642dSLukas Hanel #ifdef SPD_spmd 916971642dSLukas Hanel static const io_uuid_spec_t bl32_tos_fw_spec = { 926971642dSLukas Hanel .uuid = UUID_TOS_FW_CONFIG, 936971642dSLukas Hanel }; 946971642dSLukas Hanel #endif 956971642dSLukas Hanel 962f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = { 972f2abcf4SHaojian Zhuang .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 982f2abcf4SHaojian Zhuang }; 992f2abcf4SHaojian Zhuang 100745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT 101745d8a82STeddy Reed static const io_uuid_spec_t trusted_key_cert_uuid_spec = { 102745d8a82STeddy Reed .uuid = UUID_TRUSTED_KEY_CERT, 103745d8a82STeddy Reed }; 104745d8a82STeddy Reed 105745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { 106745d8a82STeddy Reed .uuid = UUID_SCP_FW_KEY_CERT, 107745d8a82STeddy Reed }; 108745d8a82STeddy Reed 109745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { 110745d8a82STeddy Reed .uuid = UUID_SOC_FW_KEY_CERT, 111745d8a82STeddy Reed }; 112745d8a82STeddy Reed 113745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { 114745d8a82STeddy Reed .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, 115745d8a82STeddy Reed }; 116745d8a82STeddy Reed 117745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { 118745d8a82STeddy Reed .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, 119745d8a82STeddy Reed }; 120745d8a82STeddy Reed 121745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_cert_uuid_spec = { 122745d8a82STeddy Reed .uuid = UUID_SCP_FW_CONTENT_CERT, 123745d8a82STeddy Reed }; 124745d8a82STeddy Reed 125745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_cert_uuid_spec = { 126745d8a82STeddy Reed .uuid = UUID_SOC_FW_CONTENT_CERT, 127745d8a82STeddy Reed }; 128745d8a82STeddy Reed 129745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_cert_uuid_spec = { 130745d8a82STeddy Reed .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, 131745d8a82STeddy Reed }; 132745d8a82STeddy Reed 133745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_cert_uuid_spec = { 134745d8a82STeddy Reed .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, 135745d8a82STeddy Reed }; 136745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */ 137745d8a82STeddy Reed 1382f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = { 1392f2abcf4SHaojian Zhuang [FIP_IMAGE_ID] = { 1402f2abcf4SHaojian Zhuang &ufs_dev_handle, 1412f2abcf4SHaojian Zhuang (uintptr_t)&ufs_fip_spec, 1422f2abcf4SHaojian Zhuang check_ufs 1432f2abcf4SHaojian Zhuang }, 1442f2abcf4SHaojian Zhuang [SCP_BL2_IMAGE_ID] = { 1452f2abcf4SHaojian Zhuang &fip_dev_handle, 1462f2abcf4SHaojian Zhuang (uintptr_t)&scp_bl2_uuid_spec, 1472f2abcf4SHaojian Zhuang check_fip 1482f2abcf4SHaojian Zhuang }, 1492f2abcf4SHaojian Zhuang [BL31_IMAGE_ID] = { 1502f2abcf4SHaojian Zhuang &fip_dev_handle, 1512f2abcf4SHaojian Zhuang (uintptr_t)&bl31_uuid_spec, 1522f2abcf4SHaojian Zhuang check_fip 1532f2abcf4SHaojian Zhuang }, 1545e3325e7SVictor Chong [BL32_IMAGE_ID] = { 1555e3325e7SVictor Chong &fip_dev_handle, 1565e3325e7SVictor Chong (uintptr_t)&bl32_uuid_spec, 1575e3325e7SVictor Chong check_fip 1585e3325e7SVictor Chong }, 159b16bb16eSVictor Chong [BL32_EXTRA1_IMAGE_ID] = { 160b16bb16eSVictor Chong &fip_dev_handle, 161b16bb16eSVictor Chong (uintptr_t)&bl32_extra1_uuid_spec, 162b16bb16eSVictor Chong check_fip 163b16bb16eSVictor Chong }, 164b16bb16eSVictor Chong [BL32_EXTRA2_IMAGE_ID] = { 165b16bb16eSVictor Chong &fip_dev_handle, 166b16bb16eSVictor Chong (uintptr_t)&bl32_extra2_uuid_spec, 167b16bb16eSVictor Chong check_fip 168b16bb16eSVictor Chong }, 1696971642dSLukas Hanel 1706971642dSLukas Hanel #ifdef SPD_spmd 1716971642dSLukas Hanel [TOS_FW_CONFIG_ID] = { 1726971642dSLukas Hanel &fip_dev_handle, 1736971642dSLukas Hanel (uintptr_t)&bl32_tos_fw_spec, 1746971642dSLukas Hanel check_fip 1756971642dSLukas Hanel }, 1766971642dSLukas Hanel #endif 1776971642dSLukas Hanel 1782f2abcf4SHaojian Zhuang [BL33_IMAGE_ID] = { 1792f2abcf4SHaojian Zhuang &fip_dev_handle, 1802f2abcf4SHaojian Zhuang (uintptr_t)&bl33_uuid_spec, 1812f2abcf4SHaojian Zhuang check_fip 182745d8a82STeddy Reed }, 183745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT 184745d8a82STeddy Reed [TRUSTED_KEY_CERT_ID] = { 185745d8a82STeddy Reed &fip_dev_handle, 186745d8a82STeddy Reed (uintptr_t)&trusted_key_cert_uuid_spec, 187745d8a82STeddy Reed check_fip 188745d8a82STeddy Reed }, 189745d8a82STeddy Reed [SCP_FW_KEY_CERT_ID] = { 190745d8a82STeddy Reed &fip_dev_handle, 191745d8a82STeddy Reed (uintptr_t)&scp_fw_key_cert_uuid_spec, 192745d8a82STeddy Reed check_fip 193745d8a82STeddy Reed }, 194745d8a82STeddy Reed [SOC_FW_KEY_CERT_ID] = { 195745d8a82STeddy Reed &fip_dev_handle, 196745d8a82STeddy Reed (uintptr_t)&soc_fw_key_cert_uuid_spec, 197745d8a82STeddy Reed check_fip 198745d8a82STeddy Reed }, 199745d8a82STeddy Reed [TRUSTED_OS_FW_KEY_CERT_ID] = { 200745d8a82STeddy Reed &fip_dev_handle, 201745d8a82STeddy Reed (uintptr_t)&tos_fw_key_cert_uuid_spec, 202745d8a82STeddy Reed check_fip 203745d8a82STeddy Reed }, 204745d8a82STeddy Reed [NON_TRUSTED_FW_KEY_CERT_ID] = { 205745d8a82STeddy Reed &fip_dev_handle, 206745d8a82STeddy Reed (uintptr_t)&nt_fw_key_cert_uuid_spec, 207745d8a82STeddy Reed check_fip 208745d8a82STeddy Reed }, 209745d8a82STeddy Reed [SCP_FW_CONTENT_CERT_ID] = { 210745d8a82STeddy Reed &fip_dev_handle, 211745d8a82STeddy Reed (uintptr_t)&scp_fw_cert_uuid_spec, 212745d8a82STeddy Reed check_fip 213745d8a82STeddy Reed }, 214745d8a82STeddy Reed [SOC_FW_CONTENT_CERT_ID] = { 215745d8a82STeddy Reed &fip_dev_handle, 216745d8a82STeddy Reed (uintptr_t)&soc_fw_cert_uuid_spec, 217745d8a82STeddy Reed check_fip 218745d8a82STeddy Reed }, 219745d8a82STeddy Reed [TRUSTED_OS_FW_CONTENT_CERT_ID] = { 220745d8a82STeddy Reed &fip_dev_handle, 221745d8a82STeddy Reed (uintptr_t)&tos_fw_cert_uuid_spec, 222745d8a82STeddy Reed check_fip 223745d8a82STeddy Reed }, 224745d8a82STeddy Reed [NON_TRUSTED_FW_CONTENT_CERT_ID] = { 225745d8a82STeddy Reed &fip_dev_handle, 226745d8a82STeddy Reed (uintptr_t)&nt_fw_cert_uuid_spec, 227745d8a82STeddy Reed check_fip 228745d8a82STeddy Reed }, 229745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */ 230c61cf58fSHaojian Zhuang [GPT_IMAGE_ID] = { 231c61cf58fSHaojian Zhuang &ufs_dev_handle, 232c61cf58fSHaojian Zhuang (uintptr_t)&ufs_gpt_spec, 233c61cf58fSHaojian Zhuang check_ufs 234c61cf58fSHaojian Zhuang }, 2352f2abcf4SHaojian Zhuang }; 2362f2abcf4SHaojian Zhuang 2372f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec) 2382f2abcf4SHaojian Zhuang { 2392f2abcf4SHaojian Zhuang int result; 2402f2abcf4SHaojian Zhuang uintptr_t local_handle; 2412f2abcf4SHaojian Zhuang 2422f2abcf4SHaojian Zhuang result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); 2432f2abcf4SHaojian Zhuang if (result == 0) { 2442f2abcf4SHaojian Zhuang result = io_open(ufs_dev_handle, spec, &local_handle); 2452f2abcf4SHaojian Zhuang if (result == 0) 2462f2abcf4SHaojian Zhuang io_close(local_handle); 2472f2abcf4SHaojian Zhuang } 2482f2abcf4SHaojian Zhuang return result; 2492f2abcf4SHaojian Zhuang } 2502f2abcf4SHaojian Zhuang 2512f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec) 2522f2abcf4SHaojian Zhuang { 2532f2abcf4SHaojian Zhuang int result; 2542f2abcf4SHaojian Zhuang uintptr_t local_image_handle; 2552f2abcf4SHaojian Zhuang 2562f2abcf4SHaojian Zhuang /* See if a Firmware Image Package is available */ 2572f2abcf4SHaojian Zhuang result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 2582f2abcf4SHaojian Zhuang if (result == 0) { 2592f2abcf4SHaojian Zhuang result = io_open(fip_dev_handle, spec, &local_image_handle); 2602f2abcf4SHaojian Zhuang if (result == 0) { 2612f2abcf4SHaojian Zhuang VERBOSE("Using FIP\n"); 2622f2abcf4SHaojian Zhuang io_close(local_image_handle); 2632f2abcf4SHaojian Zhuang } 2642f2abcf4SHaojian Zhuang } 2652f2abcf4SHaojian Zhuang return result; 2662f2abcf4SHaojian Zhuang } 2672f2abcf4SHaojian Zhuang 268*c371b83fSArthur Cassegrain int hikey960_load_serialno(uint64_t *serno) 269*c371b83fSArthur Cassegrain { 270*c371b83fSArthur Cassegrain int result; 271*c371b83fSArthur Cassegrain size_t len = 0; 272*c371b83fSArthur Cassegrain uintptr_t local_handle; 273*c371b83fSArthur Cassegrain uint64_t buf[HIKEY960_SERIAL_NUMBER_SIZE / sizeof(uint64_t)]; 274*c371b83fSArthur Cassegrain 275*c371b83fSArthur Cassegrain if (serno == NULL) { 276*c371b83fSArthur Cassegrain return -1; 277*c371b83fSArthur Cassegrain } 278*c371b83fSArthur Cassegrain 279*c371b83fSArthur Cassegrain result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); 280*c371b83fSArthur Cassegrain if (result != 0) { 281*c371b83fSArthur Cassegrain return result; 282*c371b83fSArthur Cassegrain } 283*c371b83fSArthur Cassegrain 284*c371b83fSArthur Cassegrain result = io_open(ufs_dev_handle, 285*c371b83fSArthur Cassegrain (uintptr_t)&ufs_fastboot_spec, &local_handle); 286*c371b83fSArthur Cassegrain if (result != 0) { 287*c371b83fSArthur Cassegrain return result; 288*c371b83fSArthur Cassegrain } 289*c371b83fSArthur Cassegrain 290*c371b83fSArthur Cassegrain result = io_seek(local_handle, IO_SEEK_SET, 291*c371b83fSArthur Cassegrain HIKEY960_SERIAL_NUMBER_LBA * UFS_BLOCK_SIZE); 292*c371b83fSArthur Cassegrain if (result != 0) { 293*c371b83fSArthur Cassegrain goto closing; 294*c371b83fSArthur Cassegrain } 295*c371b83fSArthur Cassegrain 296*c371b83fSArthur Cassegrain result = io_read(local_handle, (uintptr_t)buf, 297*c371b83fSArthur Cassegrain HIKEY960_SERIAL_NUMBER_SIZE, &len); 298*c371b83fSArthur Cassegrain if (result != 0) { 299*c371b83fSArthur Cassegrain goto closing; 300*c371b83fSArthur Cassegrain } 301*c371b83fSArthur Cassegrain 302*c371b83fSArthur Cassegrain if (len != HIKEY960_SERIAL_NUMBER_SIZE) { 303*c371b83fSArthur Cassegrain result = -1; 304*c371b83fSArthur Cassegrain goto closing; 305*c371b83fSArthur Cassegrain } 306*c371b83fSArthur Cassegrain 307*c371b83fSArthur Cassegrain /* UEFI fastboot app stores a 16 bytes blob */ 308*c371b83fSArthur Cassegrain /* We extract only relevant 8 bytes serial number */ 309*c371b83fSArthur Cassegrain *serno = buf[1]; 310*c371b83fSArthur Cassegrain 311*c371b83fSArthur Cassegrain closing: 312*c371b83fSArthur Cassegrain io_close(local_handle); 313*c371b83fSArthur Cassegrain return result; 314*c371b83fSArthur Cassegrain } 315*c371b83fSArthur Cassegrain 3162f2abcf4SHaojian Zhuang void hikey960_io_setup(void) 3172f2abcf4SHaojian Zhuang { 3182f2abcf4SHaojian Zhuang int result; 3192f2abcf4SHaojian Zhuang 3202f2abcf4SHaojian Zhuang result = register_io_dev_block(&ufs_dev_con); 3212f2abcf4SHaojian Zhuang assert(result == 0); 3222f2abcf4SHaojian Zhuang 3232f2abcf4SHaojian Zhuang result = register_io_dev_fip(&fip_dev_con); 3242f2abcf4SHaojian Zhuang assert(result == 0); 3252f2abcf4SHaojian Zhuang 3262f2abcf4SHaojian Zhuang result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, 3272f2abcf4SHaojian Zhuang &ufs_dev_handle); 3282f2abcf4SHaojian Zhuang assert(result == 0); 3292f2abcf4SHaojian Zhuang 3302f2abcf4SHaojian Zhuang result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 3312f2abcf4SHaojian Zhuang assert(result == 0); 3322f2abcf4SHaojian Zhuang 3332f2abcf4SHaojian Zhuang /* Ignore improbable errors in release builds */ 3342f2abcf4SHaojian Zhuang (void)result; 3352f2abcf4SHaojian Zhuang } 3362f2abcf4SHaojian Zhuang 337c61cf58fSHaojian Zhuang int hikey960_set_fip_addr(unsigned int image_id, const char *name) 338c61cf58fSHaojian Zhuang { 339c61cf58fSHaojian Zhuang const partition_entry_t *entry; 340c61cf58fSHaojian Zhuang 341c61cf58fSHaojian Zhuang if (ufs_fip_spec.length == 0) { 342c61cf58fSHaojian Zhuang partition_init(GPT_IMAGE_ID); 343c61cf58fSHaojian Zhuang entry = get_partition_entry(name); 344c61cf58fSHaojian Zhuang if (entry == NULL) { 345c61cf58fSHaojian Zhuang ERROR("Could NOT find the %s partition!\n", name); 346c61cf58fSHaojian Zhuang return -ENOENT; 347c61cf58fSHaojian Zhuang } 348c61cf58fSHaojian Zhuang ufs_fip_spec.offset = entry->start; 349c61cf58fSHaojian Zhuang ufs_fip_spec.length = entry->length; 350c61cf58fSHaojian Zhuang } 351c61cf58fSHaojian Zhuang return 0; 352c61cf58fSHaojian Zhuang } 353c61cf58fSHaojian Zhuang 3542f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access 3552f2abcf4SHaojian Zhuang * an image. Use this to enforce platform load policy 3562f2abcf4SHaojian Zhuang */ 3572f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 3582f2abcf4SHaojian Zhuang uintptr_t *image_spec) 3592f2abcf4SHaojian Zhuang { 3602f2abcf4SHaojian Zhuang int result; 3612f2abcf4SHaojian Zhuang const struct plat_io_policy *policy; 3622f2abcf4SHaojian Zhuang 3632f2abcf4SHaojian Zhuang assert(image_id < ARRAY_SIZE(policies)); 3642f2abcf4SHaojian Zhuang 3652f2abcf4SHaojian Zhuang policy = &policies[image_id]; 3662f2abcf4SHaojian Zhuang result = policy->check(policy->image_spec); 3672f2abcf4SHaojian Zhuang assert(result == 0); 3682f2abcf4SHaojian Zhuang 3692f2abcf4SHaojian Zhuang *image_spec = policy->image_spec; 3702f2abcf4SHaojian Zhuang *dev_handle = *(policy->dev_handle); 3712f2abcf4SHaojian Zhuang 3722f2abcf4SHaojian Zhuang return result; 3732f2abcf4SHaojian Zhuang } 3742f2abcf4SHaojian Zhuang 3752f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) 3762f2abcf4SHaojian Zhuang { 3772f2abcf4SHaojian Zhuang return ufs_read_blocks(3, lba, buf, size); 3782f2abcf4SHaojian Zhuang } 3792f2abcf4SHaojian Zhuang 3802f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) 3812f2abcf4SHaojian Zhuang { 3822f2abcf4SHaojian Zhuang return ufs_write_blocks(3, lba, buf, size); 3832f2abcf4SHaojian Zhuang } 384