diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index 845f140..ad6b4f8 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -87,7 +87,7 @@ #if TRUSTED_BOARD_BOOT # define PLAT_ARM_MAX_BL2_SIZE 0x1E000 #else -# define PLAT_ARM_MAX_BL2_SIZE 0xF000 +# define PLAT_ARM_MAX_BL2_SIZE 0x10000 #endif /* diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 4473b53..18390d6 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -317,7 +317,7 @@ * and limit. Leave enough space of BL2 meminfo. */ #define ARM_TB_FW_CONFIG_BASE ARM_BL_RAM_BASE + sizeof(meminfo_t) -#define ARM_TB_FW_CONFIG_LIMIT BL2_LIMIT +#define ARM_TB_FW_CONFIG_LIMIT BL2_BASE /******************************************************************************* * BL1 specific defines. diff --git a/include/plat/arm/common/arm_dyn_cfg_helpers.h b/include/plat/arm/common/arm_dyn_cfg_helpers.h index 826924d..382ec60 100644 --- a/include/plat/arm/common/arm_dyn_cfg_helpers.h +++ b/include/plat/arm/common/arm_dyn_cfg_helpers.h @@ -9,8 +9,8 @@ #include /* Function declaration */ -int arm_dyn_get_hwconfig_info(void *dtb, int node, - uint64_t *hw_config_addr, uint32_t *hw_config_size); +int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id, + uint64_t *config_addr, uint32_t *config_size); int arm_dyn_tb_fw_cfg_init(void *dtb, int *node); int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth); diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts new file mode 100644 index 0000000..7ab980b --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; diff --git a/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts new file mode 100644 index 0000000..7ab980b --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts index fb7e2c5..716b023 100644 --- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts +++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts @@ -13,6 +13,18 @@ hw_config_addr = <0x0 0x82000000>; hw_config_max_size = <0x01000000>; /* Disable authentication for development */ - disable_auth = <0x0>; + disable_auth = <0x1>; + /* + * Load SoC and TOS firmware configs at the base of + * non shared SRAM. The runtime checks ensure we don't + * overlap BL2, BL31 or BL32. The NT firmware config + * is loaded at base of DRAM. + */ + soc_fw_config_addr = <0x0 0x04001000>; + soc_fw_config_max_size = <0x200>; + tos_fw_config_addr = <0x0 0x04001200>; + tos_fw_config_max_size = <0x200>; + nt_fw_config_addr = <0x0 0x80000000>; + nt_fw_config_max_size = <0x200>; }; }; diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts new file mode 100644 index 0000000..7ab980b --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index c5e33d2..f807dc6 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -166,11 +166,30 @@ # Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) ifdef UNIX_MK FVP_HW_CONFIG_DTS := fdts/${FVP_DT_PREFIX}.dts -FDT_SOURCES += plat/arm/board/fvp/fdts/${PLAT}_tb_fw_config.dts +FDT_SOURCES += $(addprefix plat/arm/board/fvp/fdts/, \ + ${PLAT}_tb_fw_config.dts \ + ${PLAT}_soc_fw_config.dts \ + ${PLAT}_nt_fw_config.dts \ + ) + FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb +FVP_SOC_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb +FVP_NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +ifeq (${SPD},tspd) +FDT_SOURCES += plat/arm/board/fvp/fdts/${PLAT}_tsp_fw_config.dts +FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tsp_fw_config.dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config)) +endif # Add the TB_FW_CONFIG to FIP and specify the same to certtool $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config)) +# Add the SOC_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_SOC_FW_CONFIG},--soc-fw-config)) +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_NT_FW_CONFIG},--nt-fw-config)) FDT_SOURCES += ${FVP_HW_CONFIG_DTS} $(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(FVP_HW_CONFIG_DTS))) diff --git a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c index fef01c9..8e6d00d 100644 --- a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c +++ b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c @@ -91,6 +91,15 @@ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), .next_handoff_image_id = INVALID_IMAGE_ID, }, + /* Fill SOC_FW_CONFIG related information */ + { + .image_id = SOC_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, # ifdef BL32_BASE /* Fill BL32 related information */ { @@ -144,6 +153,16 @@ #endif .next_handoff_image_id = INVALID_IMAGE_ID, }, + + /* Fill TOS_FW_CONFIG related information */ + { + .image_id = TOS_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, # endif /* BL32_BASE */ /* Fill BL33 related information */ @@ -166,6 +185,15 @@ # endif /* PRELOADED_BL33_BASE */ .next_handoff_image_id = INVALID_IMAGE_ID, + }, + /* Fill NT_FW_CONFIG related information */ + { + .image_id = NT_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, NON_SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, } #endif /* EL3_PAYLOAD_BASE */ }; diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c index 33dc08b..3f0a9b4 100644 --- a/plat/arm/common/arm_dyn_cfg.c +++ b/plat/arm/common/arm_dyn_cfg.c @@ -85,14 +85,25 @@ /* * BL2 utility function to initialize dynamic configuration specified by - * TB_FW_CONFIG. Return early if TB_FW_CONFIG is not found or HW_CONFIG is - * not specified in TB_FW_CONFIG. + * TB_FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if + * specified in TB_FW_CONFIG. */ void arm_bl2_dyn_cfg_init(void) { - int err = 0; - int tb_fw_node; - bl_mem_params_node_t *hw_cfg_mem_params = NULL; + int err = 0, tb_fw_node; + unsigned int i; + bl_mem_params_node_t *cfg_mem_params = NULL; + uint64_t image_base; + uint32_t image_size; + const unsigned int config_ids[] = { + HW_CONFIG_ID, + SOC_FW_CONFIG_ID, + NT_FW_CONFIG_ID, +#ifdef SPD_tspd + /* Currently tos_fw_config is only present for TSP */ + TOS_FW_CONFIG_ID +#endif + }; if (tb_fw_cfg_dtb == NULL) { VERBOSE("No TB_FW_CONFIG specified\n"); @@ -105,23 +116,57 @@ panic(); } - /* Get the hw_config load address and size from TB_FW_CONFIG */ - hw_cfg_mem_params = get_bl_mem_params_node(HW_CONFIG_ID); - if (hw_cfg_mem_params == NULL) { - VERBOSE("Couldn't find HW_CONFIG in bl_mem_params_node\n"); - return; - } + /* Iterate through all the fw config IDs */ + for (i = 0; i < ARRAY_SIZE(config_ids); i++) { + /* Get the config load address and size from TB_FW_CONFIG */ + cfg_mem_params = get_bl_mem_params_node(config_ids[i]); + if (cfg_mem_params == NULL) { + VERBOSE("Couldn't find HW_CONFIG in bl_mem_params_node\n"); + continue; + } - err = arm_dyn_get_hwconfig_info((void *)tb_fw_cfg_dtb, tb_fw_node, - (uint64_t *) &hw_cfg_mem_params->image_info.image_base, - &hw_cfg_mem_params->image_info.image_max_size); - if (err < 0) { - VERBOSE("Couldn't find HW_CONFIG load info in TB_FW_CONFIG\n"); - return; - } + err = arm_dyn_get_config_load_info((void *)tb_fw_cfg_dtb, tb_fw_node, + config_ids[i], &image_base, &image_size); + if (err < 0) { + VERBOSE("Couldn't find config_id %d load info in TB_FW_CONFIG\n", + config_ids[i]); + continue; + } - /* Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from HW_CONFIG node */ - hw_cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; + /* + * Do some runtime checks on the load addresses of soc_fw_config, + * tos_fw_config, nt_fw_config. This is not a comprehensive check + * of all invalid addresses but to prevent trivial porting errors. + */ + if (config_ids[i] != HW_CONFIG_ID) { + + if (check_uptr_overflow(image_base, image_size) != 0) + continue; + + /* Ensure the configs don't overlap with BL2 */ + if ((image_base > BL2_BASE) || ((image_base + image_size) > BL2_BASE)) + continue; + + /* Ensure the configs are loaded in a valid address */ + if (image_base < ARM_BL_RAM_BASE) + continue; +#ifdef BL32_BASE + /* + * If BL32 is present, ensure that the configs don't + * overlap with it. + */ + if (image_base >= BL32_BASE && image_base <= BL32_LIMIT) + continue; +#endif + } + + + cfg_mem_params->image_info.image_base = (uintptr_t)image_base; + cfg_mem_params->image_info.image_max_size = image_size; + + /* Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from HW_CONFIG node */ + cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; + } #if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH) uint32_t disable_auth = 0; diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c index e37e7e7..5a7e20a 100644 --- a/plat/arm/common/arm_dyn_cfg_helpers.c +++ b/plat/arm/common/arm_dyn_cfg_helpers.c @@ -11,31 +11,57 @@ #include #include + +typedef struct config_load_info_prop { + unsigned int config_id; + const char *config_addr; + const char *config_max_size; +} config_load_info_prop_t; + +static const config_load_info_prop_t prop_names[] = { + {HW_CONFIG_ID, "hw_config_addr", "hw_config_max_size"}, + {SOC_FW_CONFIG_ID, "soc_fw_config_addr", "soc_fw_config_max_size"}, + {TOS_FW_CONFIG_ID, "tos_fw_config_addr", "tos_fw_config_max_size"}, + {NT_FW_CONFIG_ID, "nt_fw_config_addr", "nt_fw_config_max_size"} +}; + /******************************************************************************* - * Helper to read the `hw_config` property in config DTB. This function - * expects the following properties to be present in the config DTB. - * name : hw_config_addr size : 2 cells - * name : hw_config_max_size size : 1 cell + * Helper to read the load information corresponding to the `config_id` in + * TB_FW_CONFIG. This function expects the following properties to be defined : + * _addr size : 2 cells + * _max_size size : 1 cell * * Arguments: * void *dtb - pointer to the TB_FW_CONFIG in memory * int node - The node offset to appropriate node in the * DTB. - * uint64_t *hw_config_addr - Returns the `hw_config` load address if read + * unsigned int config_id - The configuration id + * uint64_t *config_addr - Returns the `config` load address if read * is successful. - * uint32_t *hw_config_size - Returns the `hw_config` size if read is + * uint32_t *config_size - Returns the `config` size if read is * successful. * * Returns 0 on success and -1 on error. ******************************************************************************/ -int arm_dyn_get_hwconfig_info(void *dtb, int node, - uint64_t *hw_config_addr, uint32_t *hw_config_size) +int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id, + uint64_t *config_addr, uint32_t *config_size) { int err; + unsigned int i; assert(dtb != NULL); - assert(hw_config_addr != NULL); - assert(hw_config_size != NULL); + assert(config_addr != NULL); + assert(config_size != NULL); + + for (i = 0; i < ARRAY_SIZE(prop_names); i++) { + if (prop_names[i].config_id == config_id) + break; + } + + if (i == ARRAY_SIZE(prop_names)) { + WARN("Invalid config id %d\n", config_id); + return -1; + } /* Check if the pointer to DT is correct */ assert(fdt_check_header(dtb) == 0); @@ -43,22 +69,22 @@ /* Assert the node offset point to "arm,tb_fw" compatible property */ assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw")); - err = fdtw_read_cells(dtb, node, "hw_config_addr", 2, - (void *) hw_config_addr); + err = fdtw_read_cells(dtb, node, prop_names[i].config_addr, 2, + (void *) config_addr); if (err < 0) { - WARN("Read cell failed for hw_config_addr\n"); + WARN("Read cell failed for %s\n", prop_names[i].config_addr); return -1; } - err = fdtw_read_cells(dtb, node, "hw_config_max_size", 1, - (void *) hw_config_size); + err = fdtw_read_cells(dtb, node, prop_names[i].config_max_size, 1, + (void *) config_size); if (err < 0) { - WARN("Read cell failed for hw_config_max_size\n"); + WARN("Read cell failed for %s\n", prop_names[i].config_max_size); return -1; } - VERBOSE("Dyn cfg: Read hw_config address from TB_FW_CONFIG 0x%p %p\n", - hw_config_addr, hw_config_size); + VERBOSE("Dyn cfg: Read config_id %d load info from TB_FW_CONFIG 0x%llx 0x%x\n", + config_id, (unsigned long long)*config_addr, *config_size); return 0; } @@ -98,7 +124,7 @@ } /* Check if the value is boolean */ - if (*disable_auth != 0 && *disable_auth != 1) { + if ((*disable_auth != 0U) && (*disable_auth != 1U)) { WARN("Invalid value for `disable_auth` cell %d\n", *disable_auth); return -1; } diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c index 652f5e9..cd58e45 100644 --- a/plat/arm/common/arm_io_storage.c +++ b/plat/arm/common/arm_io_storage.c @@ -63,6 +63,18 @@ .uuid = UUID_HW_CONFIG, }; +static const io_uuid_spec_t soc_fw_config_uuid_spec = { + .uuid = UUID_SOC_FW_CONFIG, +}; + +static const io_uuid_spec_t tos_fw_config_uuid_spec = { + .uuid = UUID_TOS_FW_CONFIG, +}; + +static const io_uuid_spec_t nt_fw_config_uuid_spec = { + .uuid = UUID_NT_FW_CONFIG, +}; + #if TRUSTED_BOARD_BOOT static const io_uuid_spec_t tb_fw_cert_uuid_spec = { .uuid = UUID_TRUSTED_BOOT_FW_CERT, @@ -167,6 +179,21 @@ (uintptr_t)&hw_config_uuid_spec, open_fip }, + [SOC_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_config_uuid_spec, + open_fip + }, + [TOS_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_config_uuid_spec, + open_fip + }, + [NT_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_config_uuid_spec, + open_fip + }, #if TRUSTED_BOARD_BOOT [TRUSTED_BOOT_FW_CERT_ID] = { &fip_dev_handle,