Merge pull request #1554 from jts-arm/mbed

Mbed TLS shared heap
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index de7b5db..84f4c9d 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -1055,7 +1055,7 @@
 to the next BL image, when LOAD\_IMAGE\_V2 is enabled.
 
 Function : plat\_log\_get\_prefix()
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ::
 
@@ -1066,9 +1066,32 @@
 prepended to all the log output from TF-A. The `log_level` (argument) will
 correspond to one of the standard log levels defined in debug.h. The platform
 can override the common implementation to define a different prefix string for
-the log output.  The implementation should be robust to future changes that
+the log output. The implementation should be robust to future changes that
 increase the number of log levels.
 
+Function : plat\_get\_mbedtls\_heap()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Arguments : void **heap_addr, size_t *heap_size
+    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.
+
+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/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c
index 7095fde..dbf45ba 100644
--- a/drivers/auth/mbedtls/mbedtls_common.c
+++ b/drivers/auth/mbedtls/mbedtls_common.c
@@ -4,26 +4,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
 #include <debug.h>
-#include <stdlib.h>
-#include <stdio.h>
-
 /* mbed TLS headers */
 #include <mbedtls/memory_buffer_alloc.h>
 #include <mbedtls/platform.h>
-#include <mbedtls_config.h>
 #include <mbedtls_common.h>
