Abstract details about memory layout.

Details of the loaded image come from the linker. Abstracting these
details hides the linker specifics and gives more flexibility for
overriding in a test in future.

Change-Id: I70fd71bd117a99fae461530c95b8f8f6260fdc3e
diff --git a/inc/hf/layout.h b/inc/hf/layout.h
new file mode 100644
index 0000000..9075d87
--- /dev/null
+++ b/inc/hf/layout.h
@@ -0,0 +1,78 @@
+#pragma once
+
+#include "hf/addr.h"
+
+/**
+ * Get the address the .text section begins at.
+ */
+static inline paddr_t layout_text_begin(void)
+{
+	extern uint8_t text_begin[];
+	return pa_init((uintpaddr_t)text_begin);
+}
+
+/**
+ * Get the address the .text section ends at.
+ */
+static inline paddr_t layout_text_end(void)
+{
+	extern uint8_t text_end[];
+	return pa_init((uintpaddr_t)text_end);
+}
+
+/**
+ * Get the address the .rodata section begins at.
+ */
+static inline paddr_t layout_rodata_begin(void)
+{
+	extern uint8_t rodata_begin[];
+	return pa_init((uintpaddr_t)rodata_begin);
+}
+
+/**
+ * Get the address the .rodata section ends at.
+ */
+static inline paddr_t layout_rodata_end(void)
+{
+	extern uint8_t rodata_end[];
+	return pa_init((uintpaddr_t)rodata_end);
+}
+
+/**
+ * Get the address the .data section begins at.
+ */
+static inline paddr_t layout_data_begin(void)
+{
+	extern uint8_t data_begin[];
+	return pa_init((uintpaddr_t)data_begin);
+}
+
+/**
+ * Get the address the .data section ends at.
+ */
+static inline paddr_t layout_data_end(void)
+{
+	extern uint8_t data_end[];
+	return pa_init((uintpaddr_t)data_end);
+}
+
+/**
+ * Get the address the loaded image ends at.
+ */
+static inline paddr_t layout_bin_end(void)
+{
+	extern uint8_t bin_end[];
+	return pa_init((uintpaddr_t)bin_end);
+}
+
+/**
+ * Get the address to load the primary VM at.
+ *
+ * This is placed just after the image.
+ */
+static inline paddr_t layout_primary_begin(void)
+{
+	/* TODO: This is a hack. We must read the alignment from the binary. */
+	paddr_t bin_end = layout_bin_end();
+	return pa_init((pa_addr(bin_end) + 0x80000 - 1) & ~(0x80000 - 1));
+}
diff --git a/src/BUILD.gn b/src/BUILD.gn
index f0f2b35..55a6422 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -110,6 +110,8 @@
     "-defsym=data_begin=400",
     "-Xlinker",
     "-defsym=data_end=500",
+    "-Xlinker",
+    "-defsym=bin_end=600",
   ]
   deps = [
     ":fdt",
diff --git a/src/fdt_handler.c b/src/fdt_handler.c
index 8fa84c9..cb910ac 100644
--- a/src/fdt_handler.c
+++ b/src/fdt_handler.c
@@ -3,6 +3,7 @@
 #include "hf/boot_params.h"
 #include "hf/dlog.h"
 #include "hf/fdt.h"
+#include "hf/layout.h"
 #include "hf/mm.h"
 #include "hf/std.h"
 
@@ -279,11 +280,8 @@
 	}
 
 	/* Patch fdt to reserve primary VM memory. */
