feat(drtm): prepare DLME data for DLME launch

Prepared DLME data before DLME launch

Change-Id: I28e2132d9c832ab5bd25cf884925b99cc48258ea
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index a96706d..ad2b774 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -33,12 +33,17 @@
 /* DRTM-formatted memory map. */
 static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map;
 
+/* DLME header */
+struct_dlme_data_header dlme_data_hdr_init;
+
+/* Minimum data memory requirement */
+uint64_t dlme_data_min_size;
+
 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");
 
@@ -85,6 +90,7 @@
 		dlme_data_min_size =
 			sizeof(drtm_memory_region_descriptor_table_t) +
 			sizeof(drtm_mem_region_t);
+		dlme_data_hdr_init.dlme_prot_regions_size = dlme_data_min_size;
 	} else {
 		/*
 		 * TODO set protected regions table size based on platform DMA
@@ -93,10 +99,16 @@
 		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_hdr_init.dlme_addr_map_size = drtm_get_address_map_size();
+	dlme_data_hdr_init.dlme_tcb_hashes_table_size =
+				plat_drtm_get_tcb_hash_table_size();
+	dlme_data_hdr_init.dlme_impdef_region_size =
+				plat_drtm_get_imp_def_dlme_region_size();
+
+	dlme_data_min_size += dlme_data_hdr_init.dlme_addr_map_size +
+			      PLAT_DRTM_EVENT_LOG_MAX_SIZE +
+			      dlme_data_hdr_init.dlme_tcb_hashes_table_size +
+			      dlme_data_hdr_init.dlme_impdef_region_size;
 
 	dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE;
 
@@ -196,12 +208,97 @@
 	return SUCCESS;
 }
 
-static enum drtm_retc drtm_dl_prepare_dlme_data(const struct_drtm_dl_args *args,
-						size_t *dlme_data_size_out)
+static enum drtm_retc drtm_dl_prepare_dlme_data(const struct_drtm_dl_args *args)
 {
-	size_t dlme_data_total_bytes_req = 0;
+	int rc;
+	uint64_t dlme_data_paddr;
+	size_t dlme_data_max_size;
+	uintptr_t dlme_data_mapping;
+	struct_dlme_data_header *dlme_data_hdr;
+	uint8_t *dlme_data_cursor;
+	size_t dlme_data_mapping_bytes;
+	size_t serialised_bytes_actual;
 
-	*dlme_data_size_out = dlme_data_total_bytes_req;
+	dlme_data_paddr = args->dlme_paddr + args->dlme_data_off;
+	dlme_data_max_size = args->dlme_size - args->dlme_data_off;
+
+	/*
+	 * The capacity of the given DLME data region is checked when
+	 * the other dynamic launch arguments are.
+	 */
+	if (dlme_data_max_size < dlme_data_min_size) {
+		ERROR("%s: assertion failed:"
+		      " dlme_data_max_size (%ld) < dlme_data_total_bytes_req (%ld)\n",
+		      __func__, dlme_data_max_size, dlme_data_min_size);
+		panic();
+	}
+
+	/* Map the DLME data region as NS memory. */
+	dlme_data_mapping_bytes = ALIGNED_UP(dlme_data_max_size, DRTM_PAGE_SIZE);
+	rc = mmap_add_dynamic_region_alloc_va(dlme_data_paddr,
+					      &dlme_data_mapping,
+					      dlme_data_mapping_bytes,
+					      MT_RW_DATA | MT_NS |
+					      MT_SHAREABILITY_ISH);
+	if (rc != 0) {
+		WARN("DRTM: %s: mmap_add_dynamic_region() failed rc=%d\n",
+		     __func__, rc);
+		return INTERNAL_ERROR;
+	}
+	dlme_data_hdr = (struct_dlme_data_header *)dlme_data_mapping;
+	dlme_data_cursor = (uint8_t *)dlme_data_hdr + sizeof(*dlme_data_hdr);
+
+	memcpy(dlme_data_hdr, (const void *)&dlme_data_hdr_init,
+	       sizeof(*dlme_data_hdr));
+
+	/* Set the header version and size. */
+	dlme_data_hdr->version = 1;
+	dlme_data_hdr->this_hdr_size = sizeof(*dlme_data_hdr);
+
+	/* Prepare DLME protected regions. */
+	drtm_dma_prot_serialise_table(dlme_data_cursor,
+				      &serialised_bytes_actual);
+	assert(serialised_bytes_actual ==
+	       dlme_data_hdr->dlme_prot_regions_size);
+	dlme_data_cursor += serialised_bytes_actual;
+
+	/* Prepare DLME address map. */
+	if (plat_drtm_mem_map != NULL) {
+		memcpy(dlme_data_cursor, plat_drtm_mem_map,
+		       dlme_data_hdr->dlme_addr_map_size);
+	} else {
+		WARN("DRTM: DLME address map is not in the cache\n");
+	}
+	dlme_data_cursor += dlme_data_hdr->dlme_addr_map_size;
+
+	/* Prepare DRTM event log for DLME. */
+	drtm_serialise_event_log(dlme_data_cursor, &serialised_bytes_actual);
+	assert(serialised_bytes_actual <= PLAT_DRTM_EVENT_LOG_MAX_SIZE);
+	dlme_data_hdr->dlme_tpm_log_size = serialised_bytes_actual;
+	dlme_data_cursor += serialised_bytes_actual;
+
+	/*
+	 * TODO: Prepare the TCB hashes for DLME, currently its size
+	 * 0
+	 */
+	dlme_data_cursor += dlme_data_hdr->dlme_tcb_hashes_table_size;
+
+	/* Implementation-specific region size is unused. */
+	dlme_data_cursor += dlme_data_hdr->dlme_impdef_region_size;
+
+	/*
+	 * Prepare DLME data size, includes all data region referenced above
+	 * alongwith the DLME data header
+	 */
+	dlme_data_hdr->dlme_data_size = dlme_data_cursor - (uint8_t *)dlme_data_hdr;
+
+	/* Unmap the DLME data region. */
+	rc = mmap_remove_dynamic_region(dlme_data_mapping, dlme_data_mapping_bytes);
+	if (rc != 0) {
+		ERROR("%s(): mmap_remove_dynamic_region() failed"
+		      " unexpectedly rc=%d\n", __func__, rc);
+		panic();
+	}
 
 	return SUCCESS;
 }
