aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamas Ban <tamas.ban@arm.com>2018-09-18 08:15:18 +0100
committerTamas Ban <tamas.ban@arm.com>2018-12-05 16:04:52 +0100
commit9ff535b5b2b66527c31f2ab84ec4efd00572d8c5 (patch)
tree3a8e416b182103226c20192b50d2d2a622c32e2a
parenta9de4a6e9caecc6b1f9be038016686149eefa9f9 (diff)
downloadtrusted-firmware-m-9ff535b5b2b66527c31f2ab84ec4efd00572d8c5.tar.gz
Core: Add data exchange b/w runtime and BL2
Details: - extend SPM's services API with new functions, which is used by partitions to retrive relevant data from bootloader Change-Id: I0efecfd86137f8059be2221ba5e3f9386f1b60d0 Signed-off-by: Tamas Ban <tamas.ban@arm.com>
-rw-r--r--secure_fw/core/CMakeLists.inc1
-rw-r--r--secure_fw/core/tfm_boot_data.c124
-rw-r--r--secure_fw/core/tfm_core.c2
-rw-r--r--secure_fw/core/tfm_handler.c3
-rw-r--r--secure_fw/core/tfm_internal.h37
-rw-r--r--secure_fw/core/tfm_secure_api.c32
-rw-r--r--secure_fw/core/tfm_secure_api.h3
-rw-r--r--secure_fw/core/tfm_spm_services.c9
-rw-r--r--secure_fw/core/tfm_svc.h1
9 files changed, 189 insertions, 23 deletions
diff --git a/secure_fw/core/CMakeLists.inc b/secure_fw/core/CMakeLists.inc
index 668d98a18b..a4b6229568 100644
--- a/secure_fw/core/CMakeLists.inc
+++ b/secure_fw/core/CMakeLists.inc
@@ -36,6 +36,7 @@ set (SS_CORE_C_SRC
"${SS_CORE_DIR}/tfm_secure_api.c"
"${SS_CORE_DIR}/tfm_spm_services.c"
"${SS_CORE_DIR}/tfm_nspm.c"
+ "${SS_CORE_DIR}/tfm_boot_data.c"
)
#Append all our source files to global lists.
diff --git a/secure_fw/core/tfm_boot_data.c b/secure_fw/core/tfm_boot_data.c
new file mode 100644
index 0000000000..cad2b70b89
--- /dev/null
+++ b/secure_fw/core/tfm_boot_data.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "bl2/include/tfm_boot_status.h"
+#include "secure_utilities.h"
+#include "tfm_internal.h"
+#include "tfm_api.h"
+#include "flash_layout.h"
+#include "secure_fw/spm/spm_api.h"
+
+/*!
+ * \def BOOT_DATA_VALID
+ *
+ * \brief Indicates that shared data between bootloader and runtime firmware was
+ * passed the sanity check with success.
+ */
+#define BOOT_DATA_VALID (1u)
+
+/*!
+ * \def BOOT_DATA_INVALID
+ *
+ * \brief Indicates that shared data between bootloader and runtime firmware was
+ * failed on sanity check.
+ */
+#define BOOT_DATA_INVALID (0u)
+
+/*!
+ * \var is_boot_data_valid
+ *
+ * \brief Indicates the status of shared data between bootloader and runtime
+ * firmware
+ */
+static uint32_t is_boot_data_valid = BOOT_DATA_INVALID;
+
+void tfm_core_validate_boot_data(void)
+{
+ struct shared_data_tlv_header *tlv_header;
+
+ tlv_header = (struct shared_data_tlv_header *)BOOT_TFM_SHARED_DATA_BASE;
+
+ /* FixMe: Enhance sanity check of shared memory area, it might be invalid:
+ * - temporal exposure of RAM to non-secure actors
+ * - mismatched addresses
+ * - version mismatch between bootloader and runtime binary
+ * - etc.
+ */
+ if (tlv_header->tlv_magic == SHARED_DATA_TLV_INFO_MAGIC) {
+ is_boot_data_valid = BOOT_DATA_VALID;
+ }
+}
+
+void tfm_core_get_boot_data_handler(uint32_t args[])
+{
+ uint8_t tlv_major = (uint8_t)args[0];
+ uint8_t *ptr = (uint8_t *)args[1];
+ uint16_t buf_size = (uint16_t)args[2];
+ uint8_t *buf_start = ptr;
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ struct shared_data_tlv_header *tlv_header;
+ struct shared_data_tlv_entry *tlv_entry;
+ uintptr_t tlv_end, offset;
+ uint32_t res;
+
+ /* Make sure that the output pointer points to a memory area that is owned
+ * by the partition
+ */
+ res = tfm_core_check_buffer_access(running_partition_idx,
+ (void*)buf_start,
+ buf_size,
+ 2);
+ if (!res) {
+ /* Not in accessible range, return error */
+ args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* FixMe: Check whether caller has access right to given tlv_major_type */
+
+ if (is_boot_data_valid != BOOT_DATA_VALID) {
+ args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* Get the boundaries of TLV section */
+ tlv_header = (struct shared_data_tlv_header *)BOOT_TFM_SHARED_DATA_BASE;
+ tlv_end = BOOT_TFM_SHARED_DATA_BASE + tlv_header->tlv_tot_len;
+ offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
+
+ /* Add header to output buffer as well */
+ if (buf_size < SHARED_DATA_HEADER_SIZE) {
+ args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ } else {
+ tfm_memcpy(ptr, tlv_header, SHARED_DATA_HEADER_SIZE);
+ ptr += SHARED_DATA_HEADER_SIZE;
+ }
+
+ /* Iterates over the TLV section and copy TLVs with requested major
+ * type to the provided buffer.
+ */
+ for(; offset < tlv_end; offset += tlv_entry->tlv_len) {
+ tlv_entry = (struct shared_data_tlv_entry *)offset;
+ if (tlv_entry->tlv_major_type == tlv_major) {
+ /* Check buffer overflow */
+ if ((ptr - buf_start + tlv_entry->tlv_len) > buf_size) {
+ args[0] = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ tfm_memcpy(ptr, (const void *)tlv_entry, tlv_entry->tlv_len);
+
+ ptr += tlv_entry->tlv_len;
+ tlv_header->tlv_tot_len += tlv_entry->tlv_len;
+ }
+ }
+ args[0] = TFM_SUCCESS;
+ return;
+}
diff --git a/secure_fw/core/tfm_core.c b/secure_fw/core/tfm_core.c
index 68c5e23b77..651bbf806a 100644
--- a/secure_fw/core/tfm_core.c
+++ b/secure_fw/core/tfm_core.c
@@ -134,6 +134,8 @@ int32_t tfm_core_init(void)
printf("TFM level is: %d\r\n", TFM_LVL);
#endif
+ tfm_core_validate_boot_data();
+
tfm_spm_hal_init_isolation_hw();
configure_ns_code();
diff --git a/secure_fw/core/tfm_handler.c b/secure_fw/core/tfm_handler.c
index 92d7f5cee4..4cf313c401 100644
--- a/secure_fw/core/tfm_handler.c
+++ b/secure_fw/core/tfm_handler.c
@@ -172,6 +172,9 @@ uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr)
case TFM_SVC_PRINT:
printf("\e[1;34m[Sec Thread] %s\e[0m\r\n", (char *)svc_args[0]);
break;
+ case TFM_SVC_GET_BOOT_DATA:
+ tfm_core_get_boot_data_handler(svc_args);
+ break;
default:
LOG_MSG("Unknown SVC number requested!");
break;
diff --git a/secure_fw/core/tfm_internal.h b/secure_fw/core/tfm_internal.h
index 79242723e6..18a56ecdac 100644
--- a/secure_fw/core/tfm_internal.h
+++ b/secure_fw/core/tfm_internal.h
@@ -5,6 +5,8 @@
*
*/
+#include "secure_utilities.h"
+
#ifndef __TFM_INTERNAL_H__
#define __TFM_INTERNAL_H__
@@ -60,4 +62,39 @@ void tfm_core_memory_permission_check_handler(const uint32_t svc_args[]);
*/
void tfm_core_spm_request_handler(const struct tfm_exc_stack_t *svc_ctx);
+/**
+ * \brief Check whether a buffer is ok for writing to by the privileged API
+ * function.
+ *
+ * This function checks whether the caller partition owns the buffer, can write
+ * to it, and the buffer has proper alignment.
+ *
+ * \param[in] partition_idx Partition index
+ * \param[in] start_addr The start address of the buffer
+ * \param[in] len The length of the buffer
+ * \param[in] alignment The expected alignment (in bits)
+ *
+ * \return 1 if the check passes, 0 otherwise.
+ *
+ * \note For a 0 long buffer the check fails.
+ */
+int32_t tfm_core_check_buffer_access(uint32_t partition_idx,
+ void *start_addr,
+ size_t len,
+ uint32_t alignment);
+
+/**
+ * \brief Retrieve secure partition related data from shared memory area, which
+ * stores shared data between bootloader and runtime firmware.
+ *
+ * \param[in] args Pointer to stack frame, which carries input parameters.
+ */
+void tfm_core_get_boot_data_handler(uint32_t args[]);
+
+/**
+ * \brief Validate the content of shared memory area, which stores the shared
+ * data between bootloader and runtime firmware.
+ */
+void tfm_core_validate_boot_data(void);
+
#endif /* __TFM_INTERNAL_H__ */
diff --git a/secure_fw/core/tfm_secure_api.c b/secure_fw/core/tfm_secure_api.c
index d3a0f952ba..0b66ba57a4 100644
--- a/secure_fw/core/tfm_secure_api.c
+++ b/secure_fw/core/tfm_secure_api.c
@@ -486,25 +486,11 @@ void tfm_core_validate_secure_caller_handler(uint32_t *svc_args)
}
svc_args[0] = res;
}
-/**
- * \brief Check whether a buffer is ok for writing to by the privileged API
- * function.
- *
- * This function checks whether the caller partition owns the buffer, can write
- * to it, and the buffer has proper alignment.
- *
- * \param[in] partition_idx Partition index
- * \param[in] start_addr The start address of the buffer
- * \param[in] len The length of the buffer
- * \param[in] alignment The expected alignment (in bits)
- *
- * \return 1 if the check passes, 0 otherwise.
- *
- * \note For a 0 long buffer the check fails.
- */
-static int32_t check_buffer_access(uint32_t partition_idx,
- void* start_addr, size_t len,
- uint32_t alignment)
+
+int32_t tfm_core_check_buffer_access(uint32_t partition_idx,
+ void *start_addr,
+ size_t len,
+ uint32_t alignment)
{
uintptr_t start_addr_value = (uintptr_t)start_addr;
uintptr_t end_addr_value = (uintptr_t)start_addr + len;
@@ -580,10 +566,10 @@ void tfm_core_get_caller_client_id_handler(uint32_t *svc_args)
/* Make sure that the output pointer points to a memory area that is owned
* by the partition
*/
- res = check_buffer_access(running_partition_idx,
- (void*)result_ptr_value,
- sizeof(curr_part_data->caller_client_id),
- 2);
+ res = tfm_core_check_buffer_access(running_partition_idx,
+ (void *)result_ptr_value,
+ sizeof(curr_part_data->caller_client_id),
+ 2);
if (!res) {
/* Not in accessible range, return error */
svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
diff --git a/secure_fw/core/tfm_secure_api.h b/secure_fw/core/tfm_secure_api.h
index 8fb94c7566..2f253e1ae6 100644
--- a/secure_fw/core/tfm_secure_api.h
+++ b/secure_fw/core/tfm_secure_api.h
@@ -76,6 +76,9 @@ extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);
extern int32_t tfm_core_memory_permission_check(
void *ptr, uint32_t size, int32_t access);
+extern int32_t tfm_core_get_boot_data(uint8_t major_type, void *ptr,
+ uint32_t len);
+
int32_t tfm_core_sfn_request(struct tfm_sfn_req_s *desc_ptr);
int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
diff --git a/secure_fw/core/tfm_spm_services.c b/secure_fw/core/tfm_spm_services.c
index 48fd343215..9052ef7369 100644
--- a/secure_fw/core/tfm_spm_services.c
+++ b/secure_fw/core/tfm_spm_services.c
@@ -153,3 +153,12 @@ int32_t tfm_core_set_buffer_area(enum tfm_buffer_share_region_e share)
"BX lr\n"
: : "I" (TFM_SVC_SET_SHARE_AREA));
}
+
+__attribute__((naked))
+int32_t tfm_core_get_boot_data(uint8_t major_type, void *ptr, uint32_t len)
+{
+ __ASM(
+ "SVC %0\n"
+ "BX lr\n"
+ : : "I" (TFM_SVC_GET_BOOT_DATA));
+}
diff --git a/secure_fw/core/tfm_svc.h b/secure_fw/core/tfm_svc.h
index b4817503af..60c9ac80f1 100644
--- a/secure_fw/core/tfm_svc.h
+++ b/secure_fw/core/tfm_svc.h
@@ -19,6 +19,7 @@ typedef enum {
TFM_SVC_SET_SHARE_AREA,
TFM_SVC_SPM_REQUEST,
TFM_SVC_PRINT,
+ TFM_SVC_GET_BOOT_DATA,
} tfm_svc_number_t;
#define SVC(code) __ASM("svc %0" : : "I" (code))