diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h index 0fda8c9b2037be5d2867aa6d538422a6b90e4b36..9816d6fe0d000a81ca5be9065643350c6624f0b5 100644 --- a/include/lib/fconf/fconf_dyn_cfg_getter.h +++ b/include/lib/fconf/fconf_dyn_cfg_getter.h @@ -21,4 +21,7 @@ struct dyn_cfg_dtb_info_t { struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id); int fconf_populate_dtb_registry(uintptr_t config); +/* Set fw_config information in global DTB array */ +void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size); + #endif /* FCONF_DYN_CFG_GETTER_H */ diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 1b59795293bbfeb86604fd27173cfb56647c55ab..36255300ebe0fa58b381da0cf98ac5c14d52322f 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -190,7 +190,7 @@ void arm_bl1_platform_setup(void); void arm_bl1_plat_arch_setup(void); /* BL2 utility functions */ -void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, struct meminfo *mem_layout); +void arm_bl2_early_platform_setup(uintptr_t fw_config, struct meminfo *mem_layout); void arm_bl2_platform_setup(void); void arm_bl2_plat_arch_setup(void); uint32_t arm_get_spsr_for_bl32_entry(void); diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c index affec54dbbd856d5b92ce9da1b19e0b5dc531246..bc4fa8ea8b2113a712207e0be43e591df2743320 100644 --- a/lib/fconf/fconf.c +++ b/lib/fconf/fconf.c @@ -29,8 +29,11 @@ int fconf_load_config(unsigned int image_id) }; config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_id); + assert(config_info != NULL); + config_image_info.image_base = config_info->config_addr; - config_image_info.image_max_size = (uint32_t)config_info->config_max_size; + config_image_info.image_max_size = + (uint32_t)config_info->config_max_size; VERBOSE("FCONF: Loading config with image ID: %d\n", image_id); err = load_auth_image(image_id, &config_image_info); diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c index 1828a80bf03177d29a01ea8e198b11328232bf23..902c07d955eaa5b1e19d1c0c37471e2445216050 100644 --- a/lib/fconf/fconf_dyn_cfg_getter.c +++ b/lib/fconf/fconf_dyn_cfg_getter.c @@ -15,22 +15,23 @@ /* We currently use FW, TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs */ #define MAX_DTB_INFO U(6) -#ifdef IMAGE_BL1 -static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO] = { - [0] = { - .config_addr = ARM_FW_CONFIG_BASE, - .config_max_size = (uint32_t) - (ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE), - .config_id = FW_CONFIG_ID - }, -}; -/* Create an object pool starting at the second element */ -static OBJECT_POOL(dtb_info_pool, &dtb_infos[1], - sizeof(struct dyn_cfg_dtb_info_t), MAX_DTB_INFO-1); -#else static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO]; static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos); -#endif + +/* + * This function is used to alloc memory for fw config information from + * global pool and set fw configuration information. + * Specifically used by BL1 to set fw_config information in global array + */ +void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size) +{ + struct dyn_cfg_dtb_info_t *dtb_info; + + dtb_info = pool_alloc(&dtb_info_pool); + dtb_info->config_addr = config_addr; + dtb_info->config_max_size = config_max_size; + dtb_info->config_id = FW_CONFIG_ID; +} struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id) { @@ -62,6 +63,30 @@ int fconf_populate_dtb_registry(uintptr_t config) /* As libfdt use void *, we can't avoid this cast */ const void *dtb = (void *)config; + /* + * Compile time assert if FW_CONFIG_ID is 0 which is more + * unlikely as 0 is a valid image id for FIP as per the current + * code but still to avoid code breakage in case of unlikely + * event when image ids gets changed. + */ + CASSERT(FW_CONFIG_ID != 0, assert_invalid_fw_config_id); + + /* + * In case of BL1, fw_config dtb information is already + * populated in global dtb_infos array by 'set_fw_config_info' + * function, Below check is present to avoid re-population of + * fw_config information. + * + * Other BLs, satisfy below check and populate fw_config information + * in global dtb_infos array. + */ + if (dtb_infos[0].config_id == 0) { + dtb_info = pool_alloc(&dtb_info_pool); + dtb_info->config_addr = config; + dtb_info->config_max_size = fdt_totalsize(dtb); + dtb_info->config_id = FW_CONFIG_ID; + } + /* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */ const char *compatible_str = "fconf,dyn_cfg-dtb_registry"; node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); @@ -70,15 +95,6 @@ int fconf_populate_dtb_registry(uintptr_t config) return node; } -#ifndef IMAGE_BL1 - /* Save config dtb information */ - dtb_info = pool_alloc(&dtb_info_pool); - - dtb_info->config_addr = config; - dtb_info->config_max_size = fdt_totalsize(dtb); - dtb_info->config_id = FW_CONFIG_ID; -#endif - fdt_for_each_subnode(child, dtb, node) { uint32_t val32; uint64_t val64; diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 4011dc9fc134c214078311a920c8458841cb0b02..6b630b9805c37b00983df1c3ec4d30fca1e72923 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -12,6 +12,7 @@ #include <bl1/bl1.h> #include <common/bl_common.h> #include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> #include <lib/utils.h> #include <lib/xlat_tables/xlat_tables_compat.h> #include <plat/arm/common/plat_arm.h> @@ -142,11 +143,58 @@ void bl1_plat_arch_setup(void) */ void arm_bl1_platform_setup(void) { + const struct dyn_cfg_dtb_info_t *fw_config_info; + image_desc_t *desc; + uint32_t fw_config_max_size; + int err = -1; + /* Initialise the IO layer and register platform IO devices */ plat_arm_io_setup(); - /* Fill the properties struct with the info from the config dtb */ - fconf_load_config(FW_CONFIG_ID); + /* Check if we need FWU before further processing */ + err = plat_arm_bl1_fwu_needed(); + if (err) { + ERROR("Skip platform setup as FWU detected\n"); + return; + } + + /* Set global DTB info for fixed fw_config information */ + fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE; + set_fw_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size); + + /* Fill the device tree information struct with the info from the config dtb */ + err = fconf_load_config(FW_CONFIG_ID); + if (err < 0) { + ERROR("Loading of FW_CONFIG failed %d\n", err); + plat_error_handler(err); + } + + /* + * FW_CONFIG loaded successfully. If FW_CONFIG device tree parsing + * is successful then load TB_FW_CONFIG device tree. + */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + if (fw_config_info != NULL) { + err = fconf_populate_dtb_registry(fw_config_info->config_addr); + if (err < 0) { + ERROR("Parsing of FW_CONFIG failed %d\n", err); + plat_error_handler(err); + } + /* load TB_FW_CONFIG */ + err = fconf_load_config(TB_FW_CONFIG_ID); + if (err < 0) { + ERROR("Loading of TB_FW_CONFIG failed %d\n", err); + plat_error_handler(err); + } + } else { + ERROR("Invalid FW_CONFIG address\n"); + plat_error_handler(err); + } + + /* The BL2 ep_info arg0 is modified to point to FW_CONFIG */ + desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(desc != NULL); + desc->ep_info.args.arg0 = fw_config_info->config_addr; #if TRUSTED_BOARD_BOOT /* Share the Mbed TLS heap info with other images */ diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index 9d5526f1b67410917dbeb9d9fffbd25b3861f776..e4a4f8724f0e4c7dcdafe1c2ad6a0dcd67379a20 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -15,6 +15,7 @@ #include <common/desc_image_load.h> #include <drivers/generic_delay_timer.h> #include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> #ifdef SPD_opteed #include <lib/optee_utils.h> #endif @@ -53,6 +54,7 @@ CASSERT(BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl2_base_overflows); void arm_bl2_early_platform_setup(uintptr_t fw_config, struct meminfo *mem_layout) { + const struct dyn_cfg_dtb_info_t *tb_fw_config_info; /* Initialize the console to provide early debug support */ arm_console_boot_init(); @@ -61,7 +63,13 @@ void arm_bl2_early_platform_setup(uintptr_t fw_config, /* Fill the properties struct with the info from the config dtb */ if (fw_config != 0U) { - fconf_populate("TB_FW", fw_config); + fconf_populate("FW_CONFIG", fw_config); + } + + /* TB_FW_CONFIG was also loaded by BL1 */ + tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); + if (tb_fw_config_info != NULL) { + fconf_populate("TB_FW", tb_fw_config_info->config_addr); } /* Initialise the IO layer and register platform IO devices */