@@ -220,7 +317,6 @@
 	size_t args_mapping_size;
 	struct_drtm_dl_args *a;
 	struct_drtm_dl_args args_buf;
-	size_t dlme_data_size_req;
 	int rc;
 
 	if (x1 % DRTM_PAGE_SIZE != 0) {
@@ -324,15 +420,9 @@
 		return INVALID_PARAMETERS;
 	}
 
-	rc = drtm_dl_prepare_dlme_data(NULL, &dlme_data_size_req);
-	if (rc) {
-		ERROR("%s: drtm_dl_prepare_dlme_data() failed unexpectedly rc=%d\n",
-		      __func__, rc);
-		panic();
-	}
-	if (dlme_data_end - dlme_data_start < dlme_data_size_req) {
+	if (dlme_data_end - dlme_data_start < dlme_data_min_size) {
 		ERROR("DRTM: argument DLME data region is short of %lu bytes\n",
-		      dlme_data_size_req - (size_t)(dlme_data_end - dlme_data_start));
+		      dlme_data_min_size - (size_t)(dlme_data_end - dlme_data_start));
 		return INVALID_PARAMETERS;
 	}
 
@@ -404,6 +494,11 @@
 		goto err_undo_dma_prot;
 	}
 
+	ret = drtm_dl_prepare_dlme_data(&args);
+	if (ret != SUCCESS) {
+		goto err_undo_dma_prot;
+	}
+
 	SMC_RET1(handle, ret);
 
 err_undo_dma_prot:
diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h
index 9bf5400..230cbcf 100644
--- a/services/std_svc/drtm/drtm_main.h
+++ b/services/std_svc/drtm/drtm_main.h
@@ -55,7 +55,7 @@
 } drtm_features_t;
 
 struct __packed drtm_dl_args_v1 {
-	uint16_t version;        /* Must be 1. */
+	uint16_t version;	/* Must be 1. */
 	uint8_t __res[2];
 	uint32_t features;
 	uint64_t dlme_paddr;
@@ -69,6 +69,20 @@
 	drtm_dl_dma_prot_args_v1_t dma_prot_args;
 } __aligned(__alignof(uint16_t /* First member's type, `uint16_t version' */));
 
+struct __packed dlme_data_header_v1 {
+	uint16_t version;	/* Must be 1. */
+	uint16_t this_hdr_size;
+	uint8_t __res[4];
+	uint64_t dlme_data_size;
+	uint64_t dlme_prot_regions_size;
+	uint64_t dlme_addr_map_size;
+	uint64_t dlme_tpm_log_size;
+	uint64_t dlme_tcb_hashes_table_size;
+	uint64_t dlme_impdef_region_size;
+} __aligned(__alignof(uint16_t /* First member's type, `uint16_t version'. */));
+
+typedef struct dlme_data_header_v1 struct_dlme_data_header;
+
 drtm_memory_region_descriptor_table_t *drtm_build_address_map(void);
 uint64_t drtm_get_address_map_size(void);