Ramdisk in the manifest, simplify initrd generation
We currently support loading a ramdisk for the primary. In fact, all
primaries are required to have one called 'initrd.img'. This makes
the ramdisk optional and specifies its filename in the manifest.
With that, generate_initrd.py loses the last remaining hardcoded
assumption about the structure of the Hafnium ramdisk. Refactor the
script and the build so that generate_initrd.py simply accepts a list of
(name in ramdisk, path on host) pairs.
Bug: 117551352
Change-Id: Iff2d70205940a1740c473d1cac34d5a05d6d6791
diff --git a/src/boot_flow/android.c b/src/boot_flow/android.c
index cf7246e..0221674 100644
--- a/src/boot_flow/android.c
+++ b/src/boot_flow/android.c
@@ -51,10 +51,12 @@
* Android boot flow does not change based on the updates.
*/
bool plat_boot_flow_update(struct mm_stage1_locked stage1_locked,
+ const struct manifest *manifest,
struct boot_params_update *p, struct memiter *cpio,
struct mpool *ppool)
{
(void)stage1_locked;
+ (void)manifest;
(void)p;
(void)cpio;
(void)ppool;
diff --git a/src/boot_flow/common.c b/src/boot_flow/common.c
index 586d3d2..b295824 100644
--- a/src/boot_flow/common.c
+++ b/src/boot_flow/common.c
@@ -87,8 +87,9 @@
* Takes action on any updates that were generated.
*/
bool boot_flow_update(struct mm_stage1_locked stage1_locked,
+ const struct manifest *manifest,
struct boot_params_update *p, struct memiter *cpio,
struct mpool *ppool)
{
- return plat_boot_flow_update(stage1_locked, p, cpio, ppool);
+ return plat_boot_flow_update(stage1_locked, manifest, p, cpio, ppool);
}
diff --git a/src/boot_flow/linux.c b/src/boot_flow/linux.c
index 9d4d886..e1e257c 100644
--- a/src/boot_flow/linux.c
+++ b/src/boot_flow/linux.c
@@ -52,14 +52,19 @@
}
bool plat_boot_flow_update(struct mm_stage1_locked stage1_locked,
+ const struct manifest *manifest,
struct boot_params_update *update,
struct memiter *cpio, struct mpool *ppool)
{
- static struct string filename = STRING_INIT("initrd.img");
struct memiter primary_initrd;
+ const struct string *filename =
+ &manifest->vm[HF_PRIMARY_VM_INDEX].primary.ramdisk_filename;
- if (!cpio_get_file(cpio, &filename, &primary_initrd)) {
- dlog("Unable to find initrd.img\n");
+ if (string_is_empty(filename)) {
+ memiter_init(&primary_initrd, NULL, 0);
+ } else if (!cpio_get_file(cpio, filename, &primary_initrd)) {
+ dlog("Unable to find primary initrd \"%s\".\n",
+ string_data(filename));
return false;
}
diff --git a/src/init.c b/src/init.c
index 4948697..6d9e8ad 100644
--- a/src/init.c
+++ b/src/init.c
@@ -116,7 +116,8 @@
panic("Unable to load VMs.");
}
- if (!boot_flow_update(mm_stage1_locked, &update, &cpio, &ppool)) {
+ if (!boot_flow_update(mm_stage1_locked, &manifest, &update, &cpio,
+ &ppool)) {
panic("Unable to update boot flow.");
}
diff --git a/src/load.c b/src/load.c
index 7138824..01640f8 100644
--- a/src/load.c
+++ b/src/load.c
@@ -100,8 +100,8 @@
struct mpool *ppool)
{
paddr_t primary_begin = layout_primary_begin();
- const struct manifest_vm *manifest_vm =
- &manifest->vm[HF_PRIMARY_VM_ID - HF_VM_ID_OFFSET];
+ struct vm *vm;
+ struct vcpu_locked vcpu_locked;
/*
* TODO: This bound is currently meaningless but will be addressed when
@@ -109,46 +109,41 @@
*/
paddr_t primary_end = pa_add(primary_begin, 0x8000000);
- if (!load_kernel(stage1_locked, primary_begin, primary_end, manifest_vm,
- cpio, ppool)) {
+ if (!load_kernel(stage1_locked, primary_begin, primary_end,
+ &manifest->vm[HF_PRIMARY_VM_INDEX], cpio, ppool)) {
dlog("Unable to load primary kernel.");
return false;
}
- {
- struct vm *vm;
- struct vcpu_locked vcpu_locked;
-
- if (!vm_init(MAX_CPUS, ppool, &vm)) {
- dlog("Unable to initialise primary vm\n");
- return false;
- }
-
- if (vm->id != HF_PRIMARY_VM_ID) {
- dlog("Primary vm was not given correct id\n");
- return false;
- }
-
- /* Map the 1TB of memory. */
- /* TODO: We should do a whitelist rather than a blacklist. */
- if (!mm_vm_identity_map(
- &vm->ptable, pa_init(0),
- pa_init(UINT64_C(1024) * 1024 * 1024 * 1024),
- MM_MODE_R | MM_MODE_W | MM_MODE_X, NULL, ppool)) {
- dlog("Unable to initialise memory for primary vm\n");
- return false;
- }
-
- if (!mm_vm_unmap_hypervisor(&vm->ptable, ppool)) {
- dlog("Unable to unmap hypervisor from primary vm\n");
- return false;
- }
-
- vcpu_locked = vcpu_lock(vm_get_vcpu(vm, 0));
- vcpu_on(vcpu_locked, ipa_from_pa(primary_begin), kernel_arg);
- vcpu_unlock(&vcpu_locked);
+ if (!vm_init(MAX_CPUS, ppool, &vm)) {
+ dlog("Unable to initialise primary vm\n");
+ return false;
}
+ if (vm->id != HF_PRIMARY_VM_ID) {
+ dlog("Primary vm was not given correct id\n");
+ return false;
+ }
+
+ /* Map the 1TB of memory. */
+ /* TODO: We should do a whitelist rather than a blacklist. */
+ if (!mm_vm_identity_map(&vm->ptable, pa_init(0),
+ pa_init(UINT64_C(1024) * 1024 * 1024 * 1024),
+ MM_MODE_R | MM_MODE_W | MM_MODE_X, NULL,
+ ppool)) {
+ dlog("Unable to initialise memory for primary vm\n");
+ return false;
+ }
+
+ if (!mm_vm_unmap_hypervisor(&vm->ptable, ppool)) {
+ dlog("Unable to unmap hypervisor from primary vm\n");
+ return false;
+ }
+
+ vcpu_locked = vcpu_lock(vm_get_vcpu(vm, 0));
+ vcpu_on(vcpu_locked, ipa_from_pa(primary_begin), kernel_arg);
+ vcpu_unlock(&vcpu_locked);
+
return true;
}
diff --git a/src/manifest.c b/src/manifest.c
index 6d8b4ba..222716f 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -209,7 +209,10 @@
TRY(read_string(node, "debug_name", &vm->debug_name));
TRY(read_optional_string(node, "kernel_filename",
&vm->kernel_filename));
- if (vm_id != HF_PRIMARY_VM_ID) {
+ if (vm_id == HF_PRIMARY_VM_ID) {
+ TRY(read_optional_string(node, "ramdisk_filename",
+ &vm->primary.ramdisk_filename));
+ } else {
TRY(read_uint64(node, "mem_size", &vm->secondary.mem_size));
TRY(read_uint16(node, "vcpu_count", &vm->secondary.vcpu_count));
}
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index d7690b4..902cf21 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -161,6 +161,11 @@
return StringProperty("kernel_filename", value);
}
+ ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
+ {
+ return StringProperty("ramdisk_filename", value);
+ }
+
ManifestDtBuilder &VcpuCount(uint64_t value)
{
return IntegerProperty("vcpu_count", value);
@@ -398,6 +403,29 @@
MANIFEST_ERROR_INTEGER_OVERFLOW);
}
+TEST(manifest, no_ramdisk_primary)
+{
+ struct manifest m;
+ struct fdt_node fdt_root;
+
+ /* clang-format off */
+ std::vector<char> dtb = ManifestDtBuilder()
+ .StartChild("hypervisor")
+ .Compatible()
+ .StartChild("vm1")
+ .DebugName("primary_vm")
+ .EndChild()
+ .EndChild()
+ .Build();
+ /* clang-format on */
+
+ ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
+ ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
+ ASSERT_EQ(m.vm_count, 1);
+ ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
+ ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
+}
+
TEST(manifest, valid)
{
struct manifest m;
@@ -411,6 +439,7 @@
.StartChild("vm1")
.DebugName("primary_vm")
.KernelFilename("primary_kernel")
+ .RamdiskFilename("primary_ramdisk")
.EndChild()
.StartChild("vm3")
.DebugName("second_secondary_vm")
@@ -435,6 +464,8 @@
vm = &m.vm[0];
ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
+ ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
+ "primary_ramdisk");
vm = &m.vm[1];
ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");