Allow projects to define their own build.

To create a new project, add a directory under `project` and pass the
project name to `make`:

    mkdir project/my_project
    # Describe the build for the project.
    PROJECT=my_project make

Projects can be maintained separately from the main repository.

Change-Id: I33a9d7ca801e2fb3dd9795ece44577b3b565e913
diff --git a/build/BUILD.gn b/build/BUILD.gn
index 06cf616..1c753ff 100644
--- a/build/BUILD.gn
+++ b/build/BUILD.gn
@@ -36,12 +36,12 @@
   include_dirs = [
     "//inc",
     "//inc/vmapi",
-    "//src/arch/${arch}/inc",
+    "//src/arch/${plat_arch}/inc",
   ]
 
   defines = [
-    "MAX_CPUS=${platform_max_cpus}",
-    "MAX_VMS=${platform_max_vms}",
+    "MAX_CPUS=${plat_max_cpus}",
+    "MAX_VMS=${plat_max_vms}",
   ]
 
   if (is_debug) {
diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn
index aca2f24..ce3069d 100644
--- a/build/BUILDCONFIG.gn
+++ b/build/BUILDCONFIG.gn
@@ -14,11 +14,16 @@
 
 # Configuration of the build toolchain.
 declare_args() {
+  # The name of the project being built.
+  project = "reference"
+
   # Enable extra debugging.
   is_debug = true
 
-  # The architecture to build the bare metal images for.
-  arch = "host"
+  # Whether to build against the platform for embedded images consisting of
+  # include paths and defines. This is also used for host targets that simulate
+  # an embedded image.
+  use_platform = false
 }
 
 # Check that we support the attempted build.
@@ -45,7 +50,7 @@
 _shared_binary_target_configs = [ "//build:compiler_defaults" ]
 
 # If it's not building a host utility, it's building against the platform so apply the configuration.
-if (arch != "host") {
+if (use_platform) {
   _shared_binary_target_configs += [ "//build:platform" ]
 }
 
diff --git a/build/image/image.ld b/build/image/image.ld
index cede756..5973488 100644
--- a/build/image/image.ld
+++ b/build/image/image.ld
@@ -1,4 +1,20 @@
 /*
+ * Copyright 2018 Google LLC
+ *
+ * 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.
+ */
+
+/*
  * Code will start running at this symbol which is places at the start of the
  * image.
  */
@@ -84,6 +100,29 @@
 	rodata_end = .;
 
 	/*
+	 * A platform may choose to link blobs such as the FDT or the initrd
+	 * into the image rather than having them loaded separately. These are
+	 * placed at the end of the image and will not be mapped automatically
+	 * on boot so they can be treated as if they were loaded as separate
+	 * blobs. They are page aligned so they can be mapped individually.
+	 *
+	 * TODO: remove this when the loader can reliably deliver both the
+	 * binary and a separate blob for the initrd.
+	 */
+	. = ALIGN(4096);
+	initrd_begin = .;
+	.initrd : {
+		KEEP(*(.plat.initrd))
+	}
+	initrd_end = .;
+	. = ALIGN(4096);
+	fdt_begin = .;
+	.fdt : {
+		KEEP(*(.plat.fdt))
+	}
+	fdt_end = .;
+
+	/*
 	 * Collect together the read-write data including .bss at the end which
 	 * will be zero'd by the entry code. This is page aligned so it can be
 	 * mapped as non-executable.
diff --git a/build/toolchain/BUILD.gn b/build/toolchain/BUILD.gn
index 344d30e..916c1c7 100644
--- a/build/toolchain/BUILD.gn
+++ b/build/toolchain/BUILD.gn
@@ -12,42 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("//build/toolchain/embedded.gni")
 import("//build/toolchain/host.gni")
 
 host_toolchain("host") {
-  use_fake_arch = false
-}
-
-host_toolchain("host_fake") {
-  use_fake_arch = true
-  max_cpus = 4
-  max_vms = 6
-}
-
-aarch64_toolchain("qemu_aarch64") {
-  cpu = "cortex-a57+nofp"
-  origin_address = "0x40001000"
-  use_pl011 = true
-  pl011_base_address = "0x09000000"
-  max_cpus = 8
-  max_vms = 16
-}
-
-aarch64_toolchain("hikey") {
-  cpu = "cortex-a53+nofp"
-  origin_address = "0x01000000"
-  use_pl011 = true
-  pl011_base_address = "0xf8015000"
-  max_cpus = 8
-  max_vms = 16
-}
-
-aarch64_toolchain("aem_v8a_fvp") {
-  cpu = "cortex-a57+nofp"
-  origin_address = "0x88000000"
-  use_pl011 = true
-  pl011_base_address = "0x1c090000"
-  max_cpus = 8
-  max_vms = 16
+  use_platform = false
 }
diff --git a/build/toolchain/embedded.gni b/build/toolchain/embedded.gni
index b9a5cdd..290f163 100644
--- a/build/toolchain/embedded.gni
+++ b/build/toolchain/embedded.gni
@@ -185,9 +185,11 @@
     extra_cflags = cflags
     extra_ldflags = ldflags
     toolchain_args = {
-      platform_max_cpus = invoker.max_cpus
-      platform_max_vms = invoker.max_vms
-      arch = invoker.arch
+      use_platform = true
+      plat_name = invoker.target_name
+      plat_arch = invoker.arch
+      plat_max_cpus = invoker.max_cpus
+      plat_max_vms = invoker.max_vms
       if (defined(invoker.toolchain_args)) {
         forward_variables_from(invoker.toolchain_args, "*")
       }
@@ -200,9 +202,11 @@
     extra_cflags = cflags
     extra_ldflags = ldflags
     toolchain_args = {
-      platform_max_cpus = invoker.max_cpus
-      platform_max_vms = invoker.max_vms
-      arch = invoker.arch
+      use_platform = true
+      plat_name = invoker.target_name
+      plat_arch = invoker.arch
+      plat_max_cpus = invoker.max_cpus
+      plat_max_vms = invoker.max_vms
       if (defined(invoker.toolchain_args)) {
         forward_variables_from(invoker.toolchain_args, "*")
       }
diff --git a/build/toolchain/host.gni b/build/toolchain/host.gni
index 8b39a77..11bf388 100644
--- a/build/toolchain/host.gni
+++ b/build/toolchain/host.gni
@@ -123,9 +123,9 @@
 }
 
 template("host_toolchain") {
-  assert(defined(invoker.use_fake_arch),
-         "\"use_fake_arch\" must be defined for ${target_name}.")
-  if (invoker.use_fake_arch) {
+  assert(defined(invoker.use_platform),
+         "\"use_platform\" must be defined for ${target_name}.")
+  if (invoker.use_platform) {
     assert(defined(invoker.max_cpus),
            "\"max_cpus\" must be defined for ${target_name}.")
     assert(defined(invoker.max_vms),
@@ -141,14 +141,15 @@
     # TODO: remove the need for this
     extra_defines = "-DPL011_BASE=0"
 
-    if (invoker.use_fake_arch) {
+    if (invoker.use_platform) {
       toolchain_args = {
-        platform_max_cpus = invoker.max_cpus
-        platform_max_vms = invoker.max_vms
+        use_platform = true
 
         # When building for the ${target_name}, use the fake architecture to make things
         # testable.
-        arch = "fake"
+        plat_arch = "fake"
+        plat_max_cpus = invoker.max_cpus
+        plat_max_vms = invoker.max_vms
       }
     }
   }
@@ -162,14 +163,15 @@
     # TODO: remove the need for this
     extra_defines = "-DPL011_BASE=0"
 
-    if (invoker.use_fake_arch) {
+    if (invoker.use_platform) {
       toolchain_args = {
-        platform_max_cpus = invoker.max_cpus
-        platform_max_vms = invoker.max_vms
+        use_platform = true
 
         # When building for the ${target_name}, use the fake architecture to make things
         # testable.
-        arch = "fake"
+        plat_arch = "fake"
+        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 7a1c8a9..4bcfdc3 100644
--- a/build/toolchain/platform.gni
+++ b/build/toolchain/platform.gni
@@ -14,9 +14,15 @@
 
 # Configuration of the build for the platform.
 declare_args() {
+  # The name of the platform.
+  plat_name = ""
+
+  # The architecture of the platform.
+  plat_arch = ""
+
   # The maximum number of CPUs available on the platform.
-  platform_max_cpus = 0
+  plat_max_cpus = 0
 
   # The maximum number of VMs required for the platform.
-  platform_max_vms = 0
+  plat_max_vms = 0
 }