diff options
author | Tamas Ban <tamas.ban@arm.com> | 2018-09-18 08:15:18 +0100 |
---|---|---|
committer | Tamas Ban <tamas.ban@arm.com> | 2018-12-05 16:04:52 +0100 |
commit | 9ff535b5b2b66527c31f2ab84ec4efd00572d8c5 (patch) | |
tree | 3a8e416b182103226c20192b50d2d2a622c32e2a | |
parent | a9de4a6e9caecc6b1f9be038016686149eefa9f9 (diff) | |
download | trusted-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.inc | 1 | ||||
-rw-r--r-- | secure_fw/core/tfm_boot_data.c | 124 | ||||
-rw-r--r-- | secure_fw/core/tfm_core.c | 2 | ||||
-rw-r--r-- | secure_fw/core/tfm_handler.c | 3 | ||||
-rw-r--r-- | secure_fw/core/tfm_internal.h | 37 | ||||
-rw-r--r-- | secure_fw/core/tfm_secure_api.c | 32 | ||||
-rw-r--r-- | secure_fw/core/tfm_secure_api.h | 3 | ||||
-rw-r--r-- | secure_fw/core/tfm_spm_services.c | 9 | ||||
-rw-r--r-- | secure_fw/core/tfm_svc.h | 1 |
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)) |