feat(drtm): add platform functions for DRTM

Added platform hooks to retrieve DRTM features and
address map.
Additionally, implemented these hooks for the FVP platform.

Signed-off-by: John Powell <john.powell@arm.com>
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
Change-Id: I5621cc9807ffff8139ae8876250147f7b2c76759
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index ec70627..f435815 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -148,8 +148,9 @@
 endif
 
 ifeq (${DRTM_SUPPORT},1)
-BL31_SOURCES		+=	services/std_svc/drtm/drtm_main.c	\
-				services/std_svc/drtm/drtm_dma_prot.c	\
+BL31_SOURCES		+=	services/std_svc/drtm/drtm_main.c		\
+				services/std_svc/drtm/drtm_dma_prot.c		\
+				services/std_svc/drtm/drtm_res_address_map.c	\
 				${MBEDTLS_SOURCES}
 endif
 
diff --git a/include/lib/xlat_tables/xlat_tables_compat.h b/include/lib/xlat_tables/xlat_tables_compat.h
index 90768db..5f28195 100644
--- a/include/lib/xlat_tables/xlat_tables_compat.h
+++ b/include/lib/xlat_tables/xlat_tables_compat.h
@@ -1,11 +1,16 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#ifndef XLAT_TABLES_COMPAT_H
+#define XLAT_TABLES_COMPAT_H
+
 #if XLAT_TABLES_LIB_V2
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #else
 #include <lib/xlat_tables/xlat_tables.h>
 #endif
+
+#endif /* XLAT_TABLES_COMPAT_H */
diff --git a/include/plat/common/plat_drtm.h b/include/plat/common/plat_drtm.h
index 3c4e3d5..e9b8d6a 100644
--- a/include/plat/common/plat_drtm.h
+++ b/include/plat/common/plat_drtm.h
@@ -7,11 +7,57 @@
 #ifndef PLAT_DRTM_H
 #define PLAT_DRTM_H
 
+#include <stdint.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+
+typedef struct {
+	uint8_t max_num_mem_prot_regions;
+	uint8_t dma_protection_support;
+} plat_drtm_dma_prot_features_t;
+
+typedef struct {
+	bool tpm_based_hash_support;
+	uint32_t firmware_hash_algorithm;
+} plat_drtm_tpm_features_t;
+
+typedef struct {
+	uint64_t region_address;
+	uint64_t region_size_type;
+} __attribute__((packed)) drtm_mem_region_t;
+
+/*
+ * Memory region descriptor table structure as per DRTM beta0 section 3.13
+ * Table 11 MEMORY_REGION_DESCRIPTOR_TABLE
+ */
+typedef struct {
+	uint16_t revision;
+	uint16_t reserved;
+	uint32_t num_regions;
+	drtm_mem_region_t region[];
+} __attribute__((packed)) drtm_memory_region_descriptor_table_t;
+
+/* platform specific address map functions */
+const mmap_region_t *plat_get_addr_mmap(void);
+
 /* platform-specific DMA protection functions */
 bool plat_has_non_host_platforms(void);
 bool plat_has_unmanaged_dma_peripherals(void);
 unsigned int plat_get_total_smmus(void);
 void plat_enumerate_smmus(const uintptr_t **smmus_out,
 			  size_t *smmu_count_out);
+const plat_drtm_dma_prot_features_t *plat_drtm_get_dma_prot_features(void);
+uint64_t plat_drtm_dma_prot_get_max_table_bytes(void);
+
+/* platform-specific TPM functions */
+const plat_drtm_tpm_features_t *plat_drtm_get_tpm_features(void);
+
+/*
+ * TODO: Implement these functions as per the platform use case,
+ * as of now none of the platform uses these functions
+ */
+uint64_t plat_drtm_get_min_size_normal_world_dce(void);
+uint64_t plat_drtm_get_tcb_hash_table_size(void);
+uint64_t plat_drtm_get_imp_def_dlme_region_size(void);
+uint64_t plat_drtm_get_tcb_hash_features(void);
 
 #endif /* PLAT_DRTM_H */
