Move manifest to initrd
Supporting the manifest as part of FDT is problematic for testing
under the Android boot flow because it requires compiling and flashing
a different Hafnium image per test suite. Moving it back to the initrd
allows us to run different test suites against the same Hafnium image,
only by swapping the RAM disks.
Hafnium's one_time_init() routine will now expect to find the manifest
under "manifest.dtb".
Change-Id: Ifabffb50b06ffaba786046733d575adc9d43f4ad
diff --git a/src/boot_flow/common.c b/src/boot_flow/common.c
index 834f746..c256eac 100644
--- a/src/boot_flow/common.c
+++ b/src/boot_flow/common.c
@@ -22,8 +22,8 @@
/**
* Extract the boot parameters from the FDT and the boot-flow driver.
*/
-static bool boot_params_init(struct boot_params *p,
- const struct fdt_node *fdt_root)
+bool boot_flow_get_params(struct boot_params *p,
+ const struct fdt_node *fdt_root)
{
p->mem_ranges_count = 0;
p->kernel_arg = plat_boot_flow_get_kernel_arg();
@@ -35,32 +35,6 @@
}
/**
- * Parses information from FDT needed to initialize Hafnium.
- * FDT is mapped at the beginning and unmapped before exiting the function.
- */
-bool boot_flow_init(const struct fdt_node *fdt_root, struct manifest *manifest,
- struct boot_params *boot_params)
-{
- enum manifest_return_code manifest_ret;
-
- /* Get the memory map from the FDT. */
-
- manifest_ret = manifest_init(manifest, fdt_root);
- if (manifest_ret != MANIFEST_SUCCESS) {
- dlog("Could not parse manifest: %s.\n",
- manifest_strerror(manifest_ret));
- return false;
- }
-
- if (!boot_params_init(boot_params, fdt_root)) {
- dlog("Could not parse boot params.\n");
- return false;
- }
-
- return true;
-}
-
-/**
* Takes action on any updates that were generated.
*/
bool boot_flow_update(struct mm_stage1_locked stage1_locked,
diff --git a/src/fdt.c b/src/fdt.c
index 752e9d8..b046662 100644
--- a/src/fdt.c
+++ b/src/fdt.c
@@ -463,7 +463,7 @@
return sizeof(struct fdt_header);
}
-uint32_t fdt_total_size(struct fdt_header *hdr)
+uint32_t fdt_total_size(const struct fdt_header *hdr)
{
return be32toh(hdr->totalsize);
}
diff --git a/src/init.c b/src/init.c
index 897039f..34cabd9 100644
--- a/src/init.c
+++ b/src/init.c
@@ -71,12 +71,15 @@
*/
void one_time_init(void)
{
+ struct string manifest_fname = STRING_INIT("manifest.dtb");
struct fdt_header *fdt;
struct fdt_node fdt_root;
struct manifest manifest;
+ enum manifest_return_code manifest_ret;
struct boot_params params;
struct boot_params_update update;
struct memiter cpio;
+ struct memiter manifest_it;
void *initrd;
size_t i;
struct mm_stage1_locked mm_stage1_locked;
@@ -92,27 +95,17 @@
fdt = fdt_map(mm_stage1_locked, plat_boot_flow_get_fdt_addr(),
&fdt_root, &ppool);
if (fdt == NULL) {
- panic("Unable to map FDT.\n");
+ panic("Unable to map FDT.");
}
if (!fdt_find_child(&fdt_root, "")) {
- panic("Unable to find FDT root node.\n");
+ panic("Unable to find FDT root node.");
}
- if (!boot_flow_init(&fdt_root, &manifest, ¶ms)) {
- panic("Could not parse data from FDT.");
+ if (!boot_flow_get_params(¶ms, &fdt_root)) {
+ panic("Could not parse boot params.");
}
- if (!plat_iommu_init(&fdt_root, mm_stage1_locked, &ppool)) {
- panic("Could not initialize IOMMUs.");
- }
-
- if (!fdt_unmap(mm_stage1_locked, fdt, &ppool)) {
- panic("Unable to unmap FDT.\n");
- }
-
- cpu_module_init(params.cpu_ids, params.cpu_count);
-
for (i = 0; i < params.mem_ranges_count; ++i) {
dlog("Memory range: %#x - %#x\n",
pa_addr(params.mem_ranges[i].begin),
@@ -132,6 +125,26 @@
memiter_init(&cpio, initrd,
pa_difference(params.initrd_begin, params.initrd_end));
+ if (!cpio_get_file(&cpio, &manifest_fname, &manifest_it)) {
+ panic("Could not find manifest in initrd.");
+ }
+
+ manifest_ret = manifest_init(&manifest, &manifest_it);
+ if (manifest_ret != MANIFEST_SUCCESS) {
+ panic("Could not parse manifest: %s.",
+ manifest_strerror(manifest_ret));
+ }
+
+ if (!plat_iommu_init(&fdt_root, mm_stage1_locked, &ppool)) {
+ panic("Could not initialize IOMMUs.");
+ }
+
+ if (!fdt_unmap(mm_stage1_locked, fdt, &ppool)) {
+ panic("Unable to unmap FDT.");
+ }
+
+ cpu_module_init(params.cpu_ids, params.cpu_count);
+
/* Load all VMs. */
update.reserved_ranges_count = 0;
if (!load_vms(mm_stage1_locked, &manifest, &cpio, ¶ms, &update,
diff --git a/src/manifest.c b/src/manifest.c
index d574e55..93560c5 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -306,9 +306,10 @@
* Parse manifest from FDT.
*/
enum manifest_return_code manifest_init(struct manifest *manifest,
- const struct fdt_node *fdt_root)
+ struct memiter *manifest_fdt)
{
char vm_name_buf[VM_NAME_BUF_SIZE];
+ const struct fdt_header *fdt;
struct fdt_node hyp_node;
struct stringlist_iter compatible_list;
size_t i = 0;
@@ -316,8 +317,18 @@
memset_s(manifest, sizeof(*manifest), 0, sizeof(*manifest));
+ fdt = (const struct fdt_header *)memiter_base(manifest_fdt);
+ if (memiter_size(manifest_fdt) != fdt_total_size(fdt)) {
+ return MANIFEST_ERROR_FILE_SIZE;
+ }
+
/* Find hypervisor node. */
- hyp_node = *fdt_root;
+ if (!fdt_root_node(&hyp_node, fdt)) {
+ return MANIFEST_ERROR_NO_ROOT_NODE;
+ }
+ if (!fdt_find_child(&hyp_node, "")) {
+ return MANIFEST_ERROR_NO_ROOT_NODE;
+ }
if (!fdt_find_child(&hyp_node, "hypervisor")) {
return MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE;
}
@@ -374,6 +385,10 @@
switch (ret_code) {
case MANIFEST_SUCCESS:
return "Success";
+ case MANIFEST_ERROR_FILE_SIZE:
+ return "Total size in header does not match file size";
+ case MANIFEST_ERROR_NO_ROOT_NODE:
+ return "Could not find root node in manifest";
case MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE:
return "Could not find \"hypervisor\" node in manifest";
case MANIFEST_ERROR_NOT_COMPATIBLE:
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index fdfd7f5..097c93e 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -260,31 +260,27 @@
std::stringstream dts_;
};
-static bool get_fdt_root(const std::vector<char> &dtb,
- struct fdt_node *fdt_root)
+static enum manifest_return_code manifest_from_vec(struct manifest *m,
+ const std::vector<char> &vec)
{
- const struct fdt_header *fdt_header;
+ struct memiter it;
- fdt_header = reinterpret_cast<const struct fdt_header *>(dtb.data());
- return fdt_root_node(fdt_root, fdt_header) &&
- fdt_find_child(fdt_root, "");
+ memiter_init(&it, vec.data(), vec.size());
+ return manifest_init(m, &it);
}
TEST(manifest, no_hypervisor_node)
{
struct manifest m;
- struct fdt_node fdt_root;
std::vector<char> dtb = ManifestDtBuilder().Build();
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root),
+ ASSERT_EQ(manifest_from_vec(&m, dtb),
MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
}
TEST(manifest, no_compatible_property)
{
struct manifest m;
- struct fdt_node fdt_root;
/* clang-format off */
std::vector<char> dtb = ManifestDtBuilder()
@@ -293,15 +289,13 @@
.Build();
/* clang-format on */
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root),
+ ASSERT_EQ(manifest_from_vec(&m, dtb),
MANIFEST_ERROR_PROPERTY_NOT_FOUND);
}
TEST(manifest, not_compatible)
{
struct manifest m;
- struct fdt_node fdt_root;
/* clang-format off */
std::vector<char> dtb = ManifestDtBuilder()
@@ -311,14 +305,12 @@
.Build();
/* clang-format on */
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_NOT_COMPATIBLE);
+ ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
}
TEST(manifest, compatible_one_of_many)
{
struct manifest m;
- struct fdt_node fdt_root;
/* clang-format off */
std::vector<char> dtb = ManifestDtBuilder()
@@ -331,14 +323,12 @@
.Build();
/* clang-format on */
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
+ ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
}
TEST(manifest, no_vm_nodes)
{
struct manifest m;
- struct fdt_node fdt_root;
/* clang-format off */
std::vector<char> dtb = ManifestDtBuilder()
@@ -348,8 +338,7 @@
.Build();
/* clang-format on */
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_NO_PRIMARY_VM);
+ ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
}
static std::vector<char> gen_long_string_dtb(bool valid)
@@ -374,22 +363,17 @@
TEST(manifest, long_string)
{
struct manifest m;
- struct fdt_node fdt_root;
-
std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
- ASSERT_TRUE(get_fdt_root(dtb_last_valid, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
-
- ASSERT_TRUE(get_fdt_root(dtb_first_invalid, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_STRING_TOO_LONG);
+ ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
+ ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
+ MANIFEST_ERROR_STRING_TOO_LONG);
}
TEST(manifest, reserved_vm_id)
{
struct manifest m;
- struct fdt_node fdt_root;
/* clang-format off */
std::vector<char> dtb = ManifestDtBuilder()
@@ -408,8 +392,7 @@
.Build();
/* clang-format on */
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_RESERVED_VM_ID);
+ ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
}
static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
@@ -435,25 +418,21 @@
TEST(manifest, vcpu_count_limit)
{
struct manifest m;
- struct fdt_node fdt_root;
std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
std::vector<char> dtb_first_invalid =
gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
- ASSERT_TRUE(get_fdt_root(dtb_last_valid, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
+ ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
ASSERT_EQ(m.vm_count, 2);
ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX);
- ASSERT_TRUE(get_fdt_root(dtb_first_invalid, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root),
+ ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
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()
@@ -466,8 +445,7 @@
.Build();
/* clang-format on */
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
+ ASSERT_EQ(manifest_from_vec(&m, dtb), 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), "");
@@ -492,27 +470,19 @@
TEST(manifest, malformed_booleans)
{
struct manifest m;
- struct fdt_node fdt_root;
std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
- ASSERT_TRUE(get_fdt_root(dtb_false, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root),
+ ASSERT_EQ(manifest_from_vec(&m, dtb_false),
MANIFEST_ERROR_MALFORMED_BOOLEAN);
-
- ASSERT_TRUE(get_fdt_root(dtb_true, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root),
+ ASSERT_EQ(manifest_from_vec(&m, dtb_true),
MANIFEST_ERROR_MALFORMED_BOOLEAN);
-
- ASSERT_TRUE(get_fdt_root(dtb_0, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root),
+ ASSERT_EQ(manifest_from_vec(&m, dtb_0),
MANIFEST_ERROR_MALFORMED_BOOLEAN);
-
- ASSERT_TRUE(get_fdt_root(dtb_1, &fdt_root));
- ASSERT_EQ(manifest_init(&m, &fdt_root),
+ ASSERT_EQ(manifest_from_vec(&m, dtb_1),
MANIFEST_ERROR_MALFORMED_BOOLEAN);
}
@@ -520,7 +490,6 @@
{
struct manifest m;
struct manifest_vm *vm;
- struct fdt_node fdt_root;
/* clang-format off */
std::vector<char> dtb = ManifestDtBuilder()
@@ -549,9 +518,7 @@
.Build();
/* clang-format on */
- ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
-
- ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
+ ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
ASSERT_EQ(m.vm_count, 3);
vm = &m.vm[0];