Merge manifest into the board DT, add boot flow drivers
Hafnium currently supports two kinds of boot flow:
(a) Linux-like, where the board FDT is passed by the boot loader to
the OS kernel in first kernel arg (this is used by QEMU, FVP, RPi, ...),
(b) Android-like, where the FDT used by Hafnium is compiled into it and
the VMs have their own.
This used to be implemented using weak symbols and each board spec
overriding it with its own implementation. This patch introduces the
concept of boot-flow drivers in the main tree, and the corresponding
driver selected using a config option in board spec. Drivers for the two
boot-flows described above are implemented.
Simultaneously, the manifest is now read from the FDT available at
Hafnium init time. This required two notable changes:
(1) all values are copied into the manifest struct because FDT is
unmapped, modified and passed to the primary VM,
(2) manifest is now written as an overlay; QEMU and FVP test drivers
overlay it automatically.
Bug: 117551352
Change-Id: Ieae7fe4ef5b3047174ec0ad057e487660ccd5a03
diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md
index dba6365..1989855 100644
--- a/docs/GettingStarted.md
+++ b/docs/GettingStarted.md
@@ -51,11 +51,32 @@
machines to run. Follow the [Hafnium RAM disk](HafniumRamDisk.md) instructions
to create an initial RAM disk for Hafnium with Linux as the primary VM.
+Next, you need to create a manifest which will describe the VM to Hafnium.
+Follow the [Manifest](Manifest.md) instructions and build a DTBO with:
+```
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ hypervisor {
+ vm1 {
+ debug_name = "Linux VM";
+ };
+ };
+};
+```
+
+Dump the DTB used by QEMU:
+```shell
+qemu-system-aarch64 -M virt,gic_version=3 -cpu cortex-a57 -nographic -machine virtualization=true -kernel out/reference/qemu_aarch64_clang/hafnium.bin -initrd initrd.img -append "rdinit=/sbin/init" -machine dumpdtb=qemu.dtb
+```
+and follow instructions in [Manifest](Manifest.md) to overlay it with the manifest.
+
The following command line will run Hafnium, with the RAM disk just created,
which will then boot into the primary Linux VM:
```shell
-qemu-system-aarch64 -M virt,gic_version=3 -cpu cortex-a57 -nographic -machine virtualization=true -kernel out/reference/qemu_aarch64_clang/hafnium.bin -initrd initrd.img -append "rdinit=/sbin/init"
+qemu-system-aarch64 -M virt,gic_version=3 -cpu cortex-a57 -nographic -machine virtualization=true -kernel out/reference/qemu_aarch64_clang/hafnium.bin -initrd initrd.img -append "rdinit=/sbin/init" -dtb=qemu_with_manifest.dtb
```
## Running tests
diff --git a/docs/HafniumRamDisk.md b/docs/HafniumRamDisk.md
index 37e27db..c09568d 100644
--- a/docs/HafniumRamDisk.md
+++ b/docs/HafniumRamDisk.md
@@ -5,71 +5,11 @@
* `vmlinuz` -- the kernel of the primary VM.
* `initrd.img` -- the initial ramdisk of the primary VM.
-* `manifest.dtb` -- hypervisor configuration file.
* kernels for the secondary VMs, whose names are described in the manifest.
Follow the [preparing Linux](PreparingLinux.md) instructions to produce
`vmlinuz` and `initrd.img` for a basic Linux primary VM.
-## Manifest file
-
-The format is currently a simple Device Tree:
-
-```
-/dts-v1/;
-
-/ {
- hypervisor {
- vm1 {
- debug_name = "name";
- };
-
- vm2 {
- debug_name = "name";
- kernel_filename = "filename";
- vcpu_count = <N>;
- mem_size = <M>;
- };
- ...
- };
-};
-```
-
-For example, the following defines two secondary VMs, the first one with 1MB of
-memory, 2 CPUs and kernel image called `kernel0`, while the second one has 2MB
-of memory, 4 CPUs and a kernel image called `kernel1`.
-
-```
-/dts-v1/;
-
-/ {
- hypervisor {
- vm1 {
- debug_name = "primary VM";
- };
-
- vm2 {
- debug_name = "secondary VM 1";
- kernel_filename = "kernel0";
- vcpu_count = <2>;
- mem_size = <0x100000>;
- };
-
- vm3 {
- debug_name = "secondary VM 2";
- kernel_filename = "kernel1";
- vcpu_count = <4>;
- mem_size = <0x200000>;
- };
- };
-};
-```
-
-Hafnium expects the manifest in Device Tree Blob format. Compile it with:
-```shell
-dtc -I dts -O dtb --out-version 17 -o manifest.dtb <manifest_source_file>
-```
-
## Create a RAM disk for Hafnium
Assuming that a subdirectory called `initrd` contains the files listed in the
diff --git a/docs/Manifest.md b/docs/Manifest.md
new file mode 100644
index 0000000..58a5600
--- /dev/null
+++ b/docs/Manifest.md
@@ -0,0 +1,79 @@
+# Hafnium Manifest
+
+## Format
+
+The format of the manifest is a simple DeviceTree overlay:
+
+```
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ hypervisor {
+ vm1 {
+ debug_name = "name";
+ };
+
+ vm2 {
+ debug_name = "name";
+ kernel_filename = "filename";
+ vcpu_count = <N>;
+ mem_size = <M>;
+ };
+ ...
+ };
+};
+```
+
+Note: `&{/}` is a syntactic sugar expanded by the DTC compiler. Make sure to
+use the DTC in `prebuilts/` as the version packaged with your OS may not support
+it yet.
+
+## Example
+
+The following manifest defines two secondary VMs, the first one with 1MB of
+memory, 2 CPUs and kernel image called `kernel0` (matches filename in Hafnium's
+[ramdisk](HafniumRamDisk.md)), while the second one has 2MB of memory, 4 CPUs
+and a kernel image called `kernel1`.
+
+```
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ hypervisor {
+ vm1 {
+ debug_name = "primary VM";
+ };
+
+ vm2 {
+ debug_name = "secondary VM 1";
+ kernel_filename = "kernel0";
+ vcpu_count = <2>;
+ mem_size = <0x100000>;
+ };
+
+ vm3 {
+ debug_name = "secondary VM 2";
+ kernel_filename = "kernel1";
+ vcpu_count = <4>;
+ mem_size = <0x200000>;
+ };
+ };
+};
+```
+
+## Compiling
+
+Hafnium expects the manifest as part of the board FDT, i.e. DeviceTree in binary
+format (DTB).
+
+First, compile the manifest into a DTBO (binary overlay):
+```shell
+prebuilts/linux-x64/dtc/dtc -I dts -O dtb --out-version 17 -o manifest.dtbo <manifest_source_file>
+```
+
+Then overlay it with the DTB of your board:
+```shell
+prebuilts/linux-x64/dtc/fdtoverlay -i <board DTB> -o <output DTB> manifest.dtbo
+```