feat(arm): add ep_info handoff args setter
Add support for project specific APIs and re-introduce API for setting
TF-A `entry_point_info` arguments following the Arm register convention.
Change-Id: Ic40ef6d34771fe54b152312779620f22bc106640
Signed-off-by: Harrison Mutai <harrison.mutai@arm.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 35c8379..6aa68d9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,7 +19,12 @@
SET(TARGET_GROUP release CACHE STRING "Specify the Build Target [\"release\" by default]")
-add_library(tl STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/transfer_list.c")
+
+add_library(tl
+ STATIC
+ ${PROJECT_SOURCE_DIR}/src/generic/transfer_list.c
+)
+
target_include_directories(tl
PUBLIC
${PROJECT_SOURCE_DIR}/include
@@ -27,6 +32,10 @@
target_link_libraries(tl PUBLIC cxx_compiler_flags)
+if(PROJECT_API)
+ include(${PROJECT_SOURCE_DIR}/cmake/ProjectApi.cmake)
+endif()
+
if(TARGET_GROUP STREQUAL test)
include(CTest)
diff --git a/cmake/ProjectApi.cmake b/cmake/ProjectApi.cmake
new file mode 100644
index 0000000..c0d338a
--- /dev/null
+++ b/cmake/ProjectApi.cmake
@@ -0,0 +1,10 @@
+set(PROJECT_API_SRC_DIR ${PROJECT_SOURCE_DIR}/src/${PROJECT_API})
+set(PROJECT_API_INC_DIR ${PROJECT_SOURCE_DIR}/include/${PROJECT_API})
+
+if(EXISTS "${PROJECT_API_SRC_DIR}")
+ file(GLOB PROJECT_SOURCES "${PROJECT_API_SRC_DIR}/*.c")
+ target_sources(tl PRIVATE ${PROJECT_SOURCES})
+ target_include_directories(tl PUBLIC ${PROJECT_API_INC_DIR})
+else()
+ message(FATAL_ERROR "Project-specific API '${PROJECT_API}' not found")
+endif()
diff --git a/include/arm/ep_info.h b/include/arm/ep_info.h
new file mode 100644
index 0000000..a76c6ae
--- /dev/null
+++ b/include/arm/ep_info.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright The Transfer List Library Contributors
+ *
+ * SPDX-License-Identifier: MIT OR GPL-2.0-or-later
+ */
+
+#ifndef EP_INFO_H
+#define EP_INFO_H
+
+#include <stdint.h>
+
+struct 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 */
+};
+
+struct aapcs_params {
+#ifdef __aarch64__
+ uint64_t arg0;
+ uint64_t arg1;
+ uint64_t arg2;
+ uint64_t arg3;
+ uint64_t arg4;
+ uint64_t arg5;
+ uint64_t arg6;
+ uint64_t arg7;
+#else
+ uint32_t arg0;
+ uint32_t arg1;
+ uint32_t arg2;
+ uint32_t arg3;
+#endif
+};
+
+struct entry_point_info {
+ struct param_header h;
+ uintptr_t pc;
+ uint32_t spsr;
+#ifndef __aarch64__
+ uintptr_t lr_svc;
+#endif
+ struct aapcs_params args;
+};
+
+#define GET_SPSR_RW(mode) (((mode) >> 0x4U) & 0x1U)
+
+#endif
\ No newline at end of file
diff --git a/include/transfer_list.h b/include/transfer_list.h
index 1e4bd7b..0d9b5a3 100644
--- a/include/transfer_list.h
+++ b/include/transfer_list.h
@@ -9,6 +9,7 @@
#include <assert.h>
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
#define TRANSFER_LIST_SIGNATURE 0x4a0fb10b
@@ -163,5 +164,9 @@
struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
uint32_t tag_id);
+struct entry_point_info *
+transfer_list_set_handoff_args(struct transfer_list_header *tl,
+ struct entry_point_info *ep_info);
+
#endif /* __ASSEMBLER__ */
#endif /* TRANSFER_LIST_H */
diff --git a/src/arm/ep_info.c b/src/arm/ep_info.c
new file mode 100644
index 0000000..f6b26be
--- /dev/null
+++ b/src/arm/ep_info.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright The Transfer List Library Contributors
+ *
+ * SPDX-License-Identifier: MIT OR GPL-2.0-or-later
+ */
+
+#include <ep_info.h>
+#include <stddef.h>
+#include <transfer_list.h>
+
+/**
+ * Set handoff arguments in the entry point info structure.
+ *
+ * This function populates the provided entry point info structure with data
+ * from the transfer list.
+ *
+ * @param[in] tl Pointer to the transfer list.
+ * @param[out] ep_info Pointer to the entry point info structure to populate.
+ *
+ * @return Pointer to the populated entry point info structure.
+ */
+struct entry_point_info *
+transfer_list_set_handoff_args(struct transfer_list_header *tl,
+ struct entry_point_info *ep_info)
+{
+ struct transfer_list_entry *te = NULL;
+ void *dt = NULL;
+
+ if (!ep_info || !tl || transfer_list_check_header(tl) == TL_OPS_NON) {
+ return NULL;
+ }
+
+ te = transfer_list_find(tl, TL_TAG_FDT);
+ dt = transfer_list_entry_data(te);
+
+#ifdef __aarch64__
+ if (GET_SPSR_RW(ep_info->spsr) == 0U) {
+ ep_info->args.arg0 = (uintptr_t)dt;
+ ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_X1_VALUE(
+ REGISTER_CONVENTION_VERSION);
+ ep_info->args.arg2 = 0;
+ } else
+#endif
+ {
+ ep_info->args.arg0 = 0;
+ ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_R1_VALUE(
+ REGISTER_CONVENTION_VERSION);
+ ep_info->args.arg2 = (uintptr_t)dt;
+ }
+
+ ep_info->args.arg3 = (uintptr_t)tl;
+
+ return ep_info;
+}
diff --git a/src/transfer_list.c b/src/generic/transfer_list.c
similarity index 99%
rename from src/transfer_list.c
rename to src/generic/transfer_list.c
index 2aa584c..2e681dc 100644
--- a/src/transfer_list.c
+++ b/src/generic/transfer_list.c
@@ -47,7 +47,7 @@
printf("hdr_size 0x%x\n", te->hdr_size);
printf("data_size 0x%x\n", te->data_size);
printf("data_addr 0x%lx\n",
- (unsigned long)transfer_list_entry_data(te));
+ (unsigned long)transfer_list_entry_data(te));
}
}