Abstract UART.

Let different toolchains use different implementations of console driver.

Bug: 115484857
Change-Id: I230c2c2dc2570c55eead4eed597663e52160f064
diff --git a/build/toolchain/BUILD.gn b/build/toolchain/BUILD.gn
index 625c6b5..f7caa6c 100644
--- a/build/toolchain/BUILD.gn
+++ b/build/toolchain/BUILD.gn
@@ -39,5 +39,6 @@
   toolchain_args = {
     use_platform = true
     plat_arch = "fake"
+    plat_console = "//src/arch/fake:console"
   }
 }
diff --git a/build/toolchain/embedded.gni b/build/toolchain/embedded.gni
index 2b232c6..12dcd30 100644
--- a/build/toolchain/embedded.gni
+++ b/build/toolchain/embedded.gni
@@ -305,8 +305,8 @@
          "\"tool_prefix\" must be defined for ${target_name}")
   assert(defined(invoker.origin_address),
          "\"origin_address\" must be defined for ${target_name}.")
-  assert(defined(invoker.use_pl011),
-         "\"use_pl011\" must be defined for ${target_name}.")
+  assert(defined(invoker.console),
+         "\"console\" must be defined for ${target_name}.")
   assert(defined(invoker.heap_pages),
          "\"heap_pages\" must be defined for ${target_name}.")
   assert(defined(invoker.max_cpus),
@@ -345,11 +345,6 @@
       extra_defines += " ${invoker.extra_defines}"
     }
 
-    if (invoker.use_pl011) {
-      assert(defined(invoker.pl011_base_address),
-             "\"pl011_base_address\" must be defined for ${target_name}.")
-      extra_defines += " -DPL011_BASE=${invoker.pl011_base_address}"
-    }
     if (invoker.gic_version > 0) {
       extra_defines += " -DGIC_VERSION=${invoker.gic_version}"
     }
@@ -358,7 +353,8 @@
     }
 
     toolchain_args = {
-      arch_aarch64_use_pl011 = invoker.use_pl011
+      plat_console = invoker.console
+      forward_variables_from(invoker.toolchain_args, "*")
     }
   }
 }
@@ -377,14 +373,14 @@
     forward_variables_from(invoker,
                            [
                              "origin_address",
-                             "use_pl011",
-                             "pl011_base_address",
+                             "console",
                              "gic_version",
                              "gicd_base_address",
                              "gicr_base_address",
                              "heap_pages",
                              "max_cpus",
                              "max_vms",
+                             "toolchain_args",
                            ])
     cpu = "${invoker.cpu}+nofp"
   }
@@ -395,17 +391,17 @@
     forward_variables_from(invoker,
                            [
                              "origin_address",
-                             "use_pl011",
-                             "pl011_base_address",
+                             "console",
                              "gic_version",
                              "gicd_base_address",
                              "gicr_base_address",
+                             "toolchain_args",
                            ])
     cpu = "${invoker.cpu}+fp"
 
     # Nonsense values because they are required but shouldn't be used.
     heap_pages = 0
-    max_cpus = 0
-    max_vms = 0
+    max_cpus = 1
+    max_vms = 1
   }
 }
diff --git a/build/toolchain/host.gni b/build/toolchain/host.gni
index 577b5f5..5b646b6 100644
--- a/build/toolchain/host.gni
+++ b/build/toolchain/host.gni
@@ -150,6 +150,7 @@
         # When building for the ${target_name}, use the fake architecture to make things
         # testable.
         plat_arch = "fake"
+        plat_console = "//src/arch/fake:console"
         plat_heap_pages = invoker.heap_pages
         plat_max_cpus = invoker.max_cpus
         plat_max_vms = invoker.max_vms
@@ -173,6 +174,7 @@
         # When building for the ${target_name}, use the fake architecture to make things
         # testable.
         plat_arch = "fake"
+        plat_console = "//src/arch/fake:console"
         plat_heap_pages = invoker.heap_pages
         plat_max_cpus = invoker.max_cpus
         plat_max_vms = invoker.max_vms
