xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_io_storage.c (revision 6971642d23d0c5e33e507eb78b7c569045e2f85d)
12f2abcf4SHaojian Zhuang /*
2*6971642dSLukas 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 
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 
40c61cf58fSHaojian Zhuang static io_block_spec_t ufs_fip_spec;
41c61cf58fSHaojian Zhuang 
42c61cf58fSHaojian Zhuang static const io_block_spec_t ufs_gpt_spec = {
43c61cf58fSHaojian Zhuang 	.offset		= 0,
44c61cf58fSHaojian Zhuang 	.length		= PLAT_PARTITION_BLOCK_SIZE *
45c61cf58fSHaojian 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 
81*6971642dSLukas Hanel #ifdef SPD_spmd
82*6971642dSLukas Hanel static const io_uuid_spec_t bl32_tos_fw_spec = {
83*6971642dSLukas Hanel 	.uuid = UUID_TOS_FW_CONFIG,
84*6971642dSLukas Hanel };
85*6971642dSLukas Hanel #endif
86*6971642dSLukas Hanel 
872f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = {
882f2abcf4SHaojian Zhuang 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
892f2abcf4SHaojian Zhuang };
902f2abcf4SHaojian Zhuang 
91745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT
92745d8a82STeddy Reed static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
93745d8a82STeddy Reed 	.uuid = UUID_TRUSTED_KEY_CERT,
94745d8a82STeddy Reed };
95745d8a82STeddy Reed 
96745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = {
97745d8a82STeddy Reed 	.uuid = UUID_SCP_FW_KEY_CERT,
98745d8a82STeddy Reed };
99745d8a82STeddy Reed 
100745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
101745d8a82STeddy Reed 	.uuid = UUID_SOC_FW_KEY_CERT,
102745d8a82STeddy Reed };
103745d8a82STeddy Reed 
104745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
105745d8a82STeddy Reed 	.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
106745d8a82STeddy Reed };
107745d8a82STeddy Reed 
108745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
109745d8a82STeddy Reed 	.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
110745d8a82STeddy Reed };
111745d8a82STeddy Reed 
112745d8a82STeddy Reed static const io_uuid_spec_t scp_fw_cert_uuid_spec = {
113745d8a82STeddy Reed 	.uuid = UUID_SCP_FW_CONTENT_CERT,
114745d8a82STeddy Reed };
115745d8a82STeddy Reed 
116745d8a82STeddy Reed static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
117745d8a82STeddy Reed 	.uuid = UUID_SOC_FW_CONTENT_CERT,
118745d8a82STeddy Reed };
119745d8a82STeddy Reed 
120745d8a82STeddy Reed static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
121745d8a82STeddy Reed 	.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
122745d8a82STeddy Reed };
123745d8a82STeddy Reed 
124745d8a82STeddy Reed static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
125745d8a82STeddy Reed 	.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
126745d8a82STeddy Reed };
127745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */
128745d8a82STeddy Reed 
1292f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = {
1302f2abcf4SHaojian Zhuang 	[FIP_IMAGE_ID] = {
1312f2abcf4SHaojian Zhuang 		&ufs_dev_handle,
1322f2abcf4SHaojian Zhuang 		(uintptr_t)&ufs_fip_spec,
1332f2abcf4SHaojian Zhuang 		check_ufs
1342f2abcf4SHaojian Zhuang 	},
1352f2abcf4SHaojian Zhuang 	[SCP_BL2_IMAGE_ID] = {
1362f2abcf4SHaojian Zhuang 		&fip_dev_handle,
1372f2abcf4SHaojian Zhuang 		(uintptr_t)&scp_bl2_uuid_spec,
1382f2abcf4SHaojian Zhuang 		check_fip
1392f2abcf4SHaojian Zhuang 	},
1402f2abcf4SHaojian Zhuang 	[BL31_IMAGE_ID] = {
1412f2abcf4SHaojian Zhuang 		&fip_dev_handle,
1422f2abcf4SHaojian Zhuang 		(uintptr_t)&bl31_uuid_spec,
1432f2abcf4SHaojian Zhuang 		check_fip
1442f2abcf4SHaojian Zhuang 	},
1455e3325e7SVictor Chong 	[BL32_IMAGE_ID] = {
1465e3325e7SVictor Chong 		&fip_dev_handle,
1475e3325e7SVictor Chong 		(uintptr_t)&bl32_uuid_spec,
1485e3325e7SVictor Chong 		check_fip
1495e3325e7SVictor Chong 	},
150b16bb16eSVictor Chong 	[BL32_EXTRA1_IMAGE_ID] = {
151b16bb16eSVictor Chong 		&fip_dev_handle,
152b16bb16eSVictor Chong 		(uintptr_t)&bl32_extra1_uuid_spec,
153b16bb16eSVictor Chong 		check_fip
154b16bb16eSVictor Chong 	},
155b16bb16eSVictor Chong 	[BL32_EXTRA2_IMAGE_ID] = {
156b16bb16eSVictor Chong 		&fip_dev_handle,
157b16bb16eSVictor Chong 		(uintptr_t)&bl32_extra2_uuid_spec,
158b16bb16eSVictor Chong 		check_fip
159b16bb16eSVictor Chong 	},
160*6971642dSLukas Hanel 
161*6971642dSLukas Hanel #ifdef SPD_spmd
162*6971642dSLukas Hanel 	[TOS_FW_CONFIG_ID] = {
163*6971642dSLukas Hanel 		&fip_dev_handle,
164*6971642dSLukas Hanel 		(uintptr_t)&bl32_tos_fw_spec,
165*6971642dSLukas Hanel 		check_fip
166*6971642dSLukas Hanel 	},
167*6971642dSLukas Hanel #endif
168*6971642dSLukas Hanel 
1692f2abcf4SHaojian Zhuang 	[BL33_IMAGE_ID] = {
1702f2abcf4SHaojian Zhuang 		&fip_dev_handle,
1712f2abcf4SHaojian Zhuang 		(uintptr_t)&bl33_uuid_spec,
1722f2abcf4SHaojian Zhuang 		check_fip
173745d8a82STeddy Reed 	},
174745d8a82STeddy Reed #if TRUSTED_BOARD_BOOT
175745d8a82STeddy Reed 	[TRUSTED_KEY_CERT_ID] = {
176745d8a82STeddy Reed 		&fip_dev_handle,
177745d8a82STeddy Reed 		(uintptr_t)&trusted_key_cert_uuid_spec,
178745d8a82STeddy Reed 		check_fip
179745d8a82STeddy Reed 	},
180745d8a82STeddy Reed 	[SCP_FW_KEY_CERT_ID] = {
181745d8a82STeddy Reed 		&fip_dev_handle,
182745d8a82STeddy Reed 		(uintptr_t)&scp_fw_key_cert_uuid_spec,
183745d8a82STeddy Reed 		check_fip
184745d8a82STeddy Reed 	},
185745d8a82STeddy Reed 	[SOC_FW_KEY_CERT_ID] = {
186745d8a82STeddy Reed 		&fip_dev_handle,
187745d8a82STeddy Reed 		(uintptr_t)&soc_fw_key_cert_uuid_spec,
188745d8a82STeddy Reed 		check_fip
189745d8a82STeddy Reed 	},
190745d8a82STeddy Reed 	[TRUSTED_OS_FW_KEY_CERT_ID] = {
191745d8a82STeddy Reed 		&fip_dev_handle,
192745d8a82STeddy Reed 		(uintptr_t)&tos_fw_key_cert_uuid_spec,
193745d8a82STeddy Reed 		check_fip
194745d8a82STeddy Reed 	},
195745d8a82STeddy Reed 	[NON_TRUSTED_FW_KEY_CERT_ID] = {
196745d8a82STeddy Reed 		&fip_dev_handle,
197745d8a82STeddy Reed 		(uintptr_t)&nt_fw_key_cert_uuid_spec,
198745d8a82STeddy Reed 		check_fip
199745d8a82STeddy Reed 	},
200745d8a82STeddy Reed 	[SCP_FW_CONTENT_CERT_ID] = {
201745d8a82STeddy Reed 		&fip_dev_handle,
202745d8a82STeddy Reed 		(uintptr_t)&scp_fw_cert_uuid_spec,
203745d8a82STeddy Reed 		check_fip
204745d8a82STeddy Reed 	},
205745d8a82STeddy Reed 	[SOC_FW_CONTENT_CERT_ID] = {
206745d8a82STeddy Reed 		&fip_dev_handle,
207745d8a82STeddy Reed 		(uintptr_t)&soc_fw_cert_uuid_spec,
208745d8a82STeddy Reed 		check_fip
209745d8a82STeddy Reed 	},
210745d8a82STeddy Reed 	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
211745d8a82STeddy Reed 		&fip_dev_handle,
212745d8a82STeddy Reed 		(uintptr_t)&tos_fw_cert_uuid_spec,
213745d8a82STeddy Reed 		check_fip
214745d8a82STeddy Reed 	},
215745d8a82STeddy Reed 	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
216745d8a82STeddy Reed 		&fip_dev_handle,
217745d8a82STeddy Reed 		(uintptr_t)&nt_fw_cert_uuid_spec,
218745d8a82STeddy Reed 		check_fip
219745d8a82STeddy Reed 	},
220745d8a82STeddy Reed #endif /* TRUSTED_BOARD_BOOT */
221c61cf58fSHaojian Zhuang 	[GPT_IMAGE_ID] = {
222c61cf58fSHaojian Zhuang 		&ufs_dev_handle,
223c61cf58fSHaojian Zhuang 		(uintptr_t)&ufs_gpt_spec,
224c61cf58fSHaojian Zhuang 		check_ufs
225c61cf58fSHaojian Zhuang 	},
2262f2abcf4SHaojian Zhuang };
2272f2abcf4SHaojian Zhuang 
2282f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec)
2292f2abcf4SHaojian Zhuang {
2302f2abcf4SHaojian Zhuang 	int result;
2312f2abcf4SHaojian Zhuang 	uintptr_t local_handle;
2322f2abcf4SHaojian Zhuang 
2332f2abcf4SHaojian Zhuang 	result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL);
2342f2abcf4SHaojian Zhuang 	if (result == 0) {
2352f2abcf4SHaojian Zhuang 		result = io_open(ufs_dev_handle, spec, &local_handle);
2362f2abcf4SHaojian Zhuang 		if (result == 0)
2372f2abcf4SHaojian Zhuang 			io_close(local_handle);
2382f2abcf4SHaojian Zhuang 	}
2392f2abcf4SHaojian Zhuang 	return result;
2402f2abcf4SHaojian Zhuang }
2412f2abcf4SHaojian Zhuang 
2422f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec)
2432f2abcf4SHaojian Zhuang {
2442f2abcf4SHaojian Zhuang 	int result;
2452f2abcf4SHaojian Zhuang 	uintptr_t local_image_handle;
2462f2abcf4SHaojian Zhuang 
2472f2abcf4SHaojian Zhuang 	/* See if a Firmware Image Package is available */
2482f2abcf4SHaojian Zhuang 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
2492f2abcf4SHaojian Zhuang 	if (result == 0) {
2502f2abcf4SHaojian Zhuang 		result = io_open(fip_dev_handle, spec, &local_image_handle);
2512f2abcf4SHaojian Zhuang 		if (result == 0) {
2522f2abcf4SHaojian Zhuang 			VERBOSE("Using FIP\n");
2532f2abcf4SHaojian Zhuang 			io_close(local_image_handle);
2542f2abcf4SHaojian Zhuang 		}
2552f2abcf4SHaojian Zhuang 	}
2562f2abcf4SHaojian Zhuang 	return result;
2572f2abcf4SHaojian Zhuang }
2582f2abcf4SHaojian Zhuang 
2592f2abcf4SHaojian Zhuang void hikey960_io_setup(void)
2602f2abcf4SHaojian Zhuang {
2612f2abcf4SHaojian Zhuang 	int result;
2622f2abcf4SHaojian Zhuang 
2632f2abcf4SHaojian Zhuang 	result = register_io_dev_block(&ufs_dev_con);
2642f2abcf4SHaojian Zhuang 	assert(result == 0);
2652f2abcf4SHaojian Zhuang 
2662f2abcf4SHaojian Zhuang 	result = register_io_dev_fip(&fip_dev_con);
2672f2abcf4SHaojian Zhuang 	assert(result == 0);
2682f2abcf4SHaojian Zhuang 
2692f2abcf4SHaojian Zhuang 	result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec,
2702f2abcf4SHaojian Zhuang 			     &ufs_dev_handle);
2712f2abcf4SHaojian Zhuang 	assert(result == 0);
2722f2abcf4SHaojian Zhuang 
2732f2abcf4SHaojian Zhuang 	result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
2742f2abcf4SHaojian Zhuang 	assert(result == 0);
2752f2abcf4SHaojian Zhuang 
2762f2abcf4SHaojian Zhuang 	/* Ignore improbable errors in release builds */
2772f2abcf4SHaojian Zhuang 	(void)result;
2782f2abcf4SHaojian Zhuang }
2792f2abcf4SHaojian Zhuang 
280c61cf58fSHaojian Zhuang int hikey960_set_fip_addr(unsigned int image_id, const char *name)
281c61cf58fSHaojian Zhuang {
282c61cf58fSHaojian Zhuang 	const partition_entry_t *entry;
283c61cf58fSHaojian Zhuang 
284c61cf58fSHaojian Zhuang 	if (ufs_fip_spec.length == 0) {
285c61cf58fSHaojian Zhuang 		partition_init(GPT_IMAGE_ID);
286c61cf58fSHaojian Zhuang 		entry = get_partition_entry(name);
287c61cf58fSHaojian Zhuang 		if (entry == NULL) {
288c61cf58fSHaojian Zhuang 			ERROR("Could NOT find the %s partition!\n", name);
289c61cf58fSHaojian Zhuang 			return -ENOENT;
290c61cf58fSHaojian Zhuang 		}
291c61cf58fSHaojian Zhuang 		ufs_fip_spec.offset = entry->start;
292c61cf58fSHaojian Zhuang 		ufs_fip_spec.length = entry->length;
293c61cf58fSHaojian Zhuang 	}
294c61cf58fSHaojian Zhuang 	return 0;
295c61cf58fSHaojian Zhuang }
296c61cf58fSHaojian Zhuang 
2972f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access
2982f2abcf4SHaojian Zhuang  * an image. Use this to enforce platform load policy
2992f2abcf4SHaojian Zhuang  */
3002f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
3012f2abcf4SHaojian Zhuang 			  uintptr_t *image_spec)
3022f2abcf4SHaojian Zhuang {
3032f2abcf4SHaojian Zhuang 	int result;
3042f2abcf4SHaojian Zhuang 	const struct plat_io_policy *policy;
3052f2abcf4SHaojian Zhuang 
3062f2abcf4SHaojian Zhuang 	assert(image_id < ARRAY_SIZE(policies));
3072f2abcf4SHaojian Zhuang 
3082f2abcf4SHaojian Zhuang 	policy = &policies[image_id];
3092f2abcf4SHaojian Zhuang 	result = policy->check(policy->image_spec);
3102f2abcf4SHaojian Zhuang 	assert(result == 0);
3112f2abcf4SHaojian Zhuang 
3122f2abcf4SHaojian Zhuang 	*image_spec = policy->image_spec;
3132f2abcf4SHaojian Zhuang 	*dev_handle = *(policy->dev_handle);
3142f2abcf4SHaojian Zhuang 
3152f2abcf4SHaojian Zhuang 	return result;
3162f2abcf4SHaojian Zhuang }
3172f2abcf4SHaojian Zhuang 
3182f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size)
3192f2abcf4SHaojian Zhuang {
3202f2abcf4SHaojian Zhuang 	return ufs_read_blocks(3, lba, buf, size);
3212f2abcf4SHaojian Zhuang }
3222f2abcf4SHaojian Zhuang 
3232f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size)
3242f2abcf4SHaojian Zhuang {
3252f2abcf4SHaojian Zhuang 	return ufs_write_blocks(3, lba, buf, size);
3262f2abcf4SHaojian Zhuang }
327