xref: /arm-trusted-firmware/plat/arm/common/arm_io_storage.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2015-2021, ARM Limited. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <common/debug.h>
8*91f16700Schasinglulu #include <drivers/fwu/fwu_metadata.h>
9*91f16700Schasinglulu #include <drivers/io/io_driver.h>
10*91f16700Schasinglulu #include <drivers/io/io_fip.h>
11*91f16700Schasinglulu #include <drivers/io/io_memmap.h>
12*91f16700Schasinglulu #include <drivers/io/io_storage.h>
13*91f16700Schasinglulu #include <drivers/partition/partition.h>
14*91f16700Schasinglulu #include <lib/utils.h>
15*91f16700Schasinglulu 
16*91f16700Schasinglulu #include <plat/arm/common/arm_fconf_getter.h>
17*91f16700Schasinglulu #include <plat/arm/common/arm_fconf_io_storage.h>
18*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h>
19*91f16700Schasinglulu #include <plat/common/platform.h>
20*91f16700Schasinglulu #include <platform_def.h>
21*91f16700Schasinglulu 
22*91f16700Schasinglulu /* IO devices */
23*91f16700Schasinglulu static const io_dev_connector_t *fip_dev_con;
24*91f16700Schasinglulu uintptr_t fip_dev_handle;
25*91f16700Schasinglulu static const io_dev_connector_t *memmap_dev_con;
26*91f16700Schasinglulu uintptr_t memmap_dev_handle;
27*91f16700Schasinglulu 
28*91f16700Schasinglulu #if ARM_GPT_SUPPORT
29*91f16700Schasinglulu /* fip partition names */
30*91f16700Schasinglulu static const char * const fip_part_names[] = {"FIP_A", "FIP_B"};
31*91f16700Schasinglulu CASSERT(sizeof(fip_part_names)/sizeof(char *) == NR_OF_FW_BANKS,
32*91f16700Schasinglulu 	assert_fip_partition_names_missing);
33*91f16700Schasinglulu #endif /* ARM_GPT_SUPPORT */
34*91f16700Schasinglulu 
35*91f16700Schasinglulu /* Weak definitions may be overridden in specific ARM standard platform */
36*91f16700Schasinglulu #pragma weak plat_arm_io_setup
37*91f16700Schasinglulu #pragma weak plat_arm_get_alt_image_source
38*91f16700Schasinglulu 
39*91f16700Schasinglulu int open_fip(const uintptr_t spec)
40*91f16700Schasinglulu {
41*91f16700Schasinglulu 	int result;
42*91f16700Schasinglulu 	uintptr_t local_image_handle;
43*91f16700Schasinglulu 
44*91f16700Schasinglulu 	/* See if a Firmware Image Package is available */
45*91f16700Schasinglulu 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
46*91f16700Schasinglulu 	if (result == 0) {
47*91f16700Schasinglulu 		result = io_open(fip_dev_handle, spec, &local_image_handle);
48*91f16700Schasinglulu 		if (result == 0) {
49*91f16700Schasinglulu 			VERBOSE("Using FIP\n");
50*91f16700Schasinglulu 			io_close(local_image_handle);
51*91f16700Schasinglulu 		}
52*91f16700Schasinglulu 	}
53*91f16700Schasinglulu 	return result;
54*91f16700Schasinglulu }
55*91f16700Schasinglulu 
56*91f16700Schasinglulu int open_memmap(const uintptr_t spec)
57*91f16700Schasinglulu {
58*91f16700Schasinglulu 	int result;
59*91f16700Schasinglulu 	uintptr_t local_image_handle;
60*91f16700Schasinglulu 
61*91f16700Schasinglulu 	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
62*91f16700Schasinglulu 	if (result == 0) {
63*91f16700Schasinglulu 		result = io_open(memmap_dev_handle, spec, &local_image_handle);
64*91f16700Schasinglulu 		if (result == 0) {
65*91f16700Schasinglulu 			VERBOSE("Using Memmap\n");
66*91f16700Schasinglulu 			io_close(local_image_handle);
67*91f16700Schasinglulu 		}
68*91f16700Schasinglulu 	}
69*91f16700Schasinglulu 	return result;
70*91f16700Schasinglulu }
71*91f16700Schasinglulu 
72*91f16700Schasinglulu int arm_io_setup(void)
73*91f16700Schasinglulu {
74*91f16700Schasinglulu 	int io_result;
75*91f16700Schasinglulu 
76*91f16700Schasinglulu 	io_result = register_io_dev_fip(&fip_dev_con);
77*91f16700Schasinglulu 	if (io_result < 0) {
78*91f16700Schasinglulu 		return io_result;
79*91f16700Schasinglulu 	}
80*91f16700Schasinglulu 
81*91f16700Schasinglulu 	io_result = register_io_dev_memmap(&memmap_dev_con);
82*91f16700Schasinglulu 	if (io_result < 0) {
83*91f16700Schasinglulu 		return io_result;
84*91f16700Schasinglulu 	}
85*91f16700Schasinglulu 
86*91f16700Schasinglulu 	/* Open connections to devices and cache the handles */
87*91f16700Schasinglulu 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
88*91f16700Schasinglulu 				&fip_dev_handle);
89*91f16700Schasinglulu 	if (io_result < 0) {
90*91f16700Schasinglulu 		return io_result;
91*91f16700Schasinglulu 	}
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
94*91f16700Schasinglulu 				&memmap_dev_handle);
95*91f16700Schasinglulu 
96*91f16700Schasinglulu 	return io_result;
97*91f16700Schasinglulu }
98*91f16700Schasinglulu 
99*91f16700Schasinglulu void plat_arm_io_setup(void)
100*91f16700Schasinglulu {
101*91f16700Schasinglulu 	int err;
102*91f16700Schasinglulu 
103*91f16700Schasinglulu 	err = arm_io_setup();
104*91f16700Schasinglulu 	if (err < 0) {
105*91f16700Schasinglulu 		panic();
106*91f16700Schasinglulu 	}
107*91f16700Schasinglulu }
108*91f16700Schasinglulu 
109*91f16700Schasinglulu int plat_arm_get_alt_image_source(
110*91f16700Schasinglulu 	unsigned int image_id __unused,
111*91f16700Schasinglulu 	uintptr_t *dev_handle __unused,
112*91f16700Schasinglulu 	uintptr_t *image_spec __unused)
113*91f16700Schasinglulu {
114*91f16700Schasinglulu 	/* By default do not try an alternative */
115*91f16700Schasinglulu 	return -ENOENT;
116*91f16700Schasinglulu }
117*91f16700Schasinglulu 
118*91f16700Schasinglulu /* Return an IO device handle and specification which can be used to access
119*91f16700Schasinglulu  * an image. Use this to enforce platform load policy */
120*91f16700Schasinglulu int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
121*91f16700Schasinglulu 			  uintptr_t *image_spec)
122*91f16700Schasinglulu {
123*91f16700Schasinglulu 	int result;
124*91f16700Schasinglulu 	const struct plat_io_policy *policy;
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 	policy = FCONF_GET_PROPERTY(arm, io_policies, image_id);
127*91f16700Schasinglulu 	result = policy->check(policy->image_spec);
128*91f16700Schasinglulu 	if (result == 0) {
129*91f16700Schasinglulu 		*image_spec = policy->image_spec;
130*91f16700Schasinglulu 		*dev_handle = *(policy->dev_handle);
131*91f16700Schasinglulu 	} else {
132*91f16700Schasinglulu 		VERBOSE("Trying alternative IO\n");
133*91f16700Schasinglulu 		result = plat_arm_get_alt_image_source(image_id, dev_handle,
134*91f16700Schasinglulu 						       image_spec);
135*91f16700Schasinglulu 	}
136*91f16700Schasinglulu 
137*91f16700Schasinglulu 	return result;
138*91f16700Schasinglulu }
139*91f16700Schasinglulu 
140*91f16700Schasinglulu /*
141*91f16700Schasinglulu  * See if a Firmware Image Package is available,
142*91f16700Schasinglulu  * by checking if TOC is valid or not.
143*91f16700Schasinglulu  */
144*91f16700Schasinglulu bool arm_io_is_toc_valid(void)
145*91f16700Schasinglulu {
146*91f16700Schasinglulu 	return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0);
147*91f16700Schasinglulu }
148*91f16700Schasinglulu 
149*91f16700Schasinglulu #if ARM_GPT_SUPPORT
150*91f16700Schasinglulu /******************************************************************************
151*91f16700Schasinglulu  * Retrieve partition entry details such as offset and length, and set these
152*91f16700Schasinglulu  * details in the I/O policy of the requested image.
153*91f16700Schasinglulu  *
154*91f16700Schasinglulu  * @image_id: image id whose I/O policy to be updated
155*91f16700Schasinglulu  *
156*91f16700Schasinglulu  * @part_name: partition name whose details to be retrieved
157*91f16700Schasinglulu  *
158*91f16700Schasinglulu  * Returns 0 on success, error otherwise
159*91f16700Schasinglulu  * Alongside, returns device handle and image specification of requested
160*91f16700Schasinglulu  * image.
161*91f16700Schasinglulu  ******************************************************************************/
162*91f16700Schasinglulu int arm_set_image_source(unsigned int image_id, const char *part_name,
163*91f16700Schasinglulu 			 uintptr_t *dev_handle, uintptr_t *image_spec)
164*91f16700Schasinglulu {
165*91f16700Schasinglulu 	const partition_entry_t *entry = get_partition_entry(part_name);
166*91f16700Schasinglulu 
167*91f16700Schasinglulu 	if (entry == NULL) {
168*91f16700Schasinglulu 		ERROR("Unable to find the %s partition\n", part_name);
169*91f16700Schasinglulu 		return -ENOENT;
170*91f16700Schasinglulu 	}
171*91f16700Schasinglulu 
172*91f16700Schasinglulu 	struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm,
173*91f16700Schasinglulu 							   io_policies,
174*91f16700Schasinglulu 							   image_id);
175*91f16700Schasinglulu 
176*91f16700Schasinglulu 	assert(policy != NULL);
177*91f16700Schasinglulu 	assert(policy->image_spec != 0UL);
178*91f16700Schasinglulu 
179*91f16700Schasinglulu 	io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
180*91f16700Schasinglulu 	/* set offset and length of the image */
181*91f16700Schasinglulu 	spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start;
182*91f16700Schasinglulu 	spec->length = entry->length;
183*91f16700Schasinglulu 
184*91f16700Schasinglulu 	*dev_handle = *(policy->dev_handle);
185*91f16700Schasinglulu 	*image_spec = policy->image_spec;
186*91f16700Schasinglulu 
187*91f16700Schasinglulu 	return 0;
188*91f16700Schasinglulu }
189*91f16700Schasinglulu 
190*91f16700Schasinglulu /*******************************************************************************
191*91f16700Schasinglulu  * Set the source offset and length of the FIP image in its I/O policy.
192*91f16700Schasinglulu  *
193*91f16700Schasinglulu  * @active_fw_bank_idx: active firmware bank index gathered from FWU metadata.
194*91f16700Schasinglulu  ******************************************************************************/
195*91f16700Schasinglulu void arm_set_fip_addr(uint32_t active_fw_bank_idx)
196*91f16700Schasinglulu {
197*91f16700Schasinglulu 	uintptr_t dev_handle __unused;
198*91f16700Schasinglulu 	uintptr_t image_spec __unused;
199*91f16700Schasinglulu 
200*91f16700Schasinglulu 	assert(active_fw_bank_idx < NR_OF_FW_BANKS);
201*91f16700Schasinglulu 
202*91f16700Schasinglulu 	INFO("Booting with partition %s\n", fip_part_names[active_fw_bank_idx]);
203*91f16700Schasinglulu 
204*91f16700Schasinglulu 	int result = arm_set_image_source(FIP_IMAGE_ID,
205*91f16700Schasinglulu 					  fip_part_names[active_fw_bank_idx],
206*91f16700Schasinglulu 					  &dev_handle,
207*91f16700Schasinglulu 					  &image_spec);
208*91f16700Schasinglulu 	if (result != 0) {
209*91f16700Schasinglulu 		panic();
210*91f16700Schasinglulu 	}
211*91f16700Schasinglulu }
212*91f16700Schasinglulu #endif /* ARM_GPT_SUPPORT */
213*91f16700Schasinglulu 
214*91f16700Schasinglulu #if PSA_FWU_SUPPORT
215*91f16700Schasinglulu /*******************************************************************************
216*91f16700Schasinglulu  * Read the FIP partition of the GPT image corresponding to the active firmware
217*91f16700Schasinglulu  * bank to get its offset and length, and update these details in the I/O policy
218*91f16700Schasinglulu  * of the FIP image.
219*91f16700Schasinglulu  ******************************************************************************/
220*91f16700Schasinglulu void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
221*91f16700Schasinglulu {
222*91f16700Schasinglulu 	arm_set_fip_addr(metadata->active_index);
223*91f16700Schasinglulu }
224*91f16700Schasinglulu 
225*91f16700Schasinglulu /*******************************************************************************
226*91f16700Schasinglulu  * Read the requested FWU metadata partition of the GPT image to get its offset
227*91f16700Schasinglulu  * and length, and update these details in the I/O policy of the requested FWU
228*91f16700Schasinglulu  * metadata image.
229*91f16700Schasinglulu  ******************************************************************************/
230*91f16700Schasinglulu int plat_fwu_set_metadata_image_source(unsigned int image_id,
231*91f16700Schasinglulu 				       uintptr_t *dev_handle,
232*91f16700Schasinglulu 				       uintptr_t *image_spec)
233*91f16700Schasinglulu {
234*91f16700Schasinglulu 	int result = -1;
235*91f16700Schasinglulu 
236*91f16700Schasinglulu 	if (image_id == FWU_METADATA_IMAGE_ID) {
237*91f16700Schasinglulu 		result = arm_set_image_source(FWU_METADATA_IMAGE_ID,
238*91f16700Schasinglulu 					      "FWU-Metadata",
239*91f16700Schasinglulu 					      dev_handle,
240*91f16700Schasinglulu 					      image_spec);
241*91f16700Schasinglulu 	} else if (image_id == BKUP_FWU_METADATA_IMAGE_ID) {
242*91f16700Schasinglulu 		result = arm_set_image_source(BKUP_FWU_METADATA_IMAGE_ID,
243*91f16700Schasinglulu 					      "Bkup-FWU-Metadata",
244*91f16700Schasinglulu 					      dev_handle,
245*91f16700Schasinglulu 					      image_spec);
246*91f16700Schasinglulu 	}
247*91f16700Schasinglulu 
248*91f16700Schasinglulu 	return result;
249*91f16700Schasinglulu }
250*91f16700Schasinglulu #endif /* PSA_FWU_SUPPORT */
251