diff --git a/build/toolchain/platform.gni b/build/toolchain/platform.gni
index b6d1f10..8e9feea 100644
--- a/build/toolchain/platform.gni
+++ b/build/toolchain/platform.gni
@@ -19,13 +19,14 @@
 
   # The architecture of the platform.
   plat_arch = ""
+  plat_console = ""
 
   # The number of pages to allocate for the hypervisor heap.
   plat_heap_pages = 0
 
   # The maximum number of CPUs available on the platform.
-  plat_max_cpus = 0
+  plat_max_cpus = 1
 
   # The maximum number of VMs required for the platform.
-  plat_max_vms = 0
+  plat_max_vms = 1
 }
diff --git a/inc/hf/arch/console.h b/inc/hf/plat/console.h
similarity index 61%
rename from inc/hf/arch/console.h
rename to inc/hf/plat/console.h
index 7865c16..604ac26 100644
--- a/inc/hf/arch/console.h
+++ b/inc/hf/plat/console.h
@@ -16,5 +16,17 @@
 
 #pragma once
 
+#include "hf/mpool.h"
+#include "hf/vm.h"
+
+/** Initialises the console hardware. */
+void plat_console_init(void);
+
+/** Initialises any memory mappings that the console driver needs. */
+void plat_console_mm_init(struct mpool *ppool);
+
+/** Initialises any per-VM memory mappings that the console driver needs. */
+void plat_console_vm_mm_init(struct vm *vm, struct mpool *ppool);
+
 /** Puts a single character on the console. */
-void arch_putchar(char c);
+void plat_console_putchar(char c);
diff --git a/project/reference b/project/reference
index b145760..808531e 160000
--- a/project/reference
+++ b/project/reference
@@ -1 +1 @@
-Subproject commit b1457609e53750bf3a895affc43f5a2d89cd9a8f
+Subproject commit 808531e100759dc273f284e0a0f0bd2ff7c51a53
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 8e1b7e2..cdc0771 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -37,6 +37,7 @@
   deps = [
     ":src_testable",
     "//project/${project}/${plat_name}",
+    plat_console,
   ]
 }
 
@@ -61,6 +62,7 @@
     ":memiter",
     ":std",
     "//src/arch/${plat_arch}",
+    plat_console,
   ]
 
   if (is_debug) {
@@ -87,7 +89,7 @@
 
   deps = [
     ":std",
-    "//src/arch/${plat_arch}:putchar",
+    plat_console,
   ]
 }
 
diff --git a/src/arch/aarch64/BUILD.gn b/src/arch/aarch64/BUILD.gn
index 5733da7..d4214ab 100644
--- a/src/arch/aarch64/BUILD.gn
+++ b/src/arch/aarch64/BUILD.gn
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("args.gni")
-
 # Hypervisor specific code.
 source_set("aarch64") {
   sources = [
@@ -65,16 +63,3 @@
     "smc.S",
   ]
 }
-
-# aarch64 implementation of putchar for debugging.
-source_set("putchar") {
-  if (arch_aarch64_use_pl011) {
-    sources = [
-      "pl011.c",
-    ]
-
-    deps = [
-      ":arch",
-    ]
-  }
-}
diff --git a/src/arch/aarch64/pl011/BUILD.gn b/src/arch/aarch64/pl011/BUILD.gn
new file mode 100644
index 0000000..7d97e33
--- /dev/null
+++ b/src/arch/aarch64/pl011/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2019 The Hafnium Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("args.gni")
+
+# aarch64 PL011 implementation of putchar for debugging.
+source_set("pl011") {
+  sources = [
+    "pl011.c",
+  ]
+  deps = [
+    "//src/arch/aarch64:arch",
+  ]
+
+  assert(defined(pl011_base_address),
+         "\"pl011_base_address\" must be defined for ${target_name}.")
+  defines = [ "PL011_BASE=${pl011_base_address}" ]
+}
diff --git a/src/arch/aarch64/args.gni b/src/arch/aarch64/pl011/args.gni
similarity index 81%
rename from src/arch/aarch64/args.gni
rename to src/arch/aarch64/pl011/args.gni
index 4e5ba11..f5b1e99 100644
--- a/src/arch/aarch64/args.gni
+++ b/src/arch/aarch64/pl011/args.gni
@@ -1,4 +1,4 @@
-# Copyright 2018 The Hafnium Authors.
+# Copyright 2019 The Hafnium Authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,6 +13,5 @@
 # limitations under the License.
 
 declare_args() {
-  # Whether to include the PrimeCell UART (PL011) driver.
-  arch_aarch64_use_pl011 = false
+  pl011_base_address = ""
 }
