refactor(manifest): function for parsing memory region's address

Extract the parsing of the `base-address` field to a separate function.
This prepares for changes to `base-address` handling in future commits.

Change-Id: I6b816297751a54041506af6398450fc0f18ad684
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
diff --git a/src/manifest.c b/src/manifest.c
index 5fb4632..91bdae7 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -666,6 +666,56 @@
 	return MANIFEST_SUCCESS;
 }
 
+/**
+ * Parse and validate a memory regions's base address.
+ *
+ * The base address can be specified either as an absolute address (with
+ * `base-address`) or as an offset from `load_address` (with
+ * `load-address-relative-offset`).
+
+ * Returns an error if:
+ * - Neither `base-address` or `load-address-relative-offset` are specified.
+ * - Both `base-address` and `load-address-relative-offset` are specified.
+ * - The effective address (`load-address-relative-offset` + `load_address`)
+ *   would overflow.
+ */
+static enum manifest_return_code parse_base_address(
+	struct fdt_node *mem_node, uintptr_t load_address,
+	struct memory_region *mem_region)
+{
+	uintptr_t relative_offset;
+	uintptr_t absolute_address;
+
+	bool is_relative;
+	bool is_absolute;
+
+	TRY(read_optional_uint64(mem_node, "base-address",
+				 MANIFEST_INVALID_ADDRESS, &absolute_address));
+
+	TRY(read_optional_uint64(mem_node, "load-address-relative-offset",
+				 MANIFEST_INVALID_ADDRESS, &relative_offset));
+
+	is_absolute = (absolute_address != MANIFEST_INVALID_ADDRESS);
+	is_relative = (relative_offset != MANIFEST_INVALID_ADDRESS);
+
+	if (!is_absolute && !is_relative) {
+		return MANIFEST_ERROR_PROPERTY_NOT_FOUND;
+	}
+
+	if (is_absolute && is_relative) {
+		return MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS;
+	}
+
+	if (is_relative && relative_offset > UINT64_MAX - load_address) {
+		return MANIFEST_ERROR_INTEGER_OVERFLOW;
+	}
+
+	mem_region->base_address =
+		is_absolute ? absolute_address : load_address + relative_offset;
+
+	return MANIFEST_SUCCESS;
+}
+
 static enum manifest_return_code parse_ffa_memory_region_node(
 	struct fdt_node *mem_node, uintptr_t load_address,
 	struct memory_region *mem_regions, uint16_t *count, struct rx_tx *rxtx,
@@ -674,7 +724,6 @@
 	uint32_t phandle;
 	uint16_t i = 0;
 	uint32_t j = 0;
-	uintptr_t relative_address;
 	struct uint32list_iter list;
 
 	dlog_verbose("  Partition memory regions\n");
@@ -695,39 +744,8 @@
 		dlog_verbose("      Name: %s\n",
 			     string_data(&mem_regions[i].name));
 
-		TRY(read_optional_uint64(mem_node, "base-address",
-					 MANIFEST_INVALID_ADDRESS,
-					 &mem_regions[i].base_address));
-		dlog_verbose("      Base address: %#lx\n",
-			     mem_regions[i].base_address);
-
-		TRY(read_optional_uint64(
-			mem_node, "load-address-relative-offset",
-			MANIFEST_INVALID_ADDRESS, &relative_address));
-		if (relative_address != MANIFEST_INVALID_ADDRESS) {
-			dlog_verbose("      Relative address:  %#lx\n",
-				     relative_address);
-		}
-
-		if (mem_regions[i].base_address == MANIFEST_INVALID_ADDRESS &&
-		    relative_address == MANIFEST_INVALID_ADDRESS) {
-			return MANIFEST_ERROR_PROPERTY_NOT_FOUND;
-		}
-
-		if (mem_regions[i].base_address != MANIFEST_INVALID_ADDRESS &&
-		    relative_address != MANIFEST_INVALID_ADDRESS) {
-			return MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS;
-		}
-
-		if (relative_address != MANIFEST_INVALID_ADDRESS &&
-		    relative_address > UINT64_MAX - load_address) {
-			return MANIFEST_ERROR_INTEGER_OVERFLOW;
-		}
-
-		if (relative_address != MANIFEST_INVALID_ADDRESS) {
-			mem_regions[i].base_address =
-				load_address + relative_address;
-		}
+		TRY(parse_base_address(mem_node, load_address,
+				       &mem_regions[i]));
 
 		TRY(read_uint32(mem_node, "pages-count",
 				&mem_regions[i].page_count));