feat(qemu): support s-el2 spmc
Supports S-EL2 SPMC + S-EL1 SP on qemu. S-EL1 SPs packaged in .pkg files
are added to the FIP as blob with an UUID. BL2 parses TB_FW_CONFIG to
know which SP blobs to load into memory.
Co-developed-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Change-Id: I4b61c4c048f31540d4f1ef9e05f0b12deb341e06
diff --git a/plat/qemu/common/qemu_io_storage.c b/plat/qemu/common/qemu_io_storage.c
index e2d4932..4c61b14 100644
--- a/plat/qemu/common/qemu_io_storage.c
+++ b/plat/qemu/common/qemu_io_storage.c
@@ -11,6 +11,8 @@
#include <common/bl_common.h>
#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/uuid.h>
#include <drivers/io/io_driver.h>
#include <drivers/io/io_encrypted.h>
#include <drivers/io/io_fip.h>
@@ -20,10 +22,13 @@
#include <lib/semihosting.h>
#include <tools_share/firmware_image_package.h>
+#include "qemu_private.h"
+
/* Semihosting filenames */
#define BL2_IMAGE_NAME "bl2.bin"
#define BL31_IMAGE_NAME "bl31.bin"
#define BL32_IMAGE_NAME "bl32.bin"
+#define TB_FW_CONFIG_NAME "tb_fw_config.dtb"
#define TOS_FW_CONFIG_NAME "tos_fw_config.dtb"
#define BL32_EXTRA1_IMAGE_NAME "bl32_extra1.bin"
#define BL32_EXTRA2_IMAGE_NAME "bl32_extra2.bin"
@@ -79,6 +84,10 @@
.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
};
+static const io_uuid_spec_t tb_fw_config_uuid_spec = {
+ .uuid = UUID_TB_FW_CONFIG,
+};
+
static const io_uuid_spec_t tos_fw_config_uuid_spec = {
.uuid = UUID_TOS_FW_CONFIG,
};
@@ -142,6 +151,10 @@
.path = BL32_EXTRA2_IMAGE_NAME,
.mode = FOPEN_MODE_RB
},
+ [TB_FW_CONFIG_ID] = {
+ .path = TB_FW_CONFIG_NAME,
+ .mode = FOPEN_MODE_RB
+ },
[TOS_FW_CONFIG_ID] = {
.path = TOS_FW_CONFIG_NAME,
.mode = FOPEN_MODE_RB
@@ -261,6 +274,11 @@
open_fip
},
#endif
+ [TB_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_config_uuid_spec,
+ open_fip
+ },
[TOS_FW_CONFIG_ID] = {
&fip_dev_handle,
(uintptr_t)&tos_fw_config_uuid_spec,
@@ -315,6 +333,80 @@
#endif /* TRUSTED_BOARD_BOOT */
};
+#if defined(SPD_spmd)
+static struct sp_pkg {
+ struct plat_io_policy policy;
+ io_file_spec_t sh_file_spec;
+ uint8_t uuid[UUID_BYTES_LENGTH];
+ char path[80];
+} sp_pkgs[MAX_SP_IDS];
+static unsigned int sp_pkg_count;
+
+int qemu_io_register_sp_pkg(const char *name, const char *uuid,
+ uintptr_t load_addr)
+{
+ struct sp_pkg *pkg;
+ bl_mem_params_node_t *mem_params;
+
+ if (sp_pkg_count == MAX_SP_IDS) {
+ INFO("Reached Max number of SPs\n");
+ return -1;
+ }
+ mem_params = get_bl_mem_params_node(SP_PKG1_ID + sp_pkg_count);
+ if (mem_params == NULL) {
+ ERROR("Can't find SP_PKG ID %u (SP_PKG%u_ID)\n",
+ SP_PKG1_ID + sp_pkg_count, sp_pkg_count);
+ return -1;
+ }
+ pkg = sp_pkgs + sp_pkg_count;
+
+ if (read_uuid(pkg->uuid, (char *)uuid)) {
+ return -1;
+ }
+
+ strlcpy(pkg->path, name, sizeof(pkg->path));
+ strlcat(pkg->path, ".pkg", sizeof(pkg->path));
+
+ pkg->policy.dev_handle = &fip_dev_handle;
+ pkg->policy.image_spec = (uintptr_t)&pkg->uuid;
+ pkg->policy.check = open_fip;
+ pkg->sh_file_spec.path = pkg->path;
+ pkg->sh_file_spec.mode = FOPEN_MODE_RB;
+
+ mem_params->image_info.image_base = load_addr;
+ mem_params->image_info.image_max_size = SZ_4M;
+ mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+
+ sp_pkg_count++;
+
+ return 0;
+}
+#endif /*SPD_spmd*/
+
+static const io_file_spec_t *get_io_file_spec(unsigned int image_id)
+{
+#if defined(SPD_spmd)
+ if (image_id >= SP_PKG1_ID && image_id <= SP_PKG8_ID) {
+ return &sp_pkgs[image_id - SP_PKG1_ID].sh_file_spec;
+ }
+#endif
+
+ assert(image_id < ARRAY_SIZE(sh_file_spec));
+ return &sh_file_spec[image_id];
+}
+
+static const struct plat_io_policy *get_io_policy(unsigned int image_id)
+{
+#if defined(SPD_spmd)
+ if (image_id >= SP_PKG1_ID && image_id <= SP_PKG8_ID) {
+ return &sp_pkgs[image_id - SP_PKG1_ID].policy;
+ }
+#endif
+
+ assert(image_id < ARRAY_SIZE(policies));
+ return &policies[image_id];
+}
+
static int open_fip(const uintptr_t spec)
{
int result;
@@ -427,11 +519,13 @@
static int get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
uintptr_t *image_spec)
{
- int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
+ const io_file_spec_t *spec = get_io_file_spec(image_id);
+ int result;
+ result = open_semihosting((const uintptr_t)spec);
if (result == 0) {
*dev_handle = sh_dev_handle;
- *image_spec = (uintptr_t)&sh_file_spec[image_id];
+ *image_spec = (uintptr_t)spec;
}
return result;
@@ -444,12 +538,9 @@
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
uintptr_t *image_spec)
{
+ const struct plat_io_policy *policy = get_io_policy(image_id);
int result;
- const struct plat_io_policy *policy;
- assert(image_id < ARRAY_SIZE(policies));
-
- policy = &policies[image_id];
result = policy->check(policy->image_spec);
if (result == 0) {
*image_spec = policy->image_spec;