diff --git a/src/arch/aarch64/io.h b/src/arch/aarch64/pl011/io.h
similarity index 100%
rename from src/arch/aarch64/io.h
rename to src/arch/aarch64/pl011/io.h
diff --git a/src/arch/aarch64/pl011.c b/src/arch/aarch64/pl011/pl011.c
similarity index 64%
rename from src/arch/aarch64/pl011.c
rename to src/arch/aarch64/pl011/pl011.c
index 4b0a78a..02b6123 100644
--- a/src/arch/aarch64/pl011.c
+++ b/src/arch/aarch64/pl011/pl011.c
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-#include "hf/dlog.h"
+#include "hf/mm.h"
+#include "hf/mpool.h"
+#include "hf/plat/console.h"
+#include "hf/vm.h"
 
 #include "io.h"
 
@@ -30,11 +33,33 @@
 /* UART Flag Register bit: UART is busy. */
 #define UARTFR_BUSY (1 << 3)
 
-void arch_putchar(char c)
+void plat_console_init(void)
+{
+	/* No hardware initialisation required. */
+}
+
+void plat_console_mm_init(struct mpool *ppool)
+{
+	/* Map page for UART. */
+	mm_identity_map(pa_init(PL011_BASE),
+			pa_add(pa_init(PL011_BASE), PAGE_SIZE),
+			MM_MODE_R | MM_MODE_W | MM_MODE_D, ppool);
+}
+
+/* TODO: Remove this. */
+void plat_console_vm_mm_init(struct vm *vm, struct mpool *ppool)
+{
+	/* Grant VM access to UART. */
+	mm_vm_identity_map(&vm->ptable, pa_init(PL011_BASE),
+			   pa_add(pa_init(PL011_BASE), PAGE_SIZE),
+			   MM_MODE_R | MM_MODE_W, NULL, ppool);
+}
+
+void plat_console_putchar(char c)
 {
 	/* Print a carriage-return as well. */
 	if (c == '\n') {
-		arch_putchar('\r');
+		plat_console_putchar('\r');
 	}
 
 	/* Wait until there is room in the tx buffer. */
diff --git a/src/arch/fake/BUILD.gn b/src/arch/fake/BUILD.gn
index e4e324c..f2b22af 100644
--- a/src/arch/fake/BUILD.gn
+++ b/src/arch/fake/BUILD.gn
@@ -21,9 +21,9 @@
 }
 
 # Fake implementation of putchar logs to the console.
