ARM Platforms: Load HW_CONFIG in BL2

The patch adds the necessary changes to load HW_CONFIG in BL2 for
ARM Platforms :

1. The load address of HW_CONFIG is specified via the `hw_config_addr`
property in TB_FW_CONFIG is loaded by BL1. The `hw_config_max_size`
property defines the maximum size to be expected for the HW_CONFIG.
The `arm_dyn_cfg_helpers.c` and corresponding header implements
utility functions to parse these DT properties defined.
The `arm_dyn_cfg.c` implements wrappers to these helpers to enable
them to be invoked from ARM platform layer.

2. `HW_CONFIG` is added to the `bl2_mem_params_descs[]` array which is
the list of images to be loaded by BL2.

3. The `libfdt` sources are now included when BL2 is built

4. A new helper `populate_next_bl_params_config()` is introduced in
desc_image_load.c to populate the subsequent executable BL images
with the `hw_config` and the corresponding `fw_config` if available.
The `plat_get_next_bl_params()` API for ARM platforms is modified to
invoke this new helper.

5. The implementation of `bl2_early_platform_setup2()` is modified to
consider `arg0` as well in addition to `arg1` passed from BL1.

6. Bump up the BL2 size for Juno to accommodate the inclusion of libfdt.

Change-Id: I80f1554adec41753e0d179a5237364f04fe13a3f
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
This commit is contained in:
Soby Mathew 2018-01-15 14:45:33 +00:00
parent c228956afa
commit cab0b5b045
16 changed files with 294 additions and 15 deletions

View File

@ -190,3 +190,65 @@ bl_params_t *get_next_bl_params_from_mem_params_desc(void)
return &next_bl_params;
}
/*******************************************************************************
* This function populates the entry point information with the corresponding
* config file for all executable BL images described in bl_params.
******************************************************************************/
void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params)
{
bl_params_node_t *params_node;
unsigned int fw_config_id;
uintptr_t hw_config_base = 0, fw_config_base;
bl_mem_params_node_t *mem_params;
assert(bl2_to_next_bl_params);
/*
* Get the `bl_mem_params_node_t` corresponding to HW_CONFIG
* if available.
*/
mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
if (mem_params != NULL)
hw_config_base = mem_params->image_info.image_base;
for (params_node = bl2_to_next_bl_params->head; params_node != NULL;
params_node = params_node->next_params_info) {
fw_config_base = 0;
switch (params_node->image_id) {
case BL31_IMAGE_ID:
fw_config_id = SOC_FW_CONFIG_ID;
break;
case BL32_IMAGE_ID:
fw_config_id = TOS_FW_CONFIG_ID;
break;
case BL33_IMAGE_ID:
fw_config_id = NT_FW_CONFIG_ID;
break;
default:
fw_config_id = INVALID_IMAGE_ID;
break;
}
if (fw_config_id != INVALID_IMAGE_ID) {
mem_params = get_bl_mem_params_node(fw_config_id);
if (mem_params != NULL)
fw_config_base = mem_params->image_info.image_base;
}
/*
* Pass hw and tb_fw config addresses to next images. NOTE - for
* EL3 runtime images (BL31 for AArch64 and BL32 for AArch32),
* arg0 is already used by generic code.
*/
if (params_node == bl2_to_next_bl_params->head) {
params_node->ep_info->args.arg1 = fw_config_base;
params_node->ep_info->args.arg2 = hw_config_base;
} else {
params_node->ep_info->args.arg0 = fw_config_base;
params_node->ep_info->args.arg1 = hw_config_base;
}
}
}

View File

@ -33,7 +33,7 @@ int get_bl_params_node_index(unsigned int image_id);
bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id);
bl_load_info_t *get_bl_load_info_from_mem_params_desc(void);
bl_params_t *get_next_bl_params_from_mem_params_desc(void);
void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params);
#endif /* LOAD_IMAGE_V2 */
#endif /* __DESC_IMAGE_LOAD_H__ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __ARM_DYN_CFG_HELPERS_H__
#define __ARM_DYN_CFG_HELPERS_H__
#include <stdint.h>
/* 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_tb_fw_cfg_init(void *dtb, int *node);
#endif /* __ARM_DYN_CFG_HELPERS_H__ */

View File

