fix(manifest): check mem regions are page aligned

Memory regions are required to be page aligned however this wasn't
being checked during manifest parsing. This patch adds that check
as well as an additional test to make sure unaligned memory regions
are caught.

Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
Change-Id: Ifa64bd4dbe8cc28064d30ffc4ec43fb9e38a8bb7
diff --git a/inc/hf/manifest.h b/inc/hf/manifest.h
index 15f415d..6ebd784 100644
--- a/inc/hf/manifest.h
+++ b/inc/hf/manifest.h
@@ -250,6 +250,7 @@
 	MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY,
 	MANIFEST_ERROR_RXTX_SIZE_MISMATCH,
 	MANIFEST_ERROR_MEM_REGION_EMPTY,
+	MANIFEST_ERROR_MEM_REGION_UNALIGNED,
 	MANIFEST_ERROR_MEM_REGION_OVERLAP,
 	MANIFEST_ERROR_INVALID_MEM_PERM,
 	MANIFEST_ERROR_INTERRUPT_ID_REPEATED,
diff --git a/src/manifest.c b/src/manifest.c
index 4875e12..a1a9d64 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -421,11 +421,17 @@
 
 	if (page_count == 0U) {
 		dlog_error(
-			"Empty memory region defined with base address: %x\n",
+			"Empty memory region defined with base address: %#x.\n",
 			base_address);
 		return MANIFEST_ERROR_MEM_REGION_EMPTY;
 	}
 
+	if (!is_aligned(base_address, PAGE_SIZE)) {
+		dlog_error("base_address (%#x) is not aligned to page size.\n",
+			   base_address);
+		return MANIFEST_ERROR_MEM_REGION_UNALIGNED;
+	}
+
 	for (size_t i = 0; i < allocated_mem_regions_index; i++) {
 		uintptr_t mem_region_base = manifest_data->mem_regions[i].base;
 		uintptr_t mem_region_limit =
@@ -1280,6 +1286,8 @@
 		return "Memory region should have at least one page";
 	case MANIFEST_ERROR_MEM_REGION_OVERLAP:
 		return "Memory region overlaps with one already allocated";
+	case MANIFEST_ERROR_MEM_REGION_UNALIGNED:
+		return "Memory region is not aligned to a page boundary";
 	case MANIFEST_ERROR_INVALID_MEM_PERM:
 		return "Memory permission should be RO, RW or RX";
 	case MANIFEST_ERROR_ARGUMENTS_LIST_EMPTY:
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index e5d03d6..a44da46 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -1225,32 +1225,6 @@
 			.Label("rx")
 			.StartChild("rx")
 				.Description("rx-buffer")
-				.Property("base-address", "<0x7300000>")
-				.Property("pages-count", "<2>")
-				.Property("attributes", "<1>")
-			.EndChild()
-			.Label("tx")
-			.StartChild("tx")
-				.Description("tx-buffer")
-				.Property("base-address", "<0x7301FFF>")
-				.Property("pages-count", "<2>")
-				.Property("attributes", "<3>")
-			.EndChild()
-		.EndChild()
-		.Build();
-	/* clang-format on */
-	ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
-		  MANIFEST_ERROR_MEM_REGION_OVERLAP);
-	manifest_dealloc();
-
-	/* clang-format off */
-	dtb = ManifestDtBuilder()
-		.FfaValidManifest()
-		.StartChild("memory-regions")
-			.Compatible({ "arm,ffa-manifest-memory-regions" })
-			.Label("rx")
-			.StartChild("rx")
-				.Description("rx-buffer")
 				.Property("base-address", "<0x7301000>")
 				.Property("pages-count", "<1>")
 				.Property("attributes", "<1>")
@@ -1267,6 +1241,34 @@
 	/* clang-format on */
 	ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
 		  MANIFEST_ERROR_MEM_REGION_OVERLAP);
+	manifest_dealloc();
+
+	/* Unaligned memory region */
+	/* clang-format off */
+	dtb = ManifestDtBuilder()
+		.FfaValidManifest()
+		.StartChild("memory-regions")
+			.Compatible({ "arm,ffa-manifest-memory-regions" })
+			.Label("rx")
+			.StartChild("rx")
+				.Description("rx-buffer")
+				.Property("base-address", "<0x7300FFF>")
+				.Property("pages-count", "<2>")
+				.Property("attributes", "<1>")
+			.EndChild()
+			.Label("tx")
+			.StartChild("tx")
+				.Description("tx-buffer")
+				.Property("base-address", "<0x7303000>")
+				.Property("pages-count", "<2>")
+				.Property("attributes", "<3>")
+			.EndChild()
+		.EndChild()
+		.Build();
+	/* clang-format on */
+	ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
+		  MANIFEST_ERROR_MEM_REGION_UNALIGNED);
+	manifest_dealloc();
 
 	/* Different RXTX buffer sizes */
 	/* clang-format off */