xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_io_storage.c (revision 745d8a82b9b42b93a1acf4249cb245190ae7d117)
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