diff --git a/include/services/drtm_svc.h b/include/services/drtm_svc.h
index 6845ace..890cdbb 100644
--- a/include/services/drtm_svc.h
+++ b/include/services/drtm_svc.h
@@ -66,6 +66,158 @@
 #define ARM_DRTM_FUNC_ID	U(0x0)
 #define ARM_DRTM_FEAT_ID	U(0x1)
 
+/*
+ * Definitions for DRTM features as per DRTM beta0 section 3.3,
+ * Table 6 DRTM_FEATURES
+ */
+#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT		U(33)
+#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK		ULL(0xF)
+#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT	ULL(0x1)
+
+#define ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT		U(32)
+#define ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK		ULL(0x1)
+#define ARM_DRTM_TPM_FEATURES_TPM_HASH_NOT_SUPPORTED	ULL(0x0)
+#define ARM_DRTM_TPM_FEATURES_TPM_HASH_SUPPORTED	ULL(0x1)
+
+#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT		U(0)
+#define ARM_DRTM_TPM_FEATURES_FW_HASH_MASK		ULL(0xFFFFFFFF)
+#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA256		ULL(0xB)
+#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA384		ULL(0xC)
+#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA512		ULL(0xD)
+
+#define ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT		U(32)
+#define ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK		ULL(0xFFFFFFFF)
+
+#define ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT	U(0)
+#define ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK	ULL(0xFFFFFFFF)
+
+#define ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT	U(8)
+#define ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK	ULL(0xF)
+
+#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT	U(0)
+#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK	ULL(0xFF)
+#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE	ULL(0x1)
+#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_REGION	ULL(0x2)
+
+#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT	U(0)
+#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK	ULL(0xFF)
+
+#define ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(reg, val)			\
+	do {								\
+		reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK \
+		<< ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT)) | (((val) & \
+		ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK) <<		\
+		ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT));		\
+	} while (false)
+
+#define ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(reg, val)			\
+	do {								\
+		reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK	\
+		<< ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT)) | (((val) &	\
+		ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK) <<			\
+		ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT));			\
+	} while (false)
+
+#define ARM_DRTM_TPM_FEATURES_SET_FW_HASH(reg, val)			\
+	do {								\
+		reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_FW_HASH_MASK	\
+		<< ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT)) | (((val) &	\
+		ARM_DRTM_TPM_FEATURES_FW_HASH_MASK) <<			\
+		ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT));			\
+	} while (false)
+
+#define ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(reg, val)			\
+	do {								\
+		reg = (((reg) & ~(ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK	\
+		<< ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT)) | (((val) &	\
+		ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK) <<			\
+		ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT));			\
+	} while (false)
+
+#define ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(reg, val)		\
+	do {								\
+		reg = (((reg) &						\
+		~(ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK <<	\
+		ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT)) |	\
+		(((val) & ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK) \
+		<< ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT));	\
+	} while (false)
+
+#define ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(reg, val)		\
+	do {								\
+		reg = (((reg) &						\
+		~(ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK <<	\
+		ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT)) |	\
+		(((val) & ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK)	\
+		<< ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT));	\
+	} while (false)
+
+#define ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(reg, val) \
+	do {								\
+		reg = (((reg) &						\
+		~(ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK <<	\
+		ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT)) |	\
+		(((val) & ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK)	\
+		<< ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT));	\
+	} while (false)
+
+#define ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(reg, val)		\
+	do {								\
+		reg = (((reg) &						\
+		~(ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK <<	\
+		ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT)) |	\
+		(((val) &						\
+		ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK) <<	\
+		ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT));	\
+	} while (false)
+
+/* Definitions for DRTM address map */
+#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT	U(55)
+#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK	ULL(0x3)
+#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_NC	ULL(0)
+#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WC	ULL(1)
+#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WT	ULL(2)
+#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WB	ULL(3)
+
+#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT	U(52)
+#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK	ULL(0x7)
+#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NORMAL	ULL(0)
+#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NCAR	ULL(1)
+#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_DEVICE	ULL(2)
+#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NV	ULL(3)
+#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_RSVD	ULL(4)
+
+#define ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT	U(0)
+#define ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK	ULL(0xFFFFFFFFFFFFF)
+
+#define ARM_DRTM_REGION_SIZE_TYPE_SET_CACHEABILITY(reg, val)		\
+	do {								\
+		reg = (((reg) &						\
+		~(ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK << 	\
+		ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT)) |	\
+		(((val) &						\
+		ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK) <<		\
+		ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT));		\
+	} while (false)
+
+#define ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE(reg, val)		\
+	do {								\
+		reg = (((reg) &						\
+		~(ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK <<		\
+		ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT)) |		\
+		(((val) & ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK)	\
+		<< ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT));	\
+	} while (false)
+
+#define ARM_DRTM_REGION_SIZE_TYPE_SET_4K_PAGE_NUM(reg, val)		\
+	do {								\
+		reg = (((reg) &						\
+		~(ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK <<		\
+		ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT)) |		\
+		(((val) & ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK)	\
+		<< ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT));	\
+	} while (false)
+
 /* Initialization routine for the DRTM service */
 int drtm_setup(void);
 