@ -19,6 +19,7 @@
struct bl31_params;
struct meminfo;
struct image_info;
struct bl_params;
#define ARM_CASSERT_MMAP \
CASSERT((ARRAY_SIZE(plat_arm_mmap) + ARM_BL_REGIONS) \
@ -138,7 +139,7 @@ void arm_bl1_platform_setup(void);
void arm_bl1_plat_arch_setup(void);
/* BL2 utility functions */
void arm_bl2_early_platform_setup(struct meminfo *mem_layout);
void arm_bl2_early_platform_setup(uintptr_t tb_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);
@ -180,6 +181,8 @@ int arm_io_is_toc_valid(void);
/* Utility functions for Dynamic Config */
void arm_load_tb_fw_config(void);
void arm_bl2_set_tb_cfg_addr(void *dtb);
void arm_bl2_dyn_cfg_init(void);
/*
* Mandatory functions required in ARM standard platforms

View File

@ -14,7 +14,7 @@
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
{
arm_bl2_early_platform_setup((meminfo_t *)arg1);
arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
/* Initialize the platform config for future decision making */
fvp_config_setup();

View File

@ -19,6 +19,7 @@
#define BL32_IMAGE_NAME "bl32.bin"
#define BL33_IMAGE_NAME "bl33.bin"
#define TB_FW_CONFIG_NAME "fvp_tb_fw_config.dtb"
#define HW_CONFIG_NAME "hw_config.dtb"
#if TRUSTED_BOARD_BOOT
#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt"
@ -56,6 +57,10 @@ static const io_file_spec_t sh_file_spec[] = {
.path = TB_FW_CONFIG_NAME,
.mode = FOPEN_MODE_RB
},
[HW_CONFIG_ID] = {
.path = HW_CONFIG_NAME,
.mode = FOPEN_MODE_RB
},
#if TRUSTED_BOARD_BOOT
[TRUSTED_BOOT_FW_CERT_ID] = {
.path = TRUSTED_BOOT_FW_CERT_NAME,

View File

@ -110,12 +110,12 @@
*/
#if TRUSTED_BOARD_BOOT
#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
# define PLAT_ARM_MAX_BL2_SIZE 0x1E000
# define PLAT_ARM_MAX_BL2_SIZE 0x1F000
#else
# define PLAT_ARM_MAX_BL2_SIZE 0x1A000
# define PLAT_ARM_MAX_BL2_SIZE 0x1B000
#endif
#else
# define PLAT_ARM_MAX_BL2_SIZE 0xC000
# define PLAT_ARM_MAX_BL2_SIZE 0xD000
#endif
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -54,7 +54,15 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
.next_handoff_image_id = BL33_IMAGE_ID,
},
/* Fill HW_CONFIG related information if it exists */
{
.image_id = HW_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,
},
/* Fill BL33 related information */
{
.image_id = BL33_IMAGE_ID,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -82,7 +82,15 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
.next_handoff_image_id = BL33_IMAGE_ID,
# endif
},
/* Fill HW_CONFIG related information */
{
.image_id = HW_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,
},
# ifdef BL32_BASE
/* Fill BL32 related information */
{

View File

@ -181,7 +181,7 @@ struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
* in x0. This memory layout is sitting at the base of the free trusted SRAM.
* Copy it to a safe location before its reclaimed by later BL2 functionality.
******************************************************************************/
void arm_bl2_early_platform_setup(meminfo_t *mem_layout)
void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, meminfo_t *mem_layout)
{
/* Initialize the console to provide early debug support */
console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
@ -192,11 +192,17 @@ void arm_bl2_early_platform_setup(meminfo_t *mem_layout)
/* Initialise the IO layer and register platform IO devices */
plat_arm_io_setup();
#if LOAD_IMAGE_V2
if (tb_fw_config != 0)
arm_bl2_set_tb_cfg_addr((void *)tb_fw_config);
#endif
}
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
{
arm_bl2_early_platform_setup((meminfo_t *)arg1);
arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
generic_delay_timer_init();
}
@ -205,6 +211,10 @@ void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_
*/
void arm_bl2_platform_setup(void)
{
#if LOAD_IMAGE_V2
arm_bl2_dyn_cfg_init();
#endif
/* Initialize the secure environment */
plat_arm_security_setup();

View File

@ -152,6 +152,13 @@ BL2_SOURCES += drivers/delay_timer/delay_timer.c \
plat/arm/common/arm_bl2_setup.c \
plat/arm/common/arm_io_storage.c
# Add `libfdt` and Arm common helpers required for Dynamic Config
include lib/libfdt/libfdt.mk
BL2_SOURCES += plat/arm/common/arm_dyn_cfg.c \
plat/arm/common/arm_dyn_cfg_helpers.c \
common/fdt_wrappers.c \
${LIBFDT_SRCS}
ifeq (${BL2_AT_EL3},1)
BL2_SOURCES += plat/arm/common/arm_bl2_el3_setup.c
endif

View File

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arm_dyn_cfg_helpers.h>
#include <assert.h>
#include <debug.h>
#include <desc_image_load.h>
@ -14,6 +15,9 @@
#if LOAD_IMAGE_V2
/* Variable to store the address to TB_FW_CONFIG passed from BL1 */
static void *tb_fw_cfg_dtb;
/*
* Helper function to load TB_FW_CONFIG and populate the load information to
* arg0 of BL2 entrypoint info.
@ -51,4 +55,54 @@ void arm_load_tb_fw_config(void)
(void *) config_base);
}
/*
* BL2 utility function to set the address of TB_FW_CONFIG passed from BL1.
*/
void arm_bl2_set_tb_cfg_addr(void *dtb)
{
assert(dtb);
tb_fw_cfg_dtb = dtb;
}
/*
* 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.
*/
void arm_bl2_dyn_cfg_init(void)
{
int err = 0;
int tb_fw_node;
bl_mem_params_node_t *hw_cfg_mem_params = NULL;
if (tb_fw_cfg_dtb == NULL) {
VERBOSE("No TB_FW_CONFIG specified\n");
return;
}
err = arm_dyn_tb_fw_cfg_init((void *)tb_fw_cfg_dtb, &tb_fw_node);
if (err < 0) {
ERROR("Invalid TB_FW_CONFIG passed from BL1\n");
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;
}
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;
}
/* Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from HW_CONFIG node */
hw_cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
}
#endif /* LOAD_IMAGE_V2 */

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <desc_image_load.h>
#include <fdt_wrappers.h>
#include <libfdt.h>
/*******************************************************************************
* 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
*
* 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
* is successful.
* uint32_t *hw_config_size - Returns the `hw_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 err;
assert(dtb);
assert(hw_config_addr);
assert(hw_config_size);
/* Check if the pointer to DT is correct */
assert(fdt_check_header(dtb) == 0);
/* 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);
if (err < 0) {
WARN("Read cell failed for hw_config_addr\n");
return -1;
}
err = fdtw_read_cells(dtb, node, "hw_config_max_size", 1,
(void *) hw_config_size);
if (err < 0) {
WARN("Read cell failed for hw_config_max_size\n");
return -1;
}
VERBOSE("Dyn cfg: Read hw_config address from TB_FW_CONFIG 0x%p %p\n",
hw_config_addr, hw_config_size);
return 0;
}
/*******************************************************************************
* Validate the tb_fw_config is a valid DTB file and returns the node offset
* to "arm,tb_fw" property.
* Arguments:
* void *dtb - pointer to the TB_FW_CONFIG in memory
* int *node - Returns the node offset to "arm,tb_fw" property if found.
*
* Returns 0 on success and -1 on error.
******************************************************************************/
int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
{
assert(dtb);
assert(node);
/* Check if the pointer to DT is correct */
if (fdt_check_header(dtb) != 0) {
WARN("Invalid DTB file passed as TB_FW_CONFIG\n");
return -1;
}
/* Assert the node offset point to "arm,tb_fw" compatible property */
*node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
if (*node < 0) {
WARN("The compatible property `arm,tb_fw` not found in the config\n");
return -1;
}
VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -7,6 +7,7 @@
#include <arm_def.h>
#include <bl_common.h>
#include <desc_image_load.h>
#include <plat_arm.h>
#include <platform.h>
@ -37,5 +38,8 @@ bl_load_info_t *plat_get_bl_image_load_info(void)
******************************************************************************/
bl_params_t *plat_get_next_bl_params(void)
{
return get_next_bl_params_from_mem_params_desc();
bl_params_t *next_bl_params = get_next_bl_params_from_mem_params_desc();
populate_next_bl_params_config(next_bl_params);
return next_bl_params;
}

View File

@ -57,6 +57,10 @@ static const io_uuid_spec_t tb_fw_config_uuid_spec = {
.uuid = UUID_TB_FW_CONFIG,
};
static const io_uuid_spec_t hw_config_uuid_spec = {
.uuid = UUID_HW_CONFIG,
};
#if TRUSTED_BOARD_BOOT
static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
.uuid = UUID_TRUSTED_BOOT_FW_CERT,
@ -156,6 +160,11 @@ static const struct plat_io_policy policies[] = {
(uintptr_t)&tb_fw_config_uuid_spec,
open_fip
},
[HW_CONFIG_ID] = {
&fip_dev_handle,
(uintptr_t)&hw_config_uuid_spec,
open_fip
},
#if TRUSTED_BOARD_BOOT
[TRUSTED_BOOT_FW_CERT_ID] = {
&fip_dev_handle,