/* * Copyright (c) 2018-2019, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * */ #include <stdint.h> #include "bl2/include/tfm_boot_status.h" #include "tfm_memory_utils.h" #include "tfm_internal.h" #include "tfm_api.h" #include "flash_layout.h" #include "secure_fw/spm/spm_api.h" #ifdef TFM_PSA_API #include "tfm_internal_defines.h" #include "tfm_utils.h" #include "psa_service.h" #include "tfm_thread.h" #include "tfm_wait.h" #include "tfm_message_queue.h" #include "tfm_spm.h" #endif /*! * \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 tfm_boot_data *boot_data; boot_data = (struct tfm_boot_data *)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 (boot_data->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 *buf_start = (uint8_t *)args[1]; uint16_t buf_size = (uint16_t)args[2]; uint8_t *ptr; struct tfm_boot_data *boot_data; struct shared_data_tlv_entry tlv_entry; uintptr_t tlv_end, offset; #ifndef TFM_PSA_API uint32_t running_partition_idx = tfm_spm_partition_get_running_partition_idx(); uint32_t res; #else struct tfm_spm_ipc_partition_t *partition = NULL; uint32_t privileged; #endif #ifndef TFM_PSA_API /* 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); /* Check 4 bytes alignment */ if (!res) { /* Not in accessible range, return error */ args[0] = TFM_ERROR_INVALID_PARAMETER; return; } #else partition = tfm_spm_get_running_partition(); if (!partition) { tfm_panic(); } privileged = tfm_spm_partition_get_privileged_mode(partition->index); if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { /* Not in accessible range, return error */ args[0] = TFM_ERROR_INVALID_PARAMETER; return; } #endif /* 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 */ boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE; tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->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 { boot_data = (struct tfm_boot_data *)buf_start; boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC; boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE; ptr = boot_data->data; } /* 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) { /* Create local copy to avoid unaligned access */ tfm_memcpy(&tlv_entry, (const void *)offset, SHARED_DATA_ENTRY_HEADER_SIZE); if (GET_MAJOR(tlv_entry.tlv_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 *)offset, tlv_entry.tlv_len); ptr += tlv_entry.tlv_len; boot_data->header.tlv_tot_len += tlv_entry.tlv_len; } } args[0] = TFM_SUCCESS; return; }