diff --git a/plat/arm/board/fvp/fvp_drtm_dma_prot.c b/plat/arm/board/fvp/fvp_drtm_dma_prot.c
index ec9cd7a..38ff7fe 100644
--- a/plat/arm/board/fvp/fvp_drtm_dma_prot.c
+++ b/plat/arm/board/fvp/fvp_drtm_dma_prot.c
@@ -58,3 +58,19 @@
 		*smmu_count_out = 0;
 	}
 }
+
+/* DRTM DMA Protection Features */
+static const plat_drtm_dma_prot_features_t dma_prot_features = {
+	.max_num_mem_prot_regions = 0, /* No protection regions are present */
+	.dma_protection_support = 0x1 /* Complete DMA protection only */
+};
+
+const plat_drtm_dma_prot_features_t *plat_drtm_get_dma_prot_features(void)
+{
+	return &dma_prot_features;
+}
+
+uint64_t plat_drtm_dma_prot_get_max_table_bytes(void)
+{
+	return 0U;
+}
diff --git a/plat/arm/board/fvp/fvp_drtm_measurement.c b/plat/arm/board/fvp/fvp_drtm_measurement.c
new file mode 100644
index 0000000..4fbedd8
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_drtm_measurement.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* DRTM TPM Features */
+static const plat_drtm_tpm_features_t tpm_features = {
+	/* No TPM-based hashing supported. */
+	.tpm_based_hash_support = false,
+
+	/* Set to decided algorithm by Event Log driver */
+	.firmware_hash_algorithm = TPM_ALG_ID
+
+};
+
+const plat_drtm_tpm_features_t *plat_drtm_get_tpm_features(void)
+{
+	return &tpm_features;
+}
diff --git a/plat/arm/board/fvp/fvp_drtm_stub.c b/plat/arm/board/fvp/fvp_drtm_stub.c
new file mode 100644
index 0000000..e2bc516
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_drtm_stub.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <stdint.h>
+
+#include <services/drtm_svc.h>
+
+/*
+ * This file contains DRTM platform functions which don't really do anything on
+ * FVP but are needed for DRTM to function.
+ */
+
+uint64_t plat_drtm_get_min_size_normal_world_dce(void)
+{
+	return 0ULL;
+}
+
+uint64_t plat_drtm_get_imp_def_dlme_region_size(void)
+{
+	return 0ULL;
+}
+
+uint64_t plat_drtm_get_tcb_hash_features(void)
+{
+	return 0ULL;
+}
+
+uint64_t plat_drtm_get_tcb_hash_table_size(void)
+{
+	return 0ULL;
+}
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index efe149a..1ef6c87 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -403,4 +403,14 @@
  */
 #define	PLAT_ARM_EVENT_LOG_MAX_SIZE		UL(0x400)
 
+/*
+ * Maximum size of Event Log buffer used for DRTM
+ */
+#define PLAT_DRTM_EVENT_LOG_MAX_SIZE		UL(0x300)
+
+/*
+ * Number of MMAP entries used by DRTM implementation
+ */
+#define PLAT_DRTM_MMAP_ENTRIES			PLAT_ARM_MMAP_ENTRIES
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 4602276..eb2b5e5 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -415,6 +415,8 @@
 
 ifeq (${DRTM_SUPPORT}, 1)
 BL31_SOURCES   += plat/arm/board/fvp/fvp_drtm_dma_prot.c	\