-	{
-		size_t tmp = (size_t)&fdt_patch;
-		tmp = (tmp + 0x80000 - 1) & ~(0x80000 - 1);
-		fdt_add_mem_reservation(fdt, tmp & ~0xfffff, 0x80000);
-	}
+	fdt_add_mem_reservation(fdt, pa_addr(layout_primary_begin()) & ~0xfffff,
+				0x80000);
 
 	/* Patch fdt to reserve memory for secondary VMs. */
 	for (i = 0; i < p->reserved_ranges_count; ++i) {
diff --git a/src/load.c b/src/load.c
index a6bf7d7..6732b28 100644
--- a/src/load.c
+++ b/src/load.c
@@ -6,6 +6,7 @@
 #include "hf/api.h"
 #include "hf/boot_params.h"
 #include "hf/dlog.h"
+#include "hf/layout.h"
 #include "hf/memiter.h"
 #include "hf/mm.h"
 #include "hf/std.h"
@@ -39,11 +40,8 @@
  */
 static bool relocate(const char *from, size_t size)
 {
-	/* TODO: This is a hack. We must read the alignment from the binary. */
-	extern char bin_end[];
-	size_t tmp = (size_t)&bin_end[0];
-	paddr_t dest = pa_init((tmp + 0x80000 - 1) & ~(0x80000 - 1));
-	dlog("bin_end is at %p, copying to %p\n", &bin_end[0], pa_addr(dest));
+	paddr_t dest = layout_primary_begin();
+	dlog("Copying to %p\n", pa_addr(dest));
 	return copy_to_unmapped(dest, from, size);
 }
 
diff --git a/src/mm.c b/src/mm.c
index 7029927..896725c 100644
--- a/src/mm.c
+++ b/src/mm.c
@@ -6,6 +6,7 @@
 
 #include "hf/alloc.h"
 #include "hf/dlog.h"
+#include "hf/layout.h"
 
 /* The type of addresses stored in the page table. */
 typedef uintvaddr_t ptable_addr_t;
@@ -27,13 +28,6 @@
 
 /* clang-format on */
 
-extern uint8_t text_begin[];
-extern uint8_t text_end[];
-extern uint8_t rodata_begin[];
-extern uint8_t rodata_end[];
-extern uint8_t data_begin[];
-extern uint8_t data_end[];
-
 static struct mm_ptable ptable;
 
 /**
@@ -378,12 +372,11 @@
 bool mm_ptable_unmap_hypervisor(struct mm_ptable *t, int mode)
 {
 	/* TODO: If we add pages dynamically, they must be included here too. */
-	return mm_ptable_unmap(t, pa_init((uintpaddr_t)text_begin),
-			       pa_init((uintpaddr_t)text_end), mode) &&
-	       mm_ptable_unmap(t, pa_init((uintpaddr_t)rodata_begin),
-			       pa_init((uintpaddr_t)rodata_end), mode) &&
-	       mm_ptable_unmap(t, pa_init((uintpaddr_t)data_begin),
-			       pa_init((uintpaddr_t)data_end), mode);
+	return mm_ptable_unmap(t, layout_text_begin(), layout_text_end(),
+			       mode) &&
+	       mm_ptable_unmap(t, layout_rodata_begin(), layout_rodata_end(),
+			       mode) &&
+	       mm_ptable_unmap(t, layout_data_begin(), layout_data_end(), mode);
 }
 
 /**
@@ -559,9 +552,12 @@
  */
 bool mm_init(void)
 {
-	dlog("text: 0x%x - 0x%x\n", text_begin, text_end);
-	dlog("rodata: 0x%x - 0x%x\n", rodata_begin, rodata_end);
-	dlog("data: 0x%x - 0x%x\n", data_begin, data_end);
+	dlog("text: 0x%x - 0x%x\n", pa_addr(layout_text_begin()),
+	     pa_addr(layout_text_end()));
+	dlog("rodata: 0x%x - 0x%x\n", pa_addr(layout_rodata_begin()),
+	     pa_addr(layout_rodata_end()));
+	dlog("data: 0x%x - 0x%x\n", pa_addr(layout_data_begin()),
+	     pa_addr(layout_data_end()));
 
 	if (!mm_ptable_init(&ptable, MM_MODE_NOSYNC | MM_MODE_STAGE1)) {
 		dlog("Unable to allocate memory for page table.\n");
@@ -575,16 +571,13 @@
 					    MM_MODE_NOSYNC | MM_MODE_STAGE1);
 
 	/* Map each section. */
-	mm_identity_map(pa_init((uintpaddr_t)text_begin),
-			pa_init((uintpaddr_t)text_end),
+	mm_identity_map(layout_text_begin(), layout_text_end(),
 			MM_MODE_X | MM_MODE_NOSYNC);
 
-	mm_identity_map(pa_init((uintpaddr_t)rodata_begin),
-			pa_init((uintpaddr_t)rodata_end),
+	mm_identity_map(layout_rodata_begin(), layout_rodata_end(),
 			MM_MODE_R | MM_MODE_NOSYNC);
 
-	mm_identity_map(pa_init((uintpaddr_t)data_begin),
-			pa_init((uintpaddr_t)data_end),
+	mm_identity_map(layout_data_begin(), layout_data_end(),
 			MM_MODE_R | MM_MODE_W | MM_MODE_NOSYNC);
 
 	return arch_mm_init(ptable.table, true);