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 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 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 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 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 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