+		  plat/arm/board/fvp/fvp_drtm_measurement.c	\
+		  plat/arm/board/fvp/fvp_drtm_stub.c	\
 		  plat/arm/common/arm_dyn_cfg.c
 endif
 
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index 946b732..fc68114 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -237,3 +237,7 @@
 }
 #endif
 
+const mmap_region_t *plat_get_addr_mmap(void)
+{
+	return plat_arm_mmap;
+}
diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index adb9293..843fc5d 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -14,22 +14,33 @@
 
 #include <arch.h>
 #include <arch_helpers.h>
+#include <common/bl_common.h>
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <drivers/auth/crypto_mod.h>
 #include "drtm_main.h"
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
 #include <services/drtm_svc.h>
+#include <platform_def.h>
 
-/* This value is used by the SMC to advertise the boot PE */
-static uint64_t boot_pe_aff_value;
+/* Structure to store DRTM features specific to the platform. */
+static drtm_features_t plat_drtm_features;
+
+/* DRTM-formatted memory map. */
+static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map;
 
 int drtm_setup(void)
 {
 	bool rc;
+	const plat_drtm_tpm_features_t *plat_tpm_feat;
+	const plat_drtm_dma_prot_features_t *plat_dma_prot_feat;
+	uint64_t dlme_data_min_size;
 
 	INFO("DRTM service setup\n");
 
-	boot_pe_aff_value = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
+	/* Read boot PE ID from MPIDR */
+	plat_drtm_features.boot_pe_id = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
 
 	rc = drtm_dma_prot_init();
 	if (rc) {
@@ -43,6 +54,68 @@
 	 */
 	crypto_mod_init();
 
+	/* Build DRTM-compatible address map. */
+	plat_drtm_mem_map = drtm_build_address_map();
+	if (plat_drtm_mem_map == NULL) {
+		return INTERNAL_ERROR;
+	}
+
+	/* Get DRTM features from platform hooks. */
+	plat_tpm_feat = plat_drtm_get_tpm_features();
+	if (plat_tpm_feat == NULL) {
+		return INTERNAL_ERROR;
+	}
+
+	plat_dma_prot_feat = plat_drtm_get_dma_prot_features();
+	if (plat_dma_prot_feat == NULL) {
+		return INTERNAL_ERROR;
+	}
+
+	/*
+	 * Add up minimum DLME data memory.
+	 *
+	 * For systems with complete DMA protection there is only one entry in
+	 * the protected regions table.
+	 */
+	if (plat_dma_prot_feat->dma_protection_support ==
+			ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE) {
+		dlme_data_min_size =
+			sizeof(drtm_memory_region_descriptor_table_t) +
+			sizeof(drtm_mem_region_t);
+	} else {
+		/*
+		 * TODO set protected regions table size based on platform DMA
+		 * protection configuration
+		 */
+		panic();
+	}
+
+	dlme_data_min_size += (drtm_get_address_map_size() +
+			       PLAT_DRTM_EVENT_LOG_MAX_SIZE +
+			       plat_drtm_get_tcb_hash_table_size() +
+			       plat_drtm_get_imp_def_dlme_region_size());
+
+	dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE;
+
+	/* Fill out platform DRTM features structure */
+	/* Only support default PCR schema (0x1) in this implementation. */
+	ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(plat_drtm_features.tpm_features,
+		ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT);
+	ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(plat_drtm_features.tpm_features,
+		plat_tpm_feat->tpm_based_hash_support);
+	ARM_DRTM_TPM_FEATURES_SET_FW_HASH(plat_drtm_features.tpm_features,
+		plat_tpm_feat->firmware_hash_algorithm);
+	ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(plat_drtm_features.minimum_memory_requirement,
+		dlme_data_min_size);
+	ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(plat_drtm_features.minimum_memory_requirement,
+		plat_drtm_get_min_size_normal_world_dce());
+	ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(plat_drtm_features.dma_prot_features,
+		plat_dma_prot_feat->max_num_mem_prot_regions);
+	ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(plat_drtm_features.dma_prot_features,
+		plat_dma_prot_feat->dma_protection_support);
+	ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(plat_drtm_features.tcb_hash_features,
+		plat_drtm_get_tcb_hash_features());
+
 	return 0;
 }
 
diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h
index 4c1adac..b60d954 100644
--- a/services/std_svc/drtm/drtm_main.h
+++ b/services/std_svc/drtm/drtm_main.h
@@ -23,4 +23,15 @@
 	MEM_PROTECT_INVALID = -6,
 };
 
