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/src/load.c b/src/load.c
index 341f276..25e593c 100644
--- a/src/load.c
+++ b/src/load.c
@@ -22,7 +22,6 @@
#include "hf/boot_params.h"
#include "hf/dlog.h"
#include "hf/layout.h"
-#include "hf/manifest.h"
#include "hf/memiter.h"
#include "hf/mm.h"
#include "hf/plat/console.h"
@@ -251,16 +250,13 @@
* Memory reserved for the VMs is added to the `reserved_ranges` of `update`.
*/
bool load_secondary(struct mm_stage1_locked stage1_locked,
- const struct memiter *cpio,
+ const struct manifest *manifest, const struct memiter *cpio,
const struct boot_params *params,
struct boot_params_update *update, struct mpool *ppool)
{
struct vm *primary;
- struct manifest manifest;
- struct memiter manifest_fdt;
struct mem_range mem_ranges_available[MAX_MEM_RANGES];
size_t i;
- enum manifest_return_code manifest_ret;
static_assert(
sizeof(mem_ranges_available) == sizeof(params->mem_ranges),
@@ -279,24 +275,13 @@
pa_addr(mem_ranges_available[i].end), PAGE_SIZE));
}
- if (!find_file(cpio, "manifest.dtb", &manifest_fdt)) {
- dlog("Could not find \"manifest.dtb\" in cpio.\n");
- return false;
- }
-
- manifest_ret = manifest_init(&manifest, &manifest_fdt);
- if (manifest_ret != MANIFEST_SUCCESS) {
- dlog("Could not parse manifest: %s.\n",
- manifest_strerror(manifest_ret));
- return false;
- }
-
- for (i = 0; i < manifest.num_vms; ++i) {
- struct manifest_vm *manifest_vm = &manifest.vm[i];
+ for (i = 0; i < manifest->num_vms; ++i) {
+ const struct manifest_vm *manifest_vm = &manifest->vm[i];
spci_vm_id_t vm_id = HF_VM_ID_OFFSET + i;
struct vm *vm;
struct vcpu *vcpu;
struct memiter kernel;
+ struct memiter kernel_filename;
uint64_t mem_size;
paddr_t secondary_mem_begin;
paddr_t secondary_mem_end;
@@ -306,17 +291,16 @@
continue;
}
- dlog("Loading VM%d: ", (int)vm_id);
- memiter_dlog_str(&manifest_vm->debug_name);
- dlog(".\n");
+ dlog("Loading VM%d: %s.\n", (int)vm_id,
+ manifest_vm->debug_name);
- if (!memiter_find_file(cpio,
- &manifest_vm->secondary.kernel_filename,
- &kernel)) {
- dlog("Could not find kernel file \"");
- memiter_dlog_str(
- &manifest_vm->secondary.kernel_filename);
- dlog("\".\n");
+ memiter_init(&kernel_filename,
+ manifest_vm->secondary.kernel_filename,
+ strnlen_s(manifest_vm->secondary.kernel_filename,
+ MANIFEST_MAX_STRING_LENGTH));
+ if (!memiter_find_file(cpio, &kernel_filename, &kernel)) {
+ dlog("Could not find kernel file \"%s\".\n",
+ manifest_vm->secondary.kernel_filename);
continue;
}