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/src/load.c b/src/load.c
index 602cfa8..341f276 100644
--- a/src/load.c
+++ b/src/load.c
@@ -22,6 +22,7 @@
#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"
@@ -40,8 +41,10 @@
* so the data must be available without the cache.
*/
static bool copy_to_unmapped(struct mm_stage1_locked stage1_locked, paddr_t to,
- const void *from, size_t size, struct mpool *ppool)
+ struct memiter *from_it, struct mpool *ppool)
{
+ const void *from = memiter_base(from_it);
+ size_t size = memiter_size(from_it);
paddr_t to_end = pa_add(to, size);
void *ptr;
@@ -120,8 +123,7 @@
}
dlog("Copying primary to %p\n", pa_addr(primary_begin));
- if (!copy_to_unmapped(stage1_locked, primary_begin, it.next,
- it.limit - it.next, ppool)) {
+ if (!copy_to_unmapped(stage1_locked, primary_begin, &it, ppool)) {
dlog("Unable to relocate kernel for primary vm.\n");
return false;
}
@@ -254,12 +256,11 @@
struct boot_params_update *update, struct mpool *ppool)
{
struct vm *primary;
- struct memiter it;
- struct memiter name;
- uint64_t mem;
- uint64_t cpu;
+ 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),
@@ -272,61 +273,74 @@
primary = vm_find(HF_PRIMARY_VM_ID);
- if (!find_file(cpio, "vms.txt", &it)) {
- dlog("vms.txt is missing\n");
- return true;
- }
-
/* Round the last addresses down to the page size. */
for (i = 0; i < params->mem_ranges_count; ++i) {
mem_ranges_available[i].end = pa_init(align_down(
pa_addr(mem_ranges_available[i].end), PAGE_SIZE));
}
- while (memiter_parse_uint(&it, &mem) && memiter_parse_uint(&it, &cpu) &&
- memiter_parse_str(&it, &name)) {
+ 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];
+ spci_vm_id_t vm_id = HF_VM_ID_OFFSET + i;
+ struct vm *vm;
+ struct vcpu *vcpu;
struct memiter kernel;
+ uint64_t mem_size;
paddr_t secondary_mem_begin;
paddr_t secondary_mem_end;
ipaddr_t secondary_entry;
- const char *p;
- struct vm *vm;
- struct vcpu *vcpu;
- dlog("Loading ");
- for (p = name.next; p != name.limit; ++p) {
- dlog("%c", *p);
- }
- dlog("\n");
-
- if (!memiter_find_file(cpio, &name, &kernel)) {
- dlog("Unable to load kernel\n");
+ if (vm_id == HF_PRIMARY_VM_ID) {
continue;
}
- /* Round up to page size. */
- mem = (mem + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ dlog("Loading VM%d: ", (int)vm_id);
+ memiter_dlog_str(&manifest_vm->debug_name);
+ dlog(".\n");
- if (mem < kernel.limit - kernel.next) {
+ 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");
+ continue;
+ }
+
+ mem_size = align_up(manifest_vm->secondary.mem_size, PAGE_SIZE);
+ if (mem_size < memiter_size(&kernel)) {
dlog("Kernel is larger than available memory\n");
continue;
}
- if (!carve_out_mem_range(
- mem_ranges_available, params->mem_ranges_count, mem,
- &secondary_mem_begin, &secondary_mem_end)) {
- dlog("Not enough memory (%u bytes)\n", mem);
+ if (!carve_out_mem_range(mem_ranges_available,
+ params->mem_ranges_count, mem_size,
+ &secondary_mem_begin,
+ &secondary_mem_end)) {
+ dlog("Not enough memory (%u bytes)\n", mem_size);
continue;
}
if (!copy_to_unmapped(stage1_locked, secondary_mem_begin,
- kernel.next, kernel.limit - kernel.next,
- ppool)) {
+ &kernel, ppool)) {
dlog("Unable to copy kernel\n");
continue;
}
- if (!vm_init(cpu, ppool, &vm)) {
+ if (!vm_init(manifest_vm->secondary.vcpu_count, ppool, &vm)) {
dlog("Unable to initialise VM\n");
continue;
}
@@ -347,7 +361,8 @@
return false;
}
- dlog("Loaded with %u vcpus, entry at %#x\n", cpu,
+ dlog("Loaded with %u vcpus, entry at %#x\n",
+ manifest_vm->secondary.vcpu_count,
pa_addr(secondary_mem_begin));
vcpu = vm_get_vcpu(vm, 0);