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>
82f1177b2SManish 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
282f1177b2SManish V Badarkhe #if ARM_GPT_SUPPORT
292f1177b2SManish V Badarkhe /* fip partition names */
302f1177b2SManish V Badarkhe static const char * const fip_part_names[] = {"FIP_A", "FIP_B"};
312f1177b2SManish V Badarkhe CASSERT(sizeof(fip_part_names)/sizeof(char *) == NR_OF_FW_BANKS,
322f1177b2SManish V Badarkhe assert_fip_partition_names_missing);
332f1177b2SManish V Badarkhe #endif /* ARM_GPT_SUPPORT */
342f1177b2SManish 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
open_fip(const uintptr_t spec)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
open_memmap(const uintptr_t spec)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
arm_io_setup(void)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
plat_arm_io_setup(void)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
plat_arm_get_alt_image_source(unsigned int image_id __unused,uintptr_t * dev_handle __unused,uintptr_t * image_spec __unused)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 */
plat_get_image_source(unsigned int image_id,uintptr_t * dev_handle,uintptr_t * image_spec)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);
127*491832feSJimmy Brisson assert(policy->check != NULL);
128b4315306SDan Handley result = policy->check(policy->image_spec);
129e098e244SJuan Castillo if (result == 0) {
130b4315306SDan Handley *image_spec = policy->image_spec;
131b4315306SDan Handley *dev_handle = *(policy->dev_handle);
132b4315306SDan Handley } else {
13316948ae1SJuan Castillo VERBOSE("Trying alternative IO\n");
13416948ae1SJuan Castillo result = plat_arm_get_alt_image_source(image_id, dev_handle,
13516948ae1SJuan Castillo image_spec);
136b4315306SDan Handley }
13716948ae1SJuan Castillo
138b4315306SDan Handley return result;
139b4315306SDan Handley }
140436223deSYatharth Kochar
141436223deSYatharth Kochar /*
142436223deSYatharth Kochar * See if a Firmware Image Package is available,
143436223deSYatharth Kochar * by checking if TOC is valid or not.
144436223deSYatharth Kochar */
arm_io_is_toc_valid(void)145d6dcbcadSLouis Mayencourt bool arm_io_is_toc_valid(void)
146436223deSYatharth Kochar {
147d6dcbcadSLouis Mayencourt return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0);
148436223deSYatharth Kochar }
149ef1daa42SManish V Badarkhe
150ef1daa42SManish V Badarkhe #if ARM_GPT_SUPPORT
1512f1177b2SManish V Badarkhe /******************************************************************************
1522f1177b2SManish V Badarkhe * Retrieve partition entry details such as offset and length, and set these
1532f1177b2SManish V Badarkhe * details in the I/O policy of the requested image.
154ef1daa42SManish V Badarkhe *
1552f1177b2SManish V Badarkhe * @image_id: image id whose I/O policy to be updated
156ef1daa42SManish V Badarkhe *
1572f1177b2SManish V Badarkhe * @part_name: partition name whose details to be retrieved
158ef1daa42SManish V Badarkhe *
1592f1177b2SManish V Badarkhe * Returns 0 on success, error otherwise
1602f1177b2SManish V Badarkhe * Alongside, returns device handle and image specification of requested
1612f1177b2SManish V Badarkhe * image.
1622f1177b2SManish V Badarkhe ******************************************************************************/
arm_set_image_source(unsigned int image_id,const char * part_name,uintptr_t * dev_handle,uintptr_t * image_spec)1632f1177b2SManish V Badarkhe int arm_set_image_source(unsigned int image_id, const char *part_name,
1642f1177b2SManish V Badarkhe uintptr_t *dev_handle, uintptr_t *image_spec)
165ef1daa42SManish V Badarkhe {
166ef1daa42SManish V Badarkhe const partition_entry_t *entry = get_partition_entry(part_name);
167ef1daa42SManish V Badarkhe
168ef1daa42SManish V Badarkhe if (entry == NULL) {
169ef1daa42SManish V Badarkhe ERROR("Unable to find the %s partition\n", part_name);
170ef1daa42SManish V Badarkhe return -ENOENT;
171ef1daa42SManish V Badarkhe }
172ef1daa42SManish V Badarkhe
1732f1177b2SManish V Badarkhe struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm,
174ef1daa42SManish V Badarkhe io_policies,
175ef1daa42SManish V Badarkhe image_id);
176ef1daa42SManish V Badarkhe
177ef1daa42SManish V Badarkhe assert(policy != NULL);
178ef1daa42SManish V Badarkhe assert(policy->image_spec != 0UL);
179ef1daa42SManish V Badarkhe
1802f1177b2SManish V Badarkhe io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
181ef1daa42SManish V Badarkhe /* set offset and length of the image */
1822f1177b2SManish V Badarkhe spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start;
1832f1177b2SManish V Badarkhe spec->length = entry->length;
184ef1daa42SManish V Badarkhe
1852f1177b2SManish V Badarkhe *dev_handle = *(policy->dev_handle);
1862f1177b2SManish V Badarkhe *image_spec = policy->image_spec;
187ef1daa42SManish V Badarkhe
188ef1daa42SManish V Badarkhe return 0;
189ef1daa42SManish V Badarkhe }
1902f1177b2SManish V Badarkhe
1912f1177b2SManish V Badarkhe /*******************************************************************************
1922f1177b2SManish V Badarkhe * Set the source offset and length of the FIP image in its I/O policy.
1932f1177b2SManish V Badarkhe *
1942f1177b2SManish V Badarkhe * @active_fw_bank_idx: active firmware bank index gathered from FWU metadata.
1952f1177b2SManish V Badarkhe ******************************************************************************/
arm_set_fip_addr(uint32_t active_fw_bank_idx)1962f1177b2SManish V Badarkhe void arm_set_fip_addr(uint32_t active_fw_bank_idx)
1972f1177b2SManish V Badarkhe {
1982f1177b2SManish V Badarkhe uintptr_t dev_handle __unused;
1992f1177b2SManish V Badarkhe uintptr_t image_spec __unused;
2002f1177b2SManish V Badarkhe
2012f1177b2SManish V Badarkhe assert(active_fw_bank_idx < NR_OF_FW_BANKS);
2022f1177b2SManish V Badarkhe
2032f1177b2SManish V Badarkhe INFO("Booting with partition %s\n", fip_part_names[active_fw_bank_idx]);
2042f1177b2SManish V Badarkhe
2052f1177b2SManish V Badarkhe int result = arm_set_image_source(FIP_IMAGE_ID,
2062f1177b2SManish V Badarkhe fip_part_names[active_fw_bank_idx],
2072f1177b2SManish V Badarkhe &dev_handle,
2082f1177b2SManish V Badarkhe &image_spec);
2092f1177b2SManish V Badarkhe if (result != 0) {
2102f1177b2SManish V Badarkhe panic();
2112f1177b2SManish V Badarkhe }
2122f1177b2SManish V Badarkhe }
2132f1177b2SManish V Badarkhe #endif /* ARM_GPT_SUPPORT */
2142f1177b2SManish V Badarkhe
2152f1177b2SManish V Badarkhe #if PSA_FWU_SUPPORT
2162f1177b2SManish V Badarkhe /*******************************************************************************
2172f1177b2SManish V Badarkhe * Read the FIP partition of the GPT image corresponding to the active firmware
2182f1177b2SManish V Badarkhe * bank to get its offset and length, and update these details in the I/O policy
2192f1177b2SManish V Badarkhe * of the FIP image.
2202f1177b2SManish V Badarkhe ******************************************************************************/
plat_fwu_set_images_source(const struct fwu_metadata * metadata)2216aaf257dSSughosh Ganu void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
2222f1177b2SManish V Badarkhe {
2232f1177b2SManish V Badarkhe arm_set_fip_addr(metadata->active_index);
2242f1177b2SManish V Badarkhe }
2252f1177b2SManish V Badarkhe
2262f1177b2SManish V Badarkhe /*******************************************************************************
2272f1177b2SManish V Badarkhe * Read the requested FWU metadata partition of the GPT image to get its offset
2282f1177b2SManish V Badarkhe * and length, and update these details in the I/O policy of the requested FWU
2292f1177b2SManish V Badarkhe * metadata image.
2302f1177b2SManish V Badarkhe ******************************************************************************/
plat_fwu_set_metadata_image_source(unsigned int image_id,uintptr_t * dev_handle,uintptr_t * image_spec)2312f1177b2SManish V Badarkhe int plat_fwu_set_metadata_image_source(unsigned int image_id,
2322f1177b2SManish V Badarkhe uintptr_t *dev_handle,
2332f1177b2SManish V Badarkhe uintptr_t *image_spec)
2342f1177b2SManish V Badarkhe {
2352f1177b2SManish V Badarkhe int result = -1;
2362f1177b2SManish V Badarkhe
2372f1177b2SManish V Badarkhe if (image_id == FWU_METADATA_IMAGE_ID) {
2382f1177b2SManish V Badarkhe result = arm_set_image_source(FWU_METADATA_IMAGE_ID,
2392f1177b2SManish V Badarkhe "FWU-Metadata",
2402f1177b2SManish V Badarkhe dev_handle,
2412f1177b2SManish V Badarkhe image_spec);
2422f1177b2SManish V Badarkhe } else if (image_id == BKUP_FWU_METADATA_IMAGE_ID) {
2432f1177b2SManish V Badarkhe result = arm_set_image_source(BKUP_FWU_METADATA_IMAGE_ID,
2442f1177b2SManish V Badarkhe "Bkup-FWU-Metadata",
2452f1177b2SManish V Badarkhe dev_handle,
2462f1177b2SManish V Badarkhe image_spec);
2472f1177b2SManish V Badarkhe }
2482f1177b2SManish V Badarkhe
2492f1177b2SManish V Badarkhe return result;
2502f1177b2SManish V Badarkhe }
2512f1177b2SManish V Badarkhe #endif /* PSA_FWU_SUPPORT */
252