Add StMM wrapper SP
Add SP that acts as wrapper around StMM image. The StMM binary is
included as payload in the SP. Path to the binary must be passed in
STMM_BIN_PATH environment variable or CMake argument.
To start StMM the caller is responsible for two steps:
1. Share memory with this SP, which will act as the communication buffer
for StMM.
2. Send direct message to this SP to trigger initialization of StMM.
After StMM is launched, the control doesn't return to the wrapper SP.
The following files were derived from optee_os:
* gen_stmm_hex.py
* stmm-wrapper.h
Repository: https://github.com/OP-TEE/optee_os.git
Commit hash: 42471ecf25b73ae0b381a78385026f0a28c20e45
Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Change-Id: I2d0e69502e3bf4c2e4531c828668de78e7890f44
diff --git a/deployments/stmm-wrapper/opteesp/.gitignore b/deployments/stmm-wrapper/opteesp/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/deployments/stmm-wrapper/opteesp/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/deployments/stmm-wrapper/opteesp/CMakeLists.txt b/deployments/stmm-wrapper/opteesp/CMakeLists.txt
new file mode 100644
index 0000000..898b9e0
--- /dev/null
+++ b/deployments/stmm-wrapper/opteesp/CMakeLists.txt
@@ -0,0 +1,104 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+cmake_minimum_required(VERSION 3.16)
+include(../../deployment.cmake REQUIRED)
+
+include(${TS_ROOT}/environments/opteesp/env.cmake)
+project(trusted-services LANGUAGES C ASM)
+add_executable(stmm-sp)
+target_include_directories(stmm-sp PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}")
+set(SP_UUID "ed32d533-99e6-4209-9cc0-2d72cdd998a7")
+
+set(SP_DEV_KIT_INC_DIR ${CMAKE_CURRENT_LIST_DIR})
+list(APPEND CMAKE_MODULE_PATH "${TS_ROOT}/external/Spdevkit")
+find_package(Spdevkit REQUIRED)
+sp_dev_kit_configure_linking(TARGET stmm-sp DEFINES ARM64=1)
+target_link_libraries(stmm-sp PRIVATE ${SP_DEV_KIT_LIBRARIES})
+
+set(FFA_DIRECT_MSG_ROUTING_EXTENSION OFF CACHE BOOL "Not supported with StMM" FORCE)
+
+if(NOT DEFINED STMM_BIN_PATH)
+ if(DEFINED ENV{STMM_BIN_PATH})
+ set(STMM_BIN_PATH $ENV{STMM_BIN_PATH} CACHE STRING "Path to StMM binary")
+ else()
+ message(FATAL_ERROR "StMM binary path not defined")
+ endif()
+endif()
+
+find_package(Python3 COMPONENTS Interpreter)
+if (NOT Python3_Interpreter_FOUND)
+ message(FATAL_ERROR "Python 3 interpreter not found.")
+endif()
+
+execute_process(COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/gen_stmm_hex.py
+ --input ${STMM_BIN_PATH} --output ${CMAKE_BINARY_DIR}/stmm_hex.c
+)
+
+add_components(TARGET stmm-sp
+ BASE_DIR ${TS_ROOT}
+ COMPONENTS
+ components/messaging/ffa/libsp
+ environments/opteesp
+)
+
+target_sources(stmm-sp PRIVATE
+ stmm-wrapper.c
+ ${CMAKE_BINARY_DIR}/stmm_hex.c
+)
+
+target_compile_definitions(stmm-sp PRIVATE
+ ARM64=1
+)
+
+target_include_directories(stmm-sp PRIVATE
+ ${TS_ROOT}
+ ${TS_ROOT}/components
+ ${TS_ROOT}/deployments/stmm-wrapper/opteesp
+)
+
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ target_compile_options(stmm-sp PRIVATE
+ -fdiagnostics-show-option
+ -fpic
+ -gdwarf-2
+ -mstrict-align
+ -O0
+ -std=gnu99
+ )
+
+ # Options for GCC that control linking
+ target_link_options(stmm-sp PRIVATE
+ -e __sp_entry
+ -fno-lto
+ -nostdlib
+ -pie
+ -zmax-page-size=4096
+ )
+ # Options directly for LD, these are not understood by GCC
+ target_link_options(stmm-sp PRIVATE
+ -Wl,--as-needed
+ -Wl,--sort-section=alignment
+ # -Wl,--dynamic-list ${CMAKE_CURRENT_LIST_DIR}/dyn_list
+ )
+endif()
+
+compiler_generate_stripped_elf(TARGET stmm-sp NAME "${SP_UUID}.stripped.elf" RES STRIPPED_ELF)
+
+######################################## install
+if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "location to install build output to." FORCE)
+endif()
+
+install(TARGETS stmm-sp
+ PUBLIC_HEADER DESTINATION ${TS_ENV}/include
+ RUNTIME DESTINATION ${TS_ENV}/bin
+ )
+install(FILES ${STRIPPED_ELF} DESTINATION ${TS_ENV}/bin)
+
+set(EXPORT_SP_NAME "stmm-wrapper")
+set(EXPORT_SP_UUID ${SP_UUID})
+include(${TS_ROOT}/environments/opteesp/ExportSp.cmake)
diff --git a/deployments/stmm-wrapper/opteesp/default_stmm-wrapper.dts.in b/deployments/stmm-wrapper/opteesp/default_stmm-wrapper.dts.in
new file mode 100644
index 0000000..5c26a17
--- /dev/null
+++ b/deployments/stmm-wrapper/opteesp/default_stmm-wrapper.dts.in
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+@DTS_TAG@
+
+@DTS_NODE@ {
+ compatible = "arm,ffa-manifest-1.0";
+ ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+ uuid = <@EXPORT_SP_UUID_DT@>;
+ description = "StMM wrapper";
+ execution-ctx-count = <1>;
+ exception-level = <1>; /* S-EL0 */
+ execution-state = <0>; /* AArch64 */
+ xlat-granule = <0>; /* 4KiB */
+ messaging-method = <0>; /* Direct messaging only */
+};
diff --git a/deployments/stmm-wrapper/opteesp/gen_stmm_hex.py b/deployments/stmm-wrapper/opteesp/gen_stmm_hex.py
new file mode 100755
index 0000000..a9269e5
--- /dev/null
+++ b/deployments/stmm-wrapper/opteesp/gen_stmm_hex.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause
+#
+# Copyright (c) 2019, Linaro Limited
+# Copyright (c) 2021, Arm Limited
+#
+
+import argparse
+
+
+def get_args():
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('--input',
+ required=True, type=argparse.FileType('rb'),
+ help='The input StMM binary (BL32_AP_MM.fd)')
+
+ parser.add_argument('--output',
+ required=True, type=argparse.FileType('w'),
+ help='The output stmm_hex.c')
+
+ return parser.parse_args()
+
+
+def main():
+ args = get_args()
+ inf = args.input
+ outf = args.output
+
+ bytes = inf.read()
+ size = len(bytes)
+
+ outf.write('/* Automatically generated, do no edit */\n')
+ outf.write('const unsigned char stmm_image[] __attribute__((section(".text"), aligned(4096))) = {\n')
+ i = 0
+ while i < size:
+ if i % 8 == 0:
+ outf.write('\t')
+ outf.write('0x{:02x},'.format(bytes[i]))
+ i = i + 1
+ if i % 8 == 0 or i == size:
+ outf.write('\n')
+ else:
+ outf.write(' ')
+ outf.write('};\n')
+
+ outf.write('const unsigned int stmm_image_size = sizeof(stmm_image);\n')
+
+ inf.close()
+ outf.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/deployments/stmm-wrapper/opteesp/optee_sp_user_defines.h b/deployments/stmm-wrapper/opteesp/optee_sp_user_defines.h
new file mode 100644
index 0000000..76d4538
--- /dev/null
+++ b/deployments/stmm-wrapper/opteesp/optee_sp_user_defines.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SP_HEADER_DEFINES_H
+#define SP_HEADER_DEFINES_H
+
+/* To get UUID definition */
+#include "stmm-wrapper.h"
+
+#define OPTEE_SP_UUID STMM_SP_UUID
+#define OPTEE_SP_FLAGS 0
+
+/* Provisioned stack size */
+#define OPTEE_SP_STACK_SIZE (4 * 4096)
+
+/* Provisioned heap size */
+#define OPTEE_SP_HEAP_SIZE (398 * 4096)
+
+#endif /* SP_HEADER_DEFINES_H */
diff --git a/deployments/stmm-wrapper/opteesp/stmm-wrapper.c b/deployments/stmm-wrapper/opteesp/stmm-wrapper.c
new file mode 100644
index 0000000..589c825
--- /dev/null
+++ b/deployments/stmm-wrapper/opteesp/stmm-wrapper.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include <components/rpc/ffarpc/caller/sp/ffarpc_sp_call_args.h>
+#include <sp_api.h>
+#include <sp_discovery.h>
+#include <sp_memory_management.h>
+#include <sp_messaging.h>
+#include <sp_rxtx.h>
+#include <trace.h>
+
+#include "stmm-wrapper.h"
+
+static uint16_t own_id = 0;
+static uint16_t sel1_sp_id = 0;
+
+static uint64_t comm_buf_addr = 0;
+static size_t comm_buf_size = 0;
+
+static uint8_t tx_buffer[4096] __aligned(4096);
+static uint8_t rx_buffer[4096] __aligned(4096);
+
+extern uint8_t sp_heap[];
+extern const size_t sp_heap_size;
+
+extern const unsigned char stmm_image[];
+extern const unsigned int stmm_image_size;
+
+// S-EL1 helper SP UUID: e15b0308-b3a9-49a8-8fb2-4880b7303f0a
+static const struct sp_uuid sel1_sp_uuid =
+ { 0xe1, 0x5b, 0x03, 0x08, 0xb3, 0xa9, 0x49, 0xa8,
+ 0x8f, 0xb2, 0x48, 0x80, 0xb7, 0x30, 0x3f, 0x0a, };
+
+static void retrieve_buf(uint16_t source_id, uint64_t handle)
+{
+ sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
+ struct sp_memory_descriptor desc = {};
+ struct sp_memory_access_descriptor acc_desc = {};
+ struct sp_memory_region region = {};
+ uint32_t in_region_count = 0;
+ uint32_t out_region_count = 1;
+
+ desc.sender_id = source_id;
+ desc.memory_type = sp_memory_type_not_specified;
+ desc.flags.transaction_type = sp_memory_transaction_type_share;
+ acc_desc.receiver_id = own_id;
+ acc_desc.data_access = sp_data_access_read_write;
+
+ sp_res = sp_memory_retrieve(&desc, &acc_desc, ®ion, in_region_count,
+ &out_region_count, handle);
+
+ if (sp_res == SP_RESULT_OK) {
+ comm_buf_addr = (uintptr_t)region.address;
+ comm_buf_size = region.page_count * 4096;
+ } else {
+ EMSG("Memory retrieve error: %d", sp_res);
+ }
+}
+
+static void stmm_init(uint16_t caller_id)
+{
+ void (*stmm_entry)(struct stmm_boot_info *boot_info, size_t boot_info_size,
+ struct stmm_ffa_ep_info *ep_info) = (void *)stmm_image;
+ struct stmm_boot_info boot_info = {};
+ struct stmm_mp_info mp_info = {};
+ struct stmm_ffa_ep_info ep_info = {};
+
+ mp_info = (struct stmm_mp_info) {
+ .mpidr = 0, //TODO: pass parameter from SPMC
+ .linear_id = 0, //TODO: pass parameter from SPMC
+ .flags = MP_INFO_FLAG_PRIMARY_CPU,
+ };
+
+ boot_info = (struct stmm_boot_info) {
+ //TODO: check missing fields
+ .h.type = STMM_PARAM_SP_IMAGE_BOOT_INFO,
+ .h.version = STMM_PARAM_VERSION_1,
+ .h.size = sizeof(struct stmm_boot_info),
+ .h.attr = 0,
+ .sp_mem_base = (uintptr_t)stmm_image,
+ .sp_mem_limit = (uintptr_t)stmm_image + stmm_image_size,
+ .sp_image_base = (uintptr_t)stmm_image,
+ .sp_heap_base = (uintptr_t)sp_heap,
+ .sp_ns_comm_buf_base = comm_buf_addr,
+ .sp_image_size = stmm_image_size,
+ .sp_heap_size = sp_heap_size,
+ .sp_ns_comm_buf_size = comm_buf_size,
+ .num_sp_mem_regions = 6,
+ .num_cpus = 1,
+ .mp_info = &mp_info,
+ };
+
+ ep_info = (struct stmm_ffa_ep_info) {
+ .own_id = own_id,
+ .helper_id = sel1_sp_id,
+ .caller_id = caller_id,
+ };
+
+ stmm_entry(&boot_info, sizeof(boot_info) + sizeof(mp_info), &ep_info);
+}
+
+void sp_main(struct ffa_init_info *init_info)
+{
+ sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
+ struct sp_msg req_msg = {};
+ struct sp_msg resp_msg = {};
+ uint64_t handle = 0;
+
+ (void)init_info;
+
+ sp_res = sp_rxtx_buffer_map(tx_buffer, rx_buffer, sizeof(rx_buffer));
+ if (sp_res != SP_RESULT_OK)
+ EMSG("rxtx map error: %d", sp_res);
+
+ sp_res = sp_discovery_own_id_get(&own_id);
+ if (sp_res != SP_RESULT_OK)
+ EMSG("own id get error: %d", sp_res);
+
+ sp_res = sp_discovery_partition_id_get(&sel1_sp_uuid, &sel1_sp_id);
+ if (sp_res != SP_RESULT_OK)
+ EMSG("part id get error: %d", sp_res);
+
+ DMSG("StMM SP ID: 0x%x, StMM S-EL1 helper ID: 0x%x", own_id, sel1_sp_id);
+
+ sp_msg_wait(&req_msg);
+
+ while (1) {
+ switch (req_msg.args[SP_CALL_ARGS_IFACE_ID_OPCODE]) {
+ case STMM_SP_MEM_RETRIEVE:
+ handle = req_msg.args[SP_CALL_ARGS_SHARE_MEM_HANDLE_MSW];
+ handle = handle << 32;
+ handle |= req_msg.args[SP_CALL_ARGS_SHARE_MEM_HANDLE_LSW];
+
+ retrieve_buf(req_msg.source_id, handle);
+
+ resp_msg.source_id = own_id;
+ resp_msg.destination_id = req_msg.source_id;
+
+ sp_msg_send_direct_resp(&resp_msg, &req_msg);
+ break;
+ case STMM_SP_INIT_STMM:
+ stmm_init(req_msg.source_id);
+ EMSG("Fatal error: StMM returned");
+ break;
+ default:
+ EMSG("Unknown request");
+ break;
+ }
+ }
+}
+
+void sp_interrupt_handler(uint32_t interrupt_id)
+{
+ (void)interrupt_id;
+}
diff --git a/deployments/stmm-wrapper/opteesp/stmm-wrapper.h b/deployments/stmm-wrapper/opteesp/stmm-wrapper.h
new file mode 100644
index 0000000..1108175
--- /dev/null
+++ b/deployments/stmm-wrapper/opteesp/stmm-wrapper.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause */
+/*
+ * Copyright (c) 2019-2020, Linaro Limited
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef STMM_WRAPPER_H
+#define STMM_WRAPPER_H
+
+#include <stdint.h>
+
+#define STMM_SP_UUID { 0xed32d533, 0x99e6, 0x4209, \
+ { 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 } }
+
+#define STMM_SP_MEM_RETRIEVE UINT32_C(1)
+#define STMM_SP_INIT_STMM UINT32_C(2)
+
+/* Param header types */
+#define STMM_PARAM_SP_IMAGE_BOOT_INFO UINT8_C(0x07)
+
+/* Param header version */
+#define STMM_PARAM_VERSION_1 UINT8_C(0x01)
+
+/*
+ * This structure provides information on format used to describe
+ * secure partition invocation parameters.
+ */
+struct stmm_param_header {
+ uint8_t type; /* type of the structure */
+ uint8_t version; /* version of this structure */
+ uint16_t size; /* size of this structure in bytes */
+ uint32_t attr; /* attributes: unused bits SBZ */
+};
+
+/*
+ * Flags used by the stmm_mp_info structure to describe the
+ * characteristics of a cpu. Only a single flag is defined at the moment to
+ * indicate the primary cpu.
+ */
+#define MP_INFO_FLAG_PRIMARY_CPU UINT32_C(0x00000001)
+
+/*
+ * This structure is used to provide information required to initialise a S-EL0
+ * partition.
+ */
+struct stmm_mp_info {
+ uint64_t mpidr;
+ uint32_t linear_id;
+ uint32_t flags;
+};
+
+struct stmm_boot_info {
+ struct stmm_param_header h;
+ uint64_t sp_mem_base;
+ uint64_t sp_mem_limit;
+ uint64_t sp_image_base;
+ uint64_t sp_stack_base;
+ uint64_t sp_heap_base;
+ uint64_t sp_ns_comm_buf_base;
+ uint64_t sp_shared_buf_base;
+ uint64_t sp_image_size;
+ uint64_t sp_pcpu_stack_size;
+ uint64_t sp_heap_size;
+ uint64_t sp_ns_comm_buf_size;
+ uint64_t sp_shared_buf_size;
+ uint32_t num_sp_mem_regions;
+ uint32_t num_cpus;
+ struct stmm_mp_info *mp_info;
+};
+
+struct stmm_ffa_ep_info {
+ uint16_t own_id;
+ uint16_t helper_id;
+ uint16_t caller_id;
+};
+
+#endif /* STMM_WRAPPER_H */