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/inc/hf/boot_flow.h b/inc/hf/boot_flow.h
new file mode 100644
index 0000000..e96ad1b
--- /dev/null
+++ b/inc/hf/boot_flow.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "hf/boot_params.h"
+#include "hf/manifest.h"
+#include "hf/mm.h"
+
+bool boot_flow_init(struct mm_stage1_locked stage1_locked,
+ struct manifest *manifest, struct boot_params *boot_params,
+ struct mpool *ppool);
diff --git a/inc/hf/boot_params.h b/inc/hf/boot_params.h
index ee46777..59b62d5 100644
--- a/inc/hf/boot_params.h
+++ b/inc/hf/boot_params.h
@@ -20,6 +20,7 @@
#include "hf/arch/cpu.h"
+#include "hf/fdt.h"
#include "hf/mm.h"
#include "hf/mpool.h"
@@ -47,7 +48,6 @@
paddr_t initrd_end;
};
-bool plat_get_boot_params(struct mm_stage1_locked stage1_locked,
- struct boot_params *p, struct mpool *ppool);
-bool plat_update_boot_params(struct mm_stage1_locked stage1_locked,
- struct boot_params_update *p, struct mpool *ppool);
+bool boot_params_init(struct boot_params *p, const struct fdt_node *fdt_root);
+bool boot_params_patch_fdt(struct mm_stage1_locked stage1_locked,
+ struct boot_params_update *p, struct mpool *ppool);
diff --git a/inc/hf/fdt_handler.h b/inc/hf/fdt_handler.h
index 49d242e..70521b5 100644
--- a/inc/hf/fdt_handler.h
+++ b/inc/hf/fdt_handler.h
@@ -26,10 +26,10 @@
struct mpool *ppool);
bool fdt_unmap(struct mm_stage1_locked stage1_locked, struct fdt_header *fdt,
struct mpool *ppool);
-void fdt_find_cpus(const struct fdt_node *root, cpu_id_t *cpu_ids,
+bool fdt_find_cpus(const struct fdt_node *root, cpu_id_t *cpu_ids,
size_t *cpu_count);
-void fdt_find_memory_ranges(const struct fdt_node *root, struct boot_params *p);
-bool fdt_find_initrd(struct fdt_node *n, paddr_t *begin, paddr_t *end);
+bool fdt_find_memory_ranges(const struct fdt_node *root, struct boot_params *p);
+bool fdt_find_initrd(const struct fdt_node *root, paddr_t *begin, paddr_t *end);
/** Apply an update to the FDT. */
bool fdt_patch(struct mm_stage1_locked stage1_locked, paddr_t fdt_addr,
diff --git a/inc/hf/load.h b/inc/hf/load.h
index 2d9394a..d7ccd71 100644
--- a/inc/hf/load.h
+++ b/inc/hf/load.h
@@ -21,6 +21,7 @@
#include "hf/boot_params.h"
#include "hf/cpio.h"
+#include "hf/manifest.h"
#include "hf/memiter.h"
#include "hf/mm.h"
#include "hf/mpool.h"
@@ -29,6 +30,6 @@
const struct memiter *cpio, uintreg_t kernel_arg,
struct memiter *initrd, struct mpool *ppool);
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);
diff --git a/inc/hf/manifest.h b/inc/hf/manifest.h
index dd7a122..46bd205 100644
--- a/inc/hf/manifest.h
+++ b/inc/hf/manifest.h
@@ -16,19 +16,25 @@
#pragma once
+#include "hf/fdt.h"
#include "hf/memiter.h"
#include "hf/spci.h"
/**
+ * Maximum length of a string parsed from the FDT, including NULL terminator.
+ */
+#define MANIFEST_MAX_STRING_LENGTH 32
+
+/**
* Holds information about one of the VMs described in the manifest.
*/
struct manifest_vm {
/* Properties defined for both primary and secondary VMs. */
- struct memiter debug_name;
+ char debug_name[MANIFEST_MAX_STRING_LENGTH];
/* Properties specific to secondary VMs. */
struct {
- struct memiter kernel_filename;
+ char kernel_filename[MANIFEST_MAX_STRING_LENGTH];
uint64_t mem_size;
spci_vcpu_count_t vcpu_count;
} secondary;
@@ -44,8 +50,6 @@
enum manifest_return_code {
MANIFEST_SUCCESS = 0,
- MANIFEST_ERROR_CORRUPTED_FDT,
- MANIFEST_ERROR_NO_ROOT_FDT_NODE,
MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE,
MANIFEST_ERROR_NOT_COMPATIBLE,
MANIFEST_ERROR_RESERVED_VM_ID,
@@ -53,12 +57,13 @@
MANIFEST_ERROR_TOO_MANY_VMS,
MANIFEST_ERROR_PROPERTY_NOT_FOUND,
MANIFEST_ERROR_MALFORMED_STRING,
+ MANIFEST_ERROR_STRING_TOO_LONG,
MANIFEST_ERROR_MALFORMED_STRING_LIST,
MANIFEST_ERROR_MALFORMED_INTEGER,
MANIFEST_ERROR_INTEGER_OVERFLOW,
};
enum manifest_return_code manifest_init(struct manifest *manifest,
- struct memiter *fdt);
+ const struct fdt_node *fdt_root);
const char *manifest_strerror(enum manifest_return_code ret_code);
diff --git a/inc/hf/memiter.h b/inc/hf/memiter.h
index f8e8c25..e3f0db8 100644
--- a/inc/hf/memiter.h
+++ b/inc/hf/memiter.h
@@ -29,7 +29,6 @@
bool memiter_parse_uint(struct memiter *it, uint64_t *value);
bool memiter_parse_str(struct memiter *it, struct memiter *str);
bool memiter_iseq(const struct memiter *it, const char *str);
-void memiter_dlog_str(struct memiter *it);
bool memiter_advance(struct memiter *it, size_t v);
const void *memiter_base(const struct memiter *it);
diff --git a/inc/hf/plat/boot_flow.h b/inc/hf/plat/boot_flow.h
new file mode 100644
index 0000000..daaf5a6
--- /dev/null
+++ b/inc/hf/plat/boot_flow.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "hf/addr.h"
+#include "hf/fdt.h"
+
+paddr_t plat_get_fdt_addr(void);
+uintreg_t plat_get_kernel_arg(void);
+bool plat_get_initrd_range(const struct fdt_node *fdt_root, paddr_t *begin,
+ paddr_t *end);