diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h index 0fda8c9..9816d6f 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 *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 1b59795..3625530 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -190,7 +190,7 @@ 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 affec54..bc4fa8e 100644 --- a/lib/fconf/fconf.c +++ b/lib/fconf/fconf.c @@ -29,8 +29,11 @@ }; 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 1828a80..902c07d 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 @@ /* 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 @@ 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 4011dc9..6b630b9 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -142,11 +143,58 @@ */ 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 9d5526f..e4a4f87 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef SPD_opteed #include #endif @@ -53,6 +54,7 @@ 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 @@ /* 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 */