aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/porting-guide.rst25
-rw-r--r--include/plat/arm/common/arm_def.h11
-rw-r--r--include/plat/arm/common/arm_dyn_cfg_helpers.h7
-rw-r--r--include/plat/arm/common/plat_arm.h2
-rw-r--r--plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts11
-rw-r--r--plat/arm/board/fvp/fvp_common.c17
-rw-r--r--plat/arm/common/arm_bl1_setup.c6
-rw-r--r--plat/arm/common/arm_dyn_cfg.c92
-rw-r--r--plat/arm/common/arm_dyn_cfg_helpers.c101
9 files changed, 255 insertions, 17 deletions
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 83fac2860..84f4c9dfa 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -1075,21 +1075,22 @@ Function : plat\_get\_mbedtls\_heap()
::
Arguments : void **heap_addr, size_t *heap_size
- Return : int
+ Return : int
This function is invoked during Mbed TLS library initialisation to get
a heap, by means of a starting address and a size. This heap will then be used
-internally by the Mbed TLS library. The heap is requested from the current
-BL stage, i.e. the current BL image inside which Mbed TLS is used.
-
-The default implementation allocates a new heap every time Mbed TLS gets
-initialised. This means that a new heap is statically allocated inside
-every image (i.e. every BL stage) that utilises Mbed TLS. In the default
-implementation, this function returns the address and size of this default
-heap. However, by overriding the default implementation, platforms have the ability
-to optimise memory usage.
-
-On success it returns 0 and a negative error code otherwise.
+internally by the Mbed TLS library. The heap is requested from the current BL
+stage, i.e. the current BL image inside which Mbed TLS is used.
+
+In the default implementation a heap is statically allocated inside every image
+(i.e. every BL stage) that utilises Mbed TLS. So, in this case, the function
+simply returns the address and size of this "pre-allocated" heap. However, by
+overriding the default implementation, platforms have the potential to optimise
+memory usage. For example, on some Arm platforms, the Mbed TLS heap is shared
+between BL1 and BL2 stages and, thus, the necessary space is not reserved
+twice.
+
+On success the function should return 0 and a negative error code otherwise.
Modifications specific to a Boot Loader stage
---------------------------------------------
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index ea9d811c2..c4994173a 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -242,6 +242,17 @@
MT_MEMORY | MT_RW | MT_SECURE)
/*
+ * Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
+ * share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides
+ * in the BL1 RW region. Hence, BL2 needs access to the BL1 RW region in order
+ * to be able to access the heap.
+ */
+#define ARM_MAP_BL1_RW MAP_REGION_FLAT( \
+ BL1_RW_BASE, \
+ BL1_RW_LIMIT - BL1_RW_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
* If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
* otherwise one region is defined containing both.
*/
diff --git a/include/plat/arm/common/arm_dyn_cfg_helpers.h b/include/plat/arm/common/arm_dyn_cfg_helpers.h
index 382ec6011..cb17c95f2 100644
--- a/include/plat/arm/common/arm_dyn_cfg_helpers.h
+++ b/include/plat/arm/common/arm_dyn_cfg_helpers.h
@@ -6,12 +6,17 @@
#ifndef __ARM_DYN_CFG_HELPERS_H__
#define __ARM_DYN_CFG_HELPERS_H__
+#include <stddef.h>
#include <stdint.h>
-/* Function declaration */
+/* Function declarations */
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);
+int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr,
+ size_t *heap_size);
+int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr,
+ size_t heap_size);
#endif /* __ARM_DYN_CFG_HELPERS_H__ */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 1af4dd1ac..0770c0ec5 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -223,6 +223,8 @@ int arm_io_is_toc_valid(void);
void arm_load_tb_fw_config(void);
void arm_bl2_set_tb_cfg_addr(void *dtb);
void arm_bl2_dyn_cfg_init(void);
+void arm_bl1_set_mbedtls_heap(void);
+int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
/*
* Mandatory functions required in ARM standard platforms
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 28299f65a..ce589385c 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -26,5 +26,16 @@
tos_fw_config_max_size = <0x200>;
nt_fw_config_addr = <0x0 0x80000000>;
nt_fw_config_max_size = <0x200>;
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
};
};
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index af258b060..1b0c764ff 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -15,6 +15,7 @@
#include <gicv2.h>
#include <mmio.h>
#include <plat_arm.h>
+#include <platform.h>
#include <secure_partition.h>
#include <v2m_def.h>
#include "../fvp_def.h"
@@ -50,7 +51,6 @@ arm_config_t arm_config;
DEVICE2_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
-
/*
* Table of memory regions for various BL stages to map using the MMU.
* This doesn't include Trusted SRAM as arm_setup_page_tables() already
@@ -92,7 +92,10 @@ const mmap_region_t plat_arm_mmap[] = {
#if TRUSTED_BOARD_BOOT
/* To access the Root of Trust Public Key registers. */
MAP_DEVICE2,
-#endif
+#if LOAD_IMAGE_V2 && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif /* LOAD_IMAGE_V2 && !BL2_AT_EL3 */
+#endif /* TRUSTED_BOARD_BOOT */
#if ENABLE_SPM
ARM_SP_IMAGE_MMAP,
#endif
@@ -395,3 +398,13 @@ void fvp_interconnect_disable(void)
}
#endif
}
+
+#if TRUSTED_BOARD_BOOT && LOAD_IMAGE_V2
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index d43555382..a4d2b44c1 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -149,7 +149,11 @@ void arm_bl1_platform_setup(void)
plat_arm_io_setup();
#if LOAD_IMAGE_V2
arm_load_tb_fw_config();
-#endif
+#if TRUSTED_BOARD_BOOT
+ /* Share the Mbed TLS heap info with other images */
+ arm_bl1_set_mbedtls_heap();
+#endif /* TRUSTED_BOARD_BOOT */
+#endif /* LOAD_IMAGE_V2 */
/*
* Allow access to the System counter timer module and program
* counter frequency for non secure images during FWU
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index b9c73f0b0..f2570a84c 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -8,6 +8,9 @@
#include <assert.h>
#include <debug.h>
#include <desc_image_load.h>
+#if TRUSTED_BOARD_BOOT
+#include <mbedtls_config.h>
+#endif
#include <plat_arm.h>
#include <platform.h>
#include <platform_def.h>
@@ -16,9 +19,94 @@
#if LOAD_IMAGE_V2
-/* Variable to store the address to TB_FW_CONFIG passed from BL1 */
+/* Variable to store the address of TB_FW_CONFIG file */
static void *tb_fw_cfg_dtb;
+
+#if TRUSTED_BOARD_BOOT
+
+static void *mbedtls_heap_addr;
+static size_t mbedtls_heap_size;
+
+/*
+ * This function is the implementation of the shared Mbed TLS heap between
+ * BL1 and BL2 for Arm platforms. The shared heap address is passed from BL1
+ * to BL2 with a pointer. This pointer resides inside the TB_FW_CONFIG file
+ * which is a DTB.
+ *
+ * This function is placed inside an #if directive for the below reasons:
+ * - To allocate space for the Mbed TLS heap --only if-- Trusted Board Boot
+ * is enabled.
+ * - This implementation requires the DTB to be present so that BL1 has a
+ * mechanism to pass the pointer to BL2. If LOAD_IMAGE_V2=0 then
+ * TB_FW_CONFIG is not present, which means that this implementation
+ * cannot be applied.
+ */
+int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+#if defined(IMAGE_BL1) || BL2_AT_EL3
+
+ /* If in BL1 or BL2_AT_EL3 define a heap */
+ static unsigned char heap[TF_MBEDTLS_HEAP_SIZE];
+
+ *heap_addr = heap;
+ *heap_size = sizeof(heap);
+ mbedtls_heap_addr = heap;
+ mbedtls_heap_size = sizeof(heap);
+
+#elif defined(IMAGE_BL2)
+
+ int err;
+
+ /* If in BL2, retrieve the already allocated heap's info from DTB */
+ err = arm_get_dtb_mbedtls_heap_info(tb_fw_cfg_dtb, heap_addr,
+ heap_size);
+ if (err < 0) {
+ ERROR("BL2: unable to retrieve shared Mbed TLS heap "
+ "information from DTB\n");
+ panic();
+ }
+#endif
+
+ return 0;
+}
+
+/*
+ * Puts the shared Mbed TLS heap information to the DTB.
+ * Executed only from BL1.
+ */
+void arm_bl1_set_mbedtls_heap(void)
+{
+ int err;
+
+ /*
+ * If tb_fw_cfg_dtb==NULL then DTB is not present for the current
+ * platform. As such, we don't attempt to write to the DTB at all.
+ *
+ * If mbedtls_heap_addr==NULL, then it means we are using the default
+ * heap implementation. As such, BL2 will have its own heap for sure
+ * and hence there is no need to pass any information to the DTB.
+ *
+ * In the latter case, if we still wanted to write in the DTB the heap
+ * information, we would need to call plat_get_mbedtls_heap to retrieve
+ * the default heap's address and size.
+ */
+ if ((tb_fw_cfg_dtb != NULL) && (mbedtls_heap_addr != NULL)) {
+ err = arm_set_dtb_mbedtls_heap_info(tb_fw_cfg_dtb,
+ mbedtls_heap_addr, mbedtls_heap_size);
+ if (err < 0) {
+ ERROR("BL1: unable to write shared Mbed TLS heap "
+ "information to DTB\n");
+ panic();
+ }
+ }
+}
+
+#endif /* TRUSTED_BOARD_BOOT */
+
/*
* Helper function to load TB_FW_CONFIG and populate the load information to
* arg0 of BL2 entrypoint info.
@@ -45,7 +133,9 @@ void arm_load_tb_fw_config(void)
return;
}
+ /* At this point we know that a DTB is indeed available */
config_base = arm_tb_fw_info.image_info.image_base;
+ tb_fw_cfg_dtb = (void *)config_base;
/* The BL2 ep_info arg0 is modified to point to TB_FW_CONFIG */
image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index 5a7e20ac8..e61090384 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -11,6 +11,8 @@
#include <libfdt.h>
#include <plat_arm.h>
+#define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr"
+#define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"
typedef struct config_load_info_prop {
unsigned int config_id;
@@ -164,3 +166,102 @@ int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
return 0;
}
+
+
+#if TRUSTED_BOARD_BOOT && LOAD_IMAGE_V2
+/*
+ * Reads and returns the Mbed TLS shared heap information from the DTB.
+ * This function is supposed to be called *only* when a DTB is present.
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * -1 = error. In this case the values of heap_addr, heap_size should be
+ * considered as garbage by the caller.
+ */
+int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr,
+ size_t *heap_size)
+{
+ int err, dtb_root;
+
+ /* Verify the DTB is valid and get the root node */
+ err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
+ if (err < 0) {
+ ERROR("%s: Invalid TB_FW_CONFIG. Cannot retrieve Mbed TLS "
+ "heap information from DTB\n", __func__);
+ return -1;
+ }
+
+ /* Retrieve the Mbed TLS heap details from the DTB */
+ err = fdtw_read_cells(dtb, dtb_root,
+ DTB_PROP_MBEDTLS_HEAP_ADDR, 2, heap_addr);
+ if (err < 0) {
+ ERROR("%s: error while reading %s from DTB\n", __func__,
+ DTB_PROP_MBEDTLS_HEAP_ADDR);
+ return -1;
+ }
+ err = fdtw_read_cells(dtb, dtb_root,
+ DTB_PROP_MBEDTLS_HEAP_SIZE, 1, heap_size);
+ if (err < 0) {
+ ERROR("%s: error while reading %s from DTB\n", __func__,
+ DTB_PROP_MBEDTLS_HEAP_SIZE);
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * This function writes the Mbed TLS heap address and size in the DTB. When it
+ * is called, it is guaranteed that a DTB is available. However it is not
+ * guaranteed that the shared Mbed TLS heap implementation is used. Thus we
+ * return error code from here and it's the responsibility of the caller to
+ * determine the action upon error.
+ *
+ * This function is supposed to be called only by BL1.
+ *
+ * Returns:
+ * 0 = success
+ * 1 = error
+ */
+int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size)
+{
+ int err, dtb_root;
+
+ /*
+ * Verify that the DTB is valid, before attempting to write to it,
+ * and get the DTB root node.
+ */
+ err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
+ if (err < 0) {
+ ERROR("%s: Invalid TB_FW_CONFIG loaded. Unable to get "
+ "root node\n", __func__);
+ return -1;
+ }
+
+ /*
+ * Write the heap address and size in the DTB.
+ *
+ * NOTE: The variables heap_addr and heap_size are corrupted
+ * by the "fdtw_write_inplace_cells" function. After the
+ * function calls they must NOT be reused.
+ */
+ err = fdtw_write_inplace_cells(dtb, dtb_root,
+ DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
+ if (err < 0) {
+ ERROR("%s: unable to write DTB property %s\n",
+ __func__, DTB_PROP_MBEDTLS_HEAP_ADDR);
+ return -1;
+ }
+
+ err = fdtw_write_inplace_cells(dtb, dtb_root,
+ DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
+ if (err < 0) {
+ ERROR("%s: unable to write DTB property %s\n",
+ __func__, DTB_PROP_MBEDTLS_HEAP_SIZE);
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* TRUSTED_BOARD_BOOT && LOAD_IMAGE_V2 */