1
0
mirror of https://git.yoctoproject.org/meta-arm synced 2026-05-08 05:09:56 +00:00

arm-bsp/u-boot: corstone1000: introducing Arm FF-A and MM support

This commit provides these new generic u-boot features:

- The FF-A low-level driver implementing Arm Firmware Framework for Armv8-A (FF-A)
- MM communication using FF-A (compatible with StandaloneMM and smm-gateway)
- A new armffa command and a test module to test the FF-A helper functions to
  communicate with secure world.

It also enables FF-A and MM communication for the Corstone-1000 platform.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Change-Id: Ic71dcae2411aefae00557284c08be662bfe80b98
Signed-off-by: Jon Mason <jon.mason@arm.com>
This commit is contained in:
Abdellatif El Khlifi
2021-11-29 12:39:59 +00:00
committed by Jon Mason
parent 2677e682d2
commit 40f3e0d10d
6 changed files with 3591 additions and 1 deletions
@@ -0,0 +1,344 @@
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
From fcb1d508e144b6239cf97dddfcb62d5f1e91ccd2 Mon Sep 17 00:00:00 2001
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Date: Tue, 16 Nov 2021 12:36:27 +0000
Subject: [PATCH 2/5] arm_ffa: introducing armffa command
A new armffa command is provided as an example of how to use
the FF-A helper functions to communicate with secure world.
The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions.
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
MAINTAINERS | 1 +
cmd/Kconfig | 10 ++
cmd/Makefile | 2 +
cmd/armffa.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 279 insertions(+)
create mode 100644 cmd/armffa.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 3f61e374aa..7db7b7d637 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -218,6 +218,7 @@ F: include/configs/turris_*.h
ARM FF-A
M: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
S: Maintained
+F: cmd/armffa.c
F: drivers/arm-ffa/
F: include/arm_ffa.h
F: include/arm_ffa_helper.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index a33b2a2a12..c34cf6dc8d 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -785,6 +785,16 @@ endmenu
menu "Device access commands"
+config CMD_ARMFFA
+ bool "Arm FF-A test command"
+ depends on ARM_FFA_TRANSPORT
+ help
+ Provides a test command for the Arm FF-A driver
+ supported options:
+ - Listing the partition(s) info
+ - Sending a data pattern to the specified partition
+ - Displaying the arm_ffa device info
+
config CMD_ARMFLASH
#depends on FLASH_CFI_DRIVER
bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index ed3669411e..ccd4882676 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
obj-y += version.o
# command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
obj-$(CONFIG_CMD_ACPI) += acpi.o
obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..71a6ebb656
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa_helper.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp: Command Table
+ * @flag: flags
+ * @argc: number of arguments
+ * @argv: arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver helper function
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct ffa_interface_data func_data = {0};
+ u32 count = 0;
+ int ret;
+ union ffa_partition_uuid service_uuid = {0};
+ struct ffa_partition_info *parts_info;
+ u32 info_idx;
+
+ if (argc != 1)
+ return -EINVAL;
+
+ if (ffa_uuid_str_to_bin(argv[0], (unsigned char *)&service_uuid)) {
+ ffa_err("Invalid UUID");
+ return -EINVAL;
+ }
+
+ /*
+ * get from the driver the count of the SPs matching the UUID
+ */
+ func_data.data0_size = sizeof(service_uuid);
+ func_data.data0 = &service_uuid;
+ func_data.data1_size = sizeof(count);
+ func_data.data1 = &count;
+
+ ret = ffa_helper_get_partitions_info(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ ffa_err("Failure in querying partitions count (error code: %d)", ret);
+ return ret;
+ }
+
+ if (!count) {
+ ffa_info("No secure partition found");
+ return ret;
+ }
+
+ /*
+ * pre-allocate a buffer to be filled by the driver
+ * with ffa_partition_info structs
+ */
+
+ parts_info = calloc(count, sizeof(struct ffa_partition_info));
+ if (!parts_info)
+ return -EINVAL;
+
+ ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+ func_data.data1_size = count * sizeof(struct ffa_partition_info);
+ func_data.data1 = parts_info;
+
+ /*
+ * ask the driver to fill the buffer with the SPs info
+ */
+ ret = ffa_helper_get_partitions_info(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+ free(parts_info);
+ return ret;
+ }
+
+ /*
+ * SPs found , show the partition information
+ */
+ for (info_idx = 0; info_idx < count ; info_idx++) {
+ ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+ parts_info[info_idx].id,
+ parts_info[info_idx].exec_ctxt,
+ parts_info[info_idx].properties);
+ }
+
+ free(parts_info);
+
+ return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp: Command Table
+ * @flag: flags
+ * @argc: number of arguments
+ * @argv: arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver helper function
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct ffa_interface_data func_data = {0};
+ struct ffa_send_direct_data msg = {0};
+ u32 pattern = 0xaabbccd0;
+ u16 part_id;
+ int ret;
+
+ if (argc != 1)
+ return -EINVAL;
+
+ errno = 0;
+ part_id = strtoul(argv[0], NULL, 16);
+
+ if (errno) {
+ ffa_err("Invalid partition ID");
+ return -EINVAL;
+ }
+
+ /*
+ * telling the driver which partition to use
+ */
+ func_data.data0_size = sizeof(part_id);
+ func_data.data0 = &part_id;
+
+ /*
+ * filling the message data
+ */
+ msg.a3 = ++pattern;
+ msg.a4 = ++pattern;
+ msg.a5 = ++pattern;
+ msg.a6 = ++pattern;
+ msg.a7 = ++pattern;
+ func_data.data1_size = sizeof(msg);
+ func_data.data1 = &msg;
+
+ ret = ffa_helper_msg_send_direct_req(&func_data);
+ if (ret == FFA_ERR_STAT_SUCCESS) {
+ u8 cnt;
+
+ ffa_info("SP response:\n[LSB]");
+ for (cnt = 0;
+ cnt < sizeof(struct ffa_send_direct_data) / sizeof(u32);
+ cnt++)
+ ffa_info("0x%x", ((u32 *)&msg)[cnt]);
+ } else {
+ ffa_err("Sending direct request error (%d)", ret);
+ }
+
+ return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in] Command Table
+ * @flag: flags
+ * @argc: number of arguments
+ * @argv: arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *dev = NULL;
+ int i, ret;
+
+ ffa_info("arm_ffa uclass entries:");
+
+ for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
+ dev;
+ ret = uclass_next_device(&dev), i++) {
+ if (ret)
+ break;
+
+ ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+ i,
+ (u32)map_to_sysmem(dev),
+ (u32)map_to_sysmem(dev->driver->ops),
+ (u32)map_to_sysmem(dev_get_plat(dev)));
+ }
+
+ return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl armffa_commands[] = {
+ U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+ U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+ U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp: Command Table
+ * @flag: flags
+ * @argc: number of arguments
+ * @argv: arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *armffa_cmd;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+ argc -= 2;
+ argv += 2;
+
+ if (!armffa_cmd || argc > armffa_cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ ret = ffa_helper_init_device();
+ if (ret != FFA_ERR_STAT_SUCCESS)
+ return cmd_process_error(cmdtp, ret);
+
+ ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+ return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+ "Arm FF-A operations test command",
+ "getpart <partition UUID>\n"
+ " - lists the partition(s) info\n"
+ "ping <partition ID>\n"
+ " - sends a data pattern to the specified partition\n"
+ "devlist\n"
+ " - displays the arm_ffa device info\n");
--
2.17.1
@@ -0,0 +1,134 @@
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
From 236c75ffffd580427c52e1a4dcaf4b058d4b0891 Mon Sep 17 00:00:00 2001
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Date: Tue, 16 Nov 2021 12:38:48 +0000
Subject: [PATCH 3/5] arm_ffa: introducing test module for UCLASS_FFA
This is the test module for the UCLASS_FFA class.
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
MAINTAINERS | 1 +
test/dm/Makefile | 1 +
test/dm/ffa.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
test/dm/ffa.h | 19 ++++++++++++++++
4 files changed, 77 insertions(+)
create mode 100644 test/dm/ffa.c
create mode 100644 test/dm/ffa.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 7db7b7d637..c2762ad5d0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -223,6 +223,7 @@ F: drivers/arm-ffa/
F: include/arm_ffa.h
F: include/arm_ffa_helper.h
F: lib/arm-ffa/
+F: test/dm/ffa.c
ARM FREESCALE IMX
M: Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 55162e9499..0403b3c622 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
obj-$(CONFIG_ACPI_PMC) += pmc.o
obj-$(CONFIG_DM_PMIC) += pmic.o
obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
obj-$(CONFIG_QFW) += qfw.o
obj-$(CONFIG_RAM) += ram.o
obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..b937cea57b
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for UCLASS_FFA class
+ *
+ * (C) Copyright 2021 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include <arm_ffa_helper.h>
+#include "ffa.h"
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+ ut_assertok(ffa_helper_init_device());
+
+ ut_assertok(console_record_reset_enable());
+
+ /* armffa getpart <UUID> */
+ ut_assertok(run_command("armffa getpart " SE_PROXY_PARTITION_UUID, 0));
+ ut_assert_console_end();
+
+ /* armffa ping <ID> */
+ ut_assertok(run_command("armffa ping " SE_PROXY_PARTITION_ID, 0));
+ ut_assert_console_end();
+
+ /* armffa devlist */
+ ut_assertok(run_command("armffa devlist", 0));
+ ut_assert_console_end();
+
+ return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int test_ffa_msg_send_direct_req(void)
+{
+ char *const argv[1] = {SE_PROXY_PARTITION_ID}; /* Corstone1000 SE Proxy ID */
+
+ return do_ffa_msg_send_direct_req(NULL, 0, 1, argv);
+}
+
+/* Basic test of the FFA uclass */
+static int dm_test_ffa_uclass(struct unit_test_state *uts)
+{
+ ut_assertok(ffa_init_device());
+ ut_assertok(test_ffa_msg_send_direct_req());
+ return 0;
+}
+
+DM_TEST(dm_test_ffa_uclass, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
diff --git a/test/dm/ffa.h b/test/dm/ffa.h
new file mode 100644
index 0000000000..a0802bd692
--- /dev/null
+++ b/test/dm/ffa.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2021 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __TEST_DM_FFA_H
+#define __TEST_DM_FFA_H
+
+#define SE_PROXY_PARTITION_ID "0x8002"
+#define SE_PROXY_PARTITION_UUID "46bb39d1-b4d9-45b5-88ff-040027dab249"
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ */
+int do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+
+#endif /*__TEST_DM_FFA_H */
--
2.17.1
@@ -0,0 +1,383 @@
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
From aa7d7298547c5e1c0e1c2aaafc28f3fdb5084780 Mon Sep 17 00:00:00 2001
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Date: Wed, 13 Oct 2021 17:51:44 +0100
Subject: [PATCH 4/5] arm_ffa: introducing MM communication with FF-A
This commit allows to perform MM communication using FF-A transport.
The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
Both partitions run in OP-TEE.
When using the u-boot FF-A driver, StandAlonneMM and smm-gateway are
supported.
On EFI services such as GetVariable()/SetVariable(), the data
is copied from the communication buffer to the MM shared buffer.
Then, notifies the MM SP about data availability in the MM shared buffer.
Communication with the MM SP is performed using FF-A transport.
On such event, MM SP can read the data and updates the MM shared buffer
with response data.
The response data is copied back to the communication buffer.
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
lib/efi_loader/Kconfig | 14 +-
lib/efi_loader/efi_variable_tee.c | 255 +++++++++++++++++++++++++++++-
2 files changed, 263 insertions(+), 6 deletions(-)
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index f48d9e8b51..5a31a42456 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
stored as file /ubootefi.var on the EFI system partition.
config EFI_MM_COMM_TEE
- bool "UEFI variables storage service via OP-TEE"
- depends on OPTEE
+ bool "UEFI variables storage service via the trusted world"
+ depends on OPTEE || ARM_FFA_TRANSPORT
help
+ The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+ When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ When using the u-boot FF-A driver, StandAlonneMM and smm-gateway are supported.
+
If OP-TEE is present and running StandAloneMM, dispatch all UEFI
variable related operations to that. The application will verify,
authenticate and store the variables on an RPMB.
+ When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+ operations to the MM SP running under Optee in the trusted world.
+ A door bell mechanism is used to notify the SP when there is data in the shared
+ MM buffer. The data is copied by u-boot to thea shared buffer before issuing
+ the door bell event.
+
endchoice
config EFI_VARIABLES_PRESEED
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index 51920bcb51..b363ec92bf 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -15,7 +15,28 @@
#include <malloc.h>
#include <mm_communication.h>
+#if (IS_ENABLED(CONFIG_OPTEE))
#define OPTEE_PAGE_SIZE BIT(12)
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa_helper.h>
+#include <mapmem.h>
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 (0xC4000061)
+#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
+
+/* MM_SP_UUID_DATA defined by the platform */
+union ffa_partition_uuid mm_sp_svc_uuid = {.bytes = {MM_SP_UUID_DATA}};
+
+static u16 __efi_runtime_data mm_sp_id;
+
+#endif
+
extern struct efi_var_file __efi_runtime_data *efi_var_buf;
static efi_uintn_t max_buffer_size; /* comm + var + func + data */
static efi_uintn_t max_payload_size; /* func + data */
@@ -25,6 +46,7 @@ struct mm_connection {
u32 session;
};
+#if (IS_ENABLED(CONFIG_OPTEE))
/**
* get_connection() - Retrieve OP-TEE session for a specific UUID.
*
@@ -140,16 +162,229 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
return ret;
}
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_notify_mm_sp(void)
+{
+ struct ffa_interface_data func_data = {0};
+ struct ffa_send_direct_data msg = {0};
+ int ret;
+ u32 sp_event_complete;
+ int sp_event_ret;
+
+ func_data.data0_size = sizeof(mm_sp_id);
+ func_data.data0 = &mm_sp_id;
+
+ msg.a3 = FFA_SHARED_MM_BUFFER_ADDR;
+ msg.a4 = FFA_SHARED_MM_BUFFER_SIZE;
+ func_data.data1_size = sizeof(msg);
+ func_data.data1 = &msg;
+
+ ret = ffa_helper_msg_send_direct_req(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ log_err("EFI: Failure to notify the MM SP , FF-A error (%d)\n", ret);
+ return ret;
+ }
+
+ sp_event_complete = msg.a3;
+ sp_event_ret = (int)msg.a4;
+
+ if (sp_event_complete == ARM_SVC_ID_SP_EVENT_COMPLETE && sp_event_ret == MM_SUCCESS)
+ return 0;
+
+ log_err("EFI: Failure to notify the MM SP (0x%x , %d)\n",
+ sp_event_complete,
+ sp_event_ret);
+
+ return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_discover_mm_sp_id(void)
+{
+ struct ffa_interface_data func_data = {0};
+ u32 count = 0;
+ int ret;
+ struct ffa_partition_info *parts_info;
+
+ /*
+ * get from the driver the count of the SPs matching the UUID
+ */
+ func_data.data0_size = sizeof(mm_sp_svc_uuid);
+ func_data.data0 = &mm_sp_svc_uuid;
+ func_data.data1_size = sizeof(count);
+ func_data.data1 = &count;
+
+ ret = ffa_helper_get_partitions_info(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+ return ret;
+ }
+
+ if (!count) {
+ log_info("EFI: No MM partition found\n");
+ return ret;
+ }
+
+ /*
+ * pre-allocate a buffer to be filled by the driver
+ * with ffa_partition_info structs
+ */
+
+ parts_info = calloc(count, sizeof(struct ffa_partition_info));
+ if (!parts_info)
+ return -EINVAL;
+
+ log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+ func_data.data1_size = count *
+ sizeof(struct ffa_partition_info);
+ func_data.data1 = parts_info;
+
+ /*
+ * ask the driver to fill the
+ * buffer with the SPs info
+ */
+ ret = ffa_helper_get_partitions_info(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+ free(parts_info);
+ return ret;
+ }
+
+ /*
+ * MM SPs found , use the first one
+ */
+
+ mm_sp_id = parts_info[0].id;
+
+ log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+ free(parts_info);
+
+ return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with the MM partition using FF-A
+ * @comm_buf: locally allocated communication buffer used for for rx/tx
+ * @dsize: communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+ ulong tx_data_size;
+ int ffa_ret;
+ struct efi_mm_communicate_header *mm_hdr;
+ void *virt_shared_buf;
+
+ if (!comm_buf)
+ return EFI_INVALID_PARAMETER;
+
+ /* Discover MM partition ID */
+ if (!mm_sp_id && ffa_discover_mm_sp_id() != FFA_ERR_STAT_SUCCESS) {
+ log_err("EFI: Failure to discover MM partition ID\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+ tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+ if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+ return EFI_INVALID_PARAMETER;
+
+ /* Copy the data to the shared buffer */
+
+ virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+ efi_memcpy_runtime(virt_shared_buf, comm_buf, tx_data_size);
+
+ /* Announce there is data in the shared buffer */
+
+ ffa_ret = ffa_notify_mm_sp();
+ if (ffa_ret)
+ unmap_sysmem(virt_shared_buf);
+
+ switch (ffa_ret) {
+ case 0:
+ {
+ ulong rx_data_size;
+ /* Copy the MM SP response from the shared buffer to the communication buffer */
+ rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+ sizeof(efi_guid_t) +
+ sizeof(size_t);
+
+ if (rx_data_size > comm_buf_size) {
+ unmap_sysmem(virt_shared_buf);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
+ unmap_sysmem(virt_shared_buf);
+
+ return EFI_SUCCESS;
+ }
+ case -EINVAL:
+ return EFI_DEVICE_ERROR;
+ case -EPERM:
+ return EFI_INVALID_PARAMETER;
+ case -EACCES:
+ return EFI_ACCESS_DENIED;
+ case -EBUSY:
+ return EFI_OUT_OF_RESOURCES;
+ default:
+ return EFI_ACCESS_DENIED;
+ }
+}
+#endif
/**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
* it to OP-TEE
*
- * @comm_buf: locally allocted communcation buffer
+ * @comm_buf: locally allocted communication buffer
* @dsize: buffer size
+ *
+ * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A driver, StandAlonneMM and smm-gateway are supported.
+ *
* Return: status code
*/
-static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
+static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
{
efi_status_t ret;
struct efi_mm_communicate_header *mm_hdr;
@@ -159,7 +394,11 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
+ #if (IS_ENABLED(CONFIG_OPTEE))
ret = optee_mm_communicate(comm_buf, dsize);
+ #elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+ ret = ffa_mm_communicate(comm_buf, dsize);
+ #endif
if (ret != EFI_SUCCESS) {
log_err("%s failed!\n", __func__);
return ret;
@@ -255,6 +494,8 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
goto out;
}
*size = var_payload->size;
+
+ #if (IS_ENABLED(CONFIG_OPTEE))
/*
* Although the max payload is configurable on StMM, we only share a
* single page from OP-TEE for the non-secure buffer used to communicate
@@ -264,6 +505,12 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
if (*size > OPTEE_PAGE_SIZE)
*size = OPTEE_PAGE_SIZE - MM_COMMUNICATE_HEADER_SIZE -
MM_VARIABLE_COMMUNICATE_SIZE;
+ #elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+ if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+ *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE -
+ MM_VARIABLE_COMMUNICATE_SIZE;
+ #endif
+
/*
* There seems to be a bug in EDK2 miscalculating the boundaries and
* size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -690,7 +937,7 @@ void efi_variables_boot_exit_notify(void)
ret = EFI_NOT_FOUND;
if (ret != EFI_SUCCESS)
- log_err("Unable to notify StMM for ExitBootServices\n");
+ log_err("Unable to notify the MM partition for ExitBootServices\n");
free(comm_buf);
/*
--
2.17.1
@@ -0,0 +1,112 @@
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
From 202f8d5783b8bcf1119574fd1b3a47ec6ff4f520 Mon Sep 17 00:00:00 2001
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Date: Wed, 24 Nov 2021 21:07:44 +0000
Subject: [PATCH] arm_ffa: corstone1000: enable FF-A and MM support
This commit allows corstone1000 platform to perform
MM communication between u-boot and the secure world
using FF-A transport.
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
arch/arm/dts/corstone1000-fvp.dts | 4 ++++
arch/arm/dts/corstone1000-mps3.dts | 4 ++++
arch/arm/dts/corstone1000.dtsi | 7 +++++++
configs/corstone1000_defconfig | 5 +++++
include/configs/corstone1000.h | 14 ++++++++++++++
5 files changed, 34 insertions(+)
diff --git a/arch/arm/dts/corstone1000-fvp.dts b/arch/arm/dts/corstone1000-fvp.dts
index 2188ca5e0e..92da15df4e 100644
--- a/arch/arm/dts/corstone1000-fvp.dts
+++ b/arch/arm/dts/corstone1000-fvp.dts
@@ -26,3 +26,7 @@
&refclk {
clock-frequency = <50000000>;
};
+
+&arm_ffa {
+ status = "okay";
+};
diff --git a/arch/arm/dts/corstone1000-mps3.dts b/arch/arm/dts/corstone1000-mps3.dts
index a3726f1e1f..6842395405 100644
--- a/arch/arm/dts/corstone1000-mps3.dts
+++ b/arch/arm/dts/corstone1000-mps3.dts
@@ -40,3 +40,7 @@
&refclk {
clock-frequency = <50000000>;
};
+
+&arm_ffa {
+ status = "okay";
+};
diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi
index da1725e01f..97dfac9ae7 100644
--- a/arch/arm/dts/corstone1000.dtsi
+++ b/arch/arm/dts/corstone1000.dtsi
@@ -153,4 +153,11 @@
compatible = "arm,psci-1.0", "arm,psci-0.2";
method = "smc";
};
+
+ arm_ffa: arm_ffa {
+ compatible = "arm,ffa";
+ method = "smc";
+ status = "disabled";
+ };
+
};
diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index dd85193c0f..48ec37f641 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -9,6 +9,7 @@ CONFIG_FIT=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk"
+CONFIG_LOGLEVEL=7
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_HUSH_PARSER=y
@@ -44,6 +45,10 @@ CONFIG_DM_SERIAL=y
CONFIG_USB=y
CONFIG_USB_ISP1760=y
CONFIG_USB_STORAGE=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_EFI_MM_COMM_TEE=y
+# CONFIG_OPTEE is not set
+# CONFIG_GENERATE_SMBIOS_TABLE is not set
# CONFIG_HEXDUMP is not set
CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
CONFIG_EFI_CAPSULE_ON_DISK=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 5e22e075ad..8014b2f688 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -12,6 +12,20 @@
#ifndef __CORSTONE1000_H
#define __CORSTONE1000_H
+#include <linux/sizes.h>
+
+/* MM SP UUID binary data (little-endian format) */
+#define MM_SP_UUID_DATA \
+ 0xed, 0x32, 0xd5, 0x33, \
+ 0x99, 0xe6, 0x42, 0x09, \
+ 0x9c, 0xc0, 0x2d, 0x72, \
+ 0xcd, 0xd9, 0x98, 0xa7
+
+#define FFA_SHARED_MM_BUFFER_SIZE SZ_4K /* 4 KB */
+
+/* shared buffer physical address used for communication between u-boot and the MM SP */
+#define FFA_SHARED_MM_BUFFER_ADDR (0x023F8000)
+
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x03f00000)
#define CONFIG_SKIP_LOWLEVEL_INIT
--
2.17.1
@@ -27,7 +27,12 @@ SRC_URI:append:corstone1000 = " \
file://0015-arm-dts-add-initial-devicetree-corstone1000-mps3.patch \
file://0016-arm-corstone1000-adding-PSCI-device-tree-node.patch \
file://0017-arm-corstone1000-amend-kernel-bootargs-with-ip-dhcp-.patch \
"
file://0018-arm_ffa-introducing-Arm-FF-A-low-level-driver.patch \
file://0019-arm_ffa-introducing-armffa-command.patch \
file://0020-arm_ffa-introducing-test-module-for-UCLASS_FFA.patch \
file://0021-arm_ffa-introducing-MM-communication-with-FF-A.patch \
file://0022-arm_ffa-corstone1000-enable-FF-A-and-MM-support.patch \
"
#
# FVP BASE