Introduce a DT-based manifest

These are first steps towards a new manifest format. A new "device_tree"
build target is introduced to compile DTS files to DTB, and
`generate_initrd.py` now does not produce a "vms.txt" file. Instead
"initrd" targets are expected to provide a path to a DTS manifest in the
format:

    /dts-v1/;

    / {
      hypervisor {
        vm1 {
	  debug_name = "primary";
	};

	vm2 {
	  debug_name = "secondary1";
	  kernel_filename = "filename";
	  vcpu_count = <N>;
          mem_size = <M>;
	};

	...
      };
    };

The information provided in the manifest matches "vms.txt".

Bug: 117551352
Test: manifest_test.cc
Test: used by hftest
Change-Id: I6b70bd44d2b110c4f7a6b971018c834084b6d8c4
diff --git a/build/image/generate_initrd.py b/build/image/generate_initrd.py
index 6fb76de..8342cfb 100644
--- a/build/image/generate_initrd.py
+++ b/build/image/generate_initrd.py
@@ -29,17 +29,27 @@
 
 def Main():
     parser = argparse.ArgumentParser()
+    parser.add_argument("--manifest", required=True)
     parser.add_argument("--primary_vm", required=True)
     parser.add_argument("--primary_vm_initrd")
     parser.add_argument(
         "--secondary_vm",
         action="append",
-        nargs=4,
-        metavar=("MEMORY", "CORES", "NAME", "IMAGE"))
+        nargs=2,
+        metavar=("NAME", "IMAGE"))
     parser.add_argument("--staging", required=True)
     parser.add_argument("--output", required=True)
     args = parser.parse_args()
     staged_files = ["vmlinuz", "initrd.img"]
+
+    # Create staging folder if needed.
+    if not os.path.isdir(args.staging):
+        os.makedirs(args.staging)
+
+    # Prepare the manifest.
+    if args.manifest:
+        shutil.copyfile(args.manifest, os.path.join(args.staging, "manifest.dtb"))
+        staged_files += ["manifest.dtb"]
     # Prepare the primary VM image.
     shutil.copyfile(args.primary_vm, os.path.join(args.staging, "vmlinuz"))
     # Prepare the primary VM's initrd.
@@ -48,14 +58,11 @@
     else:
         open(os.path.join(args.staging, "initrd.img"), "w").close()
     # Prepare the secondary VMs.
-    with open(os.path.join(args.staging, "vms.txt"), "w") as vms_txt:
-        staged_files.append("vms.txt")
-        if args.secondary_vm:
-            for vm in args.secondary_vm:
-                (vm_memory, vm_cores, vm_name, vm_image) = vm
-                staged_files.append(vm_name)
-                shutil.copy(vm_image, os.path.join(args.staging, vm_name))
-                vms_txt.write("{} {} {}\n".format(vm_memory, vm_cores, vm_name))
+    if args.secondary_vm:
+        for vm in args.secondary_vm:
+            (vm_name, vm_image) = vm
+            staged_files.append(vm_name)
+            shutil.copy(vm_image, os.path.join(args.staging, vm_name))
     # Package files into an initial RAM disk.
     with open(args.output, "w") as initrd:
         # Move into the staging directory so the file names taken by cpio don't