Support multiple memory ranges.

Bug: 114733240
Change-Id: Ifbad8688e0a0e17a4732b637711919fc18d68f7a
diff --git a/src/fdt_handler.c b/src/fdt_handler.c
index 4a93e66..91a17d8 100644
--- a/src/fdt_handler.c
+++ b/src/fdt_handler.c
@@ -108,14 +108,15 @@
 	return true;
 }
 
-static void find_memory_range(const struct fdt_node *root,
-			      struct boot_params *p)
+static void find_memory_ranges(const struct fdt_node *root,
+			       struct boot_params *p)
 {
 	struct fdt_node n = *root;
 	const char *name;
 	uint64_t address_size;
 	uint64_t size_size;
 	uint64_t entry_size;
+	size_t mem_range_index = 0;
 
 	/* Get the sizes of memory range addresses and sizes. */
 	if (fdt_read_number(&n, "#address-cells", &address_size)) {
@@ -153,16 +154,24 @@
 			size_t len =
 				convert_number(data + address_size, size_size);
 
-			if (len > pa_addr(p->mem_end) - pa_addr(p->mem_begin)) {
-				/* Remember the largest range we've found. */
-				p->mem_begin = pa_init(addr);
-				p->mem_end = pa_init(addr + len);
+			if (mem_range_index < MAX_MEM_RANGES) {
+				p->mem_ranges[mem_range_index].begin =
+					pa_init(addr);
+				p->mem_ranges[mem_range_index].end =
+					pa_init(addr + len);
+				++mem_range_index;
+			} else {
+				dlog("Found memory range %u in FDT but only "
+				     "%u supported, ignoring additional range "
+				     "of size %u.\n",
+				     mem_range_index, MAX_MEM_RANGES, len);
 			}
 
 			size -= entry_size;
 			data += entry_size;
 		}
 	} while (fdt_next_sibling(&n, &name));
+	p->mem_ranges_count = mem_range_index;
 
 	/* TODO: Check for "reserved-memory" nodes. */
 }
@@ -199,9 +208,8 @@
 		goto out_unmap_fdt;
 	}
 
-	p->mem_begin = pa_init(0);
-	p->mem_end = pa_init(0);
-	find_memory_range(&n, p);
+	p->mem_ranges_count = 0;
+	find_memory_ranges(&n, p);
 
 	if (!find_initrd(&n, p)) {
 		goto out_unmap_fdt;
@@ -224,6 +232,7 @@
 	struct fdt_header *fdt;
 	struct fdt_node n;
 	bool ret = false;
+	size_t i;
 
 	/* Map the fdt header in. */
 	fdt = mm_identity_map(fdt_addr, pa_add(fdt_addr, fdt_header_size()),
@@ -277,9 +286,12 @@
 	}
 
 	/* Patch fdt to reserve memory for secondary VMs. */
-	fdt_add_mem_reservation(
-		fdt, pa_addr(p->reserved_begin),
-		pa_addr(p->reserved_end) - pa_addr(p->reserved_begin));
+	for (i = 0; i < p->reserved_ranges_count; ++i) {
+		fdt_add_mem_reservation(
+			fdt, pa_addr(p->reserved_ranges[i].begin),
+			pa_addr(p->reserved_ranges[i].end) -
+				pa_addr(p->reserved_ranges[i].begin));
+	}
 
 	ret = true;