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