148ab3904SJassi Brar /*
248ab3904SJassi Brar * Copyright (c) 2022, Socionext Inc. All rights reserved.
348ab3904SJassi Brar *
448ab3904SJassi Brar * SPDX-License-Identifier: BSD-3-Clause
548ab3904SJassi Brar */
648ab3904SJassi Brar
748ab3904SJassi Brar #include <assert.h>
848ab3904SJassi Brar #include <errno.h>
948ab3904SJassi Brar #include <stdint.h>
1048ab3904SJassi Brar
1148ab3904SJassi Brar #include <drivers/io/io_block.h>
1248ab3904SJassi Brar #include <drivers/io/io_driver.h>
1348ab3904SJassi Brar #include <drivers/io/io_fip.h>
1448ab3904SJassi Brar #include <drivers/io/io_memmap.h>
1548ab3904SJassi Brar #include <lib/mmio.h>
1648ab3904SJassi Brar #include <lib/utils_def.h>
1748ab3904SJassi Brar #include <lib/xlat_tables/xlat_tables_v2.h>
1848ab3904SJassi Brar #include <tools_share/firmware_image_package.h>
1948ab3904SJassi Brar
2048ab3904SJassi Brar #include <platform_def.h>
2148ab3904SJassi Brar #include <sq_common.h>
2248ab3904SJassi Brar
2348ab3904SJassi Brar static const io_dev_connector_t *sq_fip_dev_con;
2448ab3904SJassi Brar static uintptr_t sq_fip_dev_handle;
2548ab3904SJassi Brar
2648ab3904SJassi Brar static const io_dev_connector_t *sq_backend_dev_con;
2748ab3904SJassi Brar static uintptr_t sq_backend_dev_handle;
2848ab3904SJassi Brar
2948ab3904SJassi Brar static io_block_spec_t sq_fip_spec = {
3048ab3904SJassi Brar .offset = PLAT_SQ_FIP_IOBASE, /* FIP Image is at 5MB offset on memory-mapped NOR flash */
3148ab3904SJassi Brar .length = PLAT_SQ_FIP_MAXSIZE, /* Expected maximum FIP image size */
3248ab3904SJassi Brar };
3348ab3904SJassi Brar
3448ab3904SJassi Brar static const io_uuid_spec_t sq_bl2_spec = {
3548ab3904SJassi Brar .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
3648ab3904SJassi Brar };
3748ab3904SJassi Brar
3848ab3904SJassi Brar static const io_uuid_spec_t sq_bl31_spec = {
3948ab3904SJassi Brar .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
4048ab3904SJassi Brar };
4148ab3904SJassi Brar
4248ab3904SJassi Brar static const io_uuid_spec_t sq_bl32_spec = {
4348ab3904SJassi Brar .uuid = UUID_SECURE_PAYLOAD_BL32,
4448ab3904SJassi Brar };
4548ab3904SJassi Brar
4648ab3904SJassi Brar static const io_uuid_spec_t sq_bl33_spec = {
4748ab3904SJassi Brar .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
4848ab3904SJassi Brar };
4948ab3904SJassi Brar
5019aaeea0SJassi Brar #if TRUSTED_BOARD_BOOT
5119aaeea0SJassi Brar static const io_uuid_spec_t sq_tb_fw_cert_spec = {
5219aaeea0SJassi Brar .uuid = UUID_TRUSTED_BOOT_FW_CERT,
5319aaeea0SJassi Brar };
5419aaeea0SJassi Brar
5519aaeea0SJassi Brar static const io_uuid_spec_t sq_trusted_key_cert_spec = {
5619aaeea0SJassi Brar .uuid = UUID_TRUSTED_KEY_CERT,
5719aaeea0SJassi Brar };
5819aaeea0SJassi Brar
5919aaeea0SJassi Brar static const io_uuid_spec_t sq_soc_fw_key_cert_spec = {
6019aaeea0SJassi Brar .uuid = UUID_SOC_FW_KEY_CERT,
6119aaeea0SJassi Brar };
6219aaeea0SJassi Brar
6319aaeea0SJassi Brar static const io_uuid_spec_t sq_tos_fw_key_cert_spec = {
6419aaeea0SJassi Brar .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
6519aaeea0SJassi Brar };
6619aaeea0SJassi Brar
6719aaeea0SJassi Brar static const io_uuid_spec_t sq_nt_fw_key_cert_spec = {
6819aaeea0SJassi Brar .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
6919aaeea0SJassi Brar };
7019aaeea0SJassi Brar
7119aaeea0SJassi Brar static const io_uuid_spec_t sq_soc_fw_cert_spec = {
7219aaeea0SJassi Brar .uuid = UUID_SOC_FW_CONTENT_CERT,
7319aaeea0SJassi Brar };
7419aaeea0SJassi Brar
7519aaeea0SJassi Brar static const io_uuid_spec_t sq_tos_fw_cert_spec = {
7619aaeea0SJassi Brar .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
7719aaeea0SJassi Brar };
7819aaeea0SJassi Brar
7919aaeea0SJassi Brar static const io_uuid_spec_t sq_nt_fw_cert_spec = {
8019aaeea0SJassi Brar .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
8119aaeea0SJassi Brar };
8219aaeea0SJassi Brar #endif /* TRUSTED_BOARD_BOOT */
8319aaeea0SJassi Brar
8448ab3904SJassi Brar struct sq_io_policy {
8548ab3904SJassi Brar uintptr_t *dev_handle;
8648ab3904SJassi Brar uintptr_t image_spec;
8748ab3904SJassi Brar uintptr_t init_params;
8848ab3904SJassi Brar };
8948ab3904SJassi Brar
9048ab3904SJassi Brar static const struct sq_io_policy sq_io_policies[] = {
9148ab3904SJassi Brar [FIP_IMAGE_ID] = {
9248ab3904SJassi Brar .dev_handle = &sq_backend_dev_handle,
9348ab3904SJassi Brar .image_spec = (uintptr_t)&sq_fip_spec,
9448ab3904SJassi Brar },
9548ab3904SJassi Brar [BL2_IMAGE_ID] = {
9648ab3904SJassi Brar .dev_handle = &sq_fip_dev_handle,
9748ab3904SJassi Brar .image_spec = (uintptr_t)&sq_bl2_spec,
9848ab3904SJassi Brar .init_params = FIP_IMAGE_ID,
9948ab3904SJassi Brar },
10048ab3904SJassi Brar [BL31_IMAGE_ID] = {
10148ab3904SJassi Brar .dev_handle = &sq_fip_dev_handle,
10248ab3904SJassi Brar .image_spec = (uintptr_t)&sq_bl31_spec,
10348ab3904SJassi Brar .init_params = FIP_IMAGE_ID,
10448ab3904SJassi Brar },
10548ab3904SJassi Brar [BL32_IMAGE_ID] = {
10648ab3904SJassi Brar .dev_handle = &sq_fip_dev_handle,
10748ab3904SJassi Brar .image_spec = (uintptr_t)&sq_bl32_spec,
10848ab3904SJassi Brar .init_params = FIP_IMAGE_ID,
10948ab3904SJassi Brar },
11048ab3904SJassi Brar [BL33_IMAGE_ID] = {
11148ab3904SJassi Brar .dev_handle = &sq_fip_dev_handle,
11248ab3904SJassi Brar .image_spec = (uintptr_t)&sq_bl33_spec,
11348ab3904SJassi Brar .init_params = FIP_IMAGE_ID,
11448ab3904SJassi Brar },
11519aaeea0SJassi Brar #if TRUSTED_BOARD_BOOT
11619aaeea0SJassi Brar [TRUSTED_BOOT_FW_CERT_ID] = {
11719aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
11819aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_tb_fw_cert_spec,
11919aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
12019aaeea0SJassi Brar },
12119aaeea0SJassi Brar [TRUSTED_KEY_CERT_ID] = {
12219aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
12319aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_trusted_key_cert_spec,
12419aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
12519aaeea0SJassi Brar },
12619aaeea0SJassi Brar [SOC_FW_KEY_CERT_ID] = {
12719aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
12819aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_soc_fw_key_cert_spec,
12919aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
13019aaeea0SJassi Brar },
13119aaeea0SJassi Brar [TRUSTED_OS_FW_KEY_CERT_ID] = {
13219aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
13319aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_tos_fw_key_cert_spec,
13419aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
13519aaeea0SJassi Brar },
13619aaeea0SJassi Brar [NON_TRUSTED_FW_KEY_CERT_ID] = {
13719aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
13819aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_nt_fw_key_cert_spec,
13919aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
14019aaeea0SJassi Brar },
14119aaeea0SJassi Brar [SOC_FW_CONTENT_CERT_ID] = {
14219aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
14319aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_soc_fw_cert_spec,
14419aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
14519aaeea0SJassi Brar },
14619aaeea0SJassi Brar [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
14719aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
14819aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_tos_fw_cert_spec,
14919aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
15019aaeea0SJassi Brar },
15119aaeea0SJassi Brar [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
15219aaeea0SJassi Brar .dev_handle = &sq_fip_dev_handle,
15319aaeea0SJassi Brar .image_spec = (uintptr_t)&sq_nt_fw_cert_spec,
15419aaeea0SJassi Brar .init_params = FIP_IMAGE_ID,
15519aaeea0SJassi Brar },
15619aaeea0SJassi Brar #endif
15748ab3904SJassi Brar };
15848ab3904SJassi Brar
sq_update_fip_spec(void)159*a1938252SJassi Brar static int sq_update_fip_spec(void)
160*a1938252SJassi Brar {
161*a1938252SJassi Brar uint32_t boot_index;
162*a1938252SJassi Brar int ret;
163*a1938252SJassi Brar
164*a1938252SJassi Brar ret = mmap_add_dynamic_region(PLAT_SQ_BOOTIDX_BASE, PLAT_SQ_BOOTIDX_BASE,
165*a1938252SJassi Brar PAGE_SIZE, MT_RO_DATA | MT_SECURE);
166*a1938252SJassi Brar if (ret) {
167*a1938252SJassi Brar return ret;
168*a1938252SJassi Brar }
169*a1938252SJassi Brar
170*a1938252SJassi Brar boot_index = mmio_read_32(PLAT_SQ_BOOTIDX_BASE);
171*a1938252SJassi Brar if (boot_index < PLAT_SQ_MAX_BOOT_INDEX) {
172*a1938252SJassi Brar sq_fip_spec.offset += PLAT_SQ_FIP_MAXSIZE * boot_index;
173*a1938252SJassi Brar INFO("FWU Enabled: boot_index %d\n", boot_index);
174*a1938252SJassi Brar } else {
175*a1938252SJassi Brar WARN("FWU Disabled: wrong boot_index value. Fallback to index 0.\n");
176*a1938252SJassi Brar }
177*a1938252SJassi Brar
178*a1938252SJassi Brar mmap_remove_dynamic_region(PLAT_SQ_BOOTIDX_BASE, PAGE_SIZE);
179*a1938252SJassi Brar return 0;
180*a1938252SJassi Brar }
181*a1938252SJassi Brar
sq_io_memmap_setup(void)18248ab3904SJassi Brar static int sq_io_memmap_setup(void)
18348ab3904SJassi Brar {
18448ab3904SJassi Brar int ret;
18548ab3904SJassi Brar
186*a1938252SJassi Brar ret = sq_update_fip_spec();
187*a1938252SJassi Brar if (ret) {
188*a1938252SJassi Brar return ret;
189*a1938252SJassi Brar }
190*a1938252SJassi Brar
19148ab3904SJassi Brar ret = mmap_add_dynamic_region(sq_fip_spec.offset, sq_fip_spec.offset,
19248ab3904SJassi Brar sq_fip_spec.length, MT_RO_DATA | MT_SECURE);
19348ab3904SJassi Brar if (ret) {
19448ab3904SJassi Brar return ret;
19548ab3904SJassi Brar }
19648ab3904SJassi Brar
19748ab3904SJassi Brar ret = register_io_dev_memmap(&sq_backend_dev_con);
19848ab3904SJassi Brar if (ret) {
19948ab3904SJassi Brar return ret;
20048ab3904SJassi Brar }
20148ab3904SJassi Brar
20248ab3904SJassi Brar return io_dev_open(sq_backend_dev_con, 0, &sq_backend_dev_handle);
20348ab3904SJassi Brar }
20448ab3904SJassi Brar
sq_io_fip_setup(void)20548ab3904SJassi Brar static int sq_io_fip_setup(void)
20648ab3904SJassi Brar {
20748ab3904SJassi Brar int ret;
20848ab3904SJassi Brar
20948ab3904SJassi Brar ret = register_io_dev_fip(&sq_fip_dev_con);
21048ab3904SJassi Brar if (ret) {
21148ab3904SJassi Brar return ret;
21248ab3904SJassi Brar }
21348ab3904SJassi Brar
21448ab3904SJassi Brar return io_dev_open(sq_fip_dev_con, 0, &sq_fip_dev_handle);
21548ab3904SJassi Brar }
21648ab3904SJassi Brar
sq_io_setup(void)21748ab3904SJassi Brar int sq_io_setup(void)
21848ab3904SJassi Brar {
21948ab3904SJassi Brar int ret;
22048ab3904SJassi Brar
22148ab3904SJassi Brar ret = sq_io_memmap_setup();
22248ab3904SJassi Brar if (ret) {
22348ab3904SJassi Brar return ret;
22448ab3904SJassi Brar }
22548ab3904SJassi Brar
22648ab3904SJassi Brar ret = sq_io_fip_setup();
22748ab3904SJassi Brar if (ret) {
22848ab3904SJassi Brar return ret;
22948ab3904SJassi Brar }
23048ab3904SJassi Brar
23148ab3904SJassi Brar return 0;
23248ab3904SJassi Brar }
23348ab3904SJassi Brar
plat_get_image_source(unsigned int image_id,uintptr_t * dev_handle,uintptr_t * image_spec)23448ab3904SJassi Brar int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
23548ab3904SJassi Brar uintptr_t *image_spec)
23648ab3904SJassi Brar {
23748ab3904SJassi Brar uintptr_t init_params;
23848ab3904SJassi Brar
23948ab3904SJassi Brar assert(image_id < ARRAY_SIZE(sq_io_policies));
24048ab3904SJassi Brar
24148ab3904SJassi Brar *dev_handle = *sq_io_policies[image_id].dev_handle;
24248ab3904SJassi Brar *image_spec = sq_io_policies[image_id].image_spec;
24348ab3904SJassi Brar init_params = sq_io_policies[image_id].init_params;
24448ab3904SJassi Brar
24548ab3904SJassi Brar return io_dev_init(*dev_handle, init_params);
24648ab3904SJassi Brar }
247