-source_set("putchar") {
+source_set("console") {
   sources = [
-    "putchar.c",
+    "console.c",
   ]
 }
 
diff --git a/src/arch/fake/putchar.c b/src/arch/fake/console.c
similarity index 76%
rename from src/arch/fake/putchar.c
rename to src/arch/fake/console.c
index b99bcaa..d906352 100644
--- a/src/arch/fake/putchar.c
+++ b/src/arch/fake/console.c
@@ -14,11 +14,22 @@
  * limitations under the License.
  */
 
+#include "hf/plat/console.h"
+
 #include <stdio.h>
 
-#include "hf/dlog.h"
+#include "hf/mm.h"
+#include "hf/mpool.h"
 
-void arch_putchar(char c)
+void plat_console_init(void)
+{
+}
+
+void plat_console_mm_init(struct mpool *ppool)
+{
+}
+
+void plat_console_putchar(char c)
 {
 	putchar(c);
 }
diff --git a/src/dlog.c b/src/dlog.c
index 369779f..080485e 100644
--- a/src/dlog.c
+++ b/src/dlog.c
@@ -19,8 +19,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 
-#include "hf/arch/console.h"
-
+#include "hf/plat/console.h"
 #include "hf/spinlock.h"
 #include "hf/std.h"
 
@@ -57,7 +56,7 @@
 	const char *c = str;
 
 	while (*c != '\0') {
-		arch_putchar(*c++);
+		plat_console_putchar(*c++);
 	}
 
 	return c - str;
@@ -79,14 +78,14 @@
 
 	/* Print the string up to the beginning of the suffix. */
 	while (str != suffix) {
-		arch_putchar(*str++);
+		plat_console_putchar(*str++);
 	}
 
 	if (flags & FLAG_MINUS) {
 		/* Left-aligned. Print suffix, then print padding if needed. */
 		len += print_raw_string(suffix);
 		while (len < width) {
-			arch_putchar(' ');
+			plat_console_putchar(' ');
 			len++;
 		}
 		return;
@@ -95,7 +94,7 @@
 	/* Fill until we reach the desired length. */
 	len += strnlen_s(suffix, DLOG_MAX_STRING_LENGTH);
 	while (len < width) {
-		arch_putchar(fill);
+		plat_console_putchar(fill);
 		len++;
 	}
 
@@ -208,7 +207,7 @@
 	for (p = fmt; *p; p++) {
 		switch (*p) {
 		default:
-			arch_putchar(*p);
+			plat_console_putchar(*p);
 			break;
 
 		case '%':
@@ -296,7 +295,7 @@
 				break;
 
 			default:
-				arch_putchar('%');
+				plat_console_putchar('%');
 			}
 
 			break;
diff --git a/src/load.c b/src/load.c
index 41c417c..c0db072 100644
--- a/src/load.c
+++ b/src/load.c
@@ -25,6 +25,7 @@
 #include "hf/layout.h"
 #include "hf/memiter.h"
 #include "hf/mm.h"
+#include "hf/plat/console.h"
 #include "hf/std.h"
 #include "hf/vm.h"
 
@@ -327,11 +328,7 @@
 			continue;
 		}
 
-		/* TODO: Remove this. */
-		/* Grant VM access to uart. */
-		mm_vm_identity_map(&vm->ptable, pa_init(PL011_BASE),
-				   pa_add(pa_init(PL011_BASE), PAGE_SIZE),
-				   MM_MODE_R | MM_MODE_W, NULL, ppool);
+		plat_console_vm_mm_init(vm, ppool);
 
 		/* Grant the VM access to the memory. */
 		if (!mm_vm_identity_map(&vm->ptable, secondary_mem_begin,
diff --git a/src/main.c b/src/main.c
index e5dc7b7..79cadc9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -28,6 +28,7 @@
 #include "hf/mm.h"
 #include "hf/mpool.h"
 #include "hf/panic.h"
+#include "hf/plat/console.h"
 #include "hf/std.h"
 #include "hf/vm.h"
 
@@ -50,6 +51,9 @@
 	size_t i;
 	struct mpool ppool;
 
+	/* Make sure the console is initialised before calling dlog. */
+	plat_console_init();
+
 	dlog("Initialising hafnium\n");
 
 	arch_one_time_init();
diff --git a/src/mm.c b/src/mm.c
index 6de6bc6..50f4aa1 100644
--- a/src/mm.c
+++ b/src/mm.c
@@ -22,6 +22,7 @@
 #include "hf/assert.h"
 #include "hf/dlog.h"
 #include "hf/layout.h"
+#include "hf/plat/console.h"
 
 /**
  * This file has functions for managing the level 1 and 2 page tables used by
@@ -906,11 +907,8 @@
 		return false;
 	}
 
-	/* Map page for uart. */
-	/* TODO: We may not want to map this. */
-	mm_identity_map(pa_init(PL011_BASE),
-			pa_add(pa_init(PL011_BASE), PAGE_SIZE),
-			MM_MODE_R | MM_MODE_W | MM_MODE_D, ppool);
+	/* Let console driver map pages for itself. */
+	plat_console_mm_init(ppool);
 
 	/* Map each section. */
 	mm_identity_map(layout_text_begin(), layout_text_end(), MM_MODE_X,