-
-/*
- * mbed TLS heap
- */
-#if (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA) \
-	|| (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
-#define MBEDTLS_HEAP_SIZE		(13*1024)
-#elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA)
-#define MBEDTLS_HEAP_SIZE		(7*1024)
-#endif
-static unsigned char heap[MBEDTLS_HEAP_SIZE];
+#include <mbedtls_config.h>
+#include <platform.h>
+#include <stddef.h>
 
 static void cleanup(void)
 {
@@ -37,13 +26,25 @@
 void mbedtls_init(void)
 {
 	static int ready;
+	void *heap_addr;
+	size_t heap_size = 0;
+	int err;
 
 	if (!ready) {
 		if (atexit(cleanup))
 			panic();
 
+		err = plat_get_mbedtls_heap(&heap_addr, &heap_size);
+
+		/* Ensure heap setup is proper */
+		if (err < 0) {
+			ERROR("Mbed TLS failed to get a heap\n");
+			panic();
+		}
+		assert(heap_size >= TF_MBEDTLS_HEAP_SIZE);
+
 		/* Initialize the mbed TLS heap */
-		mbedtls_memory_buffer_alloc_init(heap, MBEDTLS_HEAP_SIZE);
+		mbedtls_memory_buffer_alloc_init(heap_addr, heap_size);
 
 #ifdef MBEDTLS_PLATFORM_SNPRINTF_ALT
 		mbedtls_platform_set_snprintf(snprintf);
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
index f8f2608..59aeea9 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config.h
+++ b/include/drivers/auth/mbedtls/mbedtls_config.h
@@ -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
  */
@@ -95,4 +95,16 @@
 #include "mbedtls/check_config.h"
 #endif
 
+/*
+ * Determine Mbed TLS heap size
+ * 13312 = 13*1024
+ * 7168 = 7*1024
+ */
+#if (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA) \
+	|| (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
+#define TF_MBEDTLS_HEAP_SIZE		U(13312)
+#elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA)
+#define TF_MBEDTLS_HEAP_SIZE		U(7168)
+#endif
+
 #endif /* __MBEDTLS_CONFIG_H__ */
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index a388ed9..86c8512 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -102,7 +102,7 @@
  * little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE		0x1F000
+# define PLAT_ARM_MAX_BL2_SIZE		0x1C000
 #else
 # define PLAT_ARM_MAX_BL2_SIZE		0x11000
 #endif
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index ea9d811..c499417 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 382ec60..cb17c95 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 1af4dd1..0770c0e 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -223,6 +223,8 @@
 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/include/plat/common/platform.h b/include/plat/common/platform.h
index dae9589..e0297ae 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -103,6 +103,7 @@
 const char *plat_log_get_prefix(unsigned int log_level);
 void bl2_plat_preload_setup(void);
 int plat_try_next_boot_source(void);
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
 
 /*******************************************************************************
  * Mandatory BL1 functions
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 28299f6..ce58938 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 af258b0..1b0c764 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 @@
 					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 @@
 #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 @@
 	}
 #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 d435553..a4d2b44 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -149,7 +149,11 @@
 	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 b9c73f0..f2570a8 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 @@
 		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 5a7e20a..e610903 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 @@
 	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 */
diff --git a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts b/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts
index 0bb0a94..315fa69 100644
--- a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts
+++ b/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts
@@ -11,4 +11,15 @@
 	compatible = "arm,tb_fw";
 	hw_config_addr = <0x0 0xFEF00000>;
 	hw_config_max_size = <0x0100000>;
+	/*
+	 * 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/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index 6aa76ef..0a7e319 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -6,6 +6,7 @@
 
 #include <arm_def.h>
 #include <arm_spm_def.h>
+#include <assert.h>
 #include <bl_common.h>
 #include <ccn.h>
 #include <debug.h>
@@ -64,6 +65,9 @@
 #if ENABLE_SPM
 	ARM_SP_IMAGE_MMAP,
 #endif
+#if TRUSTED_BOARD_BOOT && LOAD_IMAGE_V2 && !BL2_AT_EL3
+	ARM_MAP_BL1_RW,
+#endif
 	{0}
 };
 #endif
@@ -143,3 +147,13 @@
 	return &plat_arm_secure_partition_boot_info;
 }
 #endif /* ENABLE_SPM && defined(IMAGE_BL31) */
+
+#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/css/sgm/fdts/sgm_tb_fw_config.dts b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
index 9502549..d481018 100644
--- a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
+++ b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
@@ -12,5 +12,16 @@
 		compatible = "arm,tb_fw";
 		hw_config_addr = <0x0 0x83000000>;
 		hw_config_max_size = <0x01000000>;
+		/*
+		 * 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/css/sgm/sgm_mmap_config.c b/plat/arm/css/sgm/sgm_mmap_config.c
index 009ee64..8a4a8ab 100644
--- a/plat/arm/css/sgm/sgm_mmap_config.c
+++ b/plat/arm/css/sgm/sgm_mmap_config.c
@@ -43,6 +43,9 @@
 #ifdef SPD_opteed
 	ARM_OPTEE_PAGEABLE_LOAD_MEM,
 #endif
+#if TRUSTED_BOARD_BOOT && LOAD_IMAGE_V2 && !BL2_AT_EL3
+	ARM_MAP_BL1_RW,
+#endif
 	{0}
 };
 #endif
diff --git a/plat/arm/css/sgm/sgm_plat_config.c b/plat/arm/css/sgm/sgm_plat_config.c
index 809edf6..97b16a8 100644
--- a/plat/arm/css/sgm/sgm_plat_config.c
+++ b/plat/arm/css/sgm/sgm_plat_config.c
@@ -67,3 +67,13 @@
 	assert(css_plat_info != NULL);
 	return css_plat_info;
 }
+
+#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/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index b471a7e..95d73e3 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -9,6 +9,9 @@
 #include <bl_common.h>
 #include <debug.h>
 #include <errno.h>
+#if TRUSTED_BOARD_BOOT
+#include <mbedtls_config.h>
+#endif
 #include <platform.h>
 
 /*
@@ -21,6 +24,7 @@
 #pragma weak bl2_plat_handle_pre_image_load
 #pragma weak bl2_plat_handle_post_image_load
 #pragma weak plat_try_next_boot_source
+#pragma weak plat_get_mbedtls_heap
 
 void bl2_el3_plat_prepare_exit(void)
 {
@@ -66,3 +70,22 @@
 	bl2_early_platform_setup((void *)arg1);
 }
 #endif
+
+
+#if TRUSTED_BOARD_BOOT
+/*
+ * The following default implementation of the function simply returns the
+ * by-default allocated heap.
+ */
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	static unsigned char heap[TF_MBEDTLS_HEAP_SIZE];
+
+	assert(heap_addr != NULL);
+	assert(heap_size != NULL);
+
+	*heap_addr = heap;
+	*heap_size = sizeof(heap);
+	return 0;
+}
+#endif /* TRUSTED_BOARD_BOOT */