+typedef struct {
+	uint64_t tpm_features;
+	uint64_t minimum_memory_requirement;
+	uint64_t dma_prot_features;
+	uint64_t boot_pe_id;
+	uint64_t tcb_hash_features;
+} drtm_features_t;
+
+drtm_memory_region_descriptor_table_t *drtm_build_address_map(void);
+uint64_t drtm_get_address_map_size(void);
+
 #endif /* DRTM_MAIN_H */
diff --git a/services/std_svc/drtm/drtm_res_address_map.c b/services/std_svc/drtm/drtm_res_address_map.c
new file mode 100644
index 0000000..8636706
--- /dev/null
+++ b/services/std_svc/drtm/drtm_res_address_map.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2022 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <plat/common/platform.h>
+#include <services/drtm_svc.h>
+#include <platform_def.h>
+
+/* Address map revision generated by this code. */
+#define DRTM_ADDRESS_MAP_REVISION	U(0x0001)
+
+/* Amount of space needed for address map based on PLAT_DRTM_MMAP_ENTRIES */
+#define DRTM_ADDRESS_MAP_SIZE (sizeof(drtm_memory_region_descriptor_table_t) + \
+			       (sizeof(drtm_mem_region_t) * \
+				PLAT_DRTM_MMAP_ENTRIES))
+
+/* Allocate space for DRTM-formatted address map to be constructed. */
+static uint8_t drtm_address_map[DRTM_ADDRESS_MAP_SIZE];
+
+static uint64_t drtm_address_map_size;
+
+drtm_memory_region_descriptor_table_t *drtm_build_address_map(void)
+{
+	/* Set up pointer to DRTM memory map. */
+	drtm_memory_region_descriptor_table_t *map =
+		(drtm_memory_region_descriptor_table_t *)drtm_address_map;
+
+	/* Get the platform memory map. */
+	const mmap_region_t *mmap = plat_get_addr_mmap();
+	unsigned int i;
+
+	/* Set up header for address map structure. */
+	map->revision = DRTM_ADDRESS_MAP_REVISION;
+	map->reserved = 0x0000;
+
+	/* Iterate through mmap and generate DRTM address map. */
+	for (i = 0U; mmap[i].base_pa != 0UL; i++) {
+		/* Set PA of region. */
+		map->region[i].region_address = mmap[i].base_pa;
+
+		/* Set size of region (in 4kb chunks). */
+		map->region[i].region_size_type = 0;
+		ARM_DRTM_REGION_SIZE_TYPE_SET_4K_PAGE_NUM(
+			map->region[i].region_size_type,
+			mmap[i].size / PAGE_SIZE_4KB);
+
+		/* Set type and cacheability. */
+		switch (MT_TYPE(mmap[i].attr)) {
+		case MT_DEVICE:
+			ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE(
+				map->region[i].region_size_type,
+				ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_DEVICE);
+			break;
+		case MT_NON_CACHEABLE:
+			ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE(
+				map->region[i].region_size_type,
+				ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NCAR);
+			ARM_DRTM_REGION_SIZE_TYPE_SET_CACHEABILITY(
+				map->region[i].region_size_type,
+				ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_NC);
+			break;
+		case MT_MEMORY:
+			ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE(
+				map->region[i].region_size_type,
+				ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NORMAL);
+			break;
+		default:
+			return NULL;
+		}
+	}
+
+	map->num_regions = i;
+
+	/* Store total size of address map. */
+	drtm_address_map_size = sizeof(drtm_memory_region_descriptor_table_t);
+	drtm_address_map_size += (i * sizeof(drtm_mem_region_t));
+
+	return map;
+}
+
+uint64_t drtm_get_address_map_size(void)
+{
+	return drtm_address_map_size;
+}