mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #12737 from Patater/psa-breaking-changes
Remove PSA implementation for v8-M and dual CPU targetspull/12432/head
						commit
						a9cb876b39
					
				| 
						 | 
				
			
			@ -97,6 +97,3 @@ test_suite.json
 | 
			
		|||
 | 
			
		||||
# default delivery dir
 | 
			
		||||
DELIVERY/
 | 
			
		||||
 | 
			
		||||
# Directory hosting PSA autogenerated source files
 | 
			
		||||
PSA_AUTOGEN/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								.travis.yml
								
								
								
								
							
							
						
						
									
										11
									
								
								.travis.yml
								
								
								
								
							| 
						 | 
				
			
			@ -226,8 +226,8 @@ matrix:
 | 
			
		|||
    ### Extended Tests ###
 | 
			
		||||
    - &extended-vm
 | 
			
		||||
      stage: "Extended"
 | 
			
		||||
      name: "psa autogen"
 | 
			
		||||
      env: NAME=psa-autogen
 | 
			
		||||
      name: "events"
 | 
			
		||||
      env: NAME=events EVENTS=events
 | 
			
		||||
      language: python
 | 
			
		||||
      python: 3.7
 | 
			
		||||
      install:
 | 
			
		||||
| 
						 | 
				
			
			@ -239,13 +239,6 @@ matrix:
 | 
			
		|||
        - python -m pip install --upgrade setuptools==40.4.3
 | 
			
		||||
        - pip install -r requirements.txt
 | 
			
		||||
        - pip list --verbose
 | 
			
		||||
      script:
 | 
			
		||||
        - python tools/psa/generate_partition_code.py
 | 
			
		||||
        - git diff --exit-code
 | 
			
		||||
    
 | 
			
		||||
    - <<: *extended-vm
 | 
			
		||||
      name: "events"
 | 
			
		||||
      env: NAME=events EVENTS=events
 | 
			
		||||
      script:
 | 
			
		||||
        # Check that example compiles
 | 
			
		||||
        - sed -n '/``` cpp/,/```/{/```$/Q;/```/d;p;}' ${EVENTS}/README.md > main.cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MBED_HAL_SPM_FAULT_FUNCTIONS__
 | 
			
		||||
#define __MBED_HAL_SPM_FAULT_FUNCTIONS__
 | 
			
		||||
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Retruns the value of the LR register
 | 
			
		||||
// Used to determine which stack the exception happend in
 | 
			
		||||
__STATIC_FORCEINLINE uint32_t __get_LR(void);
 | 
			
		||||
 | 
			
		||||
// This function is required as we need a symbol/address
 | 
			
		||||
// to jump to from fault handler.
 | 
			
		||||
void do_nothing(void);
 | 
			
		||||
 | 
			
		||||
// Test exception handler
 | 
			
		||||
static void hard_fault_handler_test();
 | 
			
		||||
 | 
			
		||||
// Using naked function as it will not be executed from beginning to the end.
 | 
			
		||||
// The execution flow expected to be interrupted by exception and we will
 | 
			
		||||
// return to other function.
 | 
			
		||||
// compiler will not produce prolog and epilog code for naked function
 | 
			
		||||
// and thus will preserve stack in un-corrupted state
 | 
			
		||||
__attribute__((naked)) void call_mem(uint32_t addr);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // __MBED_HAL_SPM_FAULT_FUNCTIONS__
 | 
			
		||||
| 
						 | 
				
			
			@ -1,162 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
#error [NOT_SUPPORTED] Test supported only on PSA targets
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#if (defined(__ARMCC_VERSION) || defined( __ICCARM__ ))
 | 
			
		||||
#error [NOT_SUPPORTED] this test is supported on GCC only
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#if DOMAIN_NS == 1
 | 
			
		||||
#error [NOT_SUPPORTED] Cannot run on M23/M33 core as SecureFault is implemented in secure-side and cant be remapped
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#include "utest/utest.h"
 | 
			
		||||
#include "unity/unity.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "fault_functions.h"
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define HARDFAULT_IRQn   ((IRQn_Type)-13)
 | 
			
		||||
#define EXC_RETURN_RETURN_STACK_MSK ((uint32_t)(0x00000004))
 | 
			
		||||
#define PC_INDEX_IN_STACK_FRAME 6
 | 
			
		||||
 | 
			
		||||
volatile uint32_t fault_occurred;
 | 
			
		||||
uint32_t real_hard_fault_handler;
 | 
			
		||||
 | 
			
		||||
__STATIC_FORCEINLINE uint32_t __get_LR(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t result;
 | 
			
		||||
 | 
			
		||||
    __ASM volatile("MOV %0, lr" : "=r"(result));
 | 
			
		||||
    return (result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void do_nothing(void)
 | 
			
		||||
{
 | 
			
		||||
    __NOP();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hard_fault_handler_test()
 | 
			
		||||
{
 | 
			
		||||
    fault_occurred++;
 | 
			
		||||
    // LR is set EXC_RETURN
 | 
			
		||||
    // lowest bits identify PSP vs MSP stack used for stacking
 | 
			
		||||
    uint32_t lr = __get_LR();
 | 
			
		||||
    uint32_t sp;
 | 
			
		||||
 | 
			
		||||
    if (lr & EXC_RETURN_RETURN_STACK_MSK) {
 | 
			
		||||
        sp = __get_PSP();
 | 
			
		||||
    } else {
 | 
			
		||||
        sp = __get_MSP();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Overwrite return address.
 | 
			
		||||
    // Fake return to a our special function since current
 | 
			
		||||
    // instruction under test will always fail due to memory protection
 | 
			
		||||
    ((uint32_t *)sp)[PC_INDEX_IN_STACK_FRAME] = (uint32_t)do_nothing;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked)) void call_mem(uint32_t addr)
 | 
			
		||||
{
 | 
			
		||||
    // Only first instruction will be executed in positive flow,
 | 
			
		||||
    // since exception will be generated for invalid memory access.
 | 
			
		||||
    // Other instructions are for calling do_nothing function according to AAPCS.
 | 
			
		||||
    __ASM(
 | 
			
		||||
        "LDR     r3, [r0]\n"
 | 
			
		||||
        "BX      lr\n"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_memory(uint32_t addr, uint32_t expected_fatal_count)
 | 
			
		||||
{
 | 
			
		||||
    call_mem(addr);
 | 
			
		||||
    // Although call_mem is a "naked" function, it is called using AAPCS.
 | 
			
		||||
    // Thus we can assume LR will point to next instruction, and caller save registers are backed up
 | 
			
		||||
    TEST_ASSERT_EQUAL(expected_fatal_count, fault_occurred);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void secure_ram_fault_test(void)
 | 
			
		||||
{
 | 
			
		||||
    test_memory(PSA_SECURE_RAM_START, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void secure_flash_fault_test(void)
 | 
			
		||||
{
 | 
			
		||||
    test_memory(PSA_SECURE_ROM_START, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void non_secure_ram_fault_test(void)
 | 
			
		||||
{
 | 
			
		||||
    test_memory(PSA_NON_SECURE_RAM_START, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void non_secure_flash_fault_test(void)
 | 
			
		||||
{
 | 
			
		||||
    test_memory(PSA_NON_SECURE_ROM_START, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t fault_override_setup(const Case *const source, const size_t index_of_case)
 | 
			
		||||
{
 | 
			
		||||
    // Save old hard fault handler and replace it with a new one
 | 
			
		||||
    // NOTE: only works when VTOR is set to RAM
 | 
			
		||||
    real_hard_fault_handler = NVIC_GetVector(HARDFAULT_IRQn);
 | 
			
		||||
    NVIC_SetVector(HARDFAULT_IRQn, (uint32_t)&hard_fault_handler_test);
 | 
			
		||||
    fault_occurred = 0;
 | 
			
		||||
 | 
			
		||||
    return greentea_case_setup_handler(source, index_of_case);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t fault_override_teardown(const Case *const source, const size_t passed, const size_t failed,
 | 
			
		||||
                                            const failure_t reason)
 | 
			
		||||
{
 | 
			
		||||
    // Restore real hard fault handler
 | 
			
		||||
    NVIC_SetVector(HARDFAULT_IRQn, real_hard_fault_handler);
 | 
			
		||||
 | 
			
		||||
    return greentea_case_teardown_handler(source, passed, failed, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    Case("SPM - Access non-secure RAM",   fault_override_setup, non_secure_ram_fault_test, fault_override_teardown),
 | 
			
		||||
    Case("SPM - Access non-secure Flash", fault_override_setup, non_secure_flash_fault_test, fault_override_teardown),
 | 
			
		||||
    Case("SPM - Access secure RAM",       fault_override_setup, secure_ram_fault_test, fault_override_teardown),
 | 
			
		||||
    Case("SPM - Access secure Flash",     fault_override_setup, secure_flash_fault_test, fault_override_teardown)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    GREENTEA_SETUP(20, "default_auto");
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // DOMAIN_NS == 1
 | 
			
		||||
#endif // (defined(__ARMCC_VERSION) || defined( __ICCARM__ ))
 | 
			
		||||
#endif // !defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,556 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited and affiliates
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "psa/crypto.h"
 | 
			
		||||
 | 
			
		||||
#if ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C)) || (!defined(COMPONENT_PSA_SRV_IPC)))
 | 
			
		||||
#error [NOT_SUPPORTED] These tests can run only on SPM-enabled targets and where Mbed Crypto is ON - skipping.
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "entropy.h"
 | 
			
		||||
#include "entropy_poll.h"
 | 
			
		||||
#include "test_partition_proxy.h"
 | 
			
		||||
#include "psa/lifecycle.h"
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
 | 
			
		||||
#if !defined(MAX)
 | 
			
		||||
#define MAX(a,b) (((a)>(b))?(a):(b))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \
 | 
			
		||||
            MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
 | 
			
		||||
 | 
			
		||||
void inject_entropy()
 | 
			
		||||
{
 | 
			
		||||
    uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 };
 | 
			
		||||
    for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) {
 | 
			
		||||
        seed[i] = i;
 | 
			
		||||
    }
 | 
			
		||||
    mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE);
 | 
			
		||||
}
 | 
			
		||||
#endif // defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
 | 
			
		||||
static psa_status_t create_and_generate_key_via_test_partition(
 | 
			
		||||
    const psa_key_attributes_t *attributes,
 | 
			
		||||
    psa_key_handle_t *key_handle,
 | 
			
		||||
    uint8_t close_key)
 | 
			
		||||
{
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      test_partition_crypto_generate_key(attributes,
 | 
			
		||||
                                                         key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, *key_handle);
 | 
			
		||||
    if (close_key) {
 | 
			
		||||
        TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(*key_handle));
 | 
			
		||||
    }
 | 
			
		||||
    return (PSA_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_open_other_partition_key(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
 | 
			
		||||
    static const size_t key_bits = 128;
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - create a key, generate key material and close */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* via test partition - close the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(key_handle));
 | 
			
		||||
 | 
			
		||||
    /* try to open the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, psa_open_key(key_id, &key_handle));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition and keep it open */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_create_key_same_id_different_partitions(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
 | 
			
		||||
    static const psa_key_usage_t key_usage_remote = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
 | 
			
		||||
                                 key_usage_local = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
 | 
			
		||||
    static const size_t key_bits_remote = 128,
 | 
			
		||||
                        key_bits_local = 256;
 | 
			
		||||
    psa_key_handle_t key_handle_remote = 0,
 | 
			
		||||
                     key_handle_local = 0;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - create a key, generate key material and close */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage_remote);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits_remote);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      create_and_generate_key_via_test_partition(&attributes, &key_handle_remote, 1));
 | 
			
		||||
    psa_reset_key_attributes(&attributes);
 | 
			
		||||
 | 
			
		||||
    /* create a key, generate key material and close from current partition (i.e. NSPE) */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage_local);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits_local);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generate_key(&attributes, &key_handle_local));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle_local);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_close_key(key_handle_local));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition */
 | 
			
		||||
    key_handle_remote = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle_remote));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle_remote);
 | 
			
		||||
 | 
			
		||||
    /* reopen the key created from the current partition (NSPE) */
 | 
			
		||||
    key_handle_local = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_open_key(key_id, &key_handle_local));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle_local);
 | 
			
		||||
 | 
			
		||||
    /* via test partition - get key info for the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      test_partition_crypto_get_key_attributes(key_handle_remote,
 | 
			
		||||
                                                               &attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_type, psa_get_key_type(&attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_bits_remote, psa_get_key_bits(&attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_usage_remote, psa_get_key_usage_flags(&attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_alg, psa_get_key_algorithm(&attributes));
 | 
			
		||||
 | 
			
		||||
    /* get key attributes for key created by the current partition (NSPE) */
 | 
			
		||||
    attributes = psa_key_attributes_init();
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_get_key_attributes(key_handle_local, &attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_type, psa_get_key_type(&attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_bits_local, psa_get_key_bits(&attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_usage_local, psa_get_key_usage_flags(&attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(key_alg, psa_get_key_algorithm(&attributes));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle_remote));
 | 
			
		||||
 | 
			
		||||
    /* destroy the key created by the current partition (NSPE) */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle_local));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_use_other_partition_key_manage_key(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_EXPORT;
 | 
			
		||||
    static const size_t key_bits = 128;
 | 
			
		||||
    static const uint8_t key_data[] = {
 | 
			
		||||
        0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
 | 
			
		||||
        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
 | 
			
		||||
    };
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
    uint8_t output[sizeof(key_data)] = { 0 };
 | 
			
		||||
    size_t len;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - generate a persistent key and close the key */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_generate_key(&attributes, &key_handle));
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(key_handle));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition and keep it open */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* try to work with the handle created for a key created by the test partition */
 | 
			
		||||
    attributes = psa_key_attributes_init();
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_get_key_attributes(key_handle, &attributes));
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_close_key(key_handle));
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_destroy_key(key_handle));
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_export_key(key_handle, output, sizeof(output), &len));
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_export_public_key(key_handle, output, sizeof(output), &len));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - import key data for the key created by the test partition */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      test_partition_crypto_import_key(
 | 
			
		||||
                          &attributes, key_data, sizeof(key_data), &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_use_other_partition_key_mac(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
 | 
			
		||||
    static const size_t key_bits = 128;
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    psa_mac_operation_t operation;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - create a key, generate key material and close */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* try to setup mac sign operation using the key that was created by the test partition */
 | 
			
		||||
    operation = psa_mac_operation_init();
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_mac_sign_setup(&operation, key_handle, key_alg));
 | 
			
		||||
 | 
			
		||||
    /* try to setup mac verify operation using the key that was created by the test partition */
 | 
			
		||||
    operation = psa_mac_operation_init();
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_mac_verify_setup(&operation, key_handle, key_alg));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_use_other_partition_key_cipher(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
 | 
			
		||||
    static const size_t key_bits = 128;
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    psa_cipher_operation_t operation;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - create a key, generate key material and close */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* try to setup cipher encrypt operation using the key that was created by the test partition */
 | 
			
		||||
    operation = psa_cipher_operation_init();
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_cipher_encrypt_setup(&operation, key_handle, key_alg));
 | 
			
		||||
 | 
			
		||||
    /* try to setup cipher decrypt operation using the key that was created by the test partition */
 | 
			
		||||
    operation = psa_cipher_operation_init();
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_cipher_decrypt_setup(&operation, key_handle, key_alg));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_use_other_partition_key_aead(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_GCM;
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
 | 
			
		||||
    static const size_t key_bits = 128;
 | 
			
		||||
    static const uint8_t nonce[16] = { 0 };
 | 
			
		||||
    uint8_t plain_text[] = "encrypt me!";
 | 
			
		||||
    uint8_t cipher_text[PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_alg, sizeof(plain_text))] = { 0 };
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    size_t len;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - create a key, generate key material and close */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* try to aead encrypt using the key that was created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_aead_encrypt(key_handle, key_alg, nonce, sizeof(nonce), NULL, 0,
 | 
			
		||||
                                                                 plain_text, sizeof(plain_text),
 | 
			
		||||
                                                                 cipher_text, sizeof(cipher_text), &len));
 | 
			
		||||
 | 
			
		||||
    /* try to aead decrypt using the key that was created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_aead_decrypt(key_handle, key_alg, nonce, sizeof(nonce), NULL, 0,
 | 
			
		||||
                                                                 cipher_text, sizeof(cipher_text),
 | 
			
		||||
                                                                 plain_text, sizeof(plain_text), &len));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_use_other_partition_key_asymmetric_sign_verify(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1);
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
 | 
			
		||||
    static const size_t key_bits = 256;
 | 
			
		||||
    static const uint8_t input[] = "hello world!";
 | 
			
		||||
    uint8_t signature[PSA_ECDSA_SIGNATURE_SIZE(key_bits)] = { 0 };
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    size_t len;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - create a key, generate key material and close */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, key_bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* try to asymmetric sign using the key that was created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_sign_hash(key_handle, key_alg, input, sizeof(input),
 | 
			
		||||
                                                              signature, sizeof(signature), &len));
 | 
			
		||||
 | 
			
		||||
    /* try to asymmetric verify using the key that was created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_verify_hash(key_handle, key_alg, input, sizeof(input),
 | 
			
		||||
                                                                signature, sizeof(signature)));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_use_other_partition_key_asymmetric_encrypt_decrypt(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_RSA_KEY_PAIR;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
 | 
			
		||||
    static const uint8_t input[] = "encrypt me!";
 | 
			
		||||
    static const uint8_t key_data[] = {
 | 
			
		||||
        0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xee, 0x2b,
 | 
			
		||||
        0x13, 0x1d, 0x6b, 0x18, 0x18, 0xa9, 0x4c, 0xa8, 0xe9, 0x1c, 0x42, 0x38,
 | 
			
		||||
        0x7e, 0xb1, 0x5a, 0x7c, 0x27, 0x1f, 0x57, 0xb8, 0x9e, 0x73, 0x36, 0xb1,
 | 
			
		||||
        0x44, 0xd4, 0x53, 0x5b, 0x16, 0xc8, 0x30, 0x97, 0xec, 0xde, 0xfb, 0xbb,
 | 
			
		||||
        0x92, 0xd1, 0xb5, 0x31, 0x3b, 0x5a, 0x37, 0x21, 0x4d, 0x0e, 0x8f, 0x25,
 | 
			
		||||
        0x92, 0x2d, 0xca, 0x77, 0x8b, 0x42, 0x4b, 0x25, 0x29, 0x5f, 0xc8, 0xa1,
 | 
			
		||||
        0xa7, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x41, 0x00, 0x97, 0x8a,
 | 
			
		||||
        0xc8, 0xea, 0xdb, 0x0d, 0xc6, 0x03, 0x53, 0x47, 0xd6, 0xab, 0xa8, 0x67,
 | 
			
		||||
        0x12, 0x15, 0xff, 0x21, 0x28, 0x33, 0x85, 0x39, 0x6f, 0x78, 0x97, 0xc0,
 | 
			
		||||
        0x4b, 0xaf, 0x5e, 0x2a, 0x83, 0x5f, 0x3b, 0x53, 0xef, 0x80, 0xa8, 0x2e,
 | 
			
		||||
        0xd3, 0x6a, 0xe6, 0x87, 0xa9, 0x25, 0x38, 0x0b, 0x55, 0xa0, 0xc7, 0x3e,
 | 
			
		||||
        0xb8, 0x56, 0x56, 0xe9, 0x89, 0xdc, 0xf0, 0xed, 0x7f, 0xb4, 0x88, 0x70,
 | 
			
		||||
        0x24, 0xe1, 0x02, 0x21, 0x00, 0xfd, 0xad, 0x8e, 0x1c, 0x68, 0x53, 0x56,
 | 
			
		||||
        0x3f, 0x8b, 0x92, 0x1d, 0x2d, 0x11, 0x24, 0x62, 0xae, 0x7d, 0x6b, 0x17,
 | 
			
		||||
        0x60, 0x82, 0xd2, 0xba, 0x43, 0xe8, 0x7e, 0x1a, 0x37, 0xfc, 0x1a, 0x8b,
 | 
			
		||||
        0x33, 0x02, 0x21, 0x00, 0xf0, 0x59, 0x2c, 0xf4, 0xc5, 0x5b, 0xa4, 0x43,
 | 
			
		||||
        0x07, 0xb1, 0x89, 0x81, 0xbc, 0xdb, 0xda, 0x37, 0x6c, 0x51, 0xe5, 0x90,
 | 
			
		||||
        0xff, 0xa5, 0x34, 0x5b, 0xa8, 0x66, 0xf6, 0x96, 0x2d, 0xca, 0x94, 0xdd,
 | 
			
		||||
        0x02, 0x20, 0x19, 0x95, 0xf1, 0xa9, 0x67, 0xd4, 0x4f, 0xf4, 0xa4, 0xcd,
 | 
			
		||||
        0x1d, 0xe8, 0x37, 0xbc, 0x65, 0xbf, 0x97, 0xa2, 0xbf, 0x7e, 0xda, 0x73,
 | 
			
		||||
        0x0a, 0x9a, 0x62, 0xce, 0xa5, 0x32, 0x54, 0x59, 0x11, 0x05, 0x02, 0x20,
 | 
			
		||||
        0x27, 0xf9, 0x6c, 0xf4, 0xb8, 0xee, 0x68, 0xff, 0x8d, 0x04, 0x06, 0x2e,
 | 
			
		||||
        0xc1, 0xce, 0x7f, 0x18, 0xc0, 0xb7, 0x4e, 0x4b, 0x33, 0x79, 0xb2, 0x9f,
 | 
			
		||||
        0x9b, 0xfe, 0xa3, 0xfc, 0x8e, 0x59, 0x27, 0x31, 0x02, 0x21, 0x00, 0xce,
 | 
			
		||||
        0xfa, 0x6d, 0x22, 0x04, 0x96, 0xb4, 0x3f, 0xeb, 0x83, 0x19, 0x42, 0x55,
 | 
			
		||||
        0xd8, 0xfb, 0x93, 0x0a, 0xfc, 0xf4, 0x6f, 0x36, 0x60, 0x6e, 0x3a, 0xa0,
 | 
			
		||||
        0xeb, 0x7a, 0x93, 0xad, 0x88, 0xc1, 0x0c
 | 
			
		||||
    };
 | 
			
		||||
    uint8_t encrypted[64] = { 0 };
 | 
			
		||||
    uint8_t decrypted[sizeof(input)] = { 0 };
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    size_t len;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - import key data for the key created by the test partition */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, 512);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      test_partition_crypto_import_key(
 | 
			
		||||
                          &attributes, key_data, sizeof(key_data), &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* via test partition - close the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(key_handle));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - reopen the key created by the test partition and keep it open */
 | 
			
		||||
    key_handle = 0;
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* try to asymmetric encrypt using the key that was created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_asymmetric_encrypt(key_handle, key_alg, input, sizeof(input),
 | 
			
		||||
                                                                       NULL, 0, encrypted, sizeof(encrypted), &len));
 | 
			
		||||
 | 
			
		||||
    /* try to asymmetric decrypt using the key that was created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_asymmetric_decrypt(key_handle, key_alg,
 | 
			
		||||
                                                                       encrypted, sizeof(encrypted), NULL, 0,
 | 
			
		||||
                                                                       decrypted, sizeof(decrypted), &len));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_use_other_partition_key_derivation_setup(void)
 | 
			
		||||
{
 | 
			
		||||
    static const psa_key_id_t key_id = 999;
 | 
			
		||||
    static const psa_algorithm_t key_alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
 | 
			
		||||
    static const psa_key_usage_t key_usage = PSA_KEY_USAGE_DERIVE;
 | 
			
		||||
    static const psa_key_type_t key_type = PSA_KEY_TYPE_DERIVE;
 | 
			
		||||
    static const uint8_t key_data[] = {
 | 
			
		||||
        0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xee, 0x2b,
 | 
			
		||||
        0x13, 0x1d, 0x6b, 0x18, 0x18, 0xa9, 0x4c, 0xa8, 0xe9, 0x1c, 0x42, 0x38
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
 | 
			
		||||
    size_t bits = 192;
 | 
			
		||||
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
 | 
			
		||||
    /* via test partition - import key data for the key created by the test partition */
 | 
			
		||||
    psa_set_key_usage_flags(&attributes, key_usage);
 | 
			
		||||
    psa_set_key_algorithm(&attributes, key_alg);
 | 
			
		||||
    psa_set_key_bits(&attributes, bits);
 | 
			
		||||
    psa_set_key_type(&attributes, key_type);
 | 
			
		||||
    psa_set_key_id(&attributes, key_id);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS,
 | 
			
		||||
                      test_partition_crypto_import_key(
 | 
			
		||||
                          &attributes, key_data, sizeof(key_data), &key_handle));
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(0, key_handle);
 | 
			
		||||
 | 
			
		||||
    /* try to setup key derivation using the key that was created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_key_derivation_setup(&operation, key_alg));
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE,
 | 
			
		||||
                      psa_key_derivation_input_key(
 | 
			
		||||
                          &operation, PSA_KEY_DERIVATION_INPUT_SECRET, key_handle));
 | 
			
		||||
 | 
			
		||||
    /* via test partition - destroy the key created by the test partition */
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
    status = psa_crypto_init();
 | 
			
		||||
#if defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
    if (status == PSA_ERROR_INSUFFICIENT_ENTROPY) {
 | 
			
		||||
        inject_entropy();
 | 
			
		||||
        status = psa_crypto_init();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
    return greentea_case_setup_handler(source, index_of_case);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t case_teardown_handler(const Case *const source, const size_t passed,
 | 
			
		||||
                                          const size_t failed, const failure_t failure)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
    mbedtls_psa_crypto_free();
 | 
			
		||||
    return greentea_case_teardown_handler(source, passed, failed, failure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    GREENTEA_SETUP(120, "default_auto");
 | 
			
		||||
    return verbose_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    Case("open other partition's key",
 | 
			
		||||
         case_setup_handler, test_open_other_partition_key, case_teardown_handler),
 | 
			
		||||
    Case("create key with same id different partitions",
 | 
			
		||||
         case_setup_handler, test_create_key_same_id_different_partitions, case_teardown_handler),
 | 
			
		||||
    Case("use other partition's key - key manage",
 | 
			
		||||
         case_setup_handler, test_use_other_partition_key_manage_key, case_teardown_handler),
 | 
			
		||||
    Case("use other partition's key - mac",
 | 
			
		||||
         case_setup_handler, test_use_other_partition_key_mac, case_teardown_handler),
 | 
			
		||||
    Case("use other partition's key - cipher",
 | 
			
		||||
         case_setup_handler, test_use_other_partition_key_cipher, case_teardown_handler),
 | 
			
		||||
    Case("use other partition's key - aead",
 | 
			
		||||
         case_setup_handler, test_use_other_partition_key_aead, case_teardown_handler),
 | 
			
		||||
    Case("use other partition's key - asymmetric sign verify",
 | 
			
		||||
         case_setup_handler, test_use_other_partition_key_asymmetric_sign_verify, case_teardown_handler),
 | 
			
		||||
    Case("use other partition's key - asymmetric encrypt decrypt",
 | 
			
		||||
         case_setup_handler, test_use_other_partition_key_asymmetric_encrypt_decrypt, case_teardown_handler),
 | 
			
		||||
    Case("use other partition's key - key derivation setup",
 | 
			
		||||
         case_setup_handler, test_use_other_partition_key_derivation_setup, case_teardown_handler),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Specification specification(test_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
    return !Harness::run(specification);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C)) || (!defined(COMPONENT_PSA_SRV_IPC)))
 | 
			
		||||
| 
						 | 
				
			
			@ -1,101 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited and affiliates
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa_manifest/sid.h"
 | 
			
		||||
#include "test_partition_proxy.h"
 | 
			
		||||
 | 
			
		||||
#define MINOR_VER 1
 | 
			
		||||
 | 
			
		||||
static psa_status_t invoke_ipc_call(uint32_t sid, psa_invec *in_vec, size_t in_vec_size,
 | 
			
		||||
                                    psa_outvec *out_vec, size_t out_vec_size)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status;
 | 
			
		||||
 | 
			
		||||
    psa_handle_t handle = psa_connect(sid, MINOR_VER);
 | 
			
		||||
    if (handle <= 0) {
 | 
			
		||||
        return (PSA_ERROR_COMMUNICATION_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_call(handle, in_vec, in_vec_size, out_vec, out_vec_size);
 | 
			
		||||
    psa_close(handle);
 | 
			
		||||
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_get_key_attributes(
 | 
			
		||||
    psa_key_handle_t key_handle, psa_key_attributes_t *attributes)
 | 
			
		||||
{
 | 
			
		||||
    psa_invec in_vec = { &key_handle, sizeof(key_handle) };
 | 
			
		||||
    psa_outvec out_vec[1] = {
 | 
			
		||||
        { attributes, sizeof(*attributes) }
 | 
			
		||||
    };
 | 
			
		||||
    psa_status_t status = invoke_ipc_call(CRYPTO_GET_KEY_ATTRIBUTES, &in_vec, 1, out_vec, 1);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_generate_key(
 | 
			
		||||
    const psa_key_attributes_t *attributes, psa_key_handle_t *key_handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_invec in_vec[] = {
 | 
			
		||||
        { attributes, sizeof(*attributes) },
 | 
			
		||||
    };
 | 
			
		||||
    psa_outvec out_vec[] = {
 | 
			
		||||
        { key_handle, sizeof(*key_handle) },
 | 
			
		||||
    };
 | 
			
		||||
    psa_status_t status = invoke_ipc_call(CRYPTO_GENERATE_KEY, in_vec, 1, out_vec, 1);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_open_key(psa_key_id_t key_id, psa_key_handle_t *key_handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_invec in_vec = { &key_id, sizeof(key_id) };
 | 
			
		||||
    psa_outvec out_vec = { key_handle, sizeof(*key_handle) };
 | 
			
		||||
    psa_status_t status = invoke_ipc_call(CRYPTO_OPEN_KEY, &in_vec, 1, &out_vec, 1);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_close_key(psa_key_handle_t key_handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_invec in_vec = { &key_handle, sizeof(key_handle) };
 | 
			
		||||
    psa_status_t status = invoke_ipc_call(CRYPTO_CLOSE_KEY, &in_vec, 1, NULL, 0);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_destroy_key(psa_key_handle_t key_handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_invec in_vec = { &key_handle, sizeof(key_handle) };
 | 
			
		||||
    psa_status_t status = invoke_ipc_call(CRYPTO_DESTROY_KEY, &in_vec, 1, NULL, 0);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_import_key(
 | 
			
		||||
    const psa_key_attributes_t *attributes,
 | 
			
		||||
    const uint8_t *key_data,
 | 
			
		||||
    size_t key_data_size,
 | 
			
		||||
    psa_key_handle_t *key_handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_invec in_vec[] = {
 | 
			
		||||
        { attributes, sizeof(*attributes) },
 | 
			
		||||
        { key_data, key_data_size },
 | 
			
		||||
    };
 | 
			
		||||
    psa_outvec out_vec[] = {
 | 
			
		||||
        { key_handle, sizeof(*key_handle) },
 | 
			
		||||
    };
 | 
			
		||||
    psa_status_t status = invoke_ipc_call(CRYPTO_IMPORT_KEY, in_vec, 2, out_vec, 1);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,50 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited and affiliates
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TEST_PARTITION_PROXY_H
 | 
			
		||||
#define TEST_PARTITION_PROXY_H
 | 
			
		||||
 | 
			
		||||
#include "psa/crypto.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_get_key_attributes(
 | 
			
		||||
    psa_key_handle_t key_handle, psa_key_attributes_t *attributes);
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_generate_key(
 | 
			
		||||
    const psa_key_attributes_t *attributes, psa_key_handle_t *key_handle);
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_open_key(
 | 
			
		||||
    psa_key_id_t key_id, psa_key_handle_t *key_handle);
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_close_key(psa_key_handle_t key_handle);
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_destroy_key(psa_key_handle_t key_handle);
 | 
			
		||||
 | 
			
		||||
psa_status_t test_partition_crypto_import_key(
 | 
			
		||||
    const psa_key_attributes_t *attributes,
 | 
			
		||||
    const uint8_t *key_data,
 | 
			
		||||
    size_t key_data_size,
 | 
			
		||||
    psa_key_handle_t *key_handle);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* TEST_PARTITION_PROXY_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,193 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited and affiliates
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "psa/crypto.h"
 | 
			
		||||
 | 
			
		||||
typedef psa_status_t (*SignalHandler)(psa_msg_t *);
 | 
			
		||||
 | 
			
		||||
static void read_input_param_from_message(psa_msg_t *msg, uint8_t param_index, void *param_ptr)
 | 
			
		||||
{
 | 
			
		||||
    size_t bytes_read = psa_read(msg->handle, param_index, param_ptr, msg->in_size[param_index]);
 | 
			
		||||
    if (bytes_read != msg->in_size[param_index]) {
 | 
			
		||||
        SPM_PANIC("SPM read length mismatch");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t crypto_generate_key(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status;
 | 
			
		||||
    psa_key_handle_t key_handle = 0;
 | 
			
		||||
    psa_key_type_t key_type = 0;
 | 
			
		||||
    size_t key_bits = 0;
 | 
			
		||||
    psa_key_attributes_t attributes;
 | 
			
		||||
 | 
			
		||||
    read_input_param_from_message(msg, 0, &attributes);
 | 
			
		||||
 | 
			
		||||
    status = psa_generate_key(&attributes, &key_handle);
 | 
			
		||||
    if (status == PSA_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, &key_handle, sizeof(key_handle));
 | 
			
		||||
    }
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t crypto_open_key(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status;
 | 
			
		||||
    psa_key_id_t key_id;
 | 
			
		||||
    psa_key_handle_t key_handle;
 | 
			
		||||
 | 
			
		||||
    read_input_param_from_message(msg, 0, &key_id);
 | 
			
		||||
 | 
			
		||||
    status = psa_open_key(key_id, &key_handle);
 | 
			
		||||
    if (status == PSA_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, &key_handle, sizeof(key_handle));
 | 
			
		||||
    }
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t crypto_close_key(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status;
 | 
			
		||||
    psa_key_handle_t key_handle;
 | 
			
		||||
 | 
			
		||||
    read_input_param_from_message(msg, 0, &key_handle);
 | 
			
		||||
 | 
			
		||||
    status = psa_close_key(key_handle);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t crypto_destroy_key(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status;
 | 
			
		||||
    psa_key_handle_t key_handle;
 | 
			
		||||
 | 
			
		||||
    read_input_param_from_message(msg, 0, &key_handle);
 | 
			
		||||
 | 
			
		||||
    status = psa_destroy_key(key_handle);
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t crypto_get_key_attributes(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status;
 | 
			
		||||
    psa_key_handle_t key_handle;
 | 
			
		||||
    psa_key_attributes_t attributes;
 | 
			
		||||
 | 
			
		||||
    read_input_param_from_message(msg, 0, &key_handle);
 | 
			
		||||
 | 
			
		||||
    status = psa_get_key_attributes(key_handle, &attributes);
 | 
			
		||||
    if (status == PSA_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, &attributes, sizeof(attributes));
 | 
			
		||||
    }
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t crypto_import_key(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status;
 | 
			
		||||
    psa_key_handle_t key_handle;
 | 
			
		||||
    psa_key_attributes_t attributes;
 | 
			
		||||
    uint8_t *key_data;
 | 
			
		||||
    size_t key_data_size = msg->in_size[1];
 | 
			
		||||
 | 
			
		||||
    read_input_param_from_message(msg, 0, &attributes);
 | 
			
		||||
 | 
			
		||||
    key_data = calloc(1, key_data_size);
 | 
			
		||||
    if (key_data == NULL) {
 | 
			
		||||
        return (PSA_ERROR_INSUFFICIENT_MEMORY);
 | 
			
		||||
    }
 | 
			
		||||
    read_input_param_from_message(msg, 1, key_data);
 | 
			
		||||
 | 
			
		||||
    status = psa_import_key(&attributes, key_data, key_data_size, &key_handle);
 | 
			
		||||
    if (status == PSA_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, &key_handle, sizeof(key_handle));
 | 
			
		||||
    }
 | 
			
		||||
    free(key_data);
 | 
			
		||||
 | 
			
		||||
    return (status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void message_handler(psa_msg_t *msg, SignalHandler handler)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = 0;
 | 
			
		||||
 | 
			
		||||
    switch (msg->type) {
 | 
			
		||||
        case PSA_IPC_CONNECT:
 | 
			
		||||
        case PSA_IPC_DISCONNECT: {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_CALL: {
 | 
			
		||||
            status = handler(msg);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
            SPM_PANIC("Unexpected message type %d!", (int)(msg->type));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg->handle, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_partition_main(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signal;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signal = psa_wait(CRYPTO_ACL_TEST_WAIT_ANY_SID_MSK, PSA_BLOCK);
 | 
			
		||||
        if (signal & CRYPTO_GENERATE_KEY_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(CRYPTO_GENERATE_KEY_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, crypto_generate_key);
 | 
			
		||||
        }
 | 
			
		||||
        if (signal & CRYPTO_OPEN_KEY_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(CRYPTO_OPEN_KEY_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, crypto_open_key);
 | 
			
		||||
        }
 | 
			
		||||
        if (signal & CRYPTO_CLOSE_KEY_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(CRYPTO_CLOSE_KEY_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, crypto_close_key);
 | 
			
		||||
        }
 | 
			
		||||
        if (signal & CRYPTO_DESTROY_KEY_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(CRYPTO_DESTROY_KEY_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, crypto_destroy_key);
 | 
			
		||||
        }
 | 
			
		||||
        if (signal & CRYPTO_GET_KEY_ATTRIBUTES_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(CRYPTO_GET_KEY_ATTRIBUTES_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, crypto_get_key_attributes);
 | 
			
		||||
        }
 | 
			
		||||
        if (signal & CRYPTO_IMPORT_KEY_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(CRYPTO_IMPORT_KEY_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, crypto_import_key);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,65 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "CRYPTO_ACL_TEST",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000080",
 | 
			
		||||
  "entry_point": "test_partition_main",
 | 
			
		||||
  "stack_size": "0x200",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [
 | 
			
		||||
    {
 | 
			
		||||
        "name": "CRYPTO_GENERATE_KEY",
 | 
			
		||||
        "identifier": "0x00000201",
 | 
			
		||||
        "signal": "CRYPTO_GENERATE_KEY_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name": "CRYPTO_OPEN_KEY",
 | 
			
		||||
        "identifier": "0x00000202",
 | 
			
		||||
        "signal": "CRYPTO_OPEN_KEY_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name": "CRYPTO_CLOSE_KEY",
 | 
			
		||||
        "identifier": "0x00000203",
 | 
			
		||||
        "signal": "CRYPTO_CLOSE_KEY_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name": "CRYPTO_DESTROY_KEY",
 | 
			
		||||
        "identifier": "0x00000205",
 | 
			
		||||
        "signal": "CRYPTO_DESTROY_KEY_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name": "CRYPTO_GET_KEY_ATTRIBUTES",
 | 
			
		||||
        "identifier": "0x00000206",
 | 
			
		||||
        "signal": "CRYPTO_GET_KEY_ATTRIBUTES_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name": "CRYPTO_IMPORT_KEY",
 | 
			
		||||
        "identifier": "0x00000208",
 | 
			
		||||
        "signal": "CRYPTO_IMPORT_KEY_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "extern_sids": [
 | 
			
		||||
    "PSA_KEY_MNG_ID"
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/test_partition.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,487 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef COMPONENT_PSA_SRV_IPC
 | 
			
		||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa_manifest/sid.h"
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_TFM)
 | 
			
		||||
#define MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS TFM_CONN_HANDLE_MAX_NUM
 | 
			
		||||
#define PSA_MAX_IOVEC 4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
#define MINOR_VER               0
 | 
			
		||||
#define DROP_CONN_MINOR_VER     5
 | 
			
		||||
#define CLIENT_RSP_BUF_SIZE     128
 | 
			
		||||
#define OFFSET_POS              1
 | 
			
		||||
#define INVALID_SID             0x00001A020
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct th_struct {
 | 
			
		||||
    psa_handle_t handle;
 | 
			
		||||
    psa_invec *iovec_temp;
 | 
			
		||||
    uint8_t *expected;
 | 
			
		||||
    uint8_t expected_size;
 | 
			
		||||
} th_struct_t;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------- Functions ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
static psa_handle_t client_ipc_tests_connect(uint32_t sid, uint32_t minor_version)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = psa_connect(sid, minor_version);
 | 
			
		||||
 | 
			
		||||
    TEST_ASSERT_TRUE(handle > 0);
 | 
			
		||||
 | 
			
		||||
    return handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void client_ipc_tests_call(
 | 
			
		||||
    psa_handle_t handle,
 | 
			
		||||
    psa_invec *iovec_temp,
 | 
			
		||||
    size_t tx_len,
 | 
			
		||||
    size_t rx_len,
 | 
			
		||||
    uint8_t *expected,
 | 
			
		||||
    uint8_t expected_size
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    uint8_t *response_buf = (uint8_t *)malloc(CLIENT_RSP_BUF_SIZE * sizeof(uint8_t));
 | 
			
		||||
    memset(response_buf, 0, CLIENT_RSP_BUF_SIZE);
 | 
			
		||||
    psa_outvec resp = {NULL, rx_len};
 | 
			
		||||
 | 
			
		||||
    if (rx_len > 0) {
 | 
			
		||||
        resp.base = response_buf;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_call(handle,
 | 
			
		||||
                      (tx_len ? iovec_temp : NULL),
 | 
			
		||||
                      tx_len,
 | 
			
		||||
                      (rx_len ? &resp : NULL),
 | 
			
		||||
                      (rx_len ? 1 : 0)
 | 
			
		||||
                     );
 | 
			
		||||
 | 
			
		||||
    if (expected) {
 | 
			
		||||
        TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, response_buf, expected_size);
 | 
			
		||||
    }
 | 
			
		||||
    free(response_buf);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void client_ipc_tests_close(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing iovec 0 sent as NULL
 | 
			
		||||
void iovec_0_NULL()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t expect_size = 5;
 | 
			
		||||
    uint8_t off = 2;
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec[2] = {expect_size, off};
 | 
			
		||||
    uint8_t buff1[] = {1, 2, 3, 4, 5};
 | 
			
		||||
    uint8_t expected_buff[] = {1, 2, 3, 4, 5};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {NULL, 0},
 | 
			
		||||
        {meta_iovec, sizeof(meta_iovec)},
 | 
			
		||||
        {buff1, sizeof(buff1)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing iovec 1 sent as NULL
 | 
			
		||||
void iovec_1_NULL()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t expect_size = 2;
 | 
			
		||||
    uint8_t off = 3;
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec[2] = {expect_size, off};
 | 
			
		||||
    uint8_t buff1[] = {1, 2, 3, 4, 5};
 | 
			
		||||
    uint8_t expected_buff[] = {2, 3};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
 | 
			
		||||
        {NULL, 0},
 | 
			
		||||
        {buff1, sizeof(buff1)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing iovec 2 sent as NULL
 | 
			
		||||
void iovec_2_NULL()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t expect_size = 2;
 | 
			
		||||
    uint8_t off = 3;
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec[2] = {expect_size, off};
 | 
			
		||||
    uint8_t buff1[] = {1, 2, 3, 4, 5};
 | 
			
		||||
    uint8_t expected_buff[] = {2, 3};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
 | 
			
		||||
        {buff1, sizeof(buff1)},
 | 
			
		||||
        {NULL, 0}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Testing in_vec[i] sent with size 0 and base not NULL
 | 
			
		||||
void in_vec_base_not_NULL_size_0()
 | 
			
		||||
{
 | 
			
		||||
    uint8_t     dummy_buff[]  = {1, 2, 3, 4, 5};
 | 
			
		||||
    psa_invec iovec_temp[1] = { {dummy_buff, 0} };
 | 
			
		||||
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, 1, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Testing in_len is 0 but in_vec is not NULL
 | 
			
		||||
void in_len_0_in_vec_not_NULL()
 | 
			
		||||
{
 | 
			
		||||
    uint8_t     dummy_buff[]  = {1, 2, 3, 4, 5};
 | 
			
		||||
    psa_invec iovec_temp[1] = { {dummy_buff, sizeof(dummy_buff)} };
 | 
			
		||||
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, 0, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Testing out_len is 0 but out_vec is not NULL
 | 
			
		||||
void out_len_0_outvec_not_NULL()
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    uint8_t      dummy_res[10]  = {0};
 | 
			
		||||
    psa_outvec outvec_temp[1] = {{dummy_res, sizeof(dummy_res)}};
 | 
			
		||||
 | 
			
		||||
    uint8_t dummy_buff[] = {1, 2, 3, 4, 5};
 | 
			
		||||
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    psa_invec in_vec_temp[2] = { {dummy_buff, sizeof(dummy_buff)},
 | 
			
		||||
        {dummy_buff, sizeof(dummy_buff)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    status = psa_call(handle, in_vec_temp, 2, outvec_temp, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT32(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing rx_buff sent as NULL and rx_len as 0
 | 
			
		||||
void rx_buff_null()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t expect_size = 0, off = 2;
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec[2] = {expect_size, off};
 | 
			
		||||
    uint8_t buff1[] = {1, 2, 3, 4, 5}, buff2[] = {6};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
 | 
			
		||||
        {buff1, sizeof(buff1)},
 | 
			
		||||
        {buff2, sizeof(buff2)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing tx_buff sent as NULL and tx_len as 0
 | 
			
		||||
void tx_buff_null()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, NULL, 0, CLIENT_RSP_BUF_SIZE, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing rx_buff and tx_null sent as NULL and rx_len and tx_len as 0
 | 
			
		||||
void rx_tx_null()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, NULL, 0, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing multiple subsequent calls to the same SID
 | 
			
		||||
void multiple_call()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t expect_size = 2, off = 2;
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec[2] = {expect_size, off};
 | 
			
		||||
    uint8_t buff1[] = {1, 2, 3};
 | 
			
		||||
    uint8_t buff2[] = {4, 5, 6};
 | 
			
		||||
    uint8_t expected_buff[] = {1, 2};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
 | 
			
		||||
        {buff1, sizeof(buff1)},
 | 
			
		||||
        {buff2, sizeof(buff2)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
 | 
			
		||||
 | 
			
		||||
    meta_iovec[1] = 3;              //off
 | 
			
		||||
    iovec_temp[0].base = meta_iovec;
 | 
			
		||||
    expected_buff[0] = 2;
 | 
			
		||||
    expected_buff[1] = 3;
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
 | 
			
		||||
 | 
			
		||||
    meta_iovec[1] = 4;              //off
 | 
			
		||||
    iovec_temp[0].base = meta_iovec;
 | 
			
		||||
    expected_buff[0] = 3;
 | 
			
		||||
    expected_buff[1] = 4;
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_struct(th_struct_t *thr_attr, psa_handle_t handle, psa_invec *iovec_temp, uint8_t *expect, uint8_t expected_size)
 | 
			
		||||
{
 | 
			
		||||
    thr_attr->handle = handle;
 | 
			
		||||
    thr_attr->iovec_temp = iovec_temp;
 | 
			
		||||
    thr_attr->expected = expect;
 | 
			
		||||
    thr_attr->expected_size = expected_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void call_diff_handle(th_struct_t *thr_attr)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_call(handle,
 | 
			
		||||
                          thr_attr->iovec_temp,
 | 
			
		||||
                          PSA_MAX_IOVEC - 1,
 | 
			
		||||
                          CLIENT_RSP_BUF_SIZE,
 | 
			
		||||
                          thr_attr->expected,
 | 
			
		||||
                          thr_attr->expected_size);
 | 
			
		||||
 | 
			
		||||
    osDelay(10);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing multiple parallel calls to the same SID with different handles
 | 
			
		||||
void multi_thread_diff_handles()
 | 
			
		||||
{
 | 
			
		||||
    Thread T1(osPriorityNormal, 512);
 | 
			
		||||
    Thread T2(osPriorityNormal, 512);
 | 
			
		||||
    Thread T3(osPriorityNormal, 512);
 | 
			
		||||
 | 
			
		||||
    th_struct_t thr_attr[] = {{0}, {0}, {0}};
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec_1[] = { 2,            //expect_size
 | 
			
		||||
                               2             //off
 | 
			
		||||
                             };
 | 
			
		||||
    uint8_t buff1[] = {1, 2, 3};
 | 
			
		||||
    uint8_t buff2[] = {4, 5, 6};
 | 
			
		||||
    uint8_t expected_buff_1[] = {1, 2};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp_1[PSA_MAX_IOVEC - 1] = {{meta_iovec_1, sizeof(meta_iovec_1)},
 | 
			
		||||
        {buff1, sizeof(buff1)},
 | 
			
		||||
        {buff2, sizeof(buff2)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    set_struct(&thr_attr[0], 0, iovec_temp_1, expected_buff_1, sizeof(expected_buff_1));
 | 
			
		||||
    osStatus err = T1.start(callback(call_diff_handle, (th_struct_t *)&thr_attr[0]));
 | 
			
		||||
    if (err) {
 | 
			
		||||
        TEST_FAIL_MESSAGE("creating thread failed!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec_2[] = { 2,            //expect_size
 | 
			
		||||
                               3             //off
 | 
			
		||||
                             };
 | 
			
		||||
    uint8_t expected_buff_2[] = {2, 3};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp_2[PSA_MAX_IOVEC - 1] = {{meta_iovec_2, sizeof(meta_iovec_2)},
 | 
			
		||||
        {buff1, sizeof(buff1)},
 | 
			
		||||
        {buff2, sizeof(buff2)}
 | 
			
		||||
    };
 | 
			
		||||
    set_struct(&thr_attr[1], 0, iovec_temp_2, expected_buff_2, sizeof(expected_buff_2));
 | 
			
		||||
    err = T2.start(callback(call_diff_handle, (th_struct_t *)&thr_attr[1]));
 | 
			
		||||
    if (err) {
 | 
			
		||||
        TEST_FAIL_MESSAGE("creating thread failed!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t meta_iovec_3[] = { 2,            //expect_size
 | 
			
		||||
                               4             //off
 | 
			
		||||
                             };
 | 
			
		||||
    uint8_t expected_buff_3[] = {3, 4};
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec_temp_3[PSA_MAX_IOVEC - 1] = {{meta_iovec_3, sizeof(meta_iovec_3)},
 | 
			
		||||
        {buff1, sizeof(buff1)},
 | 
			
		||||
        {buff2, sizeof(buff2)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    set_struct(&thr_attr[2], 0, iovec_temp_3, expected_buff_3, sizeof(expected_buff_3));
 | 
			
		||||
    err = T3.start(callback(call_diff_handle, (th_struct_t *)&thr_attr[2]));
 | 
			
		||||
    if (err) {
 | 
			
		||||
        TEST_FAIL_MESSAGE("creating thread failed!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    err = T1.join();
 | 
			
		||||
    if (err) {
 | 
			
		||||
        TEST_FAIL_MESSAGE("joining thread failed!");
 | 
			
		||||
    }
 | 
			
		||||
    err = T2.join();
 | 
			
		||||
    if (err) {
 | 
			
		||||
        TEST_FAIL_MESSAGE("joining thread failed!");
 | 
			
		||||
    }
 | 
			
		||||
    err = T3.join();
 | 
			
		||||
    if (err) {
 | 
			
		||||
        TEST_FAIL_MESSAGE("joining thread failed!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Testing exceeding num of max channels allowed by psa_connect
 | 
			
		||||
void exceed_num_of_max_channels()
 | 
			
		||||
{
 | 
			
		||||
    int i = 0;
 | 
			
		||||
    psa_handle_t handle[MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS + 1] = {0};
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS + 1; i++) {
 | 
			
		||||
        if (i != MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS) {
 | 
			
		||||
            handle[i] = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
        } else {
 | 
			
		||||
            handle[i] = psa_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
            TEST_ASSERT_EQUAL_INT32(PSA_CONNECTION_REFUSED, handle[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS; i++) {
 | 
			
		||||
        client_ipc_tests_close(handle[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void client_close_null_handle()
 | 
			
		||||
{
 | 
			
		||||
    client_ipc_tests_close(PSA_NULL_HANDLE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drop_connection()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_DROP_CONN, DROP_CONN_MINOR_VER);
 | 
			
		||||
    psa_status_t status = psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_DROP_CONNECTION, status);
 | 
			
		||||
 | 
			
		||||
    status = PSA_SUCCESS;
 | 
			
		||||
    status = psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_DROP_CONNECTION, status);
 | 
			
		||||
 | 
			
		||||
    client_ipc_tests_close(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void verify_psa_framework_version()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ff_version = psa_framework_version();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_FRAMEWORK_VERSION, ff_version);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_version_existing()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t rot_version = psa_version(CLIENT_TESTS_PART1_DROP_CONN);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(DROP_CONN_MINOR_VER, rot_version);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_version_non_existing()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t rot_version = psa_version(INVALID_SID);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_VERSION_NONE, rot_version);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_version_secure_access_only()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t rot_version = psa_version(CLIENT_TESTS_PART1_SECURE_CLIENTS_ONLY);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_VERSION_NONE, rot_version);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Test cases
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    Case("Testing client iovec_0_NULL", iovec_0_NULL),
 | 
			
		||||
    Case("Testing client iovec_1_NULL", iovec_1_NULL),
 | 
			
		||||
    Case("Testing client iovec_2_NULL", iovec_2_NULL),
 | 
			
		||||
    Case("Testing client in_vec 0 base not NULL size 0", in_vec_base_not_NULL_size_0),
 | 
			
		||||
    Case("Testing client in_len 0 in_vec not NULL", in_len_0_in_vec_not_NULL),
 | 
			
		||||
    Case("Testing client out_len is 0 but out_vec is not NULL", out_len_0_outvec_not_NULL),
 | 
			
		||||
    Case("Testing client rx_buff_null", rx_buff_null),
 | 
			
		||||
    Case("Testing client tx_buff_null", tx_buff_null),
 | 
			
		||||
    Case("Testing client rx_tx_null", rx_tx_null),
 | 
			
		||||
    Case("Testing client multiple_call from a single thread", multiple_call),
 | 
			
		||||
    Case("Testing client close on NULL handle", client_close_null_handle),
 | 
			
		||||
    Case("Testing DROP_CONNECTION State", drop_connection),
 | 
			
		||||
    Case("Testing client psa_framework_version() API", verify_psa_framework_version),
 | 
			
		||||
    Case("Testing client psa_version() API on existing SID", psa_version_existing),
 | 
			
		||||
    Case("Testing client psa_version() API on non-existing SID", psa_version_non_existing),
 | 
			
		||||
    Case("Testing client psa_version() API to a service that is not NSPE callable", psa_version_secure_access_only),
 | 
			
		||||
    Case("Testing client multiple calls on different channels to the same SID", multi_thread_diff_handles),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    // Setup Greentea using a reasonable timeout in seconds
 | 
			
		||||
    GREENTEA_SETUP(60, "default_auto");
 | 
			
		||||
    return verbose_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(test_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // COMPONENT_PSA_SRV_IPC
 | 
			
		||||
| 
						 | 
				
			
			@ -1,97 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
 | 
			
		||||
#define MSG_BUF_SIZE 128
 | 
			
		||||
uint8_t data[MSG_BUF_SIZE] = {0};
 | 
			
		||||
 | 
			
		||||
void client_part_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait(CLIENT_TESTS_PART1_WAIT_ANY_SID_MSK, PSA_BLOCK);
 | 
			
		||||
        if (signals & PART1_ROT_SRV1_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PART1_ROT_SRV1_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CONNECT:
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                    break;
 | 
			
		||||
                case PSA_IPC_CALL: {
 | 
			
		||||
                    memset(data, 0, sizeof(data));
 | 
			
		||||
                    if (msg.in_size[0] + msg.in_size[1] + msg.in_size[2] > 1) {
 | 
			
		||||
                        size_t offset = psa_read(msg.handle, 0, (void *)data, msg.in_size[0]);
 | 
			
		||||
                        offset += psa_read(msg.handle, 1, (void *)(data + offset), msg.in_size[1]);
 | 
			
		||||
                        psa_read(msg.handle, 2, (void *)(data + offset), msg.in_size[2]);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (msg.out_size[0] > 0) {
 | 
			
		||||
                        uint8_t resp_size = data[0];
 | 
			
		||||
                        uint8_t resp_offset = data[1];
 | 
			
		||||
                        psa_write(msg.handle, 0, (const void *)(data + resp_offset), resp_size);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                default: {
 | 
			
		||||
                    SPM_PANIC("Invalid msg type");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
        } else if (signals & DROP_CONN_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(DROP_CONN_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CONNECT:
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    break;
 | 
			
		||||
                case PSA_IPC_CALL:
 | 
			
		||||
                    psa_reply(msg.handle, PSA_DROP_CONNECTION);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    SPM_PANIC("Invalid msg type");
 | 
			
		||||
            }
 | 
			
		||||
        } else if (signals & SECURE_CLIENTS_ONLY_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(SECURE_CLIENTS_ONLY_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CONNECT:
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                case PSA_IPC_CALL:
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    SPM_PANIC("Invalid msg type");
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            SPM_PANIC("Received invalid signal %lu", signals);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,37 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "CLIENT_TESTS_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000001",
 | 
			
		||||
  "entry_point": "client_part_main",
 | 
			
		||||
  "stack_size": "0x400",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "CLIENT_TESTS_PART1_ROT_SRV1",
 | 
			
		||||
      "identifier": "0x00001A05",
 | 
			
		||||
      "signal": "PART1_ROT_SRV1_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "CLIENT_TESTS_PART1_DROP_CONN",
 | 
			
		||||
      "identifier": "0x00001A06",
 | 
			
		||||
      "signal": "DROP_CONN_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "CLIENT_TESTS_PART1_SECURE_CLIENTS_ONLY",
 | 
			
		||||
      "identifier": "0x00001A07",
 | 
			
		||||
      "signal": "SECURE_CLIENTS_ONLY_MSK",
 | 
			
		||||
      "non_secure_clients": false,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/client_tests_partition.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,276 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef COMPONENT_PSA_SRV_IPC
 | 
			
		||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "server_tests.h"
 | 
			
		||||
#include "psa_manifest/sid.h"
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_TFM)
 | 
			
		||||
#define PSA_MAX_IOVEC 4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
#define TEST_ROT_SRV_MINOR   12
 | 
			
		||||
#define OUT_BUFFER_SIZE 60
 | 
			
		||||
 | 
			
		||||
psa_handle_t control_handle = 0;
 | 
			
		||||
char test_str[] = "abcdefghijklmnopqrstuvwxyz";
 | 
			
		||||
char cross_part_buf[] = "Hello and welcome SPM";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(identity_during_connect)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(identity_during_call)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    status = psa_call(test_handle, NULL, 0, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(msg_size_assertion)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec data[PSA_MAX_IOVEC] = {
 | 
			
		||||
        {test_str, 4},
 | 
			
		||||
        {test_str + 5, 6},
 | 
			
		||||
        {test_str + 13, 1},
 | 
			
		||||
        {NULL, 0}
 | 
			
		||||
    };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    status = psa_call(test_handle, data, PSA_MAX_IOVEC, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(reject_connection)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_CONNECTION_REFUSED, test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(read_at_outofboud_offset)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec data = { test_str, sizeof(test_str) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    status = psa_call(test_handle, &data, 1, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(msg_read_truncation)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec data[3] = {
 | 
			
		||||
        {test_str, 4},
 | 
			
		||||
        {test_str + 5, 6},
 | 
			
		||||
        {test_str + 13, 1}
 | 
			
		||||
    };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    status = psa_call(test_handle, data, 3, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(skip_zero)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec data = { test_str, sizeof(test_str) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    status = psa_call(test_handle, &data, 1, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(skip_some)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec data = { test_str, sizeof(test_str) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    status = psa_call(test_handle, &data, 1, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(skip_more_than_left)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec data = { test_str, 8 };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    status = psa_call(test_handle, &data, 1, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(rhandle_factorial)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t secure_value = 0;
 | 
			
		||||
    uint32_t value = 1;
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_outvec resp = { &secure_value, sizeof(secure_value) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 1; i <= 5; i++) {
 | 
			
		||||
        value *= i;
 | 
			
		||||
        status = psa_call(test_handle, NULL, 0, &resp, 1);
 | 
			
		||||
        TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
        TEST_ASSERT_EQUAL(value, secure_value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(cross_partition_call)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    size_t in_len = strlen(cross_part_buf);
 | 
			
		||||
    TEST_ASSERT_MESSAGE(test_handle > 0, "psa_connect() failed");
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec = { cross_part_buf, in_len };
 | 
			
		||||
    uint8_t *response_buf = (uint8_t *)malloc(sizeof(uint8_t) * OUT_BUFFER_SIZE);
 | 
			
		||||
    memset(response_buf, 0, OUT_BUFFER_SIZE);
 | 
			
		||||
    psa_outvec resp = { response_buf, OUT_BUFFER_SIZE };
 | 
			
		||||
 | 
			
		||||
    psa_status_t status = psa_call(test_handle, &iovec, 1, &resp, 1);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
    TEST_ASSERT_EQUAL_STRING_LEN("MPS emoclew dna olleHMPS emoclew dna olleH", response_buf, in_len * 2);
 | 
			
		||||
    free(response_buf);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test a common DOORBELL scenario
 | 
			
		||||
PSA_TEST_CLIENT(doorbell_test)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT_MESSAGE(test_handle > 0, "psa_connect() failed");
 | 
			
		||||
 | 
			
		||||
    psa_status_t status = psa_call(test_handle, NULL, 0, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    control_handle = psa_connect(SERVER_TESTS_PART1_CONTROL, 0);
 | 
			
		||||
    if (control_handle < 0) {
 | 
			
		||||
        error("Could not open a connection with SERVER_TESTS_PART1_CONTROL ROT_SRV");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GREENTEA_SETUP(60, "default_auto");
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void spm_teardown(const size_t passed, const size_t failed, const failure_t failure)
 | 
			
		||||
{
 | 
			
		||||
    psa_close(control_handle);
 | 
			
		||||
    greentea_test_teardown_handler(passed, failed, failure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_case_setup(const Case *const source, const size_t index_of_case)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    test_action_t action = START_TEST;
 | 
			
		||||
    psa_invec data = {&action, sizeof(action)};
 | 
			
		||||
 | 
			
		||||
    status = psa_call(control_handle, &data, 1, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
    return greentea_case_setup_handler(source, index_of_case);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    test_action_t action = GET_TEST_RESULT;
 | 
			
		||||
    psa_invec data = {&action, sizeof(action)};
 | 
			
		||||
    psa_outvec resp = {&test_status, sizeof(test_status)};
 | 
			
		||||
 | 
			
		||||
    status = psa_call(control_handle, &data, 1, &resp, 1);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, test_status);
 | 
			
		||||
    return greentea_case_teardown_handler(source, passed, failed, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SPM_UTEST_CASE(desc, test) Case(desc, spm_case_setup, PSA_TEST_CLIENT_NAME(test), spm_case_teardown)
 | 
			
		||||
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    SPM_UTEST_CASE("Get identity during connect", identity_during_connect),
 | 
			
		||||
    SPM_UTEST_CASE("Get identity during call", identity_during_call),
 | 
			
		||||
    SPM_UTEST_CASE("Assert msg size", msg_size_assertion),
 | 
			
		||||
    SPM_UTEST_CASE("Reject on connect", reject_connection),
 | 
			
		||||
    SPM_UTEST_CASE("Read at an out of bound offset", read_at_outofboud_offset),
 | 
			
		||||
    SPM_UTEST_CASE("Read msg with size bigger than message", msg_read_truncation),
 | 
			
		||||
    SPM_UTEST_CASE("Make sure skip with 0 byte number skips nothing", skip_zero),
 | 
			
		||||
    SPM_UTEST_CASE("Skip a few bytes while reading a message", skip_some),
 | 
			
		||||
    SPM_UTEST_CASE("Try to skip more bytes than left while reading", skip_more_than_left),
 | 
			
		||||
    SPM_UTEST_CASE("Test rhandle implementation by calculating the factorial function", rhandle_factorial),
 | 
			
		||||
    SPM_UTEST_CASE("Test a call flow between 2 secure partitions", cross_partition_call),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//Declare your test specification with a custom setup handler
 | 
			
		||||
Specification specification(spm_setup, cases, spm_teardown);
 | 
			
		||||
 | 
			
		||||
int main(int, char **)
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // COMPONENT_PSA_SRV_IPC
 | 
			
		||||
| 
						 | 
				
			
			@ -1,57 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SERVER_TESTS_H__
 | 
			
		||||
#define __SERVER_TESTS_H__
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    START_TEST = 1,
 | 
			
		||||
    GET_TEST_RESULT = 2
 | 
			
		||||
} test_action_t;
 | 
			
		||||
 | 
			
		||||
typedef struct factorial_data {
 | 
			
		||||
    uint32_t count;
 | 
			
		||||
    uint32_t val;
 | 
			
		||||
} factorial_data_t;
 | 
			
		||||
 | 
			
		||||
typedef psa_status_t (*psa_test_server_side_func)(psa_status_t *);
 | 
			
		||||
#define PSA_TEST_ERROR (-1L)
 | 
			
		||||
#define PSA_TEST_CLIENT_NAME(name) psa_test_client_side_ ## name
 | 
			
		||||
#define PSA_TEST_SERVER_NAME(name) psa_test_server_side_ ## name
 | 
			
		||||
 | 
			
		||||
#define PSA_TEST_CLIENT(name) void PSA_TEST_CLIENT_NAME(name) (void)
 | 
			
		||||
#define PSA_TEST_SERVER(name) psa_status_t PSA_TEST_SERVER_NAME(name) (psa_status_t *status_ptr)
 | 
			
		||||
 | 
			
		||||
#define PSA_TEST(name) \
 | 
			
		||||
    PSA_TEST_CLIENT(name); \
 | 
			
		||||
    PSA_TEST_SERVER(name); \
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST(identity_during_connect)
 | 
			
		||||
PSA_TEST(identity_during_call)
 | 
			
		||||
PSA_TEST(get_msg_twice)
 | 
			
		||||
PSA_TEST(msg_size_assertion)
 | 
			
		||||
PSA_TEST(reject_connection)
 | 
			
		||||
PSA_TEST(read_at_outofboud_offset)
 | 
			
		||||
PSA_TEST(msg_read_truncation)
 | 
			
		||||
PSA_TEST(skip_zero)
 | 
			
		||||
PSA_TEST(skip_some)
 | 
			
		||||
PSA_TEST(skip_more_than_left)
 | 
			
		||||
PSA_TEST(rhandle_factorial)
 | 
			
		||||
PSA_TEST(cross_partition_call)
 | 
			
		||||
PSA_TEST(doorbell_test)
 | 
			
		||||
#endif /* __SERVER_TESTS_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,93 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "string.h"
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
#include "server_tests.h"
 | 
			
		||||
 | 
			
		||||
extern psa_test_server_side_func test_list[];
 | 
			
		||||
static size_t num_of_tests = 0;
 | 
			
		||||
static void init_num_of_tests()
 | 
			
		||||
{
 | 
			
		||||
    size_t i = 0;
 | 
			
		||||
    while (test_list[i] != NULL) {
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    num_of_tests = i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_part1_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS; // status of the api calls during the test
 | 
			
		||||
    psa_status_t test_result = PSA_SUCCESS; // result of the critical section of the test
 | 
			
		||||
    test_action_t action;
 | 
			
		||||
    uint32_t test_idx = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    init_num_of_tests();
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait(CONTROL_MSK, PSA_BLOCK);
 | 
			
		||||
        if (0 == (signals & CONTROL_MSK)) {
 | 
			
		||||
            SPM_PANIC("returned from psa_wait without CONTROL_ROT_SRV bit on signals=(0x%08x)\n", signals);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (PSA_SUCCESS != psa_get(CONTROL_MSK, &msg)) {
 | 
			
		||||
            SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
        }
 | 
			
		||||
        switch (msg.type) {
 | 
			
		||||
            case PSA_IPC_CALL:
 | 
			
		||||
                if (msg.in_size[0] == 0) {
 | 
			
		||||
                    SPM_PANIC("got a zero message size to SERVER_TESTS_PART1_CONTROL ROT_SRV\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (psa_read(msg.handle, 0, &action, sizeof(action)) != sizeof(action)) {
 | 
			
		||||
                    SPM_PANIC("could not read the entire test payload structure\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                switch (action) {
 | 
			
		||||
                    case START_TEST:
 | 
			
		||||
                        if ((test_idx >= num_of_tests) || (test_list[test_idx] == NULL)) {
 | 
			
		||||
                            SPM_PANIC("Invalid test ID was sent!\n");
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                        test_status = test_list[test_idx](&test_result);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case GET_TEST_RESULT:
 | 
			
		||||
                        test_idx++;
 | 
			
		||||
                        psa_write(msg.handle, 0, &test_result, sizeof(test_result));
 | 
			
		||||
                        psa_reply(msg.handle, test_status);
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        SPM_PANIC("Got illegal Value in test action");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
            case PSA_IPC_CONNECT:
 | 
			
		||||
            case PSA_IPC_DISCONNECT:
 | 
			
		||||
                psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                SPM_PANIC("Unexpected message type %lu!", msg.type);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,101 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
 | 
			
		||||
void server_part2_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
    char *str = NULL;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait(SERVER_TESTS_PART2_WAIT_ANY_SID_MSK, PSA_BLOCK);
 | 
			
		||||
        if (0 == (signals & SERVER_TESTS_PART2_WAIT_ANY_SID_MSK)) {
 | 
			
		||||
            SPM_PANIC("returned from psa_wait without ROT_SRV_REVERSE_MSK or ROT_SRV_DB_TST_MSK bit on\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (signals & ROT_SRV_REVERSE_MSK) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(ROT_SRV_REVERSE_MSK, &msg)) {
 | 
			
		||||
                SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
            }
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CALL: {
 | 
			
		||||
                    if ((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) == 0) {
 | 
			
		||||
                        SPM_PANIC("got a zero message size to REVERSE ROT_SRV\n");
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    len = msg.in_size[0];
 | 
			
		||||
                    str = (char *)malloc(sizeof(char) * len);
 | 
			
		||||
                    if (NULL == str) {
 | 
			
		||||
                        SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    psa_read(msg.handle, 0, str, len);
 | 
			
		||||
                    for (size_t i = 0; i < len / 2; i ++) {
 | 
			
		||||
                        char a = str[i];
 | 
			
		||||
                        str[i] = str[len - i - 1];
 | 
			
		||||
                        str[len - i - 1] = a;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    psa_write(msg.handle, 0, str, len);
 | 
			
		||||
                    free(str);
 | 
			
		||||
                    str = NULL;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                case PSA_IPC_CONNECT:
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    SPM_PANIC("Unexpected message type %lu!", msg.type);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
        } else { // -- Doorbell test
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(ROT_SRV_DB_TST_MSK, &msg)) {
 | 
			
		||||
                SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
            }
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CALL: {
 | 
			
		||||
                    int32_t caller_part_id = msg.client_id;
 | 
			
		||||
                    // Doorbell contract is valid only between secure partitions
 | 
			
		||||
                    if (caller_part_id < 0) {
 | 
			
		||||
                        SPM_PANIC("Caller partition is non secure\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    // In doorbell scenario the server first calls psa_reply()
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    // After work is done, ring the doorbell
 | 
			
		||||
                    psa_notify(caller_part_id);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case PSA_IPC_CONNECT:
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    SPM_PANIC("Unexpected message type %lu!", msg.type);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,702 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "string.h"
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
#include "server_tests.h"
 | 
			
		||||
#include "psa_manifest/sid.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Process a generic connect message to SERVER_TESTS_PART1_TEST ROT_SRV.
 | 
			
		||||
 * @return PSA_SUCCESS or negative error code if failed.
 | 
			
		||||
 */
 | 
			
		||||
static psa_status_t process_connect_request(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t res = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        res = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CONNECT) {
 | 
			
		||||
        res = ((res != PSA_SUCCESS) ? res : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, res);
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Process a generic disconnect message to SERVER_TESTS_PART1_TEST ROT_SRV.
 | 
			
		||||
 * @return PSA_SUCCESS or negative error code if failed.
 | 
			
		||||
 */
 | 
			
		||||
static psa_status_t process_disconnect_request(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t res = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        res = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_DISCONNECT) {
 | 
			
		||||
        res = ((res != PSA_SUCCESS) ? res : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(identity_during_connect)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    int32_t identity = 0;
 | 
			
		||||
 | 
			
		||||
    psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CONNECT) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    identity = msg.client_id;
 | 
			
		||||
    *status_ptr = (identity == -1) ? PSA_SUCCESS : PSA_TEST_ERROR;
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(identity_during_call)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    int32_t identity = 0;
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    identity = msg.client_id;
 | 
			
		||||
    *status_ptr = (identity == -1) ? PSA_SUCCESS : PSA_TEST_ERROR;
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(msg_size_assertion)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    size_t read_size = 0;
 | 
			
		||||
 | 
			
		||||
    char *buff = malloc(sizeof(char) * 11);
 | 
			
		||||
    if (NULL == buff) {
 | 
			
		||||
        SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
    }
 | 
			
		||||
    memset(buff, 0, 11);
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        free(buff);
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t i = 0; i < PSA_MAX_IOVEC; i++) {
 | 
			
		||||
        read_size += psa_read(msg.handle, i, buff + read_size, msg.in_size[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (((msg.in_size[0] + msg.in_size[1] + msg.in_size[2] + msg.in_size[3]) != 11)  ||
 | 
			
		||||
            (read_size != 11) ||
 | 
			
		||||
            (strncmp(buff, "abcdfghijkn", 11) != 0)) {
 | 
			
		||||
        *status_ptr = PSA_TEST_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        *status_ptr = PSA_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, test_status);
 | 
			
		||||
    free(buff);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(reject_connection)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t res = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        res = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CONNECT) {
 | 
			
		||||
        res = ((res != PSA_SUCCESS) ? res : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, PSA_CONNECTION_REFUSED);
 | 
			
		||||
    *status_ptr = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(read_at_outofboud_offset)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    uint32_t buff = 52;
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t read_size = psa_read(msg.handle, 1, &buff, sizeof(buff));
 | 
			
		||||
    if ((0 != read_size) || (52 != buff)) {
 | 
			
		||||
        *status_ptr = PSA_TEST_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        *status_ptr = PSA_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, test_status);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(msg_read_truncation)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    size_t read_size = 0;
 | 
			
		||||
    char *buff = malloc(sizeof(char) * 11);
 | 
			
		||||
    if (NULL == buff) {
 | 
			
		||||
        SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
    }
 | 
			
		||||
    memset(buff, 0, 11);
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        free(buff);
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    read_size = psa_read(msg.handle, 1, buff, 11);
 | 
			
		||||
    if ((msg.in_size[1] != read_size) ||
 | 
			
		||||
            ((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) != 11) ||
 | 
			
		||||
            (buff[6] != 0)   ||
 | 
			
		||||
            (strncmp(buff, "fghijk", 6) != 0)) {
 | 
			
		||||
        *status_ptr = PSA_TEST_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        *status_ptr = PSA_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, test_status);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    free(buff);
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(skip_zero)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    size_t read_size = 0;
 | 
			
		||||
    size_t skip_size = 0;
 | 
			
		||||
    char *buff = malloc(sizeof(char) * 11);
 | 
			
		||||
    if (NULL == buff) {
 | 
			
		||||
        SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        free(buff);
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    skip_size = psa_skip(msg.handle, 0, 0);
 | 
			
		||||
    read_size = psa_read(msg.handle, 0, buff, 11);
 | 
			
		||||
    if ((skip_size != 0) ||
 | 
			
		||||
            (read_size != 11) ||
 | 
			
		||||
            (strncmp(buff, "abcdefghijk", 11)) != 0) {
 | 
			
		||||
        *status_ptr = PSA_TEST_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        *status_ptr = PSA_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, test_status);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    free(buff);
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(skip_some)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    size_t read_size1 = 0;
 | 
			
		||||
    size_t read_size2 = 0;
 | 
			
		||||
    size_t skip_size = 0;
 | 
			
		||||
    char *buff = malloc(sizeof(char) * 11);
 | 
			
		||||
    if (NULL == buff) {
 | 
			
		||||
        SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        free(buff);
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    read_size1 = psa_read(msg.handle, 0, buff, 3);
 | 
			
		||||
    skip_size = psa_skip(msg.handle, 0, 5);
 | 
			
		||||
    read_size2 = psa_read(msg.handle, 0, buff + 3, 8);
 | 
			
		||||
    if ((read_size1 != 3) ||
 | 
			
		||||
            (skip_size != 5) ||
 | 
			
		||||
            (read_size2 != 8) ||
 | 
			
		||||
            (strncmp(buff, "abcijklmnop", 11) != 0)) {
 | 
			
		||||
        *status_ptr = PSA_TEST_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        *status_ptr = PSA_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, test_status);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    free(buff);
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(skip_more_than_left)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    size_t read_size1 = 0;
 | 
			
		||||
    size_t read_size2 = 0;
 | 
			
		||||
    size_t skip_size = 0;
 | 
			
		||||
    char *buff = malloc(sizeof(char) * 8);
 | 
			
		||||
    if (NULL == buff) {
 | 
			
		||||
        SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        free(buff);
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    read_size1 = psa_read(msg.handle, 0, buff, 5);
 | 
			
		||||
    skip_size = psa_skip(msg.handle, 0, 4);
 | 
			
		||||
    read_size2 = psa_read(msg.handle, 0, buff + 5, 2);
 | 
			
		||||
    if ((read_size1 != 5) ||
 | 
			
		||||
            (skip_size != 3) ||
 | 
			
		||||
            (read_size2 != 0) ||
 | 
			
		||||
            (strncmp(buff, "abcde", 5) != 0)) {
 | 
			
		||||
        *status_ptr = PSA_TEST_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        *status_ptr = PSA_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, test_status);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    free(buff);
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(rhandle_factorial)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    factorial_data_t *num = NULL;
 | 
			
		||||
    factorial_data_t *asserted_ptr = NULL;
 | 
			
		||||
    uint32_t connect_count = 0;
 | 
			
		||||
    uint32_t call_count = 0;
 | 
			
		||||
    uint32_t disconnect_count = 0;
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
        if (0 == (signals & TEST_MSK)) {
 | 
			
		||||
            SPM_PANIC("returned from psa_wait without TEST_MSK bit on\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
            SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (msg.type) {
 | 
			
		||||
            case PSA_IPC_CONNECT:
 | 
			
		||||
                if (NULL != msg.rhandle) {
 | 
			
		||||
                    SPM_PANIC("got rhandle on connect message\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                num = (factorial_data_t *)malloc(sizeof(factorial_data_t));
 | 
			
		||||
                if (NULL == num) {
 | 
			
		||||
                    SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
                }
 | 
			
		||||
                num->count = 0;
 | 
			
		||||
                num->val = 1;
 | 
			
		||||
                psa_set_rhandle(msg.handle, num);
 | 
			
		||||
                asserted_ptr = num;
 | 
			
		||||
                connect_count++;
 | 
			
		||||
                break;
 | 
			
		||||
            case PSA_IPC_CALL:
 | 
			
		||||
                if (msg.in_size[0] + msg.in_size[1] + msg.in_size[2] > 0) {
 | 
			
		||||
                    SPM_PANIC("ROT_SRV_FACTORIAL ROT_SRV should not get any params\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (NULL == msg.rhandle) {
 | 
			
		||||
                    SPM_PANIC("got NULL rhandle on call message\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (asserted_ptr != msg.rhandle) {
 | 
			
		||||
                    SPM_PANIC("rhandle value changed between calls\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                num = (factorial_data_t *)msg.rhandle;
 | 
			
		||||
                num->count++;
 | 
			
		||||
                num->val *= num->count;
 | 
			
		||||
                psa_write(msg.handle, 0, &(num->val), sizeof(num->val));
 | 
			
		||||
                call_count++;
 | 
			
		||||
                break;
 | 
			
		||||
            case PSA_IPC_DISCONNECT:
 | 
			
		||||
                if (NULL == msg.rhandle) {
 | 
			
		||||
                    SPM_PANIC("got NULL rhandle on disconnect message\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (asserted_ptr != msg.rhandle) {
 | 
			
		||||
                    SPM_PANIC("rhandle value changed between calls\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Setting rhandle during disconnection should have no effect
 | 
			
		||||
                uint8_t my_rhandle = 10;
 | 
			
		||||
                psa_set_rhandle(msg.handle, &my_rhandle);
 | 
			
		||||
 | 
			
		||||
                free(msg.rhandle);
 | 
			
		||||
                disconnect_count++;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                SPM_PANIC("Unexpected message type %lu!", msg.type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        num = NULL;
 | 
			
		||||
        psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
        if (disconnect_count > 0) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((connect_count != 1) ||
 | 
			
		||||
            (call_count != 5)    ||
 | 
			
		||||
            (disconnect_count != 1)) {
 | 
			
		||||
        *status_ptr = PSA_TEST_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        *status_ptr = PSA_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return *status_ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(cross_partition_call)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t partition_call_status = PSA_SUCCESS;
 | 
			
		||||
    uint32_t data_read = 0;
 | 
			
		||||
    uint32_t str_len = 0;
 | 
			
		||||
    char *buff = malloc(sizeof(char) * 60);
 | 
			
		||||
 | 
			
		||||
    if (NULL == buff) {
 | 
			
		||||
        SPM_PANIC("memory allocation failure\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(buff, 0, 60);
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        free(buff);
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) == 0) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    str_len = msg.in_size[0];
 | 
			
		||||
    data_read = psa_read(msg.handle, 0, buff, str_len);
 | 
			
		||||
    if (data_read != 21) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(buff + str_len, buff, str_len);
 | 
			
		||||
    data_read *= 2;
 | 
			
		||||
 | 
			
		||||
    psa_invec data = { buff, data_read };
 | 
			
		||||
 | 
			
		||||
    psa_outvec resp = { buff, data_read };
 | 
			
		||||
    psa_handle_t conn_handle = psa_connect(SERVER_TESTS_PART2_ROT_SRV_REVERSE, 5);
 | 
			
		||||
    if (conn_handle <= 0) {
 | 
			
		||||
        partition_call_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (partition_call_status == PSA_SUCCESS) {
 | 
			
		||||
        partition_call_status = psa_call(conn_handle, &data, 1, &resp, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *status_ptr = partition_call_status;
 | 
			
		||||
    if (partition_call_status == PSA_SUCCESS) {
 | 
			
		||||
        psa_close(conn_handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS == partition_call_status) {
 | 
			
		||||
        psa_write(msg.handle, 0, buff, data_read);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, partition_call_status);
 | 
			
		||||
    free(buff);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test a common DOORBELL scenario
 | 
			
		||||
PSA_TEST_SERVER(doorbell_test)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_status_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_status_t partition_call_status = PSA_SUCCESS;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait(TEST_MSK, PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
 | 
			
		||||
        SPM_PANIC("psa_get() failed\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) != 0) || (msg.out_size[0] != 0)) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // -- Connection with partition2 - START
 | 
			
		||||
    psa_handle_t conn_handle = psa_connect(SERVER_TESTS_PART2_ROT_SRV_DB_TST, 5);
 | 
			
		||||
    if (conn_handle <= 0) {
 | 
			
		||||
        partition_call_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (partition_call_status == PSA_SUCCESS) {
 | 
			
		||||
        partition_call_status = psa_call(conn_handle, NULL, 0, NULL, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (partition_call_status == PSA_SUCCESS) {
 | 
			
		||||
        // Wait for doorball notification - Only after that call psa_reply() for the client called you
 | 
			
		||||
        signals = psa_wait(PSA_DOORBELL, PSA_BLOCK);
 | 
			
		||||
        if ((signals & PSA_DOORBELL) == 0) {
 | 
			
		||||
            partition_call_status = PSA_TEST_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (partition_call_status == PSA_SUCCESS) {
 | 
			
		||||
        psa_clear();
 | 
			
		||||
        psa_close(conn_handle);
 | 
			
		||||
    }
 | 
			
		||||
    // -- Connection with partition2 - END
 | 
			
		||||
 | 
			
		||||
    *status_ptr = partition_call_status;
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, partition_call_status);
 | 
			
		||||
    disconnect_status = process_disconnect_request();
 | 
			
		||||
 | 
			
		||||
    test_status  = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
 | 
			
		||||
 | 
			
		||||
    return test_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
psa_test_server_side_func test_list[] = {
 | 
			
		||||
    PSA_TEST_SERVER_NAME(identity_during_connect),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(identity_during_call),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(msg_size_assertion),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(reject_connection),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(read_at_outofboud_offset),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(msg_read_truncation),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(skip_zero),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(skip_some),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(skip_more_than_left),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(rhandle_factorial),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(cross_partition_call),
 | 
			
		||||
    NULL
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,57 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __UVISOR_MBED_SPM_SERVER_TESTS_H__
 | 
			
		||||
#define __UVISOR_MBED_SPM_SERVER_TESTS_H__
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    START_TEST = 1,
 | 
			
		||||
    GET_TEST_RESULT = 2
 | 
			
		||||
} test_action_t;
 | 
			
		||||
 | 
			
		||||
typedef struct factorial_data {
 | 
			
		||||
    uint32_t count;
 | 
			
		||||
    uint32_t val;
 | 
			
		||||
} factorial_data_t;
 | 
			
		||||
 | 
			
		||||
typedef psa_status_t (*psa_test_server_side_func)(psa_status_t *);
 | 
			
		||||
#define PSA_TEST_ERROR (-1L)
 | 
			
		||||
#define PSA_TEST_CLIENT_NAME(name) psa_test_client_side_ ## name
 | 
			
		||||
#define PSA_TEST_SERVER_NAME(name) psa_test_server_side_ ## name
 | 
			
		||||
 | 
			
		||||
#define PSA_TEST_CLIENT(name) void PSA_TEST_CLIENT_NAME(name) (void)
 | 
			
		||||
#define PSA_TEST_SERVER(name) psa_status_t PSA_TEST_SERVER_NAME(name) (psa_status_t *status_ptr)
 | 
			
		||||
 | 
			
		||||
#define PSA_TEST(name) \
 | 
			
		||||
    PSA_TEST_CLIENT(name); \
 | 
			
		||||
    PSA_TEST_SERVER(name); \
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST(identity_during_connect)
 | 
			
		||||
PSA_TEST(identity_during_call)
 | 
			
		||||
PSA_TEST(get_msg_twice)
 | 
			
		||||
PSA_TEST(msg_size_assertion)
 | 
			
		||||
PSA_TEST(reject_connection)
 | 
			
		||||
PSA_TEST(read_at_outofboud_offset)
 | 
			
		||||
PSA_TEST(msg_read_truncation)
 | 
			
		||||
PSA_TEST(skip_zero)
 | 
			
		||||
PSA_TEST(skip_some)
 | 
			
		||||
PSA_TEST(skip_more_than_left)
 | 
			
		||||
PSA_TEST(rhandle_factorial)
 | 
			
		||||
PSA_TEST(cross_partition_call)
 | 
			
		||||
PSA_TEST(doorbell_test)
 | 
			
		||||
#endif /* __UVISOR_MBED_SPM_SERVER_TESTS_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,34 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "SERVER_TESTS_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000002",
 | 
			
		||||
  "entry_point": "server_part1_main",
 | 
			
		||||
  "stack_size": "0x400",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "SERVER_TESTS_PART1_CONTROL",
 | 
			
		||||
      "identifier": "0x00001A01",
 | 
			
		||||
      "signal": "CONTROL_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "SERVER_TESTS_PART1_TEST",
 | 
			
		||||
      "identifier": "0x00001A02",
 | 
			
		||||
      "signal": "TEST_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 12,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "extern_sids": [
 | 
			
		||||
    "SERVER_TESTS_PART2_ROT_SRV_REVERSE",
 | 
			
		||||
    "SERVER_TESTS_PART2_ROT_SRV_DB_TST"
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/server_tests_partition1.c",
 | 
			
		||||
    "COMPONENT_SPE/tests.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,30 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "SERVER_TESTS_PART2",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000003",
 | 
			
		||||
  "entry_point": "server_part2_main",
 | 
			
		||||
  "stack_size": "0x400",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "SERVER_TESTS_PART2_ROT_SRV_REVERSE",
 | 
			
		||||
      "identifier": "0x00001A03",
 | 
			
		||||
      "signal": "ROT_SRV_REVERSE_MSK",
 | 
			
		||||
      "non_secure_clients": false,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "SERVER_TESTS_PART2_ROT_SRV_DB_TST",
 | 
			
		||||
      "identifier": "0x00001A04",
 | 
			
		||||
      "signal": "ROT_SRV_DB_TST_MSK",
 | 
			
		||||
      "non_secure_clients": false,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/server_tests_partition2.c",
 | 
			
		||||
    "COMPONENT_SPE/tests.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,96 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef COMPONENT_PSA_SRV_IPC
 | 
			
		||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------- Includes ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa_manifest/sid.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_TFM)
 | 
			
		||||
#define PSA_MAX_IOVEC 4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------ Definitions ---------------------------------- */
 | 
			
		||||
 | 
			
		||||
#define CLIENT_MINOR_VERSION            0
 | 
			
		||||
#define CLIENT_RSP_BUF_SIZE             20
 | 
			
		||||
 | 
			
		||||
#define CLIENT_TX_MSG                   "Hello and welcome SPM"
 | 
			
		||||
#define CLIENT_EXPECTED_RESPONSE        "Response1"
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------ Client Code ---------------------------------- */
 | 
			
		||||
 | 
			
		||||
char msg_buf[] = CLIENT_TX_MSG;
 | 
			
		||||
 | 
			
		||||
void example_main(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t conn_handle = psa_connect(SMOKE_TESTS_PART1_ROT_SRV1, CLIENT_MINOR_VERSION);
 | 
			
		||||
    TEST_ASSERT_MESSAGE(conn_handle > 0, "psa_connect() failed");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    psa_invec iovec[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        { msg_buf, 6 },
 | 
			
		||||
        { msg_buf + 6, 12 },
 | 
			
		||||
        { msg_buf + 18, 4 }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    uint8_t *response_buf = (uint8_t *)malloc(sizeof(uint8_t) * CLIENT_RSP_BUF_SIZE);
 | 
			
		||||
    memset(response_buf, 0, CLIENT_RSP_BUF_SIZE);
 | 
			
		||||
    psa_outvec outvec = {response_buf, CLIENT_RSP_BUF_SIZE};
 | 
			
		||||
 | 
			
		||||
    psa_status_t status = psa_call(conn_handle, iovec, PSA_MAX_IOVEC - 1, &outvec, 1);
 | 
			
		||||
    TEST_ASSERT_MESSAGE(PSA_SUCCESS == status, "psa_call() failed");
 | 
			
		||||
    TEST_ASSERT_EQUAL_STRING(CLIENT_EXPECTED_RESPONSE, response_buf);
 | 
			
		||||
 | 
			
		||||
    free(response_buf);
 | 
			
		||||
    psa_close(conn_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --------------------------------- Test Framework ---------------------------------- */
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t greentea_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    GREENTEA_SETUP(20, "default_auto");
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    Case("example", example_main)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Declare your test specification with a custom setup handler
 | 
			
		||||
Specification specification(greentea_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main(int, char **)
 | 
			
		||||
{
 | 
			
		||||
    // Run the test specification
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // COMPONENT_PSA_SRV_IPC
 | 
			
		||||
| 
						 | 
				
			
			@ -1,122 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// -------------------------------------- Includes -----------------------------------
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------ Definitions ----------------------------------
 | 
			
		||||
 | 
			
		||||
#define SERVER_READ_MSG_BUF_SIZE        30
 | 
			
		||||
#define SERVER_RSP_BUF_SIZE             20
 | 
			
		||||
#define ACTUAL_MSG_SIZE                 22
 | 
			
		||||
 | 
			
		||||
// ---------------------------------- Global Variables -------------------------------
 | 
			
		||||
 | 
			
		||||
const char SERVER_EXPECTED_READ_MSG[] = "Hello and welcome SPM";
 | 
			
		||||
const char WRITE_MSG_BUF[] = "Response1";
 | 
			
		||||
 | 
			
		||||
// ------------------------------ Partition's Main Thread ----------------------------
 | 
			
		||||
 | 
			
		||||
void smoke_part_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t  signals   = 0;
 | 
			
		||||
    int32_t   client_id = 0;
 | 
			
		||||
    psa_msg_t msg       = {0};
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
 | 
			
		||||
        signals = psa_wait(ROT_SRV1_MSK, PSA_BLOCK);
 | 
			
		||||
        if ((signals & ROT_SRV1_MSK) != ROT_SRV1_MSK) {
 | 
			
		||||
            SPM_PANIC("Received unknown signal (0x%08lx)\n", signals);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (PSA_SUCCESS != psa_get(ROT_SRV1_MSK, &msg)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (msg.handle != PSA_NULL_HANDLE) {
 | 
			
		||||
            client_id = msg.client_id;
 | 
			
		||||
            if (client_id != -1) {
 | 
			
		||||
                SPM_PANIC("Received message from unexpected source (0x%08lx)\n", client_id);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (msg.type) {
 | 
			
		||||
            case PSA_IPC_CALL: {
 | 
			
		||||
                if (
 | 
			
		||||
                    ((msg.in_size[0] + msg.in_size[1] + msg.in_size[2] + msg.in_size[3]) != ACTUAL_MSG_SIZE) ||
 | 
			
		||||
                    (msg.out_size[0] != SERVER_RSP_BUF_SIZE)
 | 
			
		||||
                ) {
 | 
			
		||||
                    SPM_PANIC("Received message does not comply with message convention");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                char *read_msg_buf = malloc(sizeof(char) * SERVER_READ_MSG_BUF_SIZE);
 | 
			
		||||
                if (NULL == read_msg_buf) {
 | 
			
		||||
                    SPM_PANIC("Failed to allocate Memory");
 | 
			
		||||
                }
 | 
			
		||||
                memset(read_msg_buf, 0, SERVER_READ_MSG_BUF_SIZE);
 | 
			
		||||
                char *read_ptr = read_msg_buf;
 | 
			
		||||
 | 
			
		||||
                for (size_t i = 0; i < PSA_MAX_IOVEC - 1; i++) {
 | 
			
		||||
                    uint32_t bytes_read = psa_read(msg.handle, i, read_ptr, msg.in_size[i]);
 | 
			
		||||
                    if (bytes_read != msg.in_size[i]) {
 | 
			
		||||
                        SPM_PANIC("Expected to read %zu, got %lu", msg.in_size[i], bytes_read);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    read_ptr += bytes_read;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                int cmp_res = strcmp(SERVER_EXPECTED_READ_MSG, read_msg_buf);
 | 
			
		||||
                if (cmp_res != 0) {
 | 
			
		||||
                    SPM_PANIC("psa_read() - Bad reading!!");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                psa_write(msg.handle, 0, WRITE_MSG_BUF, strlen(WRITE_MSG_BUF) + 1);
 | 
			
		||||
                free(read_msg_buf);
 | 
			
		||||
                read_msg_buf = NULL;
 | 
			
		||||
                read_ptr = NULL;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case PSA_IPC_DISCONNECT:
 | 
			
		||||
            // Fallthrough
 | 
			
		||||
            case PSA_IPC_CONNECT: {
 | 
			
		||||
                if (
 | 
			
		||||
                    (msg.out_size[0] != 0) || (msg.out_size[1] != 0) ||
 | 
			
		||||
                    (msg.out_size[2] != 0) || (msg.out_size[3] != 0) ||
 | 
			
		||||
                    (msg.in_size[0] != 0) || (msg.in_size[1] != 0) ||
 | 
			
		||||
                    (msg.in_size[2] != 0) || (msg.in_size[3] != 0)
 | 
			
		||||
                ) {
 | 
			
		||||
                    SPM_PANIC("Should not receive iovecs in PSA_IPC_CONNECT or PSA_IPC_DISCONNECT");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
                SPM_PANIC("Unexpected message type %lu!", msg.type);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,21 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "SMOKE_TESTS_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000004",
 | 
			
		||||
  "entry_point": "smoke_part_main",
 | 
			
		||||
  "stack_size": "0x200",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "SMOKE_TESTS_PART1_ROT_SRV1",
 | 
			
		||||
      "identifier": "0x00001A00",
 | 
			
		||||
      "signal": "ROT_SRV1_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/smoke_tests_partition.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,217 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_BOOT_STATUS_H__
 | 
			
		||||
#define __TFM_BOOT_STATUS_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Major numbers (4 bit) to identify
 | 
			
		||||
 * the consumer of shared data in runtime SW
 | 
			
		||||
 */
 | 
			
		||||
#define TLV_MAJOR_CORE     0x0
 | 
			
		||||
#define TLV_MAJOR_IAS      0x1
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The shared data between boot loader and runtime SW is TLV encoded. The
 | 
			
		||||
 * shared data is stored in a well known location in secure memory and this is
 | 
			
		||||
 * a contract between boot loader and runtime SW.
 | 
			
		||||
 *
 | 
			
		||||
 * The structure of shared data must be the following:
 | 
			
		||||
 *  - At the beginning there must be a header: struct shared_data_tlv_header
 | 
			
		||||
 *    This contains a magic number and a size field which covers the entire
 | 
			
		||||
 *    size of the shared data area including this header.
 | 
			
		||||
 *  - After the header there come the entries which are composed from an entry
 | 
			
		||||
 *    header structure: struct shared_data_tlv_entry and the data. In the entry
 | 
			
		||||
 *    header is a type field (tly_type) which identify the consumer of the
 | 
			
		||||
 *    entry in the runtime SW and specify the subtype of that data item. There
 | 
			
		||||
 *    is a size field (tlv_len) which covers the size of the entry header and
 | 
			
		||||
 *    the data. After this structure comes the actual data.
 | 
			
		||||
 *  - Arbitrary number and size of data entry can be in the shared memory area.
 | 
			
		||||
 *
 | 
			
		||||
 * This table gives of overview about the tlv_type field in the entry header.
 | 
			
		||||
 * The tlv_type always composed from a major and minor number. Major number
 | 
			
		||||
 * identifies the addressee in runtime SW, who should process the data entry.
 | 
			
		||||
 * Minor number used to encode more info about the data entry. The actual
 | 
			
		||||
 * definition of minor number could change per major number. In case of boot
 | 
			
		||||
 * status data, which is going to be processed by initial attestation service
 | 
			
		||||
 * the minor number is split further to two part: sw_module and claim. The
 | 
			
		||||
 * sw_module identifies the SW component in the system which the data item
 | 
			
		||||
 * belongs to and the claim part identifies the exact type of the data.
 | 
			
		||||
 *
 | 
			
		||||
 * |---------------------------------------|
 | 
			
		||||
 * |            tlv_type (16)              |
 | 
			
		||||
 * |---------------------------------------|
 | 
			
		||||
 * | tlv_major(4)|      tlv_minor(12)      |
 | 
			
		||||
 * |---------------------------------------|
 | 
			
		||||
 * | MAJOR_IAS   | sw_module(6) | claim(6) |
 | 
			
		||||
 * |---------------------------------------|
 | 
			
		||||
 * | MAJOR_CORE  |          TBD            |
 | 
			
		||||
 * |---------------------------------------|
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Initial attestation: SW components / SW modules
 | 
			
		||||
 * This list is intended to be adjusted per device. It contains more SW
 | 
			
		||||
 * components than currently available in TF-M project. It serves as an example,
 | 
			
		||||
 * what kind of SW components might be available.
 | 
			
		||||
 */
 | 
			
		||||
#define SW_GENERAL     0x00
 | 
			
		||||
#define SW_BL2         0x01
 | 
			
		||||
#define SW_PROT        0x02
 | 
			
		||||
#define SW_AROT        0x03
 | 
			
		||||
#define SW_SPE         0x04
 | 
			
		||||
#define SW_NSPE        0x05
 | 
			
		||||
#define SW_S_NS        0x06
 | 
			
		||||
#define SW_MAX         0x07
 | 
			
		||||
 | 
			
		||||
/* Initial attestation: Claim per SW components / SW modules */
 | 
			
		||||
/* Bits: 0-2 */
 | 
			
		||||
#define SW_VERSION       0x00
 | 
			
		||||
#define SW_SIGNER_ID     0x01
 | 
			
		||||
#define SW_EPOCH         0x02
 | 
			
		||||
#define SW_TYPE          0x03
 | 
			
		||||
/* Bits: 3-5 */
 | 
			
		||||
#define SW_MEASURE_VALUE 0x08
 | 
			
		||||
#define SW_MEASURE_TYPE  0x09
 | 
			
		||||
 | 
			
		||||
/* Initial attestation: General claim does not belong any particular SW
 | 
			
		||||
 * component. But they might be part of the boot status.
 | 
			
		||||
 */
 | 
			
		||||
#define BOOT_SEED          0x00
 | 
			
		||||
#define HW_VERSION         0x01
 | 
			
		||||
#define SECURITY_LIFECYCLE 0x02
 | 
			
		||||
 | 
			
		||||
/* Minor numbers (12 bit) to identify attestation service related data */
 | 
			
		||||
#define TLV_MINOR_IAS_BOOT_SEED       ((SW_GENERAL << 6) | BOOT_SEED)
 | 
			
		||||
#define TLV_MINOR_IAS_HW_VERSION      ((SW_GENERAL << 6) | HW_VERSION)
 | 
			
		||||
#define TLV_MINOR_IAS_SLC             ((SW_GENERAL << 6) | SECURITY_LIFECYCLE)
 | 
			
		||||
 | 
			
		||||
/* Bootloader - It can be more stage */
 | 
			
		||||
#define TLV_MINOR_IAS_BL2_MEASURE_VALUE  ((SW_BL2  << 6) | SW_MEASURE_VALUE)
 | 
			
		||||
#define TLV_MINOR_IAS_BL2_MEASURE_TYPE   ((SW_BL2  << 6) | SW_MEASURE_TYPE)
 | 
			
		||||
#define TLV_MINOR_IAS_BL2_VERSION        ((SW_BL2  << 6) | SW_VERSION)
 | 
			
		||||
#define TLV_MINOR_IAS_BL2_SIGNER_ID      ((SW_BL2  << 6) | SW_SIGNER_ID)
 | 
			
		||||
#define TLV_MINOR_IAS_BL2_EPOCH          ((SW_BL2  << 6) | SW_EPOCH)
 | 
			
		||||
#define TLV_MINOR_IAS_BL2_TYPE           ((SW_BL2  << 6) | SW_TYPE)
 | 
			
		||||
 | 
			
		||||
/* PROT: PSA Root of Trust */
 | 
			
		||||
#define TLV_MINOR_IAS_PROT_MEASURE_VALUE ((SW_PROT << 6) | SW_MEASURE_VALUE)
 | 
			
		||||
#define TLV_MINOR_IAS_PROT_MEASURE_TYPE  ((SW_PROT << 6) | SW_MEASURE_TYPE)
 | 
			
		||||
#define TLV_MINOR_IAS_PROT_VERSION       ((SW_PROT << 6) | SW_VERSION)
 | 
			
		||||
#define TLV_MINOR_IAS_PROT_SIGNER_ID     ((SW_PROT << 6) | SW_SIGNER_ID)
 | 
			
		||||
#define TLV_MINOR_IAS_PROT_EPOCH         ((SW_PROT << 6) | SW_EPOCH)
 | 
			
		||||
#define TLV_MINOR_IAS_PROT_TYPE          ((SW_PROT << 6) | SW_TYPE)
 | 
			
		||||
 | 
			
		||||
/* AROT: Application Root of Trust */
 | 
			
		||||
#define TLV_MINOR_IAS_AROT_MEASURE_VALUE ((SW_AROT << 6) | SW_MEASURE_VALUE)
 | 
			
		||||
#define TLV_MINOR_IAS_AROT_MEASURE_TYPE  ((SW_AROT << 6) | SW_MEASURE_TYPE)
 | 
			
		||||
#define TLV_MINOR_IAS_AROT_VERSION       ((SW_AROT << 6) | SW_VERSION)
 | 
			
		||||
#define TLV_MINOR_IAS_AROT_SIGNER_ID     ((SW_AROT << 6) | SW_SIGNER_ID)
 | 
			
		||||
#define TLV_MINOR_IAS_AROT_EPOCH         ((SW_AROT << 6) | SW_EPOCH)
 | 
			
		||||
#define TLV_MINOR_IAS_AROT_TYPE          ((SW_AROT << 6) | SW_TYPE)
 | 
			
		||||
 | 
			
		||||
/* Non-secure processing environment - single non-secure image */
 | 
			
		||||
#define TLV_MINOR_IAS_NSPE_MEASURE_VALUE ((SW_NSPE << 6) | SW_MEASURE_VALUE)
 | 
			
		||||
#define TLV_MINOR_IAS_NSPE_MEASURE_TYPE  ((SW_NSPE << 6) | SW_MEASURE_TYPE)
 | 
			
		||||
#define TLV_MINOR_IAS_NSPE_VERSION       ((SW_NSPE << 6) | SW_VERSION)
 | 
			
		||||
#define TLV_MINOR_IAS_NSPE_SIGNER_ID     ((SW_NSPE << 6) | SW_SIGNER_ID)
 | 
			
		||||
#define TLV_MINOR_IAS_NSPE_EPOCH         ((SW_NSPE << 6) | SW_EPOCH)
 | 
			
		||||
#define TLV_MINOR_IAS_NSPE_TYPE          ((SW_NSPE << 6) | SW_TYPE)
 | 
			
		||||
 | 
			
		||||
/* Secure processing environment (ARoT + PRoT) - single secure image */
 | 
			
		||||
#define TLV_MINOR_IAS_SPE_MEASURE_VALUE  ((SW_SPE  << 6) | SW_MEASURE_VALUE)
 | 
			
		||||
#define TLV_MINOR_IAS_SPE_MEASURE_TYPE   ((SW_SPE  << 6) | SW_MEASURE_TYPE)
 | 
			
		||||
#define TLV_MINOR_IAS_SPE_VERSION        ((SW_SPE  << 6) | SW_VERSION)
 | 
			
		||||
#define TLV_MINOR_IAS_SPE_SIGNER_ID      ((SW_SPE  << 6) | SW_SIGNER_ID)
 | 
			
		||||
#define TLV_MINOR_IAS_SPE_EPOCH          ((SW_SPE  << 6) | SW_EPOCH)
 | 
			
		||||
#define TLV_MINOR_IAS_SPE_TYPE           ((SW_SPE  << 6) | SW_TYPE)
 | 
			
		||||
 | 
			
		||||
/* SPE + NSPE - combined secure and non-secure image */
 | 
			
		||||
#define TLV_MINOR_IAS_S_NS_MEASURE_VALUE ((SW_S_NS << 6) | SW_MEASURE_VALUE)
 | 
			
		||||
#define TLV_MINOR_IAS_S_NS_MEASURE_TYPE  ((SW_S_NS << 6) | SW_MEASURE_TYPE)
 | 
			
		||||
#define TLV_MINOR_IAS_S_NS_VERSION       ((SW_S_NS << 6) | SW_VERSION)
 | 
			
		||||
#define TLV_MINOR_IAS_S_NS_SIGNER_ID     ((SW_S_NS << 6) | SW_SIGNER_ID)
 | 
			
		||||
#define TLV_MINOR_IAS_S_NS_EPOCH         ((SW_S_NS << 6) | SW_EPOCH)
 | 
			
		||||
#define TLV_MINOR_IAS_S_NS_TYPE          ((SW_S_NS << 6) | SW_TYPE)
 | 
			
		||||
 | 
			
		||||
/* General macros to handle TLV type */
 | 
			
		||||
#define MAJOR_MASK 0xF     /* 4  bit */
 | 
			
		||||
#define MAJOR_POS  12      /* 12 bit */
 | 
			
		||||
#define MINOR_MASK 0xFFF   /* 12 bit */
 | 
			
		||||
 | 
			
		||||
#define SET_TLV_TYPE(major, minor) \
 | 
			
		||||
        ((((major) & MAJOR_MASK) << MAJOR_POS) | ((minor) & MINOR_MASK))
 | 
			
		||||
#define GET_MAJOR(tlv_type) ((tlv_type) >> MAJOR_POS)
 | 
			
		||||
#define GET_MINOR(tlv_type) ((tlv_type) &  MINOR_MASK)
 | 
			
		||||
 | 
			
		||||
/* Initial attestation specific macros */
 | 
			
		||||
#define MODULE_POS 6               /* 6 bit */
 | 
			
		||||
#define CLAIM_MASK 0x3F            /* 6 bit */
 | 
			
		||||
#define MEASUREMENT_CLAIM_POS 3    /* 3 bit */
 | 
			
		||||
 | 
			
		||||
#define GET_IAS_MODULE(tlv_type) (GET_MINOR(tlv_type) >> MODULE_POS)
 | 
			
		||||
#define GET_IAS_CLAIM(tlv_type)  (GET_MINOR(tlv_type)  & CLAIM_MASK)
 | 
			
		||||
#define SET_IAS_MINOR(sw_module, claim) (((sw_module) << 6) | (claim))
 | 
			
		||||
 | 
			
		||||
#define GET_IAS_MEASUREMENT_CLAIM(ias_claim) ((ias_claim) >> \
 | 
			
		||||
                                              MEASUREMENT_CLAIM_POS)
 | 
			
		||||
 | 
			
		||||
/* Magic value which marks the beginning of shared data area in memory */
 | 
			
		||||
#define SHARED_DATA_TLV_INFO_MAGIC    0x2016
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shared data TLV header.  All fields in little endian.
 | 
			
		||||
 *
 | 
			
		||||
 *    -----------------------------------
 | 
			
		||||
 *    | tlv_magic(16) | tlv_tot_len(16) |
 | 
			
		||||
 *    -----------------------------------
 | 
			
		||||
 */
 | 
			
		||||
struct shared_data_tlv_header {
 | 
			
		||||
    uint16_t tlv_magic;
 | 
			
		||||
    uint16_t tlv_tot_len; /* size of whole TLV area (including this header) */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SHARED_DATA_HEADER_SIZE sizeof(struct shared_data_tlv_header)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shared data TLV entry header format. All fields in little endian.
 | 
			
		||||
 *
 | 
			
		||||
 *    -------------------------------
 | 
			
		||||
 *    | tlv_type(16) |  tlv_len(16) |
 | 
			
		||||
 *    -------------------------------
 | 
			
		||||
 *    |         Raw data            |
 | 
			
		||||
 *    -------------------------------
 | 
			
		||||
 */
 | 
			
		||||
struct shared_data_tlv_entry {
 | 
			
		||||
    uint16_t tlv_type;
 | 
			
		||||
    uint16_t tlv_len; /* size of single TLV entry (including this header). */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \struct tfm_boot_data
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Store the data for the runtime SW
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_boot_data {
 | 
			
		||||
    struct shared_data_tlv_header header;
 | 
			
		||||
    uint8_t data[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SHARED_DATA_ENTRY_HEADER_SIZE sizeof(struct shared_data_tlv_entry)
 | 
			
		||||
#define SHARED_DATA_ENTRY_SIZE(size) (size + SHARED_DATA_ENTRY_HEADER_SIZE)
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_BOOT_STATUS_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,68 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2017-2019 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * Template Version 1.0
 | 
			
		||||
 * Generated by tools/psa/generate_partition_code.py Version 1.1
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_PARTITION_DEFS_INC__
 | 
			
		||||
#define __TFM_PARTITION_DEFS_INC__
 | 
			
		||||
 | 
			
		||||
/*************************** Service Partitions *******************************/
 | 
			
		||||
 | 
			
		||||
#define ATTEST_SRV_ID (TFM_SP_BASE + 0)
 | 
			
		||||
#define CRYPTO_SRV_ID (TFM_SP_BASE + 1)
 | 
			
		||||
#define PLATFORM_ID (TFM_SP_BASE + 2)
 | 
			
		||||
#define ITS_ID (TFM_SP_BASE + 3)
 | 
			
		||||
 | 
			
		||||
/*************************** Test Partitions **********************************/
 | 
			
		||||
 | 
			
		||||
#ifdef USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CRYPTO_ACL_TEST
 | 
			
		||||
#define CRYPTO_ACL_TEST_ID (TFM_SP_BASE + 4 + 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CLIENT_TESTS_PART1
 | 
			
		||||
#define CLIENT_TESTS_PART1_ID (TFM_SP_BASE + 4 + 1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART1
 | 
			
		||||
#define SERVER_TESTS_PART1_ID (TFM_SP_BASE + 4 + 2)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART2
 | 
			
		||||
#define SERVER_TESTS_PART2_ID (TFM_SP_BASE + 4 + 3)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SMOKE_TESTS_PART1
 | 
			
		||||
#define SMOKE_TESTS_PART1_ID (TFM_SP_BASE + 4 + 4)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#ifdef USE_PSA_TEST_PARTITIONS
 | 
			
		||||
#define TFM_MAX_USER_PARTITIONS (4 + 5)
 | 
			
		||||
#else
 | 
			
		||||
#define TFM_MAX_USER_PARTITIONS (4)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // __TFM_PARTITION_DEFS_INC__
 | 
			
		||||
| 
						 | 
				
			
			@ -1,107 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * Template Version 1.0
 | 
			
		||||
 * Generated by tools/psa/generate_partition_code.py Version 1.1
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_PARTITION_LIST_INC__
 | 
			
		||||
#define __TFM_PARTITION_LIST_INC__
 | 
			
		||||
 | 
			
		||||
/*************************** Service Partitions *******************************/
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * ATTEST_SRV
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(ATTEST_SRV, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 37, NORMAL, 8192);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(ATTEST_SRV, attest_main);
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CRYPTO_SRV
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(CRYPTO_SRV, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 35, NORMAL, 16384);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(CRYPTO_SRV, crypto_main);
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * PLATFORM
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(PLATFORM, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 8, NORMAL, 1024);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(PLATFORM, platform_partition_entry);
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * ITS
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(ITS, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 10, NORMAL, 2048);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(ITS, its_entry);
 | 
			
		||||
 | 
			
		||||
/*************************** Test Partitions **********************************/
 | 
			
		||||
#ifdef USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CRYPTO_ACL_TEST
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CRYPTO_ACL_TEST
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(CRYPTO_ACL_TEST, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 128, NORMAL, 512);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(CRYPTO_ACL_TEST, test_partition_main);
 | 
			
		||||
#endif // USE_CRYPTO_ACL_TEST
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CLIENT_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CLIENT_TESTS_PART1
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(CLIENT_TESTS_PART1, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 1, NORMAL, 1024);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(CLIENT_TESTS_PART1, client_part_main);
 | 
			
		||||
#endif // USE_CLIENT_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SERVER_TESTS_PART1
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(SERVER_TESTS_PART1, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 2, NORMAL, 1024);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(SERVER_TESTS_PART1, server_part1_main);
 | 
			
		||||
#endif // USE_SERVER_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART2
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SERVER_TESTS_PART2
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(SERVER_TESTS_PART2, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 3, NORMAL, 1024);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(SERVER_TESTS_PART2, server_part2_main);
 | 
			
		||||
#endif // USE_SERVER_TESTS_PART2
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SMOKE_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SMOKE_TESTS_PART1
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
PARTITION_DECLARE(SMOKE_TESTS_PART1, 0
 | 
			
		||||
    | SPM_PART_FLAG_IPC
 | 
			
		||||
    , "APPLICATION-ROT", 4, NORMAL, 512);
 | 
			
		||||
PARTITION_ADD_INIT_FUNC(SMOKE_TESTS_PART1, smoke_part_main);
 | 
			
		||||
#endif // USE_SMOKE_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#endif // USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#endif // __TFM_PARTITION_LIST_INC__
 | 
			
		||||
| 
						 | 
				
			
			@ -1,108 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * Template Version 1.0
 | 
			
		||||
 * Generated by tools/psa/generate_partition_code.py Version 1.1
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_SERVICE_LIST_INC__
 | 
			
		||||
#define __TFM_SERVICE_LIST_INC__
 | 
			
		||||
 | 
			
		||||
/*************************** Service Partitions *******************************/
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * ATTEST_SRV Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"PSA_ATTEST_GET_TOKEN_ID", ATTEST_SRV_ID, PSA_ATTEST_GET_TOKEN, 0x00000F10, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_ATTEST_GET_TOKEN_SIZE_ID", ATTEST_SRV_ID, PSA_ATTEST_GET_TOKEN_SIZE, 0x00000F11, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_ATTEST_INJECT_KEY_ID", ATTEST_SRV_ID, PSA_ATTEST_INJECT_KEY, 0x00000F12, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CRYPTO_SRV Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"PSA_CRYPTO_INIT_ID", CRYPTO_SRV_ID, PSA_CRYPTO_INIT, 0x00000F00, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_MAC_ID", CRYPTO_SRV_ID, PSA_MAC, 0x00000F01, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_HASH_ID", CRYPTO_SRV_ID, PSA_HASH, 0x00000F02, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_ASYMMETRIC_ID", CRYPTO_SRV_ID, PSA_ASYMMETRIC, 0x00000F03, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_SYMMETRIC_ID", CRYPTO_SRV_ID, PSA_SYMMETRIC, 0x00000F04, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_AEAD_ID", CRYPTO_SRV_ID, PSA_AEAD, 0x00000F05, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_KEY_MNG_ID", CRYPTO_SRV_ID, PSA_KEY_MNG, 0x00000F06, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_RNG_ID", CRYPTO_SRV_ID, PSA_RNG, 0x00000F07, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_CRYPTO_FREE_ID", CRYPTO_SRV_ID, PSA_CRYPTO_FREE, 0x00000F08, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_KEY_DERIVATION_ID", CRYPTO_SRV_ID, PSA_KEY_DERIVATION, 0x00000F09, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"PSA_ENTROPY_ID", CRYPTO_SRV_ID, PSA_ENTROPY_INJECT, 0x00000F0A, true, 1, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * PLATFORM Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"PSA_PLATFORM_LC_GET", PLATFORM_ID, PSA_PLATFORM_LC_GET_MSK, 0x00011000, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"PSA_PLATFORM_LC_SET", PLATFORM_ID, PSA_PLATFORM_LC_SET_MSK, 0x00011001, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"PSA_PLATFORM_SYSTEM_RESET", PLATFORM_ID, PSA_PLATFORM_SYSTEM_RESET_MSK, 0x00011002, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"PSA_PLATFORM_IOCTL", PLATFORM_ID, PSA_PLATFORM_IOCTL_MSK, 0x00011003, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * ITS Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"PSA_ITS_GET", ITS_ID, PSA_ITS_GET_MSK, 0x00011A00, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"PSA_ITS_SET", ITS_ID, PSA_ITS_SET_MSK, 0x00011A01, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"PSA_ITS_INFO", ITS_ID, PSA_ITS_INFO_MSK, 0x00011A02, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"PSA_ITS_REMOVE", ITS_ID, PSA_ITS_REMOVE_MSK, 0x00011A03, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"PSA_ITS_RESET", ITS_ID, PSA_ITS_RESET_MSK, 0x00011A04, false, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
 | 
			
		||||
/*************************** Test Partitions **********************************/
 | 
			
		||||
#ifdef USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CRYPTO_ACL_TEST
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CRYPTO_ACL_TEST Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"CRYPTO_GENERATE_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_GENERATE_KEY_MSK, 0x00000201, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"CRYPTO_OPEN_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_OPEN_KEY_MSK, 0x00000202, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"CRYPTO_CLOSE_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_CLOSE_KEY_MSK, 0x00000203, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"CRYPTO_DESTROY_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_DESTROY_KEY_MSK, 0x00000205, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"CRYPTO_GET_KEY_ATTRIBUTES", CRYPTO_ACL_TEST_ID, CRYPTO_GET_KEY_ATTRIBUTES_MSK, 0x00000206, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"CRYPTO_IMPORT_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_IMPORT_KEY_MSK, 0x00000208, true, 1, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
#endif // USE_CRYPTO_ACL_TEST
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CLIENT_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CLIENT_TESTS_PART1 Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"CLIENT_TESTS_PART1_ROT_SRV1", CLIENT_TESTS_PART1_ID, PART1_ROT_SRV1_MSK, 0x00001A05, true, 5, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"CLIENT_TESTS_PART1_DROP_CONN", CLIENT_TESTS_PART1_ID, DROP_CONN_MSK, 0x00001A06, true, 5, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"CLIENT_TESTS_PART1_SECURE_CLIENTS_ONLY", CLIENT_TESTS_PART1_ID, SECURE_CLIENTS_ONLY_MSK, 0x00001A07, false, 5, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
#endif // USE_CLIENT_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SERVER_TESTS_PART1 Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"SERVER_TESTS_PART1_CONTROL", SERVER_TESTS_PART1_ID, CONTROL_MSK, 0x00001A01, true, 5, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
{"SERVER_TESTS_PART1_TEST", SERVER_TESTS_PART1_ID, TEST_MSK, 0x00001A02, true, 12, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
#endif // USE_SERVER_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART2
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SERVER_TESTS_PART2 Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"SERVER_TESTS_PART2_ROT_SRV_REVERSE", SERVER_TESTS_PART2_ID, ROT_SRV_REVERSE_MSK, 0x00001A03, false, 5, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
{"SERVER_TESTS_PART2_ROT_SRV_DB_TST", SERVER_TESTS_PART2_ID, ROT_SRV_DB_TST_MSK, 0x00001A04, false, 5, TFM_VERSION_POLICY_STRICT},
 | 
			
		||||
#endif // USE_SERVER_TESTS_PART2
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SMOKE_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SMOKE_TESTS_PART1 Services
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
{"SMOKE_TESTS_PART1_ROT_SRV1", SMOKE_TESTS_PART1_ID, ROT_SRV1_MSK, 0x00001A00, true, 5, TFM_VERSION_POLICY_RELAXED},
 | 
			
		||||
#endif // USE_SMOKE_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#endif // USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#endif // __TFM_SERVICE_LIST_INC__
 | 
			
		||||
| 
						 | 
				
			
			@ -1,145 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * Template Version 1.0
 | 
			
		||||
 * Generated by tools/psa/generate_partition_code.py Version 1.1
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_SPM_SIGNAL_DEFS_H__
 | 
			
		||||
#define __TFM_SPM_SIGNAL_DEFS_H__
 | 
			
		||||
 | 
			
		||||
/*************************** Service Partitions *******************************/
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * ATTEST_SRV Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define PSA_ATTEST_GET_TOKEN_POS (4UL)
 | 
			
		||||
#define PSA_ATTEST_GET_TOKEN (1UL << PSA_ATTEST_GET_TOKEN_POS)
 | 
			
		||||
#define PSA_ATTEST_GET_TOKEN_SIZE_POS (5UL)
 | 
			
		||||
#define PSA_ATTEST_GET_TOKEN_SIZE (1UL << PSA_ATTEST_GET_TOKEN_SIZE_POS)
 | 
			
		||||
#define PSA_ATTEST_INJECT_KEY_POS (6UL)
 | 
			
		||||
#define PSA_ATTEST_INJECT_KEY (1UL << PSA_ATTEST_INJECT_KEY_POS)
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CRYPTO_SRV Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define PSA_CRYPTO_INIT_POS (4UL)
 | 
			
		||||
#define PSA_CRYPTO_INIT (1UL << PSA_CRYPTO_INIT_POS)
 | 
			
		||||
#define PSA_MAC_POS (5UL)
 | 
			
		||||
#define PSA_MAC (1UL << PSA_MAC_POS)
 | 
			
		||||
#define PSA_HASH_POS (6UL)
 | 
			
		||||
#define PSA_HASH (1UL << PSA_HASH_POS)
 | 
			
		||||
#define PSA_ASYMMETRIC_POS (7UL)
 | 
			
		||||
#define PSA_ASYMMETRIC (1UL << PSA_ASYMMETRIC_POS)
 | 
			
		||||
#define PSA_SYMMETRIC_POS (8UL)
 | 
			
		||||
#define PSA_SYMMETRIC (1UL << PSA_SYMMETRIC_POS)
 | 
			
		||||
#define PSA_AEAD_POS (9UL)
 | 
			
		||||
#define PSA_AEAD (1UL << PSA_AEAD_POS)
 | 
			
		||||
#define PSA_KEY_MNG_POS (10UL)
 | 
			
		||||
#define PSA_KEY_MNG (1UL << PSA_KEY_MNG_POS)
 | 
			
		||||
#define PSA_RNG_POS (11UL)
 | 
			
		||||
#define PSA_RNG (1UL << PSA_RNG_POS)
 | 
			
		||||
#define PSA_CRYPTO_FREE_POS (12UL)
 | 
			
		||||
#define PSA_CRYPTO_FREE (1UL << PSA_CRYPTO_FREE_POS)
 | 
			
		||||
#define PSA_KEY_DERIVATION_POS (13UL)
 | 
			
		||||
#define PSA_KEY_DERIVATION (1UL << PSA_KEY_DERIVATION_POS)
 | 
			
		||||
#define PSA_ENTROPY_INJECT_POS (14UL)
 | 
			
		||||
#define PSA_ENTROPY_INJECT (1UL << PSA_ENTROPY_INJECT_POS)
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * PLATFORM Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define PSA_PLATFORM_LC_GET_MSK_POS (4UL)
 | 
			
		||||
#define PSA_PLATFORM_LC_GET_MSK (1UL << PSA_PLATFORM_LC_GET_MSK_POS)
 | 
			
		||||
#define PSA_PLATFORM_LC_SET_MSK_POS (5UL)
 | 
			
		||||
#define PSA_PLATFORM_LC_SET_MSK (1UL << PSA_PLATFORM_LC_SET_MSK_POS)
 | 
			
		||||
#define PSA_PLATFORM_SYSTEM_RESET_MSK_POS (6UL)
 | 
			
		||||
#define PSA_PLATFORM_SYSTEM_RESET_MSK (1UL << PSA_PLATFORM_SYSTEM_RESET_MSK_POS)
 | 
			
		||||
#define PSA_PLATFORM_IOCTL_MSK_POS (7UL)
 | 
			
		||||
#define PSA_PLATFORM_IOCTL_MSK (1UL << PSA_PLATFORM_IOCTL_MSK_POS)
 | 
			
		||||
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * ITS Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define PSA_ITS_GET_MSK_POS (4UL)
 | 
			
		||||
#define PSA_ITS_GET_MSK (1UL << PSA_ITS_GET_MSK_POS)
 | 
			
		||||
#define PSA_ITS_SET_MSK_POS (5UL)
 | 
			
		||||
#define PSA_ITS_SET_MSK (1UL << PSA_ITS_SET_MSK_POS)
 | 
			
		||||
#define PSA_ITS_INFO_MSK_POS (6UL)
 | 
			
		||||
#define PSA_ITS_INFO_MSK (1UL << PSA_ITS_INFO_MSK_POS)
 | 
			
		||||
#define PSA_ITS_REMOVE_MSK_POS (7UL)
 | 
			
		||||
#define PSA_ITS_REMOVE_MSK (1UL << PSA_ITS_REMOVE_MSK_POS)
 | 
			
		||||
#define PSA_ITS_RESET_MSK_POS (8UL)
 | 
			
		||||
#define PSA_ITS_RESET_MSK (1UL << PSA_ITS_RESET_MSK_POS)
 | 
			
		||||
 | 
			
		||||
/*************************** Test Partitions **********************************/
 | 
			
		||||
#ifdef USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CRYPTO_ACL_TEST
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CRYPTO_ACL_TEST Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define CRYPTO_GENERATE_KEY_MSK_POS (4UL)
 | 
			
		||||
#define CRYPTO_GENERATE_KEY_MSK (1UL << CRYPTO_GENERATE_KEY_MSK_POS)
 | 
			
		||||
#define CRYPTO_OPEN_KEY_MSK_POS (5UL)
 | 
			
		||||
#define CRYPTO_OPEN_KEY_MSK (1UL << CRYPTO_OPEN_KEY_MSK_POS)
 | 
			
		||||
#define CRYPTO_CLOSE_KEY_MSK_POS (6UL)
 | 
			
		||||
#define CRYPTO_CLOSE_KEY_MSK (1UL << CRYPTO_CLOSE_KEY_MSK_POS)
 | 
			
		||||
#define CRYPTO_DESTROY_KEY_MSK_POS (7UL)
 | 
			
		||||
#define CRYPTO_DESTROY_KEY_MSK (1UL << CRYPTO_DESTROY_KEY_MSK_POS)
 | 
			
		||||
#define CRYPTO_GET_KEY_ATTRIBUTES_MSK_POS (8UL)
 | 
			
		||||
#define CRYPTO_GET_KEY_ATTRIBUTES_MSK (1UL << CRYPTO_GET_KEY_ATTRIBUTES_MSK_POS)
 | 
			
		||||
#define CRYPTO_IMPORT_KEY_MSK_POS (9UL)
 | 
			
		||||
#define CRYPTO_IMPORT_KEY_MSK (1UL << CRYPTO_IMPORT_KEY_MSK_POS)
 | 
			
		||||
#endif // USE_CRYPTO_ACL_TEST
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CLIENT_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * CLIENT_TESTS_PART1 Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define PART1_ROT_SRV1_MSK_POS (4UL)
 | 
			
		||||
#define PART1_ROT_SRV1_MSK (1UL << PART1_ROT_SRV1_MSK_POS)
 | 
			
		||||
#define DROP_CONN_MSK_POS (5UL)
 | 
			
		||||
#define DROP_CONN_MSK (1UL << DROP_CONN_MSK_POS)
 | 
			
		||||
#define SECURE_CLIENTS_ONLY_MSK_POS (6UL)
 | 
			
		||||
#define SECURE_CLIENTS_ONLY_MSK (1UL << SECURE_CLIENTS_ONLY_MSK_POS)
 | 
			
		||||
#endif // USE_CLIENT_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SERVER_TESTS_PART1 Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define CONTROL_MSK_POS (4UL)
 | 
			
		||||
#define CONTROL_MSK (1UL << CONTROL_MSK_POS)
 | 
			
		||||
#define TEST_MSK_POS (5UL)
 | 
			
		||||
#define TEST_MSK (1UL << TEST_MSK_POS)
 | 
			
		||||
#endif // USE_SERVER_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SERVER_TESTS_PART2
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SERVER_TESTS_PART2 Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define ROT_SRV_REVERSE_MSK_POS (4UL)
 | 
			
		||||
#define ROT_SRV_REVERSE_MSK (1UL << ROT_SRV_REVERSE_MSK_POS)
 | 
			
		||||
#define ROT_SRV_DB_TST_MSK_POS (5UL)
 | 
			
		||||
#define ROT_SRV_DB_TST_MSK (1UL << ROT_SRV_DB_TST_MSK_POS)
 | 
			
		||||
#endif // USE_SERVER_TESTS_PART2
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SMOKE_TESTS_PART1
 | 
			
		||||
/* -----------------------------------------------------------------------------
 | 
			
		||||
 * SMOKE_TESTS_PART1 Signals
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
#define ROT_SRV1_MSK_POS (4UL)
 | 
			
		||||
#define ROT_SRV1_MSK (1UL << ROT_SRV1_MSK_POS)
 | 
			
		||||
#endif // USE_SMOKE_TESTS_PART1
 | 
			
		||||
 | 
			
		||||
#endif // USE_PSA_TEST_PARTITIONS
 | 
			
		||||
 | 
			
		||||
#endif // __TFM_SPM_SIGNAL_DEFS_H__
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "tfm-s",
 | 
			
		||||
    "macros": ["MBED_FAULT_HANDLER_DISABLED"],
 | 
			
		||||
    "config": {
 | 
			
		||||
        "max_ns_thread_count": {
 | 
			
		||||
            "help": "maximum allowed number of non-secure threads",
 | 
			
		||||
            "macro_name": "TFM_MAX_NS_THREAD_COUNT",
 | 
			
		||||
            "value": 10
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,190 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_SPM_HAL_H__
 | 
			
		||||
#define __TFM_SPM_HAL_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "tfm_secure_api.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Holds peripheral specific data fields required to manage the
 | 
			
		||||
 *        peripherals isolation
 | 
			
		||||
 *
 | 
			
		||||
 * This structure has to be defined in the platform directory, and may have
 | 
			
		||||
 * different definition for each platform. The structure should contain fields
 | 
			
		||||
 * that describe the peripheral for the functions that are prototyped in this
 | 
			
		||||
 * file and are responsible for configuring the isolation of the peripherals.
 | 
			
		||||
 *
 | 
			
		||||
 * Pointers to structures of this type are managed by the SPM, and passed to the
 | 
			
		||||
 * necessary function on isolation request. The pointers are also defined by the
 | 
			
		||||
 * platform in the header file tfm_peripherals_def.h. For details on this, see
 | 
			
		||||
 * the documentation of that file.
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_spm_partition_platform_data_t;
 | 
			
		||||
 | 
			
		||||
#if defined (TFM_PSA_API) || (TFM_LVL != 1)
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Holds SPM db fields that define the memory regions used by a
 | 
			
		||||
 *        partition.
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_spm_partition_memory_data_t
 | 
			
		||||
{
 | 
			
		||||
    uint32_t code_start;   /*!< Start of the code memory of this partition. */
 | 
			
		||||
    uint32_t code_limit;   /*!< Address of the byte beyond the end of the code
 | 
			
		||||
                            *   memory of this partition.
 | 
			
		||||
                            */
 | 
			
		||||
    uint32_t ro_start;     /*!< Start of the read only memory of this
 | 
			
		||||
                            *   partition.
 | 
			
		||||
                            */
 | 
			
		||||
    uint32_t ro_limit;     /*!< Address of the byte beyond the end of the read
 | 
			
		||||
                            *   only memory of this partition.
 | 
			
		||||
                            */
 | 
			
		||||
    uint32_t rw_start;     /*!< Start of the data region of this partition. */
 | 
			
		||||
    uint32_t rw_limit;     /*!< Address of the byte beyond the end of the data
 | 
			
		||||
                            *   region of this partition.
 | 
			
		||||
                            */
 | 
			
		||||
    uint32_t zi_start;     /*!< Start of the zero initialised data region of
 | 
			
		||||
                            *   this partition.
 | 
			
		||||
                            */
 | 
			
		||||
    uint32_t zi_limit;     /*!< Address of the byte beyond the end of the zero
 | 
			
		||||
                            *   initialised region of this partition.
 | 
			
		||||
                            */
 | 
			
		||||
    uint32_t stack_bottom; /*!< The bottom of the stack for the partition. */
 | 
			
		||||
    uint32_t stack_top;    /*!< The top of the stack for the partition. */
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief This function initialises the HW used for isolation, and sets the
 | 
			
		||||
 *        default configuration for them.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is called during TF-M core early startup, before DB init
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_hal_init_isolation_hw(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief This function initialises the HW used for isolation, and sets the
 | 
			
		||||
 *        default configuration for them.
 | 
			
		||||
 * This function is called during TF-M core early startup, after DB init
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_hal_setup_isolation_hw(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Configure peripherals for a partition based on the platfotm data from
 | 
			
		||||
 *        the DB
 | 
			
		||||
 *
 | 
			
		||||
 * This function is called during partition initialisation (before calling the
 | 
			
		||||
 * init function for the partition)
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] platform_data    The platform fields of the partition DB record to
 | 
			
		||||
 *                             be used for configuration. Can be NULL.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_hal_configure_default_isolation(
 | 
			
		||||
                 const struct tfm_spm_partition_platform_data_t *platform_data);
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Configures the system debug properties.
 | 
			
		||||
 *        The default configuration of this function should disable secure debug
 | 
			
		||||
 *        when either DAUTH_NONE or DAUTH_NS_ONLY define is set. It is up to the
 | 
			
		||||
 *        platform owner to decide if secure debug can be turned on in their
 | 
			
		||||
 *        system, if DAUTH_FULL define is present.
 | 
			
		||||
 *        The DAUTH_CHIP_DEFAULT define should not be considered a safe default
 | 
			
		||||
 *        option unless explicitly noted by the chip vendor.
 | 
			
		||||
 *        The implementation has to expect that one of those defines is going to
 | 
			
		||||
 *        be set. Otherwise, a compile error needs to be triggered.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_hal_init_debug(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Enables the fault handlers
 | 
			
		||||
 */
 | 
			
		||||
void enable_fault_handlers(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Configures the system reset request properties
 | 
			
		||||
 */
 | 
			
		||||
void system_reset_cfg(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Configures all external interrupts to target the
 | 
			
		||||
 *        NS state, apart for the ones associated to secure
 | 
			
		||||
 *        peripherals (plus MPC and PPC)
 | 
			
		||||
 */
 | 
			
		||||
void nvic_interrupt_target_state_cfg(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief This function enable the interrupts associated
 | 
			
		||||
 *        to the secure peripherals (plus the isolation boundary violation
 | 
			
		||||
 *        interrupts)
 | 
			
		||||
 */
 | 
			
		||||
void nvic_interrupt_enable(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the VTOR value of non-secure image
 | 
			
		||||
 *
 | 
			
		||||
 * \return Returns the address where the vector table of the non-secure image
 | 
			
		||||
 *         is located
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_hal_get_ns_VTOR(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the initial address of non-secure image main stack
 | 
			
		||||
 *
 | 
			
		||||
 * \return Returns the initial non-secure MSP
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_hal_get_ns_MSP(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the entry point of the non-secure image
 | 
			
		||||
 *
 | 
			
		||||
 * \return Returns the address of the non-secure image entry point
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_hal_get_ns_entry_point(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Configure the sandbox for a partition.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] memory_data      The memory ranges from the partition DB for this
 | 
			
		||||
 *                             partition
 | 
			
		||||
 * \param[in] platform_data    The platform fields of the partition DB record
 | 
			
		||||
 *                             for this partition. Can be NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * \return Returns the result operation as per \ref spm_err_t
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_hal_partition_sandbox_config(
 | 
			
		||||
                 const struct tfm_spm_partition_memory_data_t *memory_data,
 | 
			
		||||
                 const struct tfm_spm_partition_platform_data_t *platform_data);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Deconfigure the sandbox for a partition.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] memory_data      The memory ranges from the partition DB for this
 | 
			
		||||
 *                             partition
 | 
			
		||||
 * \param[in] platform_data    The platform fields of the partition DB record
 | 
			
		||||
 *                             for this partition. Can be NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * \return Returns the result operation as per \ref spm_err_t
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig(
 | 
			
		||||
                 const struct tfm_spm_partition_memory_data_t *memory_data,
 | 
			
		||||
                 const struct tfm_spm_partition_platform_data_t *platform_data);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Set the share region mode
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] share      The mode to set
 | 
			
		||||
 *
 | 
			
		||||
 * \return Returns the result operation as per \ref spm_err_t
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_hal_set_share_region(
 | 
			
		||||
                                          enum tfm_buffer_share_region_e share);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_SPM_HAL_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//This file holds description for the current directory. This documentation
 | 
			
		||||
//will be included in the Doxygen output.
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
\dir
 | 
			
		||||
\brief Source code for the TF-M core.
 | 
			
		||||
\details This directory holds the source code of the "TF-M core" module.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
| 
						 | 
				
			
			@ -1,66 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_ARCH_V8M_H__
 | 
			
		||||
#define __TFM_ARCH_V8M_H__
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
 | 
			
		||||
#define XPSR_T32            0x01000000
 | 
			
		||||
#define LR_UNPRIVILEGED     0xfffffffd
 | 
			
		||||
 | 
			
		||||
/* This header file collects the ARCH related operations. */
 | 
			
		||||
struct tfm_state_context_base {
 | 
			
		||||
    uint32_t    r0;
 | 
			
		||||
    uint32_t    r1;
 | 
			
		||||
    uint32_t    r2;
 | 
			
		||||
    uint32_t    r3;
 | 
			
		||||
    uint32_t    r12;
 | 
			
		||||
    uint32_t    ra_lr;
 | 
			
		||||
    uint32_t    ra;
 | 
			
		||||
    uint32_t    xpsr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tfm_state_context_ext {
 | 
			
		||||
    uint32_t    r4;
 | 
			
		||||
    uint32_t    r5;
 | 
			
		||||
    uint32_t    r6;
 | 
			
		||||
    uint32_t    r7;
 | 
			
		||||
    uint32_t    r8;
 | 
			
		||||
    uint32_t    r9;
 | 
			
		||||
    uint32_t    r10;
 | 
			
		||||
    uint32_t    r11;
 | 
			
		||||
    uint32_t    sp;
 | 
			
		||||
    uint32_t    sp_limit;
 | 
			
		||||
    uint32_t    dummy;
 | 
			
		||||
    uint32_t    lr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tfm_state_context {
 | 
			
		||||
    struct tfm_state_context_ext     ctxb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define TFM_STATE_1ST_ARG(ctx)     \
 | 
			
		||||
                    (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r0)
 | 
			
		||||
#define TFM_STATE_2ND_ARG(ctx)     \
 | 
			
		||||
                    (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r1)
 | 
			
		||||
#define TFM_STATE_3RD_ARG(ctx)     \
 | 
			
		||||
                    (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r2)
 | 
			
		||||
#define TFM_STATE_4TH_ARG(ctx)     \
 | 
			
		||||
                    (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r3)
 | 
			
		||||
#define TFM_STATE_RET_VAL(ctx)     \
 | 
			
		||||
                    (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r0)
 | 
			
		||||
 | 
			
		||||
__STATIC_INLINE void tfm_trigger_pendsv(void)
 | 
			
		||||
{
 | 
			
		||||
    SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_initialize_context(struct tfm_state_context *ctx,
 | 
			
		||||
                            uint32_t r0, uint32_t ra,
 | 
			
		||||
                            uint32_t sp, uint32_t sp_limit);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_INTERNAL_DEFINES_H__
 | 
			
		||||
#define __TFM_INTERNAL_DEFINES_H__
 | 
			
		||||
 | 
			
		||||
/* IPC internal return status */
 | 
			
		||||
#define IPC_SUCCESS                     0
 | 
			
		||||
#define IPC_ERROR_BAD_PARAMETERS        (INT32_MIN)
 | 
			
		||||
#define IPC_ERROR_SHORT_BUFFER          (INT32_MIN + 1)
 | 
			
		||||
#define IPC_ERROR_VERSION               (INT32_MIN + 2)
 | 
			
		||||
#define IPC_ERROR_MEMORY_CHECK          (INT32_MIN + 3)
 | 
			
		||||
#define IPC_ERROR_GENERIC               (INT32_MIN + 0x1F)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,98 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_LIST_H__
 | 
			
		||||
#define __TFM_LIST_H__
 | 
			
		||||
 | 
			
		||||
/* List structure */
 | 
			
		||||
struct tfm_list_node_t {
 | 
			
		||||
    struct tfm_list_node_t *prev;
 | 
			
		||||
    struct tfm_list_node_t *next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Initialize list head.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] head              List head need to be initialized.
 | 
			
		||||
 */
 | 
			
		||||
__STATIC_INLINE void tfm_list_init(struct tfm_list_node_t *head)
 | 
			
		||||
{
 | 
			
		||||
    head->next = head;
 | 
			
		||||
    head->prev = head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Add one node to list tail.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] head              List head initialized by \ref tfm_list_init.
 | 
			
		||||
 * \param[in] node              List node want to be added.
 | 
			
		||||
 */
 | 
			
		||||
__STATIC_INLINE void
 | 
			
		||||
tfm_list_add_tail(struct tfm_list_node_t *head, struct tfm_list_node_t *node)
 | 
			
		||||
{
 | 
			
		||||
    head->prev->next = node;
 | 
			
		||||
    node->prev = head->prev;
 | 
			
		||||
    head->prev = node;
 | 
			
		||||
    node->next = head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Check if a list is empty.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] head              List head initialized by \ref tfm_list_init.
 | 
			
		||||
 *
 | 
			
		||||
 * \returns                     returns 1 for empty, or 0 for not.
 | 
			
		||||
 */
 | 
			
		||||
__STATIC_INLINE int32_t tfm_list_is_empty(struct tfm_list_node_t *head)
 | 
			
		||||
{
 | 
			
		||||
    return (head->next == head);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Insert one node to list head.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] head              List head initialized by \ref tfm_list_init.
 | 
			
		||||
 * \param[in] node              List node want to be inserted.
 | 
			
		||||
 */
 | 
			
		||||
__STATIC_INLINE void
 | 
			
		||||
tfm_list_insert_first(struct tfm_list_node_t *head,
 | 
			
		||||
                      struct tfm_list_node_t *node)
 | 
			
		||||
{
 | 
			
		||||
    node->next = head->next;
 | 
			
		||||
    node->prev = head;
 | 
			
		||||
    head->next->prev = node;
 | 
			
		||||
    head->next = node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Retrieve the fist node from list.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] head              List head initialized by \ref tfm_list_init.
 | 
			
		||||
 *
 | 
			
		||||
 *  \returns                    Returns the pointer to first list node.
 | 
			
		||||
 */
 | 
			
		||||
__STATIC_INLINE
 | 
			
		||||
struct tfm_list_node_t *tfm_list_first_node(struct tfm_list_node_t *head)
 | 
			
		||||
{
 | 
			
		||||
    return head->next;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Delete one node from list.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] node              List node want to be deleted.
 | 
			
		||||
 */
 | 
			
		||||
__STATIC_INLINE void tfm_list_del_node(struct tfm_list_node_t *node)
 | 
			
		||||
{
 | 
			
		||||
    node->prev->next = node->next;
 | 
			
		||||
    node->next->prev = node->prev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Go through each node of a list */
 | 
			
		||||
#define TFM_LIST_FOR_EACH(node, head) \
 | 
			
		||||
    for (node = (head)->next; node != head; node = node->next)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,68 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_MESSAGE_QUEUE_H__
 | 
			
		||||
#define __TFM_MESSAGE_QUEUE_H__
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_MSG_QUEUE_MAX_MSG_NUM
 | 
			
		||||
#define TFM_MSG_QUEUE_MAX_MSG_NUM   128
 | 
			
		||||
#endif
 | 
			
		||||
#define TFM_MSG_MAGIC               0x15154343
 | 
			
		||||
/* Message struct to collect parameter from client */
 | 
			
		||||
struct tfm_msg_body_t {
 | 
			
		||||
    int32_t magic;
 | 
			
		||||
    struct tfm_spm_service_t *service; /* RoT service pointer           */
 | 
			
		||||
    psa_handle_t handle;            /* Connected Service handle         */
 | 
			
		||||
    struct tfm_event_t ack_evnt;    /* Event for ack reponse            */
 | 
			
		||||
    psa_msg_t msg;                  /* PSA message body                 */
 | 
			
		||||
    psa_invec invec[PSA_MAX_IOVEC]; /* Put in/out vectors in msg body   */
 | 
			
		||||
    psa_outvec outvec[PSA_MAX_IOVEC];
 | 
			
		||||
    psa_outvec *caller_outvec;      /*
 | 
			
		||||
                                     * Save caller outvec pointer for
 | 
			
		||||
                                     * write length update
 | 
			
		||||
                                     */
 | 
			
		||||
    struct tfm_msg_body_t *next;    /* List operators                   */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tfm_msg_queue_t {
 | 
			
		||||
    struct tfm_msg_body_t *head;    /* Queue head                       */
 | 
			
		||||
    struct tfm_msg_body_t *tail;    /* Queue tail                       */
 | 
			
		||||
    uint32_t size;                  /* Number of the queue member       */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Enqueue a message into message queue.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] queue             Message queue, it will be initialized
 | 
			
		||||
 *                              if has not been initialized.
 | 
			
		||||
 * \param[in] node              Message queue node want to be enqueue.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval IPC_SUCCESS          Success.
 | 
			
		||||
 * \retval IPC_ERROR_BAD_PARAMETERS Parameters error.
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_msg_enqueue(struct tfm_msg_queue_t *queue,
 | 
			
		||||
                        struct tfm_msg_body_t *node);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Dequeue a message from message queue.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] queue             Message queue.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval node pointer         Success.
 | 
			
		||||
 * \retval NULL                 Queue is NULL or size is zero.
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_msg_body_t *tfm_msg_dequeue(struct tfm_msg_queue_t *queue);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Check if a message queue is empty.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] queue             Message queue.
 | 
			
		||||
 *
 | 
			
		||||
 * \returns                     Returns 1 for empty, or 0 for not.
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_msg_queue_is_empty(struct tfm_msg_queue_t *queue);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,85 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_POOLS_H__
 | 
			
		||||
#define __TFM_POOLS_H__
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Resource pool - few known size resources allocation/free is required,
 | 
			
		||||
 * so pool is more applicable than heap.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Pool Instance:
 | 
			
		||||
 *  [ Pool Instance ] + N * [ Pool Chunks ]
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_pool_chunk_t {
 | 
			
		||||
    struct tfm_list_node_t list;        /* Chunk list                  */
 | 
			
		||||
    void *pool;                         /* Point to the parent pool    */
 | 
			
		||||
    uint8_t data[0];                    /* Data indicator              */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tfm_pool_instance_t {
 | 
			
		||||
    size_t chunksz;                     /* Chunks size of pool member   */
 | 
			
		||||
    struct tfm_list_node_t chunks_list; /* Chunk list head in pool      */
 | 
			
		||||
    struct tfm_pool_chunk_t chunks[0];  /* Data indicator               */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This will declares a static memory pool variable with chunk memory.
 | 
			
		||||
 * Parameters:
 | 
			
		||||
 *  name        -   Variable name, will be used when register
 | 
			
		||||
 *  chunksz     -   chunk size in bytes
 | 
			
		||||
 *  num         -   Number of chunks
 | 
			
		||||
 */
 | 
			
		||||
#define TFM_POOL_DECLARE(name, chunksz, num)                                \
 | 
			
		||||
    static uint8_t name##_pool_buf[((chunksz) +                             \
 | 
			
		||||
                                   sizeof(struct tfm_pool_chunk_t)) * (num) \
 | 
			
		||||
                                   + sizeof(struct tfm_pool_instance_t)]    \
 | 
			
		||||
                                   __attribute__((aligned(4)));            \
 | 
			
		||||
    static struct tfm_pool_instance_t *name =                               \
 | 
			
		||||
                            (struct tfm_pool_instance_t *)name##_pool_buf
 | 
			
		||||
 | 
			
		||||
/* Get the head size of memory pool */
 | 
			
		||||
#define POOL_HEAD_SIZE (sizeof(struct tfm_pool_instance_t) +                \
 | 
			
		||||
                        sizeof(struct tfm_pool_chunk_t))
 | 
			
		||||
 | 
			
		||||
/* Get the whole size of memory pool */
 | 
			
		||||
#define POOL_BUFFER_SIZE(name)          sizeof(name##_pool_buf)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Register a memory pool.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] pool              Pointer to memory pool declared by
 | 
			
		||||
 *                              \ref TFM_POOL_DECLARE
 | 
			
		||||
 * \param[in] poolsz             Size of the pool buffer.
 | 
			
		||||
 * \param[in] chunksz           Size of chunks.
 | 
			
		||||
 * \param[in] num               Number of chunks.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval IPC_SUCCESS          Success.
 | 
			
		||||
 * \retval IPC_ERROR_BAD_PARAMETERS Parameters error.
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
 | 
			
		||||
                      size_t chunksz, size_t num);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Allocate a memory from pool.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] pool              pool pointer decleared by \ref TFM_POOL_DECLARE
 | 
			
		||||
 *
 | 
			
		||||
 * \retval buffer pointer       Success.
 | 
			
		||||
 * \retval NULL                 Failed.
 | 
			
		||||
 */
 | 
			
		||||
void *tfm_pool_alloc(struct tfm_pool_instance_t *pool);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Free the allocated memory.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] ptr               Buffer pointer want to free.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_pool_free(void *ptr);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,326 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_SPM_H__
 | 
			
		||||
#define __TFM_SPM_H__
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "tfm_list.h"
 | 
			
		||||
#include "tfm_secure_api.h"
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_SPM_MAX_ROT_SERV_NUM
 | 
			
		||||
#define TFM_SPM_MAX_ROT_SERV_NUM        28
 | 
			
		||||
#endif
 | 
			
		||||
#define TFM_VERSION_POLICY_RELAXED      0
 | 
			
		||||
#define TFM_VERSION_POLICY_STRICT       1
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_CONN_HANDLE_MAX_NUM
 | 
			
		||||
#define TFM_CONN_HANDLE_MAX_NUM         32
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* RoT connection handle list */
 | 
			
		||||
struct tfm_conn_handle_t {
 | 
			
		||||
    psa_handle_t handle;            /* Handle value                         */
 | 
			
		||||
    void *rhandle;                  /* Reverse handle value                 */
 | 
			
		||||
    struct tfm_list_node_t list;    /* list node                            */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Service database defined by manifest */
 | 
			
		||||
struct tfm_spm_service_db_t {
 | 
			
		||||
    char *name;                     /* Service name                          */
 | 
			
		||||
    uint32_t partition_id;          /* Partition ID which service belong to  */
 | 
			
		||||
    psa_signal_t signal;            /* Service signal                        */
 | 
			
		||||
    uint32_t sid;                   /* Service identifier                    */
 | 
			
		||||
    bool non_secure_client;         /* If can be called by non secure client */
 | 
			
		||||
    uint32_t minor_version;         /* Minor version                         */
 | 
			
		||||
    uint32_t minor_policy;          /* Minor version policy                  */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* RoT Service data */
 | 
			
		||||
struct tfm_spm_service_t {
 | 
			
		||||
    struct tfm_spm_service_db_t *service_db; /* Service database pointer     */
 | 
			
		||||
    struct tfm_spm_ipc_partition_t *partition; /*
 | 
			
		||||
                                                * Point to secure partition
 | 
			
		||||
                                                * data
 | 
			
		||||
                                                */
 | 
			
		||||
    struct tfm_list_node_t handle_list;    /* Service handle list            */
 | 
			
		||||
    struct tfm_msg_queue_t msg_queue;      /* Message queue                  */
 | 
			
		||||
    struct tfm_list_node_t list;           /* For list operation             */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FixMe: This structure is for IPC partition which is different with library
 | 
			
		||||
 * mode partition. There needs to be an alignment for IPC partition database
 | 
			
		||||
 * and library mode database.
 | 
			
		||||
 */
 | 
			
		||||
/* Secure Partition data */
 | 
			
		||||
struct tfm_spm_ipc_partition_t {
 | 
			
		||||
    int32_t index;                      /* Partition index                   */
 | 
			
		||||
    int32_t id;                         /* Secure partition ID               */
 | 
			
		||||
    struct tfm_event_t signal_evnt;     /* Event signal                      */
 | 
			
		||||
    uint32_t signals;                   /* Service signals had been triggered*/
 | 
			
		||||
    uint32_t signal_mask;        /* Service signal mask passed by psa_wait() */
 | 
			
		||||
    struct tfm_list_node_t service_list;/* Service list                      */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*************************** Extended SPM functions **************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief   Get the running partition ID.
 | 
			
		||||
 *
 | 
			
		||||
 * \return  Returns the partition ID
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_running_partition_id_ext(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Get the current partition mode.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx                 Index of current partition
 | 
			
		||||
 *
 | 
			
		||||
 * \retval TFM_PARTITION_PRIVILEGED_MODE    Privileged mode
 | 
			
		||||
 * \retval TFM_PARTITION_UNPRIVILEGED_MODE  Unprivileged mode
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/******************** Service handle management functions ********************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Create connection handle for client connect
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] service       Target service context pointer
 | 
			
		||||
 *
 | 
			
		||||
 * \retval PSA_NULL_HANDLE  Create failed \ref PSA_NULL_HANDLE
 | 
			
		||||
 * \retval >0               Service handle created, \ref psa_handle_t
 | 
			
		||||
 */
 | 
			
		||||
psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Free connection handle which not used anymore.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] service       Target service context pointer
 | 
			
		||||
 * \param[in] conn_handle   Connection handle created by
 | 
			
		||||
 *                          tfm_spm_create_conn_handle(), \ref psa_handle_t
 | 
			
		||||
 *
 | 
			
		||||
 * \retval IPC_SUCCESS      Success
 | 
			
		||||
 * \retval IPC_ERROR_BAD_PARAMETERS  Bad parameters input
 | 
			
		||||
 * \retval "Does not return"  Panic for not find service by handle
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
 | 
			
		||||
                                 psa_handle_t conn_handle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Set reverse handle value for connection.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] service       Target service context pointer
 | 
			
		||||
 * \param[in] conn_handle   Connection handle created by
 | 
			
		||||
 *                          tfm_spm_create_conn_handle(), \ref psa_handle_t
 | 
			
		||||
 * \param[in] rhandle       rhandle need to save
 | 
			
		||||
 *
 | 
			
		||||
 * \retval IPC_SUCCESS      Success
 | 
			
		||||
 * \retval IPC_ERROR_BAD_PARAMETERS  Bad parameters input
 | 
			
		||||
 * \retval "Does not return"  Panic for not find handle node
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
 | 
			
		||||
                            psa_handle_t conn_handle,
 | 
			
		||||
                            void *rhandle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Get reverse handle value from connection hanlde.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] service       Target service context pointer
 | 
			
		||||
 * \param[in] conn_handle   Connection handle created by
 | 
			
		||||
 *                          tfm_spm_create_conn_handle(), \ref psa_handle_t
 | 
			
		||||
 *
 | 
			
		||||
 * \retval void *           Success
 | 
			
		||||
 * \retval "Does not return"  Panic for those:
 | 
			
		||||
 *                              service pointer are NULL
 | 
			
		||||
 *                              hanlde is \ref PSA_NULL_HANDLE
 | 
			
		||||
 *                              handle node does not be found
 | 
			
		||||
 */
 | 
			
		||||
void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
 | 
			
		||||
                          psa_handle_t conn_handle);
 | 
			
		||||
 | 
			
		||||
/******************** Partition management functions *************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Get current running partition context.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval NULL             Failed
 | 
			
		||||
 * \retval "Not NULL"       Return the parttion context pointer
 | 
			
		||||
 *                          \ref spm_partition_t structures
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_spm_ipc_partition_t *tfm_spm_get_running_partition(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Get the service context by signal.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition     Partition context pointer
 | 
			
		||||
 *                          \ref spm_partition_t structures
 | 
			
		||||
 * \param[in] signal        Signal associated with inputs to the Secure
 | 
			
		||||
 *                          Partition, \ref psa_signal_t
 | 
			
		||||
 *
 | 
			
		||||
 * \retval NULL             Failed
 | 
			
		||||
 * \retval "Not NULL"       Target service context pointer,
 | 
			
		||||
 *                          \ref spm_service_t structures
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_spm_service_t *
 | 
			
		||||
tfm_spm_get_service_by_signal(struct tfm_spm_ipc_partition_t *partition,
 | 
			
		||||
                              psa_signal_t signal);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Get the service context by service ID.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] sid           RoT Service identity
 | 
			
		||||
 *
 | 
			
		||||
 * \retval NULL             Failed
 | 
			
		||||
 * \retval "Not NULL"       Target service context pointer,
 | 
			
		||||
 *                          \ref spm_service_t structures
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Get the service context by connection handle.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] conn_handle   Connection handle created by
 | 
			
		||||
 *                          tfm_spm_create_conn_handle()
 | 
			
		||||
 *
 | 
			
		||||
 * \retval NULL             Failed
 | 
			
		||||
 * \retval "Not NULL"       Target service context pointer,
 | 
			
		||||
 *                          \ref spm_service_t structures
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_spm_service_t *
 | 
			
		||||
        tfm_spm_get_service_by_handle(psa_handle_t conn_handle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Get the partition context by partition ID.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_id  Partition identity
 | 
			
		||||
 *
 | 
			
		||||
 * \retval NULL             Failed
 | 
			
		||||
 * \retval "Not NULL"       Target partition context pointer,
 | 
			
		||||
 *                          \ref spm_partition_t structures
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_spm_ipc_partition_t *
 | 
			
		||||
    tfm_spm_get_partition_by_id(int32_t partition_id);
 | 
			
		||||
 | 
			
		||||
/************************ Message functions **********************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  \brief                  Get message context by message handle.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] msg_handle    Message handle which is a reference generated
 | 
			
		||||
 *                          by the SPM to a specific message.
 | 
			
		||||
 *
 | 
			
		||||
 * \return                  The message body context pointer
 | 
			
		||||
 *                          \ref msg_body_t structures
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Create a message for PSA client call.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] service       Target service context pointer, which can be
 | 
			
		||||
 *                          obtained by partition management functions
 | 
			
		||||
 * \prarm[in] handle        Connect handle return by psa_connect(). Should
 | 
			
		||||
 *                          be \ref PSA_NULL_HANDLE in psa_connect().
 | 
			
		||||
 * \param[in] type          Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
 | 
			
		||||
 *                          PSA_IPC_DISCONNECT
 | 
			
		||||
 * \param[in] ns_caller     Whether from NS caller
 | 
			
		||||
 * \param[in] invec         Array of input \ref psa_invec structures
 | 
			
		||||
 * \param[in] in_len        Number of input \ref psa_invec structures
 | 
			
		||||
 * \param[in] outvec        Array of output \ref psa_outvec structures
 | 
			
		||||
 * \param[in] out_len       Number of output \ref psa_outvec structures
 | 
			
		||||
 * \param[in] caller_outvec Array of caller output \ref psa_outvec structures
 | 
			
		||||
 *
 | 
			
		||||
 * \retval NULL             Failed
 | 
			
		||||
 * \retval "Not NULL"       New message body pointer \ref msg_body_t structures
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
 | 
			
		||||
                                          psa_handle_t handle,
 | 
			
		||||
                                          uint32_t type, int32_t ns_caller,
 | 
			
		||||
                                          psa_invec *invec, size_t in_len,
 | 
			
		||||
                                          psa_outvec *outvec, size_t out_len,
 | 
			
		||||
                                          psa_outvec *caller_outvec);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Free message which unused anymore
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] msg           Message pointer which want to free
 | 
			
		||||
 *                          \ref msg_body_t structures
 | 
			
		||||
 *
 | 
			
		||||
 * \retval void             Success
 | 
			
		||||
 * \retval "Does not return" Failed
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_free_msg(struct tfm_msg_body_t *msg);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Send message and wake up the SP who is waiting on
 | 
			
		||||
 *                          message queue, block the current thread and
 | 
			
		||||
 *                          scheduler triggered
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] service       Target service context pointer, which can be
 | 
			
		||||
 *                          obtained by partition management functions
 | 
			
		||||
 * \param[in] msg           message created by spm_create_msg()
 | 
			
		||||
 *                          \ref msg_body_t structures
 | 
			
		||||
 *
 | 
			
		||||
 * \retval IPC_SUCCESS      Success
 | 
			
		||||
 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
 | 
			
		||||
 * \retval IPC_ERROR_GENERIC Failed to enqueue message to service message queue
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
 | 
			
		||||
                           struct tfm_msg_body_t *msg);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                   Check the client minor version according to
 | 
			
		||||
 *                          version policy
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] service       Target service context pointer, which can be get
 | 
			
		||||
 *                          by partition management functions
 | 
			
		||||
 * \param[in] minor_version Client support minor version
 | 
			
		||||
 *
 | 
			
		||||
 * \retval IPC_SUCCESS      Success
 | 
			
		||||
 * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
 | 
			
		||||
 * \retval IPC_ERROR_VERSION Check failed
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
 | 
			
		||||
                                     uint32_t minor_version);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief                      Check the memory reference is valid.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] buffer           Pointer of memory reference
 | 
			
		||||
 * \param[in] len              Length of memory reference in bytes
 | 
			
		||||
 * \param[in] ns_caller        From non-secure caller
 | 
			
		||||
 * \param[in] access           Type of access specified by the
 | 
			
		||||
 *                             \ref tfm_memory_access_e
 | 
			
		||||
 * \param[in] privileged       Privileged mode or unprivileged mode:
 | 
			
		||||
 *                             \ref TFM_PARTITION_UNPRIVILEGED_MODE
 | 
			
		||||
 *                             \ref TFM_PARTITION_PRIVILEGED_MODE
 | 
			
		||||
 *
 | 
			
		||||
 * \retval IPC_SUCCESS               Success
 | 
			
		||||
 * \retval IPC_ERROR_BAD_PARAMETERS  Bad parameters input
 | 
			
		||||
 * \retval IPC_ERROR_MEMORY_CHECK    Check failed
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
 | 
			
		||||
                         enum tfm_memory_access_e access,
 | 
			
		||||
                         uint32_t privileged);
 | 
			
		||||
 | 
			
		||||
/* This function should be called before schedule function */
 | 
			
		||||
void tfm_spm_init(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * PendSV specified function.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  ctxb        -    State context storage pointer
 | 
			
		||||
 *
 | 
			
		||||
 * Notes:
 | 
			
		||||
 *  This is a staging API. Scheduler should be called in SPM finally and
 | 
			
		||||
 *  this function will be obsoleted later.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,108 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_SVCALLS_H__
 | 
			
		||||
#define __TFM_SVCALLS_H__
 | 
			
		||||
 | 
			
		||||
/* Svcall for PSA Client APIs */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief SVC handler for \ref psa_framework_version.
 | 
			
		||||
 *
 | 
			
		||||
 * \return version              The version of the PSA Framework implementation
 | 
			
		||||
 *                              that is providing the runtime services to the
 | 
			
		||||
 *                              caller.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_svcall_psa_framework_version(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief SVC handler for \ref psa_version.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] args              Include all input arguments: sid.
 | 
			
		||||
 * \param[in] ns_caller         If 'non-zero', call from non-secure client.
 | 
			
		||||
 *                              Or from secure client.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval PSA_VERSION_NONE     The RoT Service is not implemented, or the
 | 
			
		||||
 *                              caller is not permitted to access the service.
 | 
			
		||||
 * \retval > 0                  The minor version of the implemented RoT
 | 
			
		||||
 *                              Service.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_svcall_psa_version(uint32_t *args, int32_t ns_caller);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief SVC handler for \ref psa_connect.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] args              Include all input arguments:
 | 
			
		||||
 *                              sid, minor_version.
 | 
			
		||||
 * \param[in] ns_caller         If 'non-zero', call from non-secure client.
 | 
			
		||||
 *                              Or from secure client.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval > 0                  A handle for the connection.
 | 
			
		||||
 * \retval PSA_CONNECTION_REFUSED The SPM or RoT Service has refused the
 | 
			
		||||
 *                              connection.
 | 
			
		||||
 * \retval PSA_CONNECTION_BUSY  The SPM or RoT Service cannot make the
 | 
			
		||||
 *                              connection at the moment.
 | 
			
		||||
 * \retval "Does not return"    The RoT Service ID and version are not
 | 
			
		||||
 *                              supported, or the caller is not permitted to
 | 
			
		||||
 *                              access the service.
 | 
			
		||||
 */
 | 
			
		||||
psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief SVC handler for \ref psa_call.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] args              Include all input arguments:
 | 
			
		||||
 *                              handle, in_vec, in_len, out_vec, out_len.
 | 
			
		||||
 * \param[in] ns_caller         If 'non-zero', call from non-secure client.
 | 
			
		||||
 *                              Or from secure client.
 | 
			
		||||
 * \param[in] lr                EXC_RETURN value of the SVC.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval >=0                  RoT Service-specific status value.
 | 
			
		||||
 * \retval <0                   RoT Service-specific error code.
 | 
			
		||||
 * \retval PSA_DROP_CONNECTION  The connection has been dropped by the RoT
 | 
			
		||||
 *                              Service. This indicates that either this or
 | 
			
		||||
 *                              a previous message was invalid.
 | 
			
		||||
 * \retval "Does not return"    The call is invalid, one or more of the
 | 
			
		||||
 *                              following are true:
 | 
			
		||||
 * \arg                           An invalid handle was passed.
 | 
			
		||||
 * \arg                           The connection is already handling a request.
 | 
			
		||||
 * \arg                           An invalid memory reference was provided.
 | 
			
		||||
 * \arg                           in_len + out_len > PSA_MAX_IOVEC.
 | 
			
		||||
 * \arg                           The message is unrecognized by the RoT
 | 
			
		||||
 *                                Service or incorrectly formatted.
 | 
			
		||||
 */
 | 
			
		||||
psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller,
 | 
			
		||||
                                 uint32_t lr);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief SVC handler for \ref psa_close.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] args              Include all input arguments: handle.
 | 
			
		||||
 * \param[in] ns_caller         If 'non-zero', call from non-secure client.
 | 
			
		||||
 *                              Or from secure client.
 | 
			
		||||
 *
 | 
			
		||||
 * \retval void                 Success.
 | 
			
		||||
 * \retval "Does not return"    The call is invalid, one or more of the
 | 
			
		||||
 *                              following are true:
 | 
			
		||||
 * \arg                           An invalid handle was provided that is not
 | 
			
		||||
 *                                the null handle.
 | 
			
		||||
 * \arg                           The connection is handling a request.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_svcall_psa_close(uint32_t *args, int32_t ns_caller);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief SVC handler for IPC functions
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] svc_num           SVC number
 | 
			
		||||
 * \param[in] ctx               Argument context
 | 
			
		||||
 * \param[in] lr                EXC_RETURN value of the SVC.
 | 
			
		||||
 *
 | 
			
		||||
 * \returns                     Return values from those who has,
 | 
			
		||||
 *                              or PSA_SUCCESS.
 | 
			
		||||
 */
 | 
			
		||||
int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx, uint32_t lr);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,232 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_THREAD_H__
 | 
			
		||||
#define __TFM_THREAD_H__
 | 
			
		||||
 | 
			
		||||
#include "tfm_arch_v8m.h"
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
 | 
			
		||||
/* Status code */
 | 
			
		||||
#define THRD_STAT_CREATING        0
 | 
			
		||||
#define THRD_STAT_RUNNING         1
 | 
			
		||||
#define THRD_STAT_BLOCK           2
 | 
			
		||||
#define THRD_STAT_DETACH          3
 | 
			
		||||
#define THRD_STAT_INVALID         4
 | 
			
		||||
 | 
			
		||||
/* Security attribute - default as security */
 | 
			
		||||
#define THRD_ATTR_SECURE_OFFSET   16
 | 
			
		||||
#define THRD_ATTR_SECURE          (0)
 | 
			
		||||
#define THRD_ATTR_NON_SECURE      (1 << THRD_ATTR_SECURE_OFFSET)
 | 
			
		||||
 | 
			
		||||
/* Lower value has higher priority */
 | 
			
		||||
#define THRD_PRIOR_MASK           0xFF
 | 
			
		||||
#define THRD_PRIOR_HIGHEST        0x0
 | 
			
		||||
#define THRD_PRIOR_MEDIUM         0x7F
 | 
			
		||||
#define THRD_PRIOR_LOWEST         0xFF
 | 
			
		||||
 | 
			
		||||
/* Error code */
 | 
			
		||||
#define THRD_SUCCESS              0
 | 
			
		||||
#define THRD_ERR_INVALID_PARAM    1
 | 
			
		||||
 | 
			
		||||
/* Thread entry function type */
 | 
			
		||||
typedef void *(*tfm_thrd_func_t)(void *);
 | 
			
		||||
 | 
			
		||||
/* Thread context */
 | 
			
		||||
struct tfm_thrd_ctx {
 | 
			
		||||
    tfm_thrd_func_t pfn;          /* entry function      */
 | 
			
		||||
    void            *param;       /* entry parameter     */
 | 
			
		||||
    uint8_t         *sp_base;     /* stack bottom        */
 | 
			
		||||
    uint8_t         *sp_top;      /* stack top           */
 | 
			
		||||
    uint32_t        prior;        /* priority            */
 | 
			
		||||
    uint32_t        status;       /* status              */
 | 
			
		||||
 | 
			
		||||
    struct tfm_state_context state_ctx; /* State context */
 | 
			
		||||
    struct tfm_thrd_ctx *next;    /* next thread in list */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialize a thread context with the necessary info.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pth         -    pointer of caller provided thread context
 | 
			
		||||
 *  pfn         -    thread entry function
 | 
			
		||||
 *  param       -    thread entry function parameter
 | 
			
		||||
 *  sp_base     -    stack pointer base (higher address)
 | 
			
		||||
 *  sp_top      -    stack pointer top (lower address)
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  Thread contex rely on caller allocated memory; initialize members in
 | 
			
		||||
 *  context. This function does not insert thread into schedulable list.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_thrd_init(struct tfm_thrd_ctx *pth,
 | 
			
		||||
                   tfm_thrd_func_t pfn, void *param,
 | 
			
		||||
                   uint8_t *sp_base, uint8_t *sp_top);
 | 
			
		||||
 | 
			
		||||
/* Set thread priority.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pth         -     pointer of thread context
 | 
			
		||||
 *  prior       -     priority value (0~255)
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  Set thread priority. Priority is set to THRD_PRIOR_MEDIUM in
 | 
			
		||||
 *  tfm_thrd_init().
 | 
			
		||||
 */
 | 
			
		||||
void __STATIC_INLINE tfm_thrd_priority(struct tfm_thrd_ctx *pth,
 | 
			
		||||
                                       uint32_t prior)
 | 
			
		||||
{
 | 
			
		||||
    pth->prior &= ~THRD_PRIOR_MASK;
 | 
			
		||||
    pth->prior |= prior & THRD_PRIOR_MASK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set thread security attribute.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pth         -     pointer of thread context
 | 
			
		||||
 *  attr_secure -     THRD_ATTR_SECURE or THRD_ATTR_NON_SECURE
 | 
			
		||||
 *
 | 
			
		||||
 * Notes
 | 
			
		||||
 *  Reuse prior of thread context to shift down non-secure thread priority.
 | 
			
		||||
 */
 | 
			
		||||
void __STATIC_INLINE tfm_thrd_secure(struct tfm_thrd_ctx *pth,
 | 
			
		||||
                                     uint32_t attr_secure)
 | 
			
		||||
{
 | 
			
		||||
    pth->prior &= ~THRD_ATTR_NON_SECURE;
 | 
			
		||||
    pth->prior |= attr_secure;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set thread status.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pth         -     pointer of thread context
 | 
			
		||||
 *  new_status  -     new status of thread
 | 
			
		||||
 *
 | 
			
		||||
 * Return :
 | 
			
		||||
 *  None
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  Thread status is not changed if invalid status value inputed.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get thread status.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pth         -     pointer of thread context
 | 
			
		||||
 *
 | 
			
		||||
 * Return :
 | 
			
		||||
 *  Status of thread
 | 
			
		||||
 */
 | 
			
		||||
uint32_t __STATIC_INLINE tfm_thrd_get_status(struct tfm_thrd_ctx *pth)
 | 
			
		||||
{
 | 
			
		||||
    return pth->status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set thread state return value.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pth         -     pointer of thread context
 | 
			
		||||
 *  retval      -     return value to be set for thread state
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  This API is useful for blocked syscall blocking thread. Syscall
 | 
			
		||||
 *  could set its return value to the caller before caller goes.
 | 
			
		||||
 */
 | 
			
		||||
void __STATIC_INLINE tfm_thrd_set_retval(struct tfm_thrd_ctx *pth,
 | 
			
		||||
                                         uint32_t retval)
 | 
			
		||||
{
 | 
			
		||||
    TFM_STATE_RET_VAL(&pth->state_ctx) = retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Validate thread context and insert it into schedulable list.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pth         -     pointer of thread context
 | 
			
		||||
 *
 | 
			
		||||
 * Return :
 | 
			
		||||
 *  THRD_SUCCESS for success. Or an error is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  This function validates thread info. It returns error if thread info
 | 
			
		||||
 *  is not correct. Thread is avaliable after successful tfm_thrd_start().
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_thrd_start(struct tfm_thrd_ctx *pth);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get current running thread.
 | 
			
		||||
 *
 | 
			
		||||
 * Return :
 | 
			
		||||
 *  Current running thread context pointer.
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_thrd_ctx *tfm_thrd_curr_thread(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get next running thread in list.
 | 
			
		||||
 *
 | 
			
		||||
 * Return :
 | 
			
		||||
 *  Pointer of next thread to be run.
 | 
			
		||||
 */
 | 
			
		||||
struct tfm_thrd_ctx *tfm_thrd_next_thread(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Start scheduler for existing threads
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters:
 | 
			
		||||
 *  pth         -     pointer of the caller context collecting thread
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  This function should be called only ONCE to start the scheduler.
 | 
			
		||||
 *  Caller needs to provide a thread object to collect current context.
 | 
			
		||||
 *  The usage of the collected context is caller defined.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_thrd_start_scheduler(struct tfm_thrd_ctx *pth);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Activate a scheduling action after exception.
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  This function could be called multiple times before scheduling.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_thrd_activate_schedule(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Save current context into 'prev' thread and switch to 'next'.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  ctxb        -     latest caller context
 | 
			
		||||
 *  prev        -     previous thread to be switched out
 | 
			
		||||
 *  next        -     thread to be run
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  This function could be called multiple times before scheduling.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb,
 | 
			
		||||
                             struct tfm_thrd_ctx *prev,
 | 
			
		||||
                             struct tfm_thrd_ctx *next);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Svcall to exit current running thread.
 | 
			
		||||
 *
 | 
			
		||||
 * Notes :
 | 
			
		||||
 *  Remove current thread out of schedulable list.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_svcall_thrd_exit(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Exit current running thread for client.
 | 
			
		||||
 *
 | 
			
		||||
 * Notes:
 | 
			
		||||
 *  Must be called in thread mode.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_thrd_exit(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,29 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_UTILS_H__
 | 
			
		||||
#define __TFM_UTILS_H__
 | 
			
		||||
 | 
			
		||||
/* CPU spin here */
 | 
			
		||||
void tfm_panic(void);
 | 
			
		||||
 | 
			
		||||
/* Assert and spin */
 | 
			
		||||
#define TFM_ASSERT(cond)                                            \
 | 
			
		||||
            do {                                                    \
 | 
			
		||||
                if (!(cond)) {                                      \
 | 
			
		||||
                    printf("Assert:%s:%d", __FUNCTION__, __LINE__); \
 | 
			
		||||
                    while (1)                                       \
 | 
			
		||||
                        ;                                           \
 | 
			
		||||
                }                                                   \
 | 
			
		||||
            } while (0)
 | 
			
		||||
 | 
			
		||||
/* Get container structure start address from member */
 | 
			
		||||
#define TFM_GET_CONTAINER_PTR(ptr, type, member) \
 | 
			
		||||
    (type *)((unsigned long)(ptr) - offsetof(type, member))
 | 
			
		||||
 | 
			
		||||
int32_t tfm_bitcount(uint32_t n);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,55 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __TFM_WAIT_H__
 | 
			
		||||
#define __TFM_WAIT_H__
 | 
			
		||||
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
 | 
			
		||||
/* The magic number has two purposes: corruption detection and debug */
 | 
			
		||||
#define TFM_EVENT_MAGIC               0x65766e74
 | 
			
		||||
 | 
			
		||||
struct tfm_event_t {
 | 
			
		||||
    uint32_t magic;               /* 'evnt'               */
 | 
			
		||||
    struct tfm_thrd_ctx *owner;   /* Event blocked thread */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialize an event object.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters:
 | 
			
		||||
 *  pevnt      -    The pointer of event object allocated by the caller
 | 
			
		||||
 */
 | 
			
		||||
void __STATIC_INLINE tfm_event_init(struct tfm_event_t *pevnt)
 | 
			
		||||
{
 | 
			
		||||
    pevnt->magic = TFM_EVENT_MAGIC;
 | 
			
		||||
    pevnt->owner = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Wait on an event object.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters:
 | 
			
		||||
 *  pevnt      -    The pointer of event object allocated by the caller
 | 
			
		||||
 *
 | 
			
		||||
 * Notes:
 | 
			
		||||
 *  Block caller thread by calling this function.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_event_wait(struct tfm_event_t *pevnt);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Wake up an event object.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters :
 | 
			
		||||
 *  pevnt      -    The pointer of event object allocated by the caller
 | 
			
		||||
 *  retval     -    Value to be returned to owner
 | 
			
		||||
 *
 | 
			
		||||
 * Notes:
 | 
			
		||||
 *  Wake up the blocked thread and set parameter 'retval' as the return value.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,55 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
uint32_t psa_framework_version(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_FRAMEWORK_VERSION));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
uint32_t psa_version(uint32_t sid)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_VERSION));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_CONNECT));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
psa_status_t psa_call(psa_handle_t handle,
 | 
			
		||||
                      const psa_invec *in_vec,
 | 
			
		||||
                      size_t in_len,
 | 
			
		||||
                      psa_outvec *out_vec,
 | 
			
		||||
                      size_t out_len)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_CALL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
void psa_close(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_CLOSE));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,96 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
#include "psa_service.h"
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_WAIT));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_GET));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_SET_RHANDLE));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
 | 
			
		||||
                void *buffer, size_t num_bytes)
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_READ));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_SKIP));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
 | 
			
		||||
               const void *buffer, size_t num_bytes)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_WRITE));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
void psa_reply(psa_handle_t msg_handle, psa_status_t retval)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_REPLY));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
void psa_notify(int32_t partition_id)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_NOTIFY));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
void psa_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_CLEAR));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked, section("SFN")))
 | 
			
		||||
void psa_eoi(psa_signal_t irq_signal)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_PSA_EOI));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,147 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "tfm_arch_v8m.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
#include "psa_service.h"
 | 
			
		||||
#include "tfm_utils.h"
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#include "tfm_memory_utils.h"
 | 
			
		||||
 | 
			
		||||
/* This file contains the ARCH code for ARM V8M */
 | 
			
		||||
 | 
			
		||||
__attribute__((section("SFN")))
 | 
			
		||||
static void exit_zone(void)
 | 
			
		||||
{
 | 
			
		||||
    tfm_thrd_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_initialize_context(struct tfm_state_context *ctx,
 | 
			
		||||
                            uint32_t r0, uint32_t ra,
 | 
			
		||||
                            uint32_t sp, uint32_t sp_limit)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * For security consideration, set unused registers into ZERO;
 | 
			
		||||
     * and only necessary registers are set here.
 | 
			
		||||
     */
 | 
			
		||||
    struct tfm_state_context_base *p_ctxa =
 | 
			
		||||
                            (struct tfm_state_context_base *)sp;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Shift back SP to leave space for holding base context
 | 
			
		||||
     * since thread is kicked off through exception return.
 | 
			
		||||
     */
 | 
			
		||||
    p_ctxa--;
 | 
			
		||||
 | 
			
		||||
    /* Basic context is considerate at thread start.*/
 | 
			
		||||
    tfm_memset(p_ctxa, 0, sizeof(*p_ctxa));
 | 
			
		||||
    p_ctxa->r0 = r0;
 | 
			
		||||
    p_ctxa->ra = ra;
 | 
			
		||||
    p_ctxa->ra_lr = (uint32_t)exit_zone;
 | 
			
		||||
    p_ctxa->xpsr = XPSR_T32;
 | 
			
		||||
 | 
			
		||||
    tfm_memset(ctx, 0, sizeof(*ctx));
 | 
			
		||||
    ctx->ctxb.sp = (uint32_t)p_ctxa;
 | 
			
		||||
    ctx->ctxb.sp_limit = sp_limit;
 | 
			
		||||
    ctx->ctxb.lr = LR_UNPRIVILEGED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Stack status at PendSV entry:
 | 
			
		||||
 *
 | 
			
		||||
 *                                            [ R0 - R3  ]<- PSP
 | 
			
		||||
 *                                            [ R12      ]
 | 
			
		||||
 *                                            [ LR_of_RA ]
 | 
			
		||||
 *                       MSP->[ ........ ]    [ RA       ]
 | 
			
		||||
 *                            [ ........ ]    [ XPSR     ]
 | 
			
		||||
 *                                            [ ........ ]
 | 
			
		||||
 *                                            [ ........ ]
 | 
			
		||||
 *
 | 
			
		||||
 * Stack status before calling pendsv_do_schedule():
 | 
			
		||||
 *
 | 
			
		||||
 *                       MSP->[ R4 - R11 ]
 | 
			
		||||
 *                            [ PSP      ]--->[ R0 - R3  ]
 | 
			
		||||
 *                            [ PSP Limit]    [ R12      ]
 | 
			
		||||
 *                            [ R2(dummy)]    [ LR_of_RA ]
 | 
			
		||||
 *                            [ LR       ]    [ RA       ]
 | 
			
		||||
 *                            [ ........ ]    [ XPSR     ]
 | 
			
		||||
 *                            [ ........ ]    [ ........ ]
 | 
			
		||||
 *                                            [ ........ ]
 | 
			
		||||
 *
 | 
			
		||||
 * pendsv_do_schedule() updates stacked context into current thread and
 | 
			
		||||
 * replace stacked context with context of next thread.
 | 
			
		||||
 *
 | 
			
		||||
 * Scheduler does not support handler mode thread so take PSP/PSP_LIMIT as
 | 
			
		||||
 * thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
 | 
			
		||||
 * aligned.
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__ARM_ARCH_8M_MAIN__)
 | 
			
		||||
__attribute__((naked)) void PendSV_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "mrs     r0, psp                    \n"
 | 
			
		||||
        "mrs     r1, psplim                 \n"
 | 
			
		||||
        "push    {r0, r1, r2, lr}           \n"
 | 
			
		||||
        "push    {r4-r11}                   \n"
 | 
			
		||||
        "mov     r0, sp                     \n"
 | 
			
		||||
        "bl      tfm_pendsv_do_schedule     \n"
 | 
			
		||||
        "pop     {r4-r11}                   \n"
 | 
			
		||||
        "pop     {r0, r1, r2, lr}           \n"
 | 
			
		||||
        "msr     psp, r0                    \n"
 | 
			
		||||
        "msr     psplim, r1                 \n"
 | 
			
		||||
        "bx      lr                         \n"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
#elif defined(__ARM_ARCH_8M_BASE__)
 | 
			
		||||
__attribute__((naked)) void PendSV_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "mrs     r0, psp                    \n"
 | 
			
		||||
        "mrs     r1, psplim                 \n"
 | 
			
		||||
        "push    {r0, r1, r2, lr}           \n"
 | 
			
		||||
        "push    {r4-r7}                    \n"
 | 
			
		||||
        "mov     r4, r8                     \n"
 | 
			
		||||
        "mov     r5, r9                     \n"
 | 
			
		||||
        "mov     r6, r10                    \n"
 | 
			
		||||
        "mov     r7, r11                    \n"
 | 
			
		||||
        "push    {r4-r7}                    \n"
 | 
			
		||||
        "mov     r0, sp                     \n"
 | 
			
		||||
        "bl      tfm_pendsv_do_schedule     \n"
 | 
			
		||||
        "pop     {r4-r7}                    \n"
 | 
			
		||||
        "mov     r8, r4                     \n"
 | 
			
		||||
        "mov     r9, r5                     \n"
 | 
			
		||||
        "mov     r10, r6                    \n"
 | 
			
		||||
        "mov     r11, r7                    \n"
 | 
			
		||||
        "pop     {r4-r7}                    \n"
 | 
			
		||||
        "pop     {r0-r3}                    \n"
 | 
			
		||||
        "mov     lr, r3                     \n"
 | 
			
		||||
        "msr     psp, r0                    \n"
 | 
			
		||||
        "msr     psplim, r1                 \n"
 | 
			
		||||
        "bx      lr                         \n"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#error "Unsupported ARM Architecture."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Reserved for future usage */
 | 
			
		||||
__attribute__((naked)) void MemManage_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("b    .");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked)) void BusFault_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("b    .");
 | 
			
		||||
}
 | 
			
		||||
__attribute__((naked)) void UsageFault_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("b    .");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,56 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#include "tfm_wait.h"
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
#include "psa_service.h"
 | 
			
		||||
#include "tfm_internal_defines.h"
 | 
			
		||||
#include "tfm_message_queue.h"
 | 
			
		||||
 | 
			
		||||
/* Message queue process */
 | 
			
		||||
int32_t tfm_msg_enqueue(struct tfm_msg_queue_t *queue,
 | 
			
		||||
                        struct tfm_msg_body_t *node)
 | 
			
		||||
{
 | 
			
		||||
    if (!queue || !node) {
 | 
			
		||||
        return IPC_ERROR_BAD_PARAMETERS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (queue->size == 0) {
 | 
			
		||||
        queue->head = node;
 | 
			
		||||
        queue->tail = node;
 | 
			
		||||
    } else {
 | 
			
		||||
        queue->tail->next = node;
 | 
			
		||||
        queue->tail = node;
 | 
			
		||||
    }
 | 
			
		||||
    queue->size++;
 | 
			
		||||
    return IPC_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tfm_msg_body_t *tfm_msg_dequeue(struct tfm_msg_queue_t *queue)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_msg_body_t *pop_node;
 | 
			
		||||
 | 
			
		||||
    if (!queue) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (queue->size == 0) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pop_node = queue->head;
 | 
			
		||||
    queue->head = queue->head->next;
 | 
			
		||||
    queue->size--;
 | 
			
		||||
    return pop_node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_msg_queue_is_empty(struct tfm_msg_queue_t *queue)
 | 
			
		||||
{
 | 
			
		||||
    return queue->size == 0 ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,87 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#include "tfm_wait.h"
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
#include "psa_service.h"
 | 
			
		||||
#include "tfm_internal_defines.h"
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
#include "tfm_utils.h"
 | 
			
		||||
#include "tfm_list.h"
 | 
			
		||||
#include "tfm_pools.h"
 | 
			
		||||
#include "tfm_memory_utils.h"
 | 
			
		||||
 | 
			
		||||
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
 | 
			
		||||
                      size_t chunksz, size_t num)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_pool_chunk_t *pchunk;
 | 
			
		||||
    size_t i;
 | 
			
		||||
 | 
			
		||||
    if (!pool || num == 0) {
 | 
			
		||||
        return IPC_ERROR_BAD_PARAMETERS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Ensure buffer is large enough */
 | 
			
		||||
    if (poolsz != ((chunksz + sizeof(struct tfm_pool_chunk_t)) * num +
 | 
			
		||||
        sizeof(struct tfm_pool_instance_t))) {
 | 
			
		||||
        return IPC_ERROR_BAD_PARAMETERS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Buffer should be BSS cleared but clear it again */
 | 
			
		||||
    tfm_memset(pool, 0, poolsz);
 | 
			
		||||
 | 
			
		||||
    /* Chain pool chunks */
 | 
			
		||||
    tfm_list_init(&pool->chunks_list);
 | 
			
		||||
 | 
			
		||||
    pchunk = (struct tfm_pool_chunk_t *)pool->chunks;
 | 
			
		||||
    for (i = 0; i < num; i++) {
 | 
			
		||||
        pchunk->pool = pool;
 | 
			
		||||
        tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
 | 
			
		||||
        pchunk = (struct tfm_pool_chunk_t *)&pchunk->data[chunksz];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Prepare instance and insert to pool list */
 | 
			
		||||
    pool->chunksz = chunksz;
 | 
			
		||||
 | 
			
		||||
    return IPC_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *tfm_pool_alloc(struct tfm_pool_instance_t *pool)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_list_node_t *node;
 | 
			
		||||
    struct tfm_pool_chunk_t *pchunk;
 | 
			
		||||
 | 
			
		||||
    if (!pool) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tfm_list_is_empty(&pool->chunks_list)) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    node = tfm_list_first_node(&pool->chunks_list);
 | 
			
		||||
    pchunk = TFM_GET_CONTAINER_PTR(node, struct tfm_pool_chunk_t, list);
 | 
			
		||||
 | 
			
		||||
    /* Remove node from list node, it will be added when pool free */
 | 
			
		||||
    tfm_list_del_node(node);
 | 
			
		||||
 | 
			
		||||
    return &pchunk->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_pool_free(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_pool_chunk_t *pchunk;
 | 
			
		||||
    struct tfm_pool_instance_t *pool;
 | 
			
		||||
 | 
			
		||||
    pchunk = TFM_GET_CONTAINER_PTR(ptr, struct tfm_pool_chunk_t, data);
 | 
			
		||||
    pool = (struct tfm_pool_instance_t *)pchunk->pool;
 | 
			
		||||
    tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,619 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
#include "psa_service.h"
 | 
			
		||||
#include "tfm_utils.h"
 | 
			
		||||
#include "platform/include/tfm_spm_hal.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
#include "spm_db.h"
 | 
			
		||||
#include "spm_db_setup.h"
 | 
			
		||||
#include "tfm_internal_defines.h"
 | 
			
		||||
#include "tfm_wait.h"
 | 
			
		||||
#include "tfm_message_queue.h"
 | 
			
		||||
#include "tfm_list.h"
 | 
			
		||||
#include "tfm_pools.h"
 | 
			
		||||
#include "tfm_spm.h"
 | 
			
		||||
#include "tfm_spm_signal_defs.h"
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#include "region_defs.h"
 | 
			
		||||
#include "tfm_nspm.h"
 | 
			
		||||
#include "tfm_memory_utils.h"
 | 
			
		||||
#include "platform/mbed_toolchain.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * IPC partitions.
 | 
			
		||||
 * FixMe: Need to get align with spm_partition_db_t.
 | 
			
		||||
 */
 | 
			
		||||
static struct tfm_spm_ipc_partition_t
 | 
			
		||||
                    g_spm_ipc_partition[SPM_MAX_PARTITIONS] = {};
 | 
			
		||||
 | 
			
		||||
/* Extern SPM variable */
 | 
			
		||||
extern struct spm_partition_db_t g_spm_partition_db;
 | 
			
		||||
 | 
			
		||||
/* Extern secure lock variable */
 | 
			
		||||
extern int32_t tfm_secure_lock;
 | 
			
		||||
/* Pools */
 | 
			
		||||
TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
 | 
			
		||||
                 TFM_CONN_HANDLE_MAX_NUM);
 | 
			
		||||
TFM_POOL_DECLARE(spm_service_pool, sizeof(struct tfm_spm_service_t),
 | 
			
		||||
                 TFM_SPM_MAX_ROT_SERV_NUM);
 | 
			
		||||
TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
 | 
			
		||||
                 TFM_MSG_QUEUE_MAX_MSG_NUM);
 | 
			
		||||
 | 
			
		||||
static struct tfm_spm_service_db_t g_spm_service_db[] = {
 | 
			
		||||
    #include "tfm_service_list.inc"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/********************** SPM functions for handler mode ***********************/
 | 
			
		||||
 | 
			
		||||
/* Service handle management functions */
 | 
			
		||||
psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_conn_handle_t *node;
 | 
			
		||||
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
 | 
			
		||||
    /* Get buffer for handle list structure from handle pool */
 | 
			
		||||
    node = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
 | 
			
		||||
    if (!node) {
 | 
			
		||||
        return PSA_NULL_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Global unique handle, use handle buffer address directly */
 | 
			
		||||
    node->handle = (psa_handle_t)node;
 | 
			
		||||
 | 
			
		||||
    /* Add handle node to list for next psa functions */
 | 
			
		||||
    tfm_list_add_tail(&service->handle_list, &node->list);
 | 
			
		||||
 | 
			
		||||
    return node->handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct tfm_conn_handle_t *
 | 
			
		||||
tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
 | 
			
		||||
                              psa_handle_t conn_handle)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_conn_handle_t *handle_node;
 | 
			
		||||
    struct tfm_list_node_t *node, *head;
 | 
			
		||||
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
 | 
			
		||||
    head = &service->handle_list;
 | 
			
		||||
    TFM_LIST_FOR_EACH(node, head) {
 | 
			
		||||
        handle_node = TFM_GET_CONTAINER_PTR(node, struct tfm_conn_handle_t,
 | 
			
		||||
                                            list);
 | 
			
		||||
        if (handle_node->handle == conn_handle) {
 | 
			
		||||
            return handle_node;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
 | 
			
		||||
                                 psa_handle_t conn_handle)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_conn_handle_t *node;
 | 
			
		||||
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
 | 
			
		||||
    /* There are many handles for each RoT Service */
 | 
			
		||||
    node = tfm_spm_find_conn_handle_node(service, conn_handle);
 | 
			
		||||
    if (!node) {
 | 
			
		||||
        tfm_panic();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Remove node from handle list */
 | 
			
		||||
    tfm_list_del_node(&node->list);
 | 
			
		||||
 | 
			
		||||
    node->rhandle = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Back handle buffer to pool */
 | 
			
		||||
    tfm_pool_free(node);
 | 
			
		||||
    return IPC_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
 | 
			
		||||
                            psa_handle_t conn_handle,
 | 
			
		||||
                            void *rhandle)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_conn_handle_t *node;
 | 
			
		||||
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
    /* Set reverse handle value only be allowed for a connected handle */
 | 
			
		||||
    TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
 | 
			
		||||
 | 
			
		||||
    /* There are many handles for each RoT Service */
 | 
			
		||||
    node = tfm_spm_find_conn_handle_node(service, conn_handle);
 | 
			
		||||
    if (!node) {
 | 
			
		||||
        tfm_panic();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    node->rhandle = rhandle;
 | 
			
		||||
    return IPC_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
 | 
			
		||||
                          psa_handle_t conn_handle)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_conn_handle_t *node;
 | 
			
		||||
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
    /* Get reverse handle value only be allowed for a connected handle */
 | 
			
		||||
    TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
 | 
			
		||||
 | 
			
		||||
    /* There are many handles for each RoT Service */
 | 
			
		||||
    node = tfm_spm_find_conn_handle_node(service, conn_handle);
 | 
			
		||||
    if (!node) {
 | 
			
		||||
        tfm_panic();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return node->rhandle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Partition management functions */
 | 
			
		||||
struct tfm_spm_service_t *
 | 
			
		||||
tfm_spm_get_service_by_signal(struct tfm_spm_ipc_partition_t *partition,
 | 
			
		||||
                              psa_signal_t signal)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_list_node_t *node, *head;
 | 
			
		||||
    struct tfm_spm_service_t *service;
 | 
			
		||||
 | 
			
		||||
    TFM_ASSERT(partition);
 | 
			
		||||
 | 
			
		||||
    if (tfm_list_is_empty(&partition->service_list)) {
 | 
			
		||||
        tfm_panic();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    head = &partition->service_list;
 | 
			
		||||
    TFM_LIST_FOR_EACH(node, head) {
 | 
			
		||||
        service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
 | 
			
		||||
        if (service->service_db->signal == signal) {
 | 
			
		||||
            return service;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    struct tfm_list_node_t *node, *head;
 | 
			
		||||
    struct tfm_spm_service_t *service;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
 | 
			
		||||
        /* Skip partition without IPC flag */
 | 
			
		||||
        if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
 | 
			
		||||
            SPM_PART_FLAG_IPC) == 0) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        head = &g_spm_ipc_partition[i].service_list;
 | 
			
		||||
        TFM_LIST_FOR_EACH(node, head) {
 | 
			
		||||
            service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
 | 
			
		||||
                                            list);
 | 
			
		||||
            if (service->service_db->sid == sid) {
 | 
			
		||||
                return service;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tfm_spm_service_t *
 | 
			
		||||
    tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    struct tfm_conn_handle_t *handle;
 | 
			
		||||
    struct tfm_list_node_t *service_node, *service_head;
 | 
			
		||||
    struct tfm_list_node_t *handle_node, *handle_head;
 | 
			
		||||
    struct tfm_spm_service_t *service;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
 | 
			
		||||
        /* Skip partition without IPC flag */
 | 
			
		||||
        if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
 | 
			
		||||
            SPM_PART_FLAG_IPC) == 0) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        service_head = &g_spm_ipc_partition[i].service_list;
 | 
			
		||||
        TFM_LIST_FOR_EACH(service_node, service_head) {
 | 
			
		||||
            service = TFM_GET_CONTAINER_PTR(service_node,
 | 
			
		||||
                                            struct tfm_spm_service_t, list);
 | 
			
		||||
            handle_head = &service->handle_list;
 | 
			
		||||
            TFM_LIST_FOR_EACH(handle_node, handle_head) {
 | 
			
		||||
                handle = TFM_GET_CONTAINER_PTR(handle_node,
 | 
			
		||||
                                               struct tfm_conn_handle_t, list);
 | 
			
		||||
                if (handle->handle == conn_handle) {
 | 
			
		||||
                    return service;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tfm_spm_ipc_partition_t *
 | 
			
		||||
    tfm_spm_get_partition_by_id(int32_t partition_id)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
 | 
			
		||||
        if (g_spm_ipc_partition[i].id == partition_id) {
 | 
			
		||||
            return &g_spm_ipc_partition[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tfm_spm_ipc_partition_t *tfm_spm_get_running_partition(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t spid;
 | 
			
		||||
 | 
			
		||||
    spid = tfm_spm_partition_get_running_partition_id_ext();
 | 
			
		||||
 | 
			
		||||
    return tfm_spm_get_partition_by_id(spid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
 | 
			
		||||
                                     uint32_t minor_version)
 | 
			
		||||
{
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
 | 
			
		||||
    switch (service->service_db->minor_policy) {
 | 
			
		||||
    case TFM_VERSION_POLICY_RELAXED:
 | 
			
		||||
        if (minor_version > service->service_db->minor_version) {
 | 
			
		||||
            return IPC_ERROR_VERSION;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_VERSION_POLICY_STRICT:
 | 
			
		||||
        if (minor_version != service->service_db->minor_version) {
 | 
			
		||||
            return IPC_ERROR_VERSION;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        return IPC_ERROR_VERSION;
 | 
			
		||||
    }
 | 
			
		||||
    return IPC_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Message functions */
 | 
			
		||||
struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * There may be one error handle passed by the caller in two conditions:
 | 
			
		||||
     *   1. Not a valid message handle.
 | 
			
		||||
     *   2. Handle between different Partitions. Partition A passes one handle
 | 
			
		||||
     *   belong to other Partitions and tries to access other's data.
 | 
			
		||||
     * So, need do necessary checking to prevent those conditions.
 | 
			
		||||
     */
 | 
			
		||||
    struct tfm_msg_body_t *msg;
 | 
			
		||||
    uint32_t partition_id;
 | 
			
		||||
 | 
			
		||||
    msg = (struct tfm_msg_body_t *)msg_handle;
 | 
			
		||||
    if (!msg) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * FixMe: For condition 1: using a magic number to define it's a message.
 | 
			
		||||
     * It needs to be an enhancement to check the handle belong to service.
 | 
			
		||||
     */
 | 
			
		||||
    if (msg->magic != TFM_MSG_MAGIC) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* For condition 2: check if the partition ID is same */
 | 
			
		||||
    partition_id = tfm_spm_partition_get_running_partition_id_ext();
 | 
			
		||||
    if (partition_id != msg->service->partition->id) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return msg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
 | 
			
		||||
                                          psa_handle_t handle,
 | 
			
		||||
                                          uint32_t type, int32_t ns_caller,
 | 
			
		||||
                                          psa_invec *invec, size_t in_len,
 | 
			
		||||
                                          psa_outvec *outvec, size_t out_len,
 | 
			
		||||
                                          psa_outvec *caller_outvec)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_msg_body_t *msg = NULL;
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
    TFM_ASSERT(!(invec == NULL && in_len != 0));
 | 
			
		||||
    TFM_ASSERT(!(outvec == NULL && out_len != 0));
 | 
			
		||||
    TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
 | 
			
		||||
    TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
 | 
			
		||||
    TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
 | 
			
		||||
 | 
			
		||||
    /* Get message buffer from message pool */
 | 
			
		||||
    msg = (struct tfm_msg_body_t *)tfm_pool_alloc(msg_db_pool);
 | 
			
		||||
    if (!msg) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Clear message buffer before using it */
 | 
			
		||||
    tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
 | 
			
		||||
 | 
			
		||||
    tfm_event_init(&msg->ack_evnt);
 | 
			
		||||
    msg->magic = TFM_MSG_MAGIC;
 | 
			
		||||
    msg->service = service;
 | 
			
		||||
    msg->handle = handle;
 | 
			
		||||
    msg->caller_outvec = caller_outvec;
 | 
			
		||||
    /* Get current partition id */
 | 
			
		||||
    if (ns_caller) {
 | 
			
		||||
        msg->msg.client_id = tfm_nspm_get_current_client_id();
 | 
			
		||||
    } else {
 | 
			
		||||
        msg->msg.client_id = tfm_spm_partition_get_running_partition_id_ext();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Copy contents */
 | 
			
		||||
    msg->msg.type = type;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < in_len; i++) {
 | 
			
		||||
        msg->msg.in_size[i] = invec[i].len;
 | 
			
		||||
        msg->invec[i].base = invec[i].base;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < out_len; i++) {
 | 
			
		||||
        msg->msg.out_size[i] = outvec[i].len;
 | 
			
		||||
        msg->outvec[i].base = outvec[i].base;
 | 
			
		||||
        /* Out len is used to record the writed number, set 0 here again */
 | 
			
		||||
        msg->outvec[i].len = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Use message address as handle */
 | 
			
		||||
    msg->msg.handle = (psa_handle_t)msg;
 | 
			
		||||
 | 
			
		||||
    /* For connected handle, set rhandle to every message */
 | 
			
		||||
    if (handle != PSA_NULL_HANDLE) {
 | 
			
		||||
        msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return msg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_spm_free_msg(struct tfm_msg_body_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    tfm_pool_free(msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
 | 
			
		||||
                           struct tfm_msg_body_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    TFM_ASSERT(service);
 | 
			
		||||
    TFM_ASSERT(msg);
 | 
			
		||||
 | 
			
		||||
    /* Enqueue message to service message queue */
 | 
			
		||||
    if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
 | 
			
		||||
        return IPC_ERROR_GENERIC;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Messages put. Update signals */
 | 
			
		||||
    service->partition->signals |= service->service_db->signal;
 | 
			
		||||
 | 
			
		||||
    tfm_event_wake(&service->partition->signal_evnt,
 | 
			
		||||
                   (service->partition->signals &
 | 
			
		||||
                    service->partition->signal_mask));
 | 
			
		||||
 | 
			
		||||
    tfm_event_wait(&msg->ack_evnt);
 | 
			
		||||
 | 
			
		||||
    return IPC_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* SPM extend functions */
 | 
			
		||||
uint32_t tfm_spm_partition_get_running_partition_id_ext(void)
 | 
			
		||||
{
 | 
			
		||||
    struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
 | 
			
		||||
    struct spm_partition_desc_t *partition;
 | 
			
		||||
 | 
			
		||||
    partition = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_desc_t,
 | 
			
		||||
                                      sp_thrd);
 | 
			
		||||
    return partition->static_data.partition_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct tfm_thrd_ctx *
 | 
			
		||||
tfm_spm_partition_get_thread_info_ext(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static tfm_thrd_func_t
 | 
			
		||||
        tfm_spm_partition_get_init_func_ext(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
                             static_data.partition_init);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t tfm_spm_partition_get_priority_ext(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].static_data.
 | 
			
		||||
                    partition_priority;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
 | 
			
		||||
                         enum tfm_memory_access_e access,
 | 
			
		||||
                         uint32_t privileged)
 | 
			
		||||
{
 | 
			
		||||
    int32_t err;
 | 
			
		||||
 | 
			
		||||
    /* If len is zero, this indicates an empty buffer and base is ignored */
 | 
			
		||||
    if (len == 0) {
 | 
			
		||||
        return IPC_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!buffer) {
 | 
			
		||||
        return IPC_ERROR_BAD_PARAMETERS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
 | 
			
		||||
        return IPC_ERROR_MEMORY_CHECK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (access == TFM_MEMORY_ACCESS_RW) {
 | 
			
		||||
        err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
 | 
			
		||||
                                                  privileged);
 | 
			
		||||
    } else {
 | 
			
		||||
        err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
 | 
			
		||||
                                                 privileged);
 | 
			
		||||
    }
 | 
			
		||||
    if (err == TFM_SUCCESS) {
 | 
			
		||||
        return IPC_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return IPC_ERROR_MEMORY_CHECK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) {
 | 
			
		||||
        return TFM_PARTITION_PRIVILEGED_MODE;
 | 
			
		||||
    } else {
 | 
			
		||||
        return TFM_PARTITION_UNPRIVILEGED_MODE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************** SPM functions for thread mode ************************/
 | 
			
		||||
 | 
			
		||||
void tfm_spm_init(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i, num;
 | 
			
		||||
    struct tfm_spm_ipc_partition_t *partition;
 | 
			
		||||
    struct tfm_spm_service_t *service;
 | 
			
		||||
    struct tfm_thrd_ctx *pth, this_thrd;
 | 
			
		||||
    struct spm_partition_desc_t *part;
 | 
			
		||||
 | 
			
		||||
    tfm_pool_init(conn_handle_pool,
 | 
			
		||||
                  POOL_BUFFER_SIZE(conn_handle_pool),
 | 
			
		||||
                  sizeof(struct tfm_conn_handle_t),
 | 
			
		||||
                  TFM_CONN_HANDLE_MAX_NUM);
 | 
			
		||||
    tfm_pool_init(spm_service_pool, POOL_BUFFER_SIZE(spm_service_pool),
 | 
			
		||||
                  sizeof(struct tfm_spm_service_t),
 | 
			
		||||
                  TFM_SPM_MAX_ROT_SERV_NUM);
 | 
			
		||||
    tfm_pool_init(msg_db_pool, POOL_BUFFER_SIZE(msg_db_pool),
 | 
			
		||||
                  sizeof(struct tfm_msg_body_t),
 | 
			
		||||
                  TFM_MSG_QUEUE_MAX_MSG_NUM);
 | 
			
		||||
 | 
			
		||||
    /* Init partition first for it will be used when init service */
 | 
			
		||||
    for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
 | 
			
		||||
        part = &g_spm_partition_db.partitions[i];
 | 
			
		||||
        tfm_spm_hal_configure_default_isolation(part->platform_data);
 | 
			
		||||
        g_spm_ipc_partition[i].index = i;
 | 
			
		||||
        if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i);
 | 
			
		||||
 | 
			
		||||
        tfm_event_init(&g_spm_ipc_partition[i].signal_evnt);
 | 
			
		||||
        tfm_list_init(&g_spm_ipc_partition[i].service_list);
 | 
			
		||||
 | 
			
		||||
        pth = tfm_spm_partition_get_thread_info_ext(i);
 | 
			
		||||
        if (!pth) {
 | 
			
		||||
            tfm_panic();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tfm_thrd_init(pth,
 | 
			
		||||
                      tfm_spm_partition_get_init_func_ext(i),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      (uint8_t *)tfm_spm_partition_get_stack_top(i),
 | 
			
		||||
                      (uint8_t *)tfm_spm_partition_get_stack_bottom(i));
 | 
			
		||||
 | 
			
		||||
        pth->prior = tfm_spm_partition_get_priority_ext(i);
 | 
			
		||||
 | 
			
		||||
        /* Kick off */
 | 
			
		||||
        if (tfm_thrd_start(pth) != THRD_SUCCESS) {
 | 
			
		||||
            tfm_panic();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Init Service */
 | 
			
		||||
    num = sizeof(g_spm_service_db) / sizeof(struct tfm_spm_service_db_t);
 | 
			
		||||
    for (i = 0; i < num; i++) {
 | 
			
		||||
        partition =
 | 
			
		||||
            tfm_spm_get_partition_by_id(g_spm_service_db[i].partition_id);
 | 
			
		||||
        if (!partition) {
 | 
			
		||||
            tfm_panic();
 | 
			
		||||
        }
 | 
			
		||||
        service = (struct tfm_spm_service_t *)tfm_pool_alloc(spm_service_pool);
 | 
			
		||||
        if (!service) {
 | 
			
		||||
            tfm_panic();
 | 
			
		||||
        }
 | 
			
		||||
        service->service_db = &g_spm_service_db[i];
 | 
			
		||||
        service->partition = partition;
 | 
			
		||||
        tfm_list_init(&service->handle_list);
 | 
			
		||||
        tfm_list_add_tail(&partition->service_list, &service->list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * All threads initialized, start the scheduler.
 | 
			
		||||
     *
 | 
			
		||||
     * NOTE:
 | 
			
		||||
     * Here is the booting privileged thread mode, and will never
 | 
			
		||||
     * return to this place after scheduler is started. The start
 | 
			
		||||
     * function has to save current runtime context to act as a
 | 
			
		||||
     * 'current thread' to avoid repeating NULL 'current thread'
 | 
			
		||||
     * checking while context switching. This saved context is worthy
 | 
			
		||||
     * of being saved somewhere if there are potential usage purpose.
 | 
			
		||||
     * Let's save this context in a local variable 'this_thrd' at
 | 
			
		||||
     * current since there is no usage for it.
 | 
			
		||||
     * Also set tfm_nspm_thread_entry as pfn for this thread to
 | 
			
		||||
     * use in detecting NS/S thread scheduling changes.
 | 
			
		||||
     */
 | 
			
		||||
    this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry;
 | 
			
		||||
    tfm_thrd_start_scheduler(&this_thrd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MBED_USED void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
 | 
			
		||||
{
 | 
			
		||||
#if TFM_LVL == 2
 | 
			
		||||
    struct spm_partition_desc_t *p_next_partition;
 | 
			
		||||
    uint32_t is_privileged;
 | 
			
		||||
#endif
 | 
			
		||||
    struct tfm_thrd_ctx *pth_next = tfm_thrd_next_thread();
 | 
			
		||||
    struct tfm_thrd_ctx *pth_curr = tfm_thrd_curr_thread();
 | 
			
		||||
 | 
			
		||||
    if (pth_curr != pth_next) {
 | 
			
		||||
#if TFM_LVL == 2
 | 
			
		||||
        p_next_partition = TFM_GET_CONTAINER_PTR(pth_next,
 | 
			
		||||
                                                 struct spm_partition_desc_t,
 | 
			
		||||
                                                 sp_thrd);
 | 
			
		||||
 | 
			
		||||
        if (p_next_partition->static_data.partition_flags &
 | 
			
		||||
            SPM_PART_FLAG_PSA_ROT) {
 | 
			
		||||
            is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
 | 
			
		||||
        } else {
 | 
			
		||||
            is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tfm_spm_partition_change_privilege(is_privileged);
 | 
			
		||||
#endif
 | 
			
		||||
        /* Increase the secure lock, if we enter secure from non-secure */
 | 
			
		||||
        if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) {
 | 
			
		||||
            ++tfm_secure_lock;
 | 
			
		||||
        }
 | 
			
		||||
        /* Decrease the secure lock, if we return from secure to non-secure */
 | 
			
		||||
        if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) {
 | 
			
		||||
            --tfm_secure_lock;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tfm_thrd_context_switch(ctxb, pth_curr, pth_next);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,181 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "tfm_arch_v8m.h"
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#include "tfm_utils.h"
 | 
			
		||||
#include "tfm_memory_utils.h"
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
 | 
			
		||||
/* Force ZERO in case ZI(bss) clear is missing */
 | 
			
		||||
static struct tfm_thrd_ctx *p_thrd_head = NULL;
 | 
			
		||||
static struct tfm_thrd_ctx *p_runn_head = NULL;
 | 
			
		||||
static struct tfm_thrd_ctx *p_curr_thrd = NULL;
 | 
			
		||||
 | 
			
		||||
/* Define Macro to fetch global to support future expansion (PERCPU e.g.) */
 | 
			
		||||
#define LIST_HEAD   p_thrd_head
 | 
			
		||||
#define RUNN_HEAD   p_runn_head
 | 
			
		||||
#define CURR_THRD   p_curr_thrd
 | 
			
		||||
 | 
			
		||||
static struct tfm_thrd_ctx *find_next_running_thread(struct tfm_thrd_ctx *pth)
 | 
			
		||||
{
 | 
			
		||||
    while (pth && pth->status != THRD_STAT_RUNNING) {
 | 
			
		||||
        pth = pth->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return pth;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* To get next running thread for scheduler */
 | 
			
		||||
struct tfm_thrd_ctx *tfm_thrd_next_thread(void)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * First RUNNING thread has highest priority since threads are sorted with
 | 
			
		||||
     * priority.
 | 
			
		||||
     */
 | 
			
		||||
    return find_next_running_thread(RUNN_HEAD);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* To get current thread for caller */
 | 
			
		||||
struct tfm_thrd_ctx *tfm_thrd_curr_thread()
 | 
			
		||||
{
 | 
			
		||||
    return CURR_THRD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Insert a new thread into list by descending priority (Highest at head) */
 | 
			
		||||
static void insert_by_prior(struct tfm_thrd_ctx **head,
 | 
			
		||||
                            struct tfm_thrd_ctx *node)
 | 
			
		||||
{
 | 
			
		||||
    if (*head == NULL || (node->prior <= (*head)->prior)) {
 | 
			
		||||
        node->next = *head;
 | 
			
		||||
        *head = node;
 | 
			
		||||
    } else {
 | 
			
		||||
        struct tfm_thrd_ctx *iter = *head;
 | 
			
		||||
 | 
			
		||||
        while (iter->next && (node->prior > iter->next->prior)) {
 | 
			
		||||
            iter = iter->next;
 | 
			
		||||
        }
 | 
			
		||||
        node->next = iter->next;
 | 
			
		||||
        iter->next = node;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set first running thread as head to reduce enumerate
 | 
			
		||||
 * depth while searching for a first running thread.
 | 
			
		||||
 */
 | 
			
		||||
static void update_running_head(struct tfm_thrd_ctx **runn,
 | 
			
		||||
                                struct tfm_thrd_ctx *node)
 | 
			
		||||
{
 | 
			
		||||
    if ((node->status == THRD_STAT_RUNNING) &&
 | 
			
		||||
        (*runn == NULL || (node->prior < (*runn)->prior))) {
 | 
			
		||||
        *runn = node;
 | 
			
		||||
    } else {
 | 
			
		||||
        *runn = find_next_running_thread(LIST_HEAD);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set context members only. No validation here */
 | 
			
		||||
void tfm_thrd_init(struct tfm_thrd_ctx *pth,
 | 
			
		||||
                   tfm_thrd_func_t pfn, void *param,
 | 
			
		||||
                   uint8_t *sp_base, uint8_t *sp_top)
 | 
			
		||||
{
 | 
			
		||||
    pth->prior = THRD_PRIOR_MEDIUM;
 | 
			
		||||
    pth->status = THRD_STAT_CREATING;
 | 
			
		||||
    pth->pfn = pfn;
 | 
			
		||||
    pth->param = param;
 | 
			
		||||
    pth->sp_base = sp_base;
 | 
			
		||||
    pth->sp_top = sp_top;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_thrd_start(struct tfm_thrd_ctx *pth)
 | 
			
		||||
{
 | 
			
		||||
    /* Validate parameters before really start */
 | 
			
		||||
    if ((pth->status != THRD_STAT_CREATING) ||
 | 
			
		||||
        (pth->pfn == NULL)                  ||
 | 
			
		||||
        (pth->sp_base == NULL)              ||
 | 
			
		||||
        (pth->sp_top == NULL)) {
 | 
			
		||||
        return THRD_ERR_INVALID_PARAM;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Thread management runs in handler mode; set context for thread mode. */
 | 
			
		||||
    tfm_initialize_context(&pth->state_ctx,
 | 
			
		||||
                           (uint32_t)pth->param, (uint32_t)pth->pfn,
 | 
			
		||||
                           (uint32_t)pth->sp_base, (uint32_t)pth->sp_top);
 | 
			
		||||
 | 
			
		||||
    /* Insert a new thread with priority */
 | 
			
		||||
    insert_by_prior(&LIST_HEAD, pth);
 | 
			
		||||
 | 
			
		||||
    /* Mark it as RUNNING after insertion */
 | 
			
		||||
    tfm_thrd_set_status(pth, THRD_STAT_RUNNING);
 | 
			
		||||
 | 
			
		||||
    return THRD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status)
 | 
			
		||||
{
 | 
			
		||||
    TFM_ASSERT(pth != NULL && new_status < THRD_STAT_INVALID);
 | 
			
		||||
 | 
			
		||||
    pth->status = new_status;
 | 
			
		||||
    update_running_head(&RUNN_HEAD, pth);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Scheduling won't happen immediately but after the exception returns */
 | 
			
		||||
void tfm_thrd_activate_schedule(void)
 | 
			
		||||
{
 | 
			
		||||
    tfm_trigger_pendsv();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_thrd_start_scheduler(struct tfm_thrd_ctx *pth)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * There is no selected thread before scheduler start, assign
 | 
			
		||||
     * a caller provided thread as current thread. This function
 | 
			
		||||
     * should get called only ONCE; further calling triggers assert.
 | 
			
		||||
     */
 | 
			
		||||
    TFM_ASSERT(CURR_THRD == NULL);
 | 
			
		||||
    TFM_ASSERT(pth != NULL);
 | 
			
		||||
 | 
			
		||||
    CURR_THRD = pth;
 | 
			
		||||
    tfm_thrd_activate_schedule();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Remove current thread out of the schedulable list */
 | 
			
		||||
void tfm_svcall_thrd_exit(void)
 | 
			
		||||
{
 | 
			
		||||
    CURR_THRD->status = THRD_STAT_DETACH;
 | 
			
		||||
    tfm_trigger_pendsv();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((section("SFN")))
 | 
			
		||||
void tfm_thrd_exit(void)
 | 
			
		||||
{
 | 
			
		||||
    SVC(TFM_SVC_EXIT_THRD);
 | 
			
		||||
    while (1) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb,
 | 
			
		||||
                             struct tfm_thrd_ctx *prev,
 | 
			
		||||
                             struct tfm_thrd_ctx *next)
 | 
			
		||||
{
 | 
			
		||||
    TFM_ASSERT(prev != NULL);
 | 
			
		||||
    TFM_ASSERT(next != NULL);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * First, update latest context into the current thread context.
 | 
			
		||||
     * Then, update background context with next thread's context.
 | 
			
		||||
     */
 | 
			
		||||
    tfm_memcpy(&prev->state_ctx.ctxb, ctxb, sizeof(*ctxb));
 | 
			
		||||
    tfm_memcpy(ctxb, &next->state_ctx.ctxb, sizeof(next->state_ctx.ctxb));
 | 
			
		||||
 | 
			
		||||
    /* Update current thread indicator */
 | 
			
		||||
    CURR_THRD = next;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,32 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "tfm_utils.h"
 | 
			
		||||
 | 
			
		||||
void tfm_panic(void)
 | 
			
		||||
{
 | 
			
		||||
    while (1)
 | 
			
		||||
        ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_bitcount(uint32_t n)
 | 
			
		||||
{
 | 
			
		||||
    int32_t count = 0;
 | 
			
		||||
    uint8_t tmp;
 | 
			
		||||
 | 
			
		||||
    while (n) {
 | 
			
		||||
        tmp = n & 0xFF;
 | 
			
		||||
        while (tmp) {
 | 
			
		||||
            count += tmp & 0x1;
 | 
			
		||||
            tmp >>= 1;
 | 
			
		||||
        }
 | 
			
		||||
        n >>= 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return count;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,30 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#include "tfm_utils.h"
 | 
			
		||||
#include "tfm_wait.h"
 | 
			
		||||
 | 
			
		||||
void tfm_event_wait(struct tfm_event_t *pevnt)
 | 
			
		||||
{
 | 
			
		||||
    TFM_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
 | 
			
		||||
 | 
			
		||||
    pevnt->owner = tfm_thrd_curr_thread();
 | 
			
		||||
    tfm_thrd_set_status(pevnt->owner, THRD_STAT_BLOCK);
 | 
			
		||||
    tfm_thrd_activate_schedule();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval)
 | 
			
		||||
{
 | 
			
		||||
    TFM_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
 | 
			
		||||
 | 
			
		||||
    if (pevnt->owner && pevnt->owner->status == THRD_STAT_BLOCK) {
 | 
			
		||||
        tfm_thrd_set_status(pevnt->owner, THRD_STAT_RUNNING);
 | 
			
		||||
        tfm_thrd_set_retval(pevnt->owner, retval);
 | 
			
		||||
        tfm_thrd_activate_schedule();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,109 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_UTILITIES_H__
 | 
			
		||||
#define __SECURE_UTILITIES_H__
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
 | 
			
		||||
#define EXC_RETURN_INDICATOR                    (0xF << 28)
 | 
			
		||||
#define EXC_RETURN_SECURITY_STACK_STATUS_MASK   (0x3 << 5)
 | 
			
		||||
#define EXC_RETURN_SECURE_STACK                 (1 << 6)
 | 
			
		||||
#define EXC_RETURN_FPU_FRAME_BASIC              (1 << 4)
 | 
			
		||||
#define EXC_RETURN_MODE_THREAD                  (1 << 3)
 | 
			
		||||
#define EXC_RETURN_STACK_PROCESS                (1 << 2)
 | 
			
		||||
#define EXC_RETURN_EXC_SECURE                   (1)
 | 
			
		||||
 | 
			
		||||
#define EXC_NUM_THREAD_MODE     (0)
 | 
			
		||||
#define EXC_NUM_SVCALL          (11)
 | 
			
		||||
#define EXC_NUM_PENDSV          (14)
 | 
			
		||||
#define EXC_NUM_SYSTICK         (15)
 | 
			
		||||
 | 
			
		||||
#define printf(...)
 | 
			
		||||
 | 
			
		||||
/* Disable NS exceptions by setting NS PRIMASK to 1 */
 | 
			
		||||
#define TFM_NS_EXC_DISABLE()    __TZ_set_PRIMASK_NS(1)
 | 
			
		||||
/* Enable NS exceptions by setting NS PRIMASK to 0 */
 | 
			
		||||
#define TFM_NS_EXC_ENABLE()    __TZ_set_PRIMASK_NS(0)
 | 
			
		||||
 | 
			
		||||
struct tfm_exc_stack_t {
 | 
			
		||||
    uint32_t R0;
 | 
			
		||||
    uint32_t R1;
 | 
			
		||||
    uint32_t R2;
 | 
			
		||||
    uint32_t R3;
 | 
			
		||||
    uint32_t R12;
 | 
			
		||||
    uint32_t LR;
 | 
			
		||||
    uint32_t RetAddr;
 | 
			
		||||
    uint32_t XPSR;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_CORE_DEBUG
 | 
			
		||||
#define LOG_MSG_HDLR(MSG) printf("[Sec Handler] %s\r\n", MSG)
 | 
			
		||||
#else
 | 
			
		||||
/* FixMe: redirect to secure log area */
 | 
			
		||||
#define LOG_MSG_HDLR(MSG) printf("[Sec Handler] %s\r\n", MSG)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define LOG_MSG_THR(MSG) \
 | 
			
		||||
            __ASM volatile("MOV r0, %0\n" \
 | 
			
		||||
                           "SVC %1\n" \
 | 
			
		||||
                           : : "r" (MSG), "I" (TFM_SVC_PRINT))
 | 
			
		||||
 | 
			
		||||
#define LOG_MSG(MSG) \
 | 
			
		||||
            do { \
 | 
			
		||||
                if (__get_active_exc_num()) { \
 | 
			
		||||
                    LOG_MSG_HDLR(MSG); \
 | 
			
		||||
                } else { \
 | 
			
		||||
                    LOG_MSG_THR(MSG); \
 | 
			
		||||
                } \
 | 
			
		||||
            } while (0)
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_CORE_DEBUG
 | 
			
		||||
#define ERROR_MSG(MSG) printf("[Sec Error] %s\r\n", MSG)
 | 
			
		||||
#else
 | 
			
		||||
/* FixMe: redirect to secure log area */
 | 
			
		||||
#define ERROR_MSG(MSG) printf("[Sec Error] %s\r\n", MSG)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get Link Register
 | 
			
		||||
 * \details Returns the value of the Link Register (LR)
 | 
			
		||||
 * \return LR value
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void)
 | 
			
		||||
{
 | 
			
		||||
    register uint32_t result;
 | 
			
		||||
 | 
			
		||||
    __ASM volatile ("MOV %0, LR\n" : "=r" (result));
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline))
 | 
			
		||||
__STATIC_INLINE uint32_t __get_active_exc_num(void)
 | 
			
		||||
{
 | 
			
		||||
    IPSR_Type IPSR;
 | 
			
		||||
 | 
			
		||||
    /* if non-zero, exception is active. NOT banked S/NS */
 | 
			
		||||
    IPSR.w = __get_IPSR();
 | 
			
		||||
    return IPSR.b.ISR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline))
 | 
			
		||||
__STATIC_INLINE void __set_CONTROL_SPSEL(uint32_t SPSEL)
 | 
			
		||||
{
 | 
			
		||||
    CONTROL_Type ctrl;
 | 
			
		||||
 | 
			
		||||
    ctrl.w = __get_CONTROL();
 | 
			
		||||
    ctrl.b.SPSEL = SPSEL;
 | 
			
		||||
    __set_CONTROL(ctrl.w);
 | 
			
		||||
    __ISB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_UTILITIES_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,158 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,234 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "region_defs.h"
 | 
			
		||||
#include "tfm_core.h"
 | 
			
		||||
#include "tfm_internal.h"
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
#include "platform/include/tfm_spm_hal.h"
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
#include "secure_fw/spm/spm_api.h"
 | 
			
		||||
#include "secure_fw/include/tfm_spm_services_api.h"
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
#include "psa_service.h"
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#include "tfm_wait.h"
 | 
			
		||||
#include "tfm_message_queue.h"
 | 
			
		||||
#include "tfm_spm.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Avoids the semihosting issue
 | 
			
		||||
 * FixMe: describe 'semihosting issue'
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__ARMCC_VERSION)
 | 
			
		||||
__asm("  .global __ARM_use_no_argv\n");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined ( __GNUC__ )
 | 
			
		||||
/* The macro cmse_nsfptr_create defined in the gcc library uses the non-standard
 | 
			
		||||
 * gcc C lanuage extension 'typeof'. TF-M is built with '-std=c99' so typeof
 | 
			
		||||
 * cannot be used in the code. As a workaround cmse_nsfptr_create is redefined
 | 
			
		||||
 * here to use only standard language elements. */
 | 
			
		||||
#undef cmse_nsfptr_create
 | 
			
		||||
#define cmse_nsfptr_create(p) ((intptr_t) (p) & ~1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_LVL
 | 
			
		||||
#error TFM_LVL is not defined!
 | 
			
		||||
#endif
 | 
			
		||||
#if (TFM_LVL != 1) && (TFM_LVL != 2) && (TFM_LVL != 3)
 | 
			
		||||
#error Only TFM_LVL 1, 2 and 3 are supported!
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API
 | 
			
		||||
/* Macros to pick linker symbols and allow to form the partition data base */
 | 
			
		||||
#define REGION(a, b, c) a##b##c
 | 
			
		||||
#define REGION_NAME(a, b, c) REGION(a, b, c)
 | 
			
		||||
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
 | 
			
		||||
 | 
			
		||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
 | 
			
		||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void configure_ns_code(void)
 | 
			
		||||
{
 | 
			
		||||
    /* SCB_NS.VTOR points to the Non-secure vector table base address */
 | 
			
		||||
    SCB_NS->VTOR = tfm_spm_hal_get_ns_VTOR();
 | 
			
		||||
 | 
			
		||||
    /* Setups Main stack pointer of the non-secure code */
 | 
			
		||||
    uint32_t ns_msp = tfm_spm_hal_get_ns_MSP();
 | 
			
		||||
 | 
			
		||||
    __TZ_set_MSP_NS(ns_msp);
 | 
			
		||||
 | 
			
		||||
    /* Get the address of non-secure code entry point to jump there */
 | 
			
		||||
    uint32_t entry_ptr = tfm_spm_hal_get_ns_entry_point();
 | 
			
		||||
 | 
			
		||||
    /* Clears LSB of the function address to indicate the function-call
 | 
			
		||||
     * will perform the switch from secure to non-secure
 | 
			
		||||
     */
 | 
			
		||||
    ns_entry = (nsfptr_t) cmse_nsfptr_create(entry_ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_core_init(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Enables fault handlers */
 | 
			
		||||
    enable_fault_handlers();
 | 
			
		||||
 | 
			
		||||
    /* Configures the system reset request properties */
 | 
			
		||||
    system_reset_cfg();
 | 
			
		||||
 | 
			
		||||
    /* Configures debug authentication */
 | 
			
		||||
    tfm_spm_hal_init_debug();
 | 
			
		||||
 | 
			
		||||
    __enable_irq();
 | 
			
		||||
 | 
			
		||||
    LOG_MSG("Secure image initializing!");
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_CORE_DEBUG
 | 
			
		||||
    printf("TFM level is: %d\r\n", TFM_LVL);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    tfm_core_validate_boot_data();
 | 
			
		||||
 | 
			
		||||
    tfm_spm_hal_init_isolation_hw();
 | 
			
		||||
 | 
			
		||||
    configure_ns_code();
 | 
			
		||||
 | 
			
		||||
    /* Configures all interrupts to retarget NS state, except for
 | 
			
		||||
     * secure peripherals
 | 
			
		||||
     */
 | 
			
		||||
    nvic_interrupt_target_state_cfg();
 | 
			
		||||
    /* Enable secure peripherals interrupts */
 | 
			
		||||
    nvic_interrupt_enable();
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
    /* FixMe: In case of IPC messaging, scratch area must not be referenced
 | 
			
		||||
     * These variables should be removed when all obsolete references are
 | 
			
		||||
     * removed from the codebase
 | 
			
		||||
     */
 | 
			
		||||
    tfm_scratch_area = NULL;
 | 
			
		||||
    tfm_scratch_area_size = 0;
 | 
			
		||||
#else
 | 
			
		||||
    tfm_scratch_area =
 | 
			
		||||
        (uint8_t *)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
 | 
			
		||||
    tfm_scratch_area_size =
 | 
			
		||||
        (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit) -
 | 
			
		||||
        (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
 | 
			
		||||
#endif
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t tfm_core_set_secure_exception_priorities(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t VECTKEY;
 | 
			
		||||
    SCB_Type *scb = SCB;
 | 
			
		||||
    uint32_t AIRCR;
 | 
			
		||||
 | 
			
		||||
    /* Set PRIS flag is AIRCR */
 | 
			
		||||
    AIRCR = scb->AIRCR;
 | 
			
		||||
    VECTKEY = (~AIRCR & SCB_AIRCR_VECTKEYSTAT_Msk);
 | 
			
		||||
    scb->AIRCR = SCB_AIRCR_PRIS_Msk |
 | 
			
		||||
                 VECTKEY |
 | 
			
		||||
                 (AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
 | 
			
		||||
 | 
			
		||||
    /* FixMe: Explicitly set secure fault and Secure SVC priority to highest */
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Set secure PendSV priority to the lowest in SECURE state.
 | 
			
		||||
     *
 | 
			
		||||
     * IMPORTANT NOTE:
 | 
			
		||||
     *
 | 
			
		||||
     * Although the priority of the secure PendSV must be the lowest possible
 | 
			
		||||
     * among other interrupts in the Secure state, it must be ensured that
 | 
			
		||||
     * PendSV is not preempted nor masked by Non-Secure interrupts to ensure
 | 
			
		||||
     * the integrity of the Secure operation.
 | 
			
		||||
     * When AIRCR.PRIS is set, the Non-Secure execution can act on
 | 
			
		||||
     * FAULTMASK_NS, PRIMASK_NS or BASEPRI_NS register to boost its priority
 | 
			
		||||
     * number up to the value 0x80.
 | 
			
		||||
     * For this reason, set the priority of the PendSV interrupt to the next
 | 
			
		||||
     * priority level configurable on the platform, just below 0x80.
 | 
			
		||||
     */
 | 
			
		||||
    NVIC_SetPriority(PendSV_IRQn, (1 << (__NVIC_PRIO_BITS - 1)) - 1);
 | 
			
		||||
 | 
			
		||||
    return TFM_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_core_spm_request_handler(const struct tfm_exc_stack_t *svc_ctx)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t *res_ptr = (uint32_t *)&svc_ctx->R0;
 | 
			
		||||
 | 
			
		||||
    /* FixMe: check if caller partition is permitted to make an SPM request */
 | 
			
		||||
 | 
			
		||||
    switch (svc_ctx->R0) {
 | 
			
		||||
    case TFM_SPM_REQUEST_RESET_VOTE:
 | 
			
		||||
        /* FixMe: this is a placeholder for checks to be performed before
 | 
			
		||||
         * allowing execution of reset
 | 
			
		||||
         */
 | 
			
		||||
        *res_ptr = TFM_SUCCESS;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        *res_ptr = TFM_ERROR_INVALID_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
    if (tfm_core_init() != 0) {
 | 
			
		||||
        /* Placeholder for error handling, currently ignored. */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tfm_spm_db_init() != SPM_ERR_OK) {
 | 
			
		||||
        /* Placeholder for error handling, currently ignored. */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tfm_spm_hal_setup_isolation_hw();
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API
 | 
			
		||||
    tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_RUNNING);
 | 
			
		||||
 | 
			
		||||
    extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
 | 
			
		||||
    uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
 | 
			
		||||
 | 
			
		||||
    __set_PSPLIM(psp_stack_bottom);
 | 
			
		||||
 | 
			
		||||
    if (tfm_spm_partition_init() != SPM_ERR_OK) {
 | 
			
		||||
        /* Certain systems might refuse to boot altogether if partitions fail
 | 
			
		||||
         * to initialize. This is a placeholder for such an error handler
 | 
			
		||||
         */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Prioritise secure exceptions to avoid NS being able to pre-empt
 | 
			
		||||
     * secure SVC or SecureFault. Do it before PSA API initialization.
 | 
			
		||||
     */
 | 
			
		||||
    tfm_core_set_secure_exception_priorities();
 | 
			
		||||
 | 
			
		||||
    /* We close the TFM_SP_CORE_ID partition, because its only purpose is
 | 
			
		||||
     * to be able to pass the state checks for the tests started from secure.
 | 
			
		||||
     */
 | 
			
		||||
    tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_CLOSED);
 | 
			
		||||
    tfm_spm_partition_set_state(TFM_SP_NON_SECURE_ID,
 | 
			
		||||
                                SPM_PARTITION_STATE_RUNNING);
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_CORE_DEBUG
 | 
			
		||||
    /* Jumps to non-secure code */
 | 
			
		||||
    LOG_MSG("Jumping to non-secure code...");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    jump_to_ns_code();
 | 
			
		||||
#else
 | 
			
		||||
    /*
 | 
			
		||||
     * Prioritise secure exceptions to avoid NS being able to pre-empt
 | 
			
		||||
     * secure SVC or SecureFault. Do it before PSA API initialization.
 | 
			
		||||
     */
 | 
			
		||||
    tfm_core_set_secure_exception_priorities();
 | 
			
		||||
    tfm_spm_init();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_CORE_H__
 | 
			
		||||
#define __TFM_CORE_H__
 | 
			
		||||
 | 
			
		||||
#include <arm_cmse.h>
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
 | 
			
		||||
extern uint32_t tfm_scratch_area_size;
 | 
			
		||||
extern uint8_t *tfm_scratch_area;
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_CORE_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,225 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
#include "tfm_secure_api.h"
 | 
			
		||||
#include "region_defs.h"
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
#include "tfm_internal.h"
 | 
			
		||||
#include "tfm_memory_utils.h"
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "tfm_svcalls.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "platform/mbed_toolchain.h"
 | 
			
		||||
 | 
			
		||||
/* This SVC handler is called when a secure partition requests access to a
 | 
			
		||||
 * buffer area
 | 
			
		||||
 */
 | 
			
		||||
extern int32_t tfm_core_set_buffer_area_handler(const uint32_t args[]);
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
extern void tfm_psa_ipc_request_handler(const uint32_t svc_args[]);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct tfm_fault_context_s {
 | 
			
		||||
    uint32_t R0;
 | 
			
		||||
    uint32_t R1;
 | 
			
		||||
    uint32_t R2;
 | 
			
		||||
    uint32_t R3;
 | 
			
		||||
    uint32_t R12;
 | 
			
		||||
    uint32_t LR;
 | 
			
		||||
    uint32_t ReturnAddress;
 | 
			
		||||
    uint32_t RETPSR;
 | 
			
		||||
} tfm_fault_context;
 | 
			
		||||
 | 
			
		||||
#if defined(__ARM_ARCH_8M_MAIN__)
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Overwrites default Secure fault handler.
 | 
			
		||||
 */
 | 
			
		||||
void SecureFault_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    /* figure out context from which we landed in fault handler */
 | 
			
		||||
    uint32_t lr = __get_LR();
 | 
			
		||||
    uint32_t sp;
 | 
			
		||||
 | 
			
		||||
    if (lr & EXC_RETURN_SECURE_STACK) {
 | 
			
		||||
        if (lr & EXC_RETURN_STACK_PROCESS) {
 | 
			
		||||
            sp = __get_PSP();
 | 
			
		||||
        } else {
 | 
			
		||||
            sp = __get_MSP();
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (lr & EXC_RETURN_STACK_PROCESS) {
 | 
			
		||||
            sp =  __TZ_get_PSP_NS();
 | 
			
		||||
        } else {
 | 
			
		||||
            sp = __TZ_get_MSP_NS();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Only save the context if sp is valid */
 | 
			
		||||
    if ((sp >=  S_DATA_START &&
 | 
			
		||||
         sp <=  (S_DATA_LIMIT - sizeof(tfm_fault_context)) + 1) ||
 | 
			
		||||
        (sp >= NS_DATA_START &&
 | 
			
		||||
         sp <= (NS_DATA_LIMIT - sizeof(tfm_fault_context)) + 1)) {
 | 
			
		||||
        tfm_memcpy(&tfm_fault_context,
 | 
			
		||||
                   (const void *)sp,
 | 
			
		||||
                   sizeof(tfm_fault_context));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LOG_MSG("Oops... Secure fault!!! You're not going anywhere!");
 | 
			
		||||
    while (1) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#elif defined(__ARM_ARCH_8M_BASE__)
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Overwrites default Hard fault handler.
 | 
			
		||||
 *
 | 
			
		||||
 * In case of a baseline implementation fault conditions that would generate a
 | 
			
		||||
 * SecureFault in a mainline implementation instead generate a Secure HardFault.
 | 
			
		||||
 */
 | 
			
		||||
void HardFault_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    /* In a baseline implementation there is no way, to find out whether this is
 | 
			
		||||
     * a hard fault triggered directly, or another fault that has been
 | 
			
		||||
     * escalated.
 | 
			
		||||
     */
 | 
			
		||||
    while (1) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#error "Unsupported ARM Architecture."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__ARM_ARCH_8M_MAIN__)
 | 
			
		||||
__attribute__((naked)) void SVC_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
    "TST     lr, #4\n"  /* Check store SP in thread mode to r0 */
 | 
			
		||||
    "IT      EQ\n"
 | 
			
		||||
    "BXEQ    lr\n"
 | 
			
		||||
    "MRS     r0, PSP\n"
 | 
			
		||||
    "MOV     r1, lr\n"
 | 
			
		||||
    "BL      SVCHandler_main\n"
 | 
			
		||||
    "BX      r0\n"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
#elif defined(__ARM_ARCH_8M_BASE__)
 | 
			
		||||
__attribute__((naked)) void SVC_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
    ".syntax unified\n"
 | 
			
		||||
    "MOVS    r0, #4\n"  /* Check store SP in thread mode to r0 */
 | 
			
		||||
    "MOV     r1, lr\n"
 | 
			
		||||
    "TST     r0, r1\n"
 | 
			
		||||
    "BEQ     handler\n"
 | 
			
		||||
    "MRS     r0, PSP\n"  /* Coming from thread mode */
 | 
			
		||||
    "B sp_stored\n"
 | 
			
		||||
    "handler:\n"
 | 
			
		||||
    "BX      lr\n"  /* Coming from handler mode */
 | 
			
		||||
    "sp_stored:\n"
 | 
			
		||||
    "MOV     r1, lr\n"
 | 
			
		||||
    "BL      SVCHandler_main\n"
 | 
			
		||||
    "BX      r0\n"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#error "Unsupported ARM Architecture."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
MBED_USED uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t svc_number;
 | 
			
		||||
    /*
 | 
			
		||||
     * Stack contains:
 | 
			
		||||
     * r0, r1, r2, r3, r12, r14 (lr), the return address and xPSR
 | 
			
		||||
     * First argument (r0) is svc_args[0]
 | 
			
		||||
     */
 | 
			
		||||
    if (lr & EXC_RETURN_SECURE_STACK) {
 | 
			
		||||
        /* SV called directly from secure context. Check instruction for
 | 
			
		||||
         * svc_number
 | 
			
		||||
         */
 | 
			
		||||
        svc_number = ((uint8_t *)svc_args[6])[-2];
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Secure SV executing with NS return.
 | 
			
		||||
         * NS cannot directly trigger S SVC so this should not happen
 | 
			
		||||
         * FixMe: check for security implications
 | 
			
		||||
         */
 | 
			
		||||
        return lr;
 | 
			
		||||
    }
 | 
			
		||||
    switch (svc_number) {
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
    case TFM_SVC_IPC_REQUEST:
 | 
			
		||||
        tfm_psa_ipc_request_handler(svc_args);
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_SVC_SCHEDULE:
 | 
			
		||||
    case TFM_SVC_EXIT_THRD:
 | 
			
		||||
    case TFM_SVC_PSA_FRAMEWORK_VERSION:
 | 
			
		||||
    case TFM_SVC_PSA_VERSION:
 | 
			
		||||
    case TFM_SVC_PSA_CONNECT:
 | 
			
		||||
    case TFM_SVC_PSA_CALL:
 | 
			
		||||
    case TFM_SVC_PSA_CLOSE:
 | 
			
		||||
    case TFM_SVC_PSA_WAIT:
 | 
			
		||||
    case TFM_SVC_PSA_GET:
 | 
			
		||||
    case TFM_SVC_PSA_SET_RHANDLE:
 | 
			
		||||
    case TFM_SVC_PSA_READ:
 | 
			
		||||
    case TFM_SVC_PSA_SKIP:
 | 
			
		||||
    case TFM_SVC_PSA_WRITE:
 | 
			
		||||
    case TFM_SVC_PSA_REPLY:
 | 
			
		||||
    case TFM_SVC_PSA_NOTIFY:
 | 
			
		||||
    case TFM_SVC_PSA_CLEAR:
 | 
			
		||||
    case TFM_SVC_PSA_EOI:
 | 
			
		||||
        svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, lr);
 | 
			
		||||
        break;
 | 
			
		||||
#else
 | 
			
		||||
    case TFM_SVC_SFN_REQUEST:
 | 
			
		||||
        lr = tfm_core_partition_request_svc_handler(svc_args, lr);
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_SVC_SFN_RETURN:
 | 
			
		||||
        lr = tfm_core_partition_return_handler(lr);
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_SVC_VALIDATE_SECURE_CALLER:
 | 
			
		||||
        tfm_core_validate_secure_caller_handler(svc_args);
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_SVC_GET_CALLER_CLIENT_ID:
 | 
			
		||||
        tfm_core_get_caller_client_id_handler(svc_args);
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_SVC_SPM_REQUEST:
 | 
			
		||||
        tfm_core_spm_request_handler((struct tfm_exc_stack_t *)svc_args);
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_SVC_MEMORY_CHECK:
 | 
			
		||||
        tfm_core_memory_permission_check_handler(svc_args);
 | 
			
		||||
        break;
 | 
			
		||||
    case TFM_SVC_SET_SHARE_AREA:
 | 
			
		||||
        tfm_core_set_buffer_area_handler(svc_args);
 | 
			
		||||
        break;
 | 
			
		||||
#endif
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return lr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_access_violation_handler(void)
 | 
			
		||||
{
 | 
			
		||||
    while (1) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,100 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_INTERNAL_H__
 | 
			
		||||
#define __TFM_INTERNAL_H__
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function pointer is meant to only hold non secure function pointers.
 | 
			
		||||
 * It will be turned into a non-secure one (LSB cleared) before being called
 | 
			
		||||
 * whatever happens anyway (unless cast to another function pointer type).
 | 
			
		||||
 * Registers will be cleared before branching so that no information leaks
 | 
			
		||||
 * from secure to non-secure world.
 | 
			
		||||
 */
 | 
			
		||||
typedef void __attribute__((cmse_nonsecure_call)) (*nsfptr_t) (void);
 | 
			
		||||
 | 
			
		||||
extern nsfptr_t ns_entry;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Signal that secure partition initialisation is finished
 | 
			
		||||
 */
 | 
			
		||||
void tfm_secure_api_init_done(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Jumps to non-secure code.
 | 
			
		||||
 */
 | 
			
		||||
void jump_to_ns_code(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Called if veneer is running in thread mode
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_core_partition_request_svc_handler(
 | 
			
		||||
        const uint32_t *svc_args, uint32_t lr);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Called when secure service returns
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_core_partition_return_handler(uint32_t lr);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Called by secure service to check if client is secure
 | 
			
		||||
 */
 | 
			
		||||
void tfm_core_validate_secure_caller_handler(const uint32_t svc_args[]);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Stores caller's client id in state context
 | 
			
		||||
 */
 | 
			
		||||
void tfm_core_get_caller_client_id_handler(const uint32_t svc_args[]);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Checks if a secure service's access to a memory location is permitted
 | 
			
		||||
 */
 | 
			
		||||
void tfm_core_memory_permission_check_handler(const uint32_t svc_args[]);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Handle an SPM request by a secure service
 | 
			
		||||
 */
 | 
			
		||||
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__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,45 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_MEMORY_UTILS_H__
 | 
			
		||||
#define __TFM_MEMORY_UTILS_H__
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* FIXME: The following functions are wrappers around standard C library
 | 
			
		||||
 *        functions: memcpy, memcmp, memset
 | 
			
		||||
 *        In long term standard C library might be removed from TF-M project or
 | 
			
		||||
 *        replaced with a secure implementation due to security concerns.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE
 | 
			
		||||
void *tfm_memcpy(void *dest, const void *src, size_t num)
 | 
			
		||||
{
 | 
			
		||||
    return (memcpy(dest, src, num));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE
 | 
			
		||||
int tfm_memcmp(const void *ptr1, const void *ptr2, size_t num)
 | 
			
		||||
{
 | 
			
		||||
    return (memcmp(ptr1, ptr2, num));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE
 | 
			
		||||
void *tfm_memset(void *ptr, int value, size_t num)
 | 
			
		||||
{
 | 
			
		||||
    return (memset(ptr, value, num));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_MEMORY_UTILS_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,324 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
#include "tfm_utils.h"
 | 
			
		||||
#include "tfm_internal.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_MAX_NS_THREAD_COUNT
 | 
			
		||||
#define TFM_MAX_NS_THREAD_COUNT 8
 | 
			
		||||
#endif
 | 
			
		||||
#define INVALID_CLIENT_ID 0
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_NS_CLIENT_ID ((int32_t)-1)
 | 
			
		||||
 | 
			
		||||
#define INVALID_NS_CLIENT_IDX (-1)
 | 
			
		||||
#define DEFAULT_NS_CLIENT_IDX   0
 | 
			
		||||
 | 
			
		||||
typedef uint32_t TZ_ModuleId_t;
 | 
			
		||||
typedef uint32_t TZ_MemoryId_t;
 | 
			
		||||
 | 
			
		||||
static struct ns_client_list_t {
 | 
			
		||||
    int32_t ns_client_id;
 | 
			
		||||
    int32_t next_free_index;
 | 
			
		||||
} NsClientIdList[TFM_MAX_NS_THREAD_COUNT];
 | 
			
		||||
 | 
			
		||||
static int32_t free_index = 0U;
 | 
			
		||||
static int32_t active_ns_client_idx = INVALID_NS_CLIENT_IDX;
 | 
			
		||||
 | 
			
		||||
static int get_next_ns_client_id()
 | 
			
		||||
{
 | 
			
		||||
#ifdef TFM_NS_CLIENT_IDENTIFICATION
 | 
			
		||||
    static int32_t next_ns_client_id = DEFAULT_NS_CLIENT_ID;
 | 
			
		||||
 | 
			
		||||
    if (next_ns_client_id > 0)
 | 
			
		||||
    {
 | 
			
		||||
        next_ns_client_id = DEFAULT_NS_CLIENT_ID;
 | 
			
		||||
    }
 | 
			
		||||
    return next_ns_client_id--;
 | 
			
		||||
#else
 | 
			
		||||
    return DEFAULT_NS_CLIENT_ID;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_nspm_configure_clients(void)
 | 
			
		||||
{
 | 
			
		||||
    int32_t i;
 | 
			
		||||
 | 
			
		||||
    /* Default to one NS client */
 | 
			
		||||
    free_index = 1;
 | 
			
		||||
    NsClientIdList[0].ns_client_id = get_next_ns_client_id();
 | 
			
		||||
    for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
 | 
			
		||||
        NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
 | 
			
		||||
    }
 | 
			
		||||
    active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_nspm_get_current_client_id()
 | 
			
		||||
{
 | 
			
		||||
    if (active_ns_client_idx == INVALID_NS_CLIENT_IDX)
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        return NsClientIdList[active_ns_client_idx].ns_client_id;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TF-M implementation of the CMSIS TZ RTOS thread context management API */
 | 
			
		||||
 | 
			
		||||
/// Initialize secure context memory system
 | 
			
		||||
/// \return execution status (1: success, 0: error)
 | 
			
		||||
/* This veneer is TF-M internal, not a secure service */
 | 
			
		||||
__attribute__((cmse_nonsecure_entry))
 | 
			
		||||
uint32_t TZ_InitContextSystem_S(void)
 | 
			
		||||
{
 | 
			
		||||
    int32_t i;
 | 
			
		||||
 | 
			
		||||
    if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
 | 
			
		||||
        /* This veneer should only be called by NS RTOS in handler mode */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* NS RTOS supports TZ context management, override defaults */
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    LOG_MSG("NS RTOS initialized TZ RTOS context management");
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
    for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
 | 
			
		||||
        NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
 | 
			
		||||
        NsClientIdList[i].next_free_index = i + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Terminate list */
 | 
			
		||||
    NsClientIdList[i - 1].next_free_index = INVALID_NS_CLIENT_IDX;
 | 
			
		||||
    /* Success */
 | 
			
		||||
    return 1U;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Allocate context memory for calling secure software modules in TrustZone
 | 
			
		||||
/// \param[in]  module   identifies software modules called from non-secure mode
 | 
			
		||||
/// \return value != 0 id TrustZone memory slot identifier
 | 
			
		||||
/// \return value 0    no memory available or internal error
 | 
			
		||||
/* This veneer is TF-M internal, not a secure service */
 | 
			
		||||
__attribute__((cmse_nonsecure_entry))
 | 
			
		||||
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module)
 | 
			
		||||
{
 | 
			
		||||
    TZ_MemoryId_t tz_id;
 | 
			
		||||
    (void) module; /* Currently unused */
 | 
			
		||||
 | 
			
		||||
    if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
 | 
			
		||||
        /* This veneer should only be called by NS RTOS in handler mode */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (free_index < 0) {
 | 
			
		||||
        /* No more free slots */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* TZ_MemoryId_t must be a positive integer */
 | 
			
		||||
    tz_id = (TZ_MemoryId_t)free_index + 1;
 | 
			
		||||
    NsClientIdList[free_index].ns_client_id = get_next_ns_client_id();
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    printf("TZ_AllocModuleContext_S called, returning id %d\r\n",
 | 
			
		||||
        NsClientIdList[free_index].ns_client_id);
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
    free_index = NsClientIdList[free_index].next_free_index;
 | 
			
		||||
 | 
			
		||||
    return tz_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
 | 
			
		||||
/// \param[in]  id  TrustZone memory slot identifier
 | 
			
		||||
/// \return execution status (1: success, 0: error)
 | 
			
		||||
/* This veneer is TF-M internal, not a secure service */
 | 
			
		||||
__attribute__((cmse_nonsecure_entry))
 | 
			
		||||
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t index;
 | 
			
		||||
 | 
			
		||||
    if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
 | 
			
		||||
        /* This veneer should only be called by NS RTOS in handler mode */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
 | 
			
		||||
        /* Invalid TZ_MemoryId_t */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    index = id - 1;
 | 
			
		||||
 | 
			
		||||
    if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
 | 
			
		||||
        /* Non-existent client */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    printf("TZ_FreeModuleContext_S called for id %d\r\n",
 | 
			
		||||
        NsClientIdList[index].ns_client_id);
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
    if (active_ns_client_idx == index) {
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
        printf("Freeing active NS client, NS inactive\r\n");
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
        active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
 | 
			
		||||
    }
 | 
			
		||||
    NsClientIdList[index].ns_client_id = INVALID_CLIENT_ID;
 | 
			
		||||
    NsClientIdList[index].next_free_index = free_index;
 | 
			
		||||
 | 
			
		||||
    free_index = index;
 | 
			
		||||
 | 
			
		||||
    return 1U;    // Success
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Load secure context (called on RTOS thread context switch)
 | 
			
		||||
/// \param[in]  id  TrustZone memory slot identifier
 | 
			
		||||
/// \return execution status (1: success, 0: error)
 | 
			
		||||
/* This veneer is TF-M internal, not a secure service */
 | 
			
		||||
__attribute__((cmse_nonsecure_entry))
 | 
			
		||||
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t index;
 | 
			
		||||
 | 
			
		||||
    if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
 | 
			
		||||
        /* This veneer should only be called by NS RTOS in handler mode */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    LOG_MSG("TZ_LoadContext_S called");
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
    if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
 | 
			
		||||
        /* Invalid TZ_MemoryId_t */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    index = id - 1;
 | 
			
		||||
 | 
			
		||||
    if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
 | 
			
		||||
        /* Non-existent client */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    active_ns_client_idx = index;
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    printf("TZ_LoadContext_S called for id %d\r\n",
 | 
			
		||||
        NsClientIdList[index].ns_client_id);
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
 | 
			
		||||
    return 1U;    // Success
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Store secure context (called on RTOS thread context switch)
 | 
			
		||||
/// \param[in]  id  TrustZone memory slot identifier
 | 
			
		||||
/// \return execution status (1: success, 0: error)
 | 
			
		||||
/* This veneer is TF-M internal, not a secure service */
 | 
			
		||||
__attribute__((cmse_nonsecure_entry))
 | 
			
		||||
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t index;
 | 
			
		||||
 | 
			
		||||
    if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
 | 
			
		||||
        /* This veneer should only be called by NS RTOS in handler mode */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    LOG_MSG("TZ_StoreContext_S called");
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
    /* id corresponds to context being swapped out on NS side */
 | 
			
		||||
    if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
 | 
			
		||||
        /* Invalid TZ_MemoryId_t */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    index = id - 1;
 | 
			
		||||
 | 
			
		||||
    if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
 | 
			
		||||
        /* Non-existent client */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (active_ns_client_idx != index) {
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
        printf("TZ_StoreContext_S called for id %d, active id: %d\r\n",
 | 
			
		||||
            NsClientIdList[index].ns_client_id,
 | 
			
		||||
            NsClientIdList[active_ns_client_idx].ns_client_id);
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
        return 0U;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    printf("TZ_StoreContext_S called for id %d\r\n",
 | 
			
		||||
        NsClientIdList[index].ns_client_id);
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
    active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
 | 
			
		||||
 | 
			
		||||
    return 1U;    // Success
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_NS_CLIENT_IDENTIFICATION
 | 
			
		||||
__attribute__((cmse_nonsecure_entry))
 | 
			
		||||
enum tfm_status_e tfm_register_client_id (int32_t ns_client_id)
 | 
			
		||||
{
 | 
			
		||||
    int current_client_id;
 | 
			
		||||
 | 
			
		||||
    if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
 | 
			
		||||
        /* This veneer should only be called by NS RTOS in handler mode */
 | 
			
		||||
        return TFM_ERROR_NS_THREAD_MODE_CALL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ns_client_id >= 0) {
 | 
			
		||||
        /* The client ID is invalid */
 | 
			
		||||
        return TFM_ERROR_INVALID_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (active_ns_client_idx < 0) {
 | 
			
		||||
        /* No client is active */
 | 
			
		||||
        return TFM_ERROR_GENERIC;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    current_client_id = NsClientIdList[active_ns_client_idx].ns_client_id;
 | 
			
		||||
    if (current_client_id >= 0 ) {
 | 
			
		||||
        /* The client ID is invalid */
 | 
			
		||||
        return TFM_ERROR_INVALID_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    NsClientIdList[active_ns_client_idx].ns_client_id = ns_client_id;
 | 
			
		||||
#ifdef PRINT_NSPM_DEBUG
 | 
			
		||||
    printf("tfm_register_client_id called with id %d\r\n", ns_client_id);
 | 
			
		||||
#endif /* PRINT_NSPM_DEBUG */
 | 
			
		||||
 | 
			
		||||
    return TFM_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
__attribute__((section("SFN")))
 | 
			
		||||
psa_status_t tfm_nspm_thread_entry(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef TFM_CORE_DEBUG
 | 
			
		||||
    /* Jumps to non-secure code */
 | 
			
		||||
    LOG_MSG("Jumping to non-secure code...");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    jump_to_ns_code();
 | 
			
		||||
 | 
			
		||||
    /* Should not run here */
 | 
			
		||||
    TFM_ASSERT(false);
 | 
			
		||||
    return PSA_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,37 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_NSPM_H__
 | 
			
		||||
#define __TFM_NSPM_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief initialise the NS context database
 | 
			
		||||
 */
 | 
			
		||||
void tfm_nspm_configure_clients(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the client ID of the current NS client
 | 
			
		||||
 *
 | 
			
		||||
 * \return The client id of the current NS client. 0 (invalid client id) is
 | 
			
		||||
 *         returned in case of error.
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_nspm_get_current_client_id(void);
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
/**
 | 
			
		||||
 * \brief NSPM thread main entry function
 | 
			
		||||
 *
 | 
			
		||||
 * \return  PSA_SUCCESS indicates failed.
 | 
			
		||||
 *
 | 
			
		||||
 * Note: This function should not return back.
 | 
			
		||||
 */
 | 
			
		||||
psa_status_t tfm_nspm_thread_entry(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_NSPM_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_PLATFORM_CORE_API_H__
 | 
			
		||||
#define __TFM_PLATFORM_CORE_API_H__
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Should be called in case of access violation.
 | 
			
		||||
 *
 | 
			
		||||
 * There might be platform specific means, by which it is possible on a
 | 
			
		||||
 * subsystem to detect access violation. For example a platform can have a
 | 
			
		||||
 * Peripheral Protection Controller, to detect unauthorised accesses to
 | 
			
		||||
 * peripheral registers. Setting up the protection, and handling the violation
 | 
			
		||||
 * is implemented in platform specific code. However TF-M should be able to
 | 
			
		||||
 * decide how to proceed if a violation happens. So to notify TF-M, platform
 | 
			
		||||
 * code have to call this function, if a violation happens.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_access_violation_handler(void);
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_PLATFORM_CORE_API_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,176 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <arm_cmse.h>
 | 
			
		||||
#include "tfm_secure_api.h"
 | 
			
		||||
#include "tfm_nspm.h"
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
#include "secure_fw/spm/spm_api.h"
 | 
			
		||||
#include "region_defs.h"
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
 | 
			
		||||
#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_LVL
 | 
			
		||||
#error TFM_LVL is not defined!
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Macros to pick linker symbols and allow references to sections */
 | 
			
		||||
#define REGION(a, b, c) a##b##c
 | 
			
		||||
#define REGION_NAME(a, b, c) REGION(a, b, c)
 | 
			
		||||
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
 | 
			
		||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
 | 
			
		||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
 | 
			
		||||
#endif /* !defined(TFM_PSA_API) */
 | 
			
		||||
 | 
			
		||||
/* This is the "Big Lock" on the secure side, to guarantee single entry
 | 
			
		||||
 * to SPE
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_secure_lock;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Check whether a memory range is inside a memory region.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] p             The start address of the range to check
 | 
			
		||||
 * \param[in] s             The size of the range to check
 | 
			
		||||
 * \param[in] region_start  The start address of the region, which should
 | 
			
		||||
 *                          contain the range
 | 
			
		||||
 * \param[in] region_len    The size of the region, which should contain the
 | 
			
		||||
 *                          range
 | 
			
		||||
 *
 | 
			
		||||
 * \return TFM_SUCCESS if the region contains the range,
 | 
			
		||||
 *         TFM_ERROR_GENERIC otherwise.
 | 
			
		||||
 */
 | 
			
		||||
static int32_t check_address_range(const void *p, size_t s,
 | 
			
		||||
                                   uintptr_t region_start, uint32_t region_len)
 | 
			
		||||
{
 | 
			
		||||
    int32_t range_in_region;
 | 
			
		||||
 | 
			
		||||
    /* Check for overflow in the range parameters */
 | 
			
		||||
    if ((uintptr_t)p > UINTPTR_MAX-s) {
 | 
			
		||||
        return TFM_ERROR_GENERIC;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* We trust the region parameters, and don't check for overflow */
 | 
			
		||||
 | 
			
		||||
    /* Calculate the result */
 | 
			
		||||
    range_in_region = ((uintptr_t)p >= region_start) &&
 | 
			
		||||
                      ((uintptr_t)p+s <= region_start+region_len);
 | 
			
		||||
    if (range_in_region) {
 | 
			
		||||
        return TFM_SUCCESS;
 | 
			
		||||
    } else {
 | 
			
		||||
        return TFM_ERROR_GENERIC;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Check whether the current partition has access to a memory range
 | 
			
		||||
 *
 | 
			
		||||
 * This function assumes, that the current MPU configuration is set for the
 | 
			
		||||
 * partition to be checked. The flags should contain information of the
 | 
			
		||||
 * execution mode of the partition code (priv/unpriv), and access type
 | 
			
		||||
 * (read/write) as specified in "ARMv8-M Security Extensions: Requirements on
 | 
			
		||||
 * Development Tools" chapter "Address range check intrinsic"
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] p      The start address of the range to check
 | 
			
		||||
 * \param[in] s      The size of the range to check
 | 
			
		||||
 * \param[in] flags  The flags to pass to the cmse_check_address_range func
 | 
			
		||||
 *
 | 
			
		||||
 * \return TFM_SUCCESS if the partition has access to the memory range,
 | 
			
		||||
 *         TFM_ERROR_GENERIC otherwise.
 | 
			
		||||
 */
 | 
			
		||||
static int32_t has_access_to_region(const void *p, size_t s, int flags)
 | 
			
		||||
{
 | 
			
		||||
    int32_t range_access_allowed_by_mpu;
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
 | 
			
		||||
    uint32_t scratch_base =
 | 
			
		||||
        (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
 | 
			
		||||
    uint32_t scratch_limit =
 | 
			
		||||
        (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
 | 
			
		||||
#endif /* !defined(TFM_PSA_API) */
 | 
			
		||||
 | 
			
		||||
    /* Use the TT instruction to check access to the partition's regions*/
 | 
			
		||||
    range_access_allowed_by_mpu =
 | 
			
		||||
                          cmse_check_address_range((void *)p, s, flags) != NULL;
 | 
			
		||||
 | 
			
		||||
    if (range_access_allowed_by_mpu) {
 | 
			
		||||
        return TFM_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
 | 
			
		||||
    /* If the check for the current MPU settings fails, check for the share
 | 
			
		||||
     * region, only if the partition is secure
 | 
			
		||||
     */
 | 
			
		||||
    if ((flags & CMSE_NONSECURE) == 0) {
 | 
			
		||||
        if (check_address_range(p, s, scratch_base,
 | 
			
		||||
                                scratch_limit+1-scratch_base) == TFM_SUCCESS) {
 | 
			
		||||
            return TFM_SUCCESS;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif /* !defined(TFM_PSA_API) */
 | 
			
		||||
 | 
			
		||||
    /* If all else fails, check whether the region is in the non-secure
 | 
			
		||||
     * memory
 | 
			
		||||
     */
 | 
			
		||||
    if (check_address_range(p, s, NS_CODE_START,
 | 
			
		||||
                            NS_CODE_LIMIT+1-NS_CODE_START) == TFM_SUCCESS ||
 | 
			
		||||
        check_address_range(p, s, NS_DATA_START,
 | 
			
		||||
                            NS_DATA_LIMIT+1-NS_DATA_START) == TFM_SUCCESS) {
 | 
			
		||||
        return TFM_SUCCESS;
 | 
			
		||||
    } else {
 | 
			
		||||
        return TFM_ERROR_GENERIC;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
 | 
			
		||||
                                           uint32_t ns_caller,
 | 
			
		||||
                                           uint32_t privileged)
 | 
			
		||||
{
 | 
			
		||||
    int flags = CMSE_MPU_READ;
 | 
			
		||||
 | 
			
		||||
    if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
 | 
			
		||||
        flags |= CMSE_MPU_UNPRIV;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ns_caller) {
 | 
			
		||||
        flags |= CMSE_NONSECURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return has_access_to_region(p, s, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
 | 
			
		||||
                                            uint32_t ns_caller,
 | 
			
		||||
                                            uint32_t privileged)
 | 
			
		||||
{
 | 
			
		||||
    int flags = CMSE_MPU_READWRITE;
 | 
			
		||||
 | 
			
		||||
    if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
 | 
			
		||||
        flags |= CMSE_MPU_UNPRIV;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ns_caller) {
 | 
			
		||||
        flags |= CMSE_NONSECURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return has_access_to_region(p, s, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_secure_api_error_handler(void)
 | 
			
		||||
{
 | 
			
		||||
    ERROR_MSG("Security violation when calling secure API");
 | 
			
		||||
    while (1) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,214 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_SECURE_API_H__
 | 
			
		||||
#define __TFM_SECURE_API_H__
 | 
			
		||||
 | 
			
		||||
#include <arm_cmse.h>
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
#include "tfm_core.h"
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
#include "bl2/include/tfm_boot_status.h"
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \def __tfm_secure_gateway_attributes__
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Attributes for secure gateway functions
 | 
			
		||||
 */
 | 
			
		||||
#define __tfm_secure_gateway_attributes__ \
 | 
			
		||||
        __attribute__((cmse_nonsecure_entry, noinline, section("SFN")))
 | 
			
		||||
 | 
			
		||||
/* Hide specific errors if not debugging */
 | 
			
		||||
#ifdef TFM_CORE_DEBUG
 | 
			
		||||
#define TFM_ERROR_STATUS(status) (status)
 | 
			
		||||
#else
 | 
			
		||||
#define TFM_ERROR_STATUS(status) (TFM_PARTITION_BUSY)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define TFM_SFN_API_LEGACY 0
 | 
			
		||||
#define TFM_SFN_API_IOVEC 1
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_LVL
 | 
			
		||||
#error TFM_LVL is not defined!
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern void tfm_secure_api_error_handler(void);
 | 
			
		||||
 | 
			
		||||
typedef int32_t(*sfn_t)(int32_t, int32_t, int32_t, int32_t);
 | 
			
		||||
 | 
			
		||||
struct tfm_sfn_req_s {
 | 
			
		||||
    uint32_t sp_id;
 | 
			
		||||
    sfn_t sfn;
 | 
			
		||||
    int32_t *args;
 | 
			
		||||
    uint32_t caller_part_idx;
 | 
			
		||||
    int32_t iovec_api;
 | 
			
		||||
    uint32_t ns_caller;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum tfm_buffer_share_region_e {
 | 
			
		||||
    TFM_BUFFER_SHARE_DISABLE,
 | 
			
		||||
    TFM_BUFFER_SHARE_NS_CODE,
 | 
			
		||||
    TFM_BUFFER_SHARE_SCRATCH,
 | 
			
		||||
    TFM_BUFFER_SHARE_PRIV, /* only for TCB in level 2, all in level 1 */
 | 
			
		||||
    TFM_BUFFER_SHARE_DEFAULT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum tfm_ns_region_e {
 | 
			
		||||
    TFM_NS_REGION_CODE = 0,
 | 
			
		||||
    TFM_NS_REGION_DATA,
 | 
			
		||||
    TFM_NS_REGION_VENEER,
 | 
			
		||||
    TFM_NS_REGION_PERIPH_1,
 | 
			
		||||
    TFM_NS_REGION_PERIPH_2,
 | 
			
		||||
    TFM_NS_SECONDARY_IMAGE_REGION,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum tfm_memory_access_e {
 | 
			
		||||
    TFM_MEMORY_ACCESS_RO = 1,
 | 
			
		||||
    TFM_MEMORY_ACCESS_RW = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern int32_t tfm_core_set_buffer_area(enum tfm_buffer_share_region_e share);
 | 
			
		||||
 | 
			
		||||
extern int32_t tfm_core_validate_secure_caller(void);
 | 
			
		||||
 | 
			
		||||
extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);
 | 
			
		||||
 | 
			
		||||
extern int32_t tfm_core_memory_permission_check(const void *ptr,
 | 
			
		||||
                                                uint32_t size,
 | 
			
		||||
                                                int32_t access);
 | 
			
		||||
 | 
			
		||||
extern int32_t tfm_core_get_boot_data(uint8_t major_type,
 | 
			
		||||
                                      struct tfm_boot_data *boot_data,
 | 
			
		||||
                                      uint32_t len);
 | 
			
		||||
 | 
			
		||||
int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr);
 | 
			
		||||
 | 
			
		||||
int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Check whether the current partition has read access to a memory range
 | 
			
		||||
 *
 | 
			
		||||
 * This function assumes, that the current MPU configuration is set for the
 | 
			
		||||
 * partition to be checked.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] p                The start address of the range to check
 | 
			
		||||
 * \param[in] s                The size of the range to check
 | 
			
		||||
 * \param[in] ns_caller        Whether the current partition is a non-secure one
 | 
			
		||||
 * \param[in] privileged       Privileged mode or unprivileged mode:
 | 
			
		||||
 *                             \ref TFM_PARTITION_UNPRIVILEGED_MODE
 | 
			
		||||
 *                             \ref TFM_PARTITION_PRIVILEGED_MODE
 | 
			
		||||
 *
 | 
			
		||||
 * \return TFM_SUCCESS if the partition has access to the memory range,
 | 
			
		||||
 *         TFM_ERROR_GENERIC otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
 | 
			
		||||
                                           uint32_t ns_caller,
 | 
			
		||||
                                           uint32_t privileged);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Check whether the current partition has write access to a memory range
 | 
			
		||||
 *
 | 
			
		||||
 * This function assumes, that the current MPU configuration is set for the
 | 
			
		||||
 * partition to be checked.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] p                The start address of the range to check
 | 
			
		||||
 * \param[in] s                The size of the range to check
 | 
			
		||||
 * \param[in] ns_caller        Whether the current partition is a non-secure one
 | 
			
		||||
 * \param[in] privileged       Privileged mode or unprivileged mode:
 | 
			
		||||
 *                             \ref TFM_PARTITION_UNPRIVILEGED_MODE
 | 
			
		||||
 *                             \ref TFM_PARTITION_PRIVILEGED_MODE
 | 
			
		||||
 *
 | 
			
		||||
 * \return TFM_SUCCESS if the partition has access to the memory range,
 | 
			
		||||
 *         TFM_ERROR_GENERIC otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
 | 
			
		||||
                                            uint32_t ns_caller,
 | 
			
		||||
                                            uint32_t privileged);
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
/* The following macros are only valid if secure services can be called
 | 
			
		||||
 * using veneer functions. This is not the case if IPC messaging is enabled
 | 
			
		||||
 */
 | 
			
		||||
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d)               \
 | 
			
		||||
        do {                                                         \
 | 
			
		||||
            ERROR_MSG("Invalid TF-M configuration detected");        \
 | 
			
		||||
            tfm_secure_api_error_handler();                          \
 | 
			
		||||
            /* This point never reached */                           \
 | 
			
		||||
            return (int32_t)TFM_ERROR_GENERIC;                       \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d)                     \
 | 
			
		||||
        do {                                                         \
 | 
			
		||||
            ERROR_MSG("Invalid TF-M configuration detected");        \
 | 
			
		||||
            tfm_secure_api_error_handler();                          \
 | 
			
		||||
            /* This point never reached */                           \
 | 
			
		||||
            return (int32_t)TFM_ERROR_GENERIC;                       \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#else
 | 
			
		||||
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
 | 
			
		||||
        return tfm_core_partition_request(id, fn, TFM_SFN_API_IOVEC, \
 | 
			
		||||
                (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
 | 
			
		||||
 | 
			
		||||
#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
 | 
			
		||||
        return tfm_core_partition_request(id, fn, TFM_SFN_API_LEGACY, \
 | 
			
		||||
                (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE
 | 
			
		||||
int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t iovec_api,
 | 
			
		||||
            int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
 | 
			
		||||
{
 | 
			
		||||
    int32_t args[4] = {arg1, arg2, arg3, arg4};
 | 
			
		||||
    struct tfm_sfn_req_s desc, *desc_ptr = &desc;
 | 
			
		||||
 | 
			
		||||
    desc.sp_id = id;
 | 
			
		||||
    desc.sfn = (sfn_t) fn;
 | 
			
		||||
    desc.args = args;
 | 
			
		||||
    /*
 | 
			
		||||
     * This preprocessor condition checks if a version of GCC smaller than
 | 
			
		||||
     * 7.3.1 is being used to compile the code.
 | 
			
		||||
     * These versions are affected by a bug on the cmse_nonsecure_caller
 | 
			
		||||
     * intrinsic which returns incorrect results.
 | 
			
		||||
     * Please check Bug 85203 on GCC Bugzilla for more information.
 | 
			
		||||
     */
 | 
			
		||||
#if defined(__GNUC__) && !defined(__ARMCC_VERSION) && \
 | 
			
		||||
    (__GNUC__ < 7 || \
 | 
			
		||||
     (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || \
 | 
			
		||||
                       (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ < 1))))
 | 
			
		||||
    /*
 | 
			
		||||
     * Use the fact that, if called from Non-Secure, the LSB of the return
 | 
			
		||||
     * address is set to 0.
 | 
			
		||||
     */
 | 
			
		||||
    desc.ns_caller = (uint32_t)!(
 | 
			
		||||
           (intptr_t)__builtin_extract_return_addr(__builtin_return_address(0U))
 | 
			
		||||
           & 1);
 | 
			
		||||
#else
 | 
			
		||||
    /*
 | 
			
		||||
     * Convert the result of cmse_nonsecure_caller from an int to a uint32_t
 | 
			
		||||
     * to prevent using an int in the tfm_sfn_req_s structure.
 | 
			
		||||
     */
 | 
			
		||||
    desc.ns_caller = (cmse_nonsecure_caller() != 0) ? 1U : 0U;
 | 
			
		||||
#endif /* Check for GCC compiler version smaller than 7.3.1 */
 | 
			
		||||
    desc.iovec_api = iovec_api;
 | 
			
		||||
    if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
 | 
			
		||||
        /* FixMe: Error severity TBD */
 | 
			
		||||
        return TFM_ERROR_GENERIC;
 | 
			
		||||
    } else {
 | 
			
		||||
#if TFM_LVL == 1
 | 
			
		||||
        if (desc.ns_caller) {
 | 
			
		||||
            return tfm_core_sfn_request(desc_ptr);
 | 
			
		||||
        } else {
 | 
			
		||||
            return tfm_core_sfn_request_thread_mode(desc_ptr);
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
        return tfm_core_sfn_request(desc_ptr);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_SECURE_API_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,166 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <arm_cmse.h>
 | 
			
		||||
 | 
			
		||||
#include "tfm_svc.h"
 | 
			
		||||
#include "tfm_secure_api.h"
 | 
			
		||||
#include "tfm_internal.h"
 | 
			
		||||
#include "secure_fw/include/tfm_spm_services_api.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
 | 
			
		||||
uint8_t *tfm_scratch_area;
 | 
			
		||||
uint32_t tfm_scratch_area_size;
 | 
			
		||||
nsfptr_t ns_entry;
 | 
			
		||||
 | 
			
		||||
void jump_to_ns_code(void)
 | 
			
		||||
{
 | 
			
		||||
#if TFM_LVL == 3 || ((!defined(TFM_PSA_API)) && (TFM_LVL != 1))
 | 
			
		||||
    /* Initialization is done, set thread mode to unprivileged. */
 | 
			
		||||
    tfm_spm_partition_change_privilege(TFM_PARTITION_UNPRIVILEGED_MODE);
 | 
			
		||||
#endif
 | 
			
		||||
    /* All changes made to memory will be effective after this point */
 | 
			
		||||
    __DSB();
 | 
			
		||||
    __ISB();
 | 
			
		||||
 | 
			
		||||
    /* Calls the non-secure Reset_Handler to jump to the non-secure binary */
 | 
			
		||||
    ns_entry();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API
 | 
			
		||||
#if defined(__ARM_ARCH_8M_MAIN__)
 | 
			
		||||
__attribute__((naked)) int32_t tfm_core_sfn_request(
 | 
			
		||||
                                           const struct tfm_sfn_req_s *desc_ptr)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
          "PUSH   {r4-r12, lr}\n"
 | 
			
		||||
          "SVC    %[SVC_REQ]\n"
 | 
			
		||||
          "MOV    r4, #0\n"
 | 
			
		||||
          "MOV    r5, #0\n"
 | 
			
		||||
          "MOV    r6, #0\n"
 | 
			
		||||
          "MOV    r7, #0\n"
 | 
			
		||||
          "MOV    r8, #0\n"
 | 
			
		||||
          "MOV    r9, #0\n"
 | 
			
		||||
          "MOV    r10, #0\n"
 | 
			
		||||
          "MOV    r11, #0\n"
 | 
			
		||||
          "BLX    lr\n"
 | 
			
		||||
          "SVC    %[SVC_RET]\n"
 | 
			
		||||
          "POP    {r4-r12, pc}\n"
 | 
			
		||||
          : : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST)
 | 
			
		||||
            , [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
 | 
			
		||||
          : "r0");
 | 
			
		||||
}
 | 
			
		||||
#elif defined(__ARM_ARCH_8M_BASE__)
 | 
			
		||||
__attribute__((naked)) int32_t tfm_core_sfn_request(
 | 
			
		||||
                                           const struct tfm_sfn_req_s *desc_ptr)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
          ".syntax unified\n"
 | 
			
		||||
          "PUSH   {lr}\n"
 | 
			
		||||
          "PUSH   {r4-r7}\n"
 | 
			
		||||
          "MOV    r4, r8\n"
 | 
			
		||||
          "MOV    r5, r9\n"
 | 
			
		||||
          "MOV    r6, r10\n"
 | 
			
		||||
          "MOV    r7, r11\n"
 | 
			
		||||
          "PUSH   {r4-r7}\n"
 | 
			
		||||
          "MOV    r4, r12\n"
 | 
			
		||||
          "PUSH   {r4}\n"
 | 
			
		||||
          "SVC    %[SVC_REQ]\n"
 | 
			
		||||
          "MOVS   r4, #0\n"
 | 
			
		||||
          "MOV    r5, r4\n"
 | 
			
		||||
          "MOV    r6, r4\n"
 | 
			
		||||
          "MOV    r7, r4\n"
 | 
			
		||||
          "MOV    r8, r4\n"
 | 
			
		||||
          "MOV    r9, r4\n"
 | 
			
		||||
          "MOV    r10, r4\n"
 | 
			
		||||
          "MOV    r11, r4\n"
 | 
			
		||||
          "BLX    lr\n"
 | 
			
		||||
          "SVC    %[SVC_RET]\n"
 | 
			
		||||
          "POP    {r4}\n"
 | 
			
		||||
          "MOV    r12, r4\n"
 | 
			
		||||
          "POP    {r4-r7}\n"
 | 
			
		||||
          "MOV    r8, r4\n"
 | 
			
		||||
          "MOV    r9, r5\n"
 | 
			
		||||
          "MOV    r10, r6\n"
 | 
			
		||||
          "MOV    r11, r7\n"
 | 
			
		||||
          "POP    {r4-r7}\n"
 | 
			
		||||
          "POP    {pc}\n"
 | 
			
		||||
          : : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST)
 | 
			
		||||
            , [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
 | 
			
		||||
          : "r0");
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#error "Unsupported ARM Architecture."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
__attribute__((naked))
 | 
			
		||||
int32_t tfm_core_memory_permission_check(const void *ptr,
 | 
			
		||||
                                         uint32_t len,
 | 
			
		||||
                                         int32_t access)
 | 
			
		||||
{
 | 
			
		||||
  __ASM volatile(
 | 
			
		||||
        "SVC    %0\n"
 | 
			
		||||
        "BX     lr\n"
 | 
			
		||||
        : : "I" (TFM_SVC_MEMORY_CHECK));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked))
 | 
			
		||||
int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "SVC %0\n"
 | 
			
		||||
        "BX LR\n"
 | 
			
		||||
        : : "I" (TFM_SVC_GET_CALLER_CLIENT_ID));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked))
 | 
			
		||||
int32_t tfm_spm_request_reset_vote(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "MOVS   R0, %0\n"
 | 
			
		||||
        "B      tfm_spm_request\n"
 | 
			
		||||
        : : "I" (TFM_SPM_REQUEST_RESET_VOTE));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked))
 | 
			
		||||
int32_t tfm_spm_request(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "SVC    %0\n"
 | 
			
		||||
        "BX     lr\n"
 | 
			
		||||
        : : "I" (TFM_SVC_SPM_REQUEST));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked))
 | 
			
		||||
int32_t tfm_core_validate_secure_caller(void)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "SVC    %0\n"
 | 
			
		||||
        "BX     lr\n"
 | 
			
		||||
        : : "I" (TFM_SVC_VALIDATE_SECURE_CALLER));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((naked))
 | 
			
		||||
int32_t tfm_core_set_buffer_area(enum tfm_buffer_share_region_e share)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "SVC    %0\n"
 | 
			
		||||
        "BX     lr\n"
 | 
			
		||||
        : : "I" (TFM_SVC_SET_SHARE_AREA));
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
__attribute__((naked))
 | 
			
		||||
int32_t tfm_core_get_boot_data(uint8_t major_type,
 | 
			
		||||
                               struct tfm_boot_data *boot_status,
 | 
			
		||||
                               uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile(
 | 
			
		||||
        "SVC    %0\n"
 | 
			
		||||
        "BX     lr\n"
 | 
			
		||||
        : : "I" (TFM_SVC_GET_BOOT_DATA));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_SVC_H__
 | 
			
		||||
#define __TFM_SVC_H__
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    TFM_SVC_SFN_REQUEST = 0,
 | 
			
		||||
    TFM_SVC_SFN_RETURN,
 | 
			
		||||
    TFM_SVC_VALIDATE_SECURE_CALLER,
 | 
			
		||||
    TFM_SVC_GET_CALLER_CLIENT_ID,
 | 
			
		||||
    TFM_SVC_MEMORY_CHECK,
 | 
			
		||||
    TFM_SVC_SET_SHARE_AREA,
 | 
			
		||||
    TFM_SVC_SPM_REQUEST,
 | 
			
		||||
    TFM_SVC_PRINT,
 | 
			
		||||
    TFM_SVC_GET_BOOT_DATA,
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
    TFM_SVC_IPC_REQUEST,
 | 
			
		||||
    TFM_SVC_SCHEDULE,
 | 
			
		||||
    TFM_SVC_EXIT_THRD,
 | 
			
		||||
    /* PSA Client SVC */
 | 
			
		||||
    TFM_SVC_PSA_FRAMEWORK_VERSION,
 | 
			
		||||
    TFM_SVC_PSA_VERSION,
 | 
			
		||||
    TFM_SVC_PSA_CONNECT,
 | 
			
		||||
    TFM_SVC_PSA_CALL,
 | 
			
		||||
    TFM_SVC_PSA_CLOSE,
 | 
			
		||||
    /* PSA Service SVC */
 | 
			
		||||
    TFM_SVC_PSA_WAIT,
 | 
			
		||||
    TFM_SVC_PSA_GET,
 | 
			
		||||
    TFM_SVC_PSA_SET_RHANDLE,
 | 
			
		||||
    TFM_SVC_PSA_READ,
 | 
			
		||||
    TFM_SVC_PSA_SKIP,
 | 
			
		||||
    TFM_SVC_PSA_WRITE,
 | 
			
		||||
    TFM_SVC_PSA_REPLY,
 | 
			
		||||
    TFM_SVC_PSA_NOTIFY,
 | 
			
		||||
    TFM_SVC_PSA_CLEAR,
 | 
			
		||||
    TFM_SVC_PSA_EOI,
 | 
			
		||||
#endif
 | 
			
		||||
} tfm_svc_number_t;
 | 
			
		||||
 | 
			
		||||
#define SVC(code) __ASM volatile("svc %0" : : "I" (code))
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_SVC_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//This file holds description for the current directory. This documentation
 | 
			
		||||
//will be included in the Doxygen output.
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
\dir
 | 
			
		||||
\brief Include files for the TF-M.
 | 
			
		||||
\details This directory currently only holds the include file for the SPM
 | 
			
		||||
module.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
| 
						 | 
				
			
			@ -1,22 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __TFM_SPM_SERVICES_API_H__
 | 
			
		||||
#define __TFM_SPM_SERVICES_API_H__
 | 
			
		||||
 | 
			
		||||
enum tfm_spm_request_type_t {
 | 
			
		||||
    TFM_SPM_REQUEST_RESET_VOTE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Request a vote from SPM on a system reset
 | 
			
		||||
 *
 | 
			
		||||
 * \return Returns 0 if request is accepted, any other value means reject
 | 
			
		||||
 */
 | 
			
		||||
int32_t tfm_spm_request_reset_vote(void);
 | 
			
		||||
 | 
			
		||||
#endif /* __TFM_SPM_SERVICES_API_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,134 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "psa_client.h"
 | 
			
		||||
#include "psa_service.h"
 | 
			
		||||
#include "secure_utilities.h"
 | 
			
		||||
#include "tfm_secure_api.h"
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
#include "tfm_svcalls.h"
 | 
			
		||||
 | 
			
		||||
/* FixMe: check if this is really needed */
 | 
			
		||||
extern int32_t tfm_secure_lock;
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE
 | 
			
		||||
int32_t tfm_psa_veneer_sanity_check(struct tfm_sfn_req_s *desc_ptr)
 | 
			
		||||
{
 | 
			
		||||
    if (desc_ptr->ns_caller) {
 | 
			
		||||
        if (tfm_secure_lock != 0) {
 | 
			
		||||
            /* Secure domain is already locked!
 | 
			
		||||
             * FixMe: Decide if this is a fault or permitted in case of PSA
 | 
			
		||||
             * API usage
 | 
			
		||||
             */
 | 
			
		||||
            return TFM_ERROR_SECURE_DOMAIN_LOCKED;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Secure partition should not call a different secure partition
 | 
			
		||||
         * using TFM PSA veneers
 | 
			
		||||
         */
 | 
			
		||||
        return TFM_ERROR_INVALID_EXC_MODE;
 | 
			
		||||
    }
 | 
			
		||||
    return TFM_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Veneer implementation */
 | 
			
		||||
 | 
			
		||||
#define TFM_CORE_NS_IPC_REQUEST_VENEER(fn, a, b, c, d) \
 | 
			
		||||
            return tfm_core_ns_ipc_request(fn, (int32_t)a, (int32_t)b, \
 | 
			
		||||
                (int32_t)c, (int32_t)d)
 | 
			
		||||
 | 
			
		||||
__attribute__ ((naked, section("SFN")))
 | 
			
		||||
static int32_t tfm_core_ipc_request(const struct tfm_sfn_req_s *desc_ptr)
 | 
			
		||||
{
 | 
			
		||||
    __ASM volatile("SVC %0           \n"
 | 
			
		||||
                   "BX LR            \n"
 | 
			
		||||
                   : : "I" (TFM_SVC_IPC_REQUEST));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE
 | 
			
		||||
int32_t tfm_core_ns_ipc_request(void *fn, int32_t arg1, int32_t arg2,
 | 
			
		||||
                                int32_t arg3, int32_t arg4)
 | 
			
		||||
{
 | 
			
		||||
    int32_t args[4] = {arg1, arg2, arg3, arg4};
 | 
			
		||||
    struct tfm_sfn_req_s desc = {0};
 | 
			
		||||
 | 
			
		||||
    desc.sfn = fn;
 | 
			
		||||
    desc.args = args;
 | 
			
		||||
    desc.ns_caller = cmse_nonsecure_caller();
 | 
			
		||||
 | 
			
		||||
    if (__get_active_exc_num() != EXC_NUM_THREAD_MODE)
 | 
			
		||||
    {
 | 
			
		||||
        /* FIXME: Proper error handling to be implemented */
 | 
			
		||||
        return TFM_ERROR_INVALID_EXC_MODE;
 | 
			
		||||
    } else {
 | 
			
		||||
        return tfm_core_ipc_request(&desc);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FixMe: these functions need to have different attributes compared to those
 | 
			
		||||
 * legacy veneers which may be called by secure partitions.
 | 
			
		||||
 * They won't call legacy SFN but instead will be handlers for TF-M
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
__tfm_secure_gateway_attributes__
 | 
			
		||||
uint32_t tfm_psa_framework_version_veneer(void)
 | 
			
		||||
{
 | 
			
		||||
    TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_framework_version, 0, 0,
 | 
			
		||||
                                   0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__tfm_secure_gateway_attributes__
 | 
			
		||||
uint32_t tfm_psa_version_veneer(uint32_t sid)
 | 
			
		||||
{
 | 
			
		||||
    TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_version, sid, 0, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__tfm_secure_gateway_attributes__
 | 
			
		||||
psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version)
 | 
			
		||||
{
 | 
			
		||||
    TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_connect, sid,
 | 
			
		||||
                                   minor_version, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__tfm_secure_gateway_attributes__
 | 
			
		||||
psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
 | 
			
		||||
                                 const psa_invec *in_vecs,
 | 
			
		||||
                                 psa_outvec *out_vecs)
 | 
			
		||||
{
 | 
			
		||||
    TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_call, handle, in_vecs,
 | 
			
		||||
                                   out_vecs, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__tfm_secure_gateway_attributes__
 | 
			
		||||
psa_status_t tfm_psa_close_veneer(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_close, handle, 0, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_psa_ipc_request_handler(uint32_t svc_ctx[])
 | 
			
		||||
{
 | 
			
		||||
    uint32_t *r0_ptr = svc_ctx;
 | 
			
		||||
 | 
			
		||||
    /* The only argument to the SVC call is stored in the stacked r0 */
 | 
			
		||||
    struct tfm_sfn_req_s *desc_ptr = (struct tfm_sfn_req_s *) *r0_ptr;
 | 
			
		||||
 | 
			
		||||
    if(tfm_psa_veneer_sanity_check(desc_ptr) != TFM_SUCCESS) {
 | 
			
		||||
        /* FixMe: consider error handling - this may be critical error */
 | 
			
		||||
        *r0_ptr = TFM_ERROR_INVALID_PARAMETER;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Store SVC return value in stacked r0 */
 | 
			
		||||
    *r0_ptr = desc_ptr->sfn((int32_t)desc_ptr->args,
 | 
			
		||||
                            desc_ptr->ns_caller,
 | 
			
		||||
                            0,
 | 
			
		||||
                            0);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//This file holds description for the current directory. This documentation
 | 
			
		||||
//will be included in the Doxygen output.
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
\dir
 | 
			
		||||
\brief Source code for the Secure Partition Manager.
 | 
			
		||||
\details This directory holds the source code of the "TF-M SPM" module.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
| 
						 | 
				
			
			@ -1,416 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* This file contains the APIs exported by the SPM to tfm core */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
#include "platform/include/tfm_spm_hal.h"
 | 
			
		||||
#include "tfm_memory_utils.h"
 | 
			
		||||
#include "spm_db_setup.h"
 | 
			
		||||
#include "tfm_internal.h"
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
#include "tfm_nspm.h"
 | 
			
		||||
#include "secure_fw/core/tfm_core.h"
 | 
			
		||||
#include "tfm_peripherals_def.h"
 | 
			
		||||
#include "spm_partition_defs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct spm_partition_db_t g_spm_partition_db = {0,};
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    TFM_INIT_FAILURE,
 | 
			
		||||
} sp_error_type_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function is called when a secure partition causes an error.
 | 
			
		||||
 * In case of an error in the error handling, a non-zero value have to be
 | 
			
		||||
 * returned.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef TFM_PSA_API
 | 
			
		||||
static void tfm_spm_partition_err_handler(
 | 
			
		||||
    const struct spm_partition_desc_t *partition,
 | 
			
		||||
    sp_error_type_t err_type,
 | 
			
		||||
    int32_t err_code)
 | 
			
		||||
{
 | 
			
		||||
#ifdef TFM_CORE_DEBUG
 | 
			
		||||
    if (err_type == TFM_INIT_FAILURE) {
 | 
			
		||||
        printf("Partition init failed for partition id 0x%08X\r\n",
 | 
			
		||||
                partition->static_data.partition_id);
 | 
			
		||||
    } else {
 | 
			
		||||
        printf(
 | 
			
		||||
            "Unknown partition error %d (code: %d) for partition id 0x%08X\r\n",
 | 
			
		||||
            err_type, err_code, partition->static_data.partition_id);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    (void)err_type;
 | 
			
		||||
    (void)err_code;
 | 
			
		||||
#endif
 | 
			
		||||
    tfm_spm_partition_set_state(partition->static_data.partition_id,
 | 
			
		||||
            SPM_PARTITION_STATE_CLOSED);
 | 
			
		||||
}
 | 
			
		||||
#endif /* !defined(TFM_PSA_API) */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function prevents name clashes between the variable names accessibles in
 | 
			
		||||
 * the scope of where tfm_partition_list.inc is included and the varaible names
 | 
			
		||||
 * defined inside tfm_partition_list.inc file.
 | 
			
		||||
 */
 | 
			
		||||
static inline enum spm_err_t add_user_defined_partitions(void) {
 | 
			
		||||
    #include "tfm_partition_list.inc"
 | 
			
		||||
 | 
			
		||||
    return SPM_ERR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t get_partition_idx(uint32_t partition_id)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
 | 
			
		||||
    if (partition_id == INVALID_PARTITION_ID) {
 | 
			
		||||
        return SPM_INVALID_PARTITION_IDX;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < g_spm_partition_db.partition_count; ++i) {
 | 
			
		||||
        if (g_spm_partition_db.partitions[i].static_data.partition_id ==
 | 
			
		||||
                partition_id) {
 | 
			
		||||
            return i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return SPM_INVALID_PARTITION_IDX;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum spm_err_t tfm_spm_db_init(void)
 | 
			
		||||
{
 | 
			
		||||
    struct spm_partition_desc_t *part_ptr;
 | 
			
		||||
    enum spm_err_t err;
 | 
			
		||||
 | 
			
		||||
    (void)tfm_memset (&g_spm_partition_db, 0, sizeof(g_spm_partition_db));
 | 
			
		||||
 | 
			
		||||
    /* This function initialises partition db */
 | 
			
		||||
    g_spm_partition_db.running_partition_idx = SPM_INVALID_PARTITION_IDX;
 | 
			
		||||
    g_spm_partition_db.partition_count = 0;
 | 
			
		||||
 | 
			
		||||
    /* There are a few partitions that are used by TF-M internally.
 | 
			
		||||
     * These are explicitly added to the partition db here.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /* For the non secure Execution environment */
 | 
			
		||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
 | 
			
		||||
    extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
 | 
			
		||||
    extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[];
 | 
			
		||||
    uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
 | 
			
		||||
    uint32_t psp_stack_top    = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Limit;
 | 
			
		||||
#endif
 | 
			
		||||
    if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) {
 | 
			
		||||
        return SPM_ERR_INVALID_CONFIG;
 | 
			
		||||
    }
 | 
			
		||||
    part_ptr = &(g_spm_partition_db.partitions[
 | 
			
		||||
            g_spm_partition_db.partition_count]);
 | 
			
		||||
    part_ptr->static_data.partition_id = TFM_SP_NON_SECURE_ID;
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
    part_ptr->static_data.partition_flags = SPM_PART_FLAG_APP_ROT |
 | 
			
		||||
                                            SPM_PART_FLAG_IPC;
 | 
			
		||||
    part_ptr->static_data.partition_priority = TFM_PRIORITY_LOW;
 | 
			
		||||
    part_ptr->static_data.partition_init = tfm_nspm_thread_entry;
 | 
			
		||||
#else
 | 
			
		||||
    part_ptr->static_data.partition_flags = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
 | 
			
		||||
    part_ptr->memory_data.stack_bottom = psp_stack_bottom;
 | 
			
		||||
    part_ptr->memory_data.stack_top    = psp_stack_top;
 | 
			
		||||
    /* Since RW, ZI and stack are configured as one MPU region, configure
 | 
			
		||||
     * RW start address to psp_stack_bottom to get RW access to stack
 | 
			
		||||
     */
 | 
			
		||||
    part_ptr->memory_data.rw_start     = psp_stack_bottom;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT;
 | 
			
		||||
    tfm_nspm_configure_clients();
 | 
			
		||||
    ++g_spm_partition_db.partition_count;
 | 
			
		||||
 | 
			
		||||
    /* For the TF-M core environment itself */
 | 
			
		||||
    if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) {
 | 
			
		||||
        return SPM_ERR_INVALID_CONFIG;
 | 
			
		||||
    }
 | 
			
		||||
    part_ptr = &(g_spm_partition_db.partitions[
 | 
			
		||||
            g_spm_partition_db.partition_count]);
 | 
			
		||||
    part_ptr->static_data.partition_id = TFM_SP_CORE_ID;
 | 
			
		||||
    part_ptr->static_data.partition_flags =
 | 
			
		||||
                    SPM_PART_FLAG_APP_ROT | SPM_PART_FLAG_PSA_ROT;
 | 
			
		||||
    part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT;
 | 
			
		||||
    ++g_spm_partition_db.partition_count;
 | 
			
		||||
 | 
			
		||||
    err = add_user_defined_partitions();
 | 
			
		||||
    if (err != SPM_ERR_OK) {
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_spm_partition_db.is_init = 1;
 | 
			
		||||
 | 
			
		||||
    return SPM_ERR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API
 | 
			
		||||
enum spm_err_t tfm_spm_partition_init(void)
 | 
			
		||||
{
 | 
			
		||||
    struct spm_partition_desc_t *part;
 | 
			
		||||
    struct tfm_sfn_req_s desc;
 | 
			
		||||
    int32_t args[4] = {0};
 | 
			
		||||
    int32_t fail_cnt = 0;
 | 
			
		||||
    uint32_t idx;
 | 
			
		||||
 | 
			
		||||
    /* Call the init function for each partition */
 | 
			
		||||
    for (idx = 0; idx < g_spm_partition_db.partition_count; ++idx) {
 | 
			
		||||
        part = &g_spm_partition_db.partitions[idx];
 | 
			
		||||
        tfm_spm_hal_configure_default_isolation(part->platform_data);
 | 
			
		||||
        if (part->static_data.partition_init == NULL) {
 | 
			
		||||
            tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
 | 
			
		||||
            tfm_spm_partition_set_caller_partition_idx(idx,
 | 
			
		||||
                                                     SPM_INVALID_PARTITION_IDX);
 | 
			
		||||
        } else {
 | 
			
		||||
            int32_t res;
 | 
			
		||||
 | 
			
		||||
            desc.args = args;
 | 
			
		||||
            desc.ns_caller = 0U;
 | 
			
		||||
            desc.iovec_api = TFM_SFN_API_IOVEC;
 | 
			
		||||
            desc.sfn = (sfn_t)part->static_data.partition_init;
 | 
			
		||||
            desc.sp_id = part->static_data.partition_id;
 | 
			
		||||
            res = tfm_core_sfn_request(&desc);
 | 
			
		||||
            if (res == TFM_SUCCESS) {
 | 
			
		||||
                tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
 | 
			
		||||
            } else {
 | 
			
		||||
                tfm_spm_partition_err_handler(part, TFM_INIT_FAILURE, res);
 | 
			
		||||
                fail_cnt++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tfm_secure_api_init_done();
 | 
			
		||||
 | 
			
		||||
    if (fail_cnt == 0) {
 | 
			
		||||
        return SPM_ERR_OK;
 | 
			
		||||
    } else {
 | 
			
		||||
        return SPM_ERR_PARTITION_NOT_AVAILABLE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif /* !defined(TFM_PSA_API) */
 | 
			
		||||
 | 
			
		||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
 | 
			
		||||
uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            memory_data.stack_bottom;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].memory_data.stack_top;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
 | 
			
		||||
enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    struct spm_partition_desc_t *part;
 | 
			
		||||
    if (!g_spm_partition_db.is_init) {
 | 
			
		||||
        return SPM_ERR_PARTITION_DB_NOT_INIT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    part = &g_spm_partition_db.partitions[partition_idx];
 | 
			
		||||
 | 
			
		||||
    return tfm_spm_hal_partition_sandbox_config(&(part->memory_data),
 | 
			
		||||
                                                part->platform_data);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    /* This function takes a partition id and disables the
 | 
			
		||||
     * SPM partition for that partition
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    struct spm_partition_desc_t *part;
 | 
			
		||||
 | 
			
		||||
    part = &g_spm_partition_db.partitions[partition_idx];
 | 
			
		||||
 | 
			
		||||
    return tfm_spm_hal_partition_sandbox_deconfig(&(part->memory_data),
 | 
			
		||||
                                                  part->platform_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_zi_start(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            memory_data.zi_start;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_zi_limit(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            memory_data.zi_limit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_rw_start(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            memory_data.rw_start;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            memory_data.rw_limit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr)
 | 
			
		||||
{
 | 
			
		||||
    g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            runtime_data.stack_ptr = stack_ptr;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].static_data.
 | 
			
		||||
            partition_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.partitions[partition_idx].static_data.
 | 
			
		||||
            partition_flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API
 | 
			
		||||
void tfm_spm_partition_store_context(uint32_t partition_idx,
 | 
			
		||||
        uint32_t stack_ptr, uint32_t lr)
 | 
			
		||||
{
 | 
			
		||||
    g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            runtime_data.stack_ptr = stack_ptr;
 | 
			
		||||
    g_spm_partition_db.partitions[partition_idx].
 | 
			
		||||
            runtime_data.lr = lr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct spm_partition_runtime_data_t *
 | 
			
		||||
            tfm_spm_partition_get_runtime_data(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    return &(g_spm_partition_db.partitions[partition_idx].runtime_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
    g_spm_partition_db.partitions[partition_idx].runtime_data.partition_state =
 | 
			
		||||
            state;
 | 
			
		||||
    if (state == SPM_PARTITION_STATE_RUNNING) {
 | 
			
		||||
        g_spm_partition_db.running_partition_idx = partition_idx;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
 | 
			
		||||
                                                uint32_t caller_partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    g_spm_partition_db.partitions[partition_idx].runtime_data.
 | 
			
		||||
            caller_partition_idx = caller_partition_idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
 | 
			
		||||
                                            int32_t caller_client_id)
 | 
			
		||||
{
 | 
			
		||||
    g_spm_partition_db.partitions[partition_idx].runtime_data.
 | 
			
		||||
            caller_client_id = caller_client_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
 | 
			
		||||
                                           uint32_t share)
 | 
			
		||||
{
 | 
			
		||||
    enum spm_err_t ret = SPM_ERR_OK;
 | 
			
		||||
 | 
			
		||||
#if TFM_LVL != 1
 | 
			
		||||
    /* Only need to set configuration on levels higher than 1 */
 | 
			
		||||
    ret = tfm_spm_hal_set_share_region(share);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (ret == SPM_ERR_OK) {
 | 
			
		||||
        g_spm_partition_db.partitions[partition_idx].runtime_data.share = share;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
 | 
			
		||||
                                           const int32_t *args)
 | 
			
		||||
{
 | 
			
		||||
    struct spm_partition_runtime_data_t *runtime_data =
 | 
			
		||||
            &g_spm_partition_db.partitions[partition_idx].runtime_data;
 | 
			
		||||
    size_t i;
 | 
			
		||||
 | 
			
		||||
    if ((args[1] < 0) || (args[3] < 0)) {
 | 
			
		||||
        return SPM_ERR_INVALID_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    runtime_data->iovec_args.in_len = (size_t)args[1];
 | 
			
		||||
    for (i = 0U; i < runtime_data->iovec_args.in_len; ++i) {
 | 
			
		||||
        runtime_data->iovec_args.in_vec[i].base =
 | 
			
		||||
                                                 ((psa_invec *)args[0])[i].base;
 | 
			
		||||
        runtime_data->iovec_args.in_vec[i].len = ((psa_invec *)args[0])[i].len;
 | 
			
		||||
    }
 | 
			
		||||
    runtime_data->iovec_args.out_len = (size_t)args[3];
 | 
			
		||||
    for (i = 0U; i < runtime_data->iovec_args.out_len; ++i) {
 | 
			
		||||
        runtime_data->iovec_args.out_vec[i].base =
 | 
			
		||||
                                                ((psa_outvec *)args[2])[i].base;
 | 
			
		||||
        runtime_data->iovec_args.out_vec[i].len =
 | 
			
		||||
                                                 ((psa_outvec *)args[2])[i].len;
 | 
			
		||||
    }
 | 
			
		||||
    runtime_data->orig_outvec = (psa_outvec *)args[2];
 | 
			
		||||
    runtime_data->iovec_api = 1;
 | 
			
		||||
 | 
			
		||||
    return SPM_ERR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tfm_spm_partition_get_running_partition_idx(void)
 | 
			
		||||
{
 | 
			
		||||
    return g_spm_partition_db.running_partition_idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfm_spm_partition_cleanup_context(uint32_t partition_idx)
 | 
			
		||||
{
 | 
			
		||||
    struct spm_partition_desc_t *partition =
 | 
			
		||||
            &(g_spm_partition_db.partitions[partition_idx]);
 | 
			
		||||
    int32_t i;
 | 
			
		||||
 | 
			
		||||
    partition->runtime_data.caller_partition_idx = SPM_INVALID_PARTITION_IDX;
 | 
			
		||||
    partition->runtime_data.share = 0;
 | 
			
		||||
    partition->runtime_data.iovec_args.in_len = 0;
 | 
			
		||||
    for (i = 0; i < PSA_MAX_IOVEC; ++i) {
 | 
			
		||||
        partition->runtime_data.iovec_args.in_vec[i].base = 0;
 | 
			
		||||
        partition->runtime_data.iovec_args.in_vec[i].len = 0;
 | 
			
		||||
    }
 | 
			
		||||
    partition->runtime_data.iovec_args.out_len = 0;
 | 
			
		||||
    for (i = 0; i < PSA_MAX_IOVEC; ++i) {
 | 
			
		||||
        partition->runtime_data.iovec_args.out_vec[i].base = 0;
 | 
			
		||||
        partition->runtime_data.iovec_args.out_vec[i].len = 0;
 | 
			
		||||
    }
 | 
			
		||||
    partition->runtime_data.orig_outvec = 0;
 | 
			
		||||
    partition->runtime_data.iovec_api = 0;
 | 
			
		||||
}
 | 
			
		||||
#endif /* !defined(TFM_PSA_API) */
 | 
			
		||||
 | 
			
		||||
__attribute__((section("SFN")))
 | 
			
		||||
void tfm_spm_partition_change_privilege(uint32_t privileged)
 | 
			
		||||
{
 | 
			
		||||
    CONTROL_Type ctrl;
 | 
			
		||||
 | 
			
		||||
    ctrl.w = __get_CONTROL();
 | 
			
		||||
 | 
			
		||||
    if (privileged == TFM_PARTITION_PRIVILEGED_MODE) {
 | 
			
		||||
        ctrl.b.nPRIV = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        ctrl.b.nPRIV = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    __set_CONTROL(ctrl.w);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,355 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPM_API_H__
 | 
			
		||||
#define __SPM_API_H__
 | 
			
		||||
 | 
			
		||||
/* This file contains the apis exported by the SPM to tfm core */
 | 
			
		||||
#include "tfm_api.h"
 | 
			
		||||
#include "spm_partition_defs.h"
 | 
			
		||||
#include "secure_fw/core/tfm_secure_api.h"
 | 
			
		||||
 | 
			
		||||
#define SPM_INVALID_PARTITION_IDX     (~0U)
 | 
			
		||||
 | 
			
		||||
/* Privileged definitions for partition thread mode */
 | 
			
		||||
#define TFM_PARTITION_PRIVILEGED_MODE   1
 | 
			
		||||
#define TFM_PARTITION_UNPRIVILEGED_MODE 0
 | 
			
		||||
 | 
			
		||||
enum spm_err_t {
 | 
			
		||||
    SPM_ERR_OK = 0,
 | 
			
		||||
    SPM_ERR_PARTITION_DB_NOT_INIT,
 | 
			
		||||
    SPM_ERR_PARTITION_ALREADY_ACTIVE,
 | 
			
		||||
    SPM_ERR_PARTITION_NOT_AVAILABLE,
 | 
			
		||||
    SPM_ERR_INVALID_PARAMETER,
 | 
			
		||||
    SPM_ERR_INVALID_CONFIG,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum spm_part_state_t {
 | 
			
		||||
    SPM_PARTITION_STATE_UNINIT = 0,
 | 
			
		||||
    SPM_PARTITION_STATE_IDLE,
 | 
			
		||||
    SPM_PARTITION_STATE_RUNNING,
 | 
			
		||||
    SPM_PARTITION_STATE_SUSPENDED,
 | 
			
		||||
    SPM_PARTITION_STATE_BLOCKED,
 | 
			
		||||
    SPM_PARTITION_STATE_CLOSED
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum spm_part_flag_mask_t {
 | 
			
		||||
    SPM_PART_FLAG_APP_ROT = 0x01,
 | 
			
		||||
    SPM_PART_FLAG_PSA_ROT = 0x02,
 | 
			
		||||
    SPM_PART_FLAG_IPC     = 0x04
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Holds the iovec parameters that are passed to a service
 | 
			
		||||
 *
 | 
			
		||||
 * \note The size of the structure is (and have to be) multiple of 8 bytes
 | 
			
		||||
 */
 | 
			
		||||
struct iovec_args_t {
 | 
			
		||||
    psa_invec in_vec[PSA_MAX_IOVEC];   /*!< Array of psa_invec objects */
 | 
			
		||||
    size_t in_len;                     /*!< Number psa_invec objects in in_vec
 | 
			
		||||
                                        */
 | 
			
		||||
    psa_outvec out_vec[PSA_MAX_IOVEC]; /*!< Array of psa_outvec objects */
 | 
			
		||||
    size_t out_len;                    /*!< Number psa_outvec objects in out_vec
 | 
			
		||||
                                        */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Runtime context information of a partition
 | 
			
		||||
 */
 | 
			
		||||
struct spm_partition_runtime_data_t {
 | 
			
		||||
    uint32_t partition_state;
 | 
			
		||||
    uint32_t caller_partition_idx;
 | 
			
		||||
    int32_t caller_client_id;
 | 
			
		||||
    uint32_t share;
 | 
			
		||||
    uint32_t stack_ptr;
 | 
			
		||||
    uint32_t lr;
 | 
			
		||||
    int32_t iovec_api;               /*!< Whether the function in the partition
 | 
			
		||||
                                      * had been called using the iovec API.
 | 
			
		||||
                                      * FIXME: Remove the field once this is the
 | 
			
		||||
                                      * only option
 | 
			
		||||
                                      */
 | 
			
		||||
    struct iovec_args_t iovec_args;
 | 
			
		||||
    psa_outvec *orig_outvec;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Returns the index of the partition with the given partition ID.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_id     Partition id
 | 
			
		||||
 *
 | 
			
		||||
 * \return the partition idx if partition_id is valid,
 | 
			
		||||
 *         \ref SPM_INVALID_PARTITION_IDX othervise
 | 
			
		||||
 */
 | 
			
		||||
uint32_t get_partition_idx(uint32_t partition_id);
 | 
			
		||||
 | 
			
		||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get bottom of stack region for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \return Stack region bottom value
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get top of stack region for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \return Stack region top value
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Configure isolated sandbox for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \return Error code \ref spm_err_t
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Deconfigure sandbox for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \return Error code \ref spm_err_t
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the start of the zero-initialised region for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition idx
 | 
			
		||||
 *
 | 
			
		||||
 * \return Start of the zero-initialised region
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_zi_start(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the limit of the zero-initialised region for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition idx
 | 
			
		||||
 *
 | 
			
		||||
 * \return Limit of the zero-initialised region
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 * \note The address returned is not part of the region.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_zi_limit(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the start of the read-write region for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition idx
 | 
			
		||||
 *
 | 
			
		||||
 * \return Start of the read-write region
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_rw_start(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the limit of the read-write region for a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition idx
 | 
			
		||||
 *
 | 
			
		||||
 * \return Limit of the read-write region
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 * \note The address returned is not part of the region.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Save stack pointer for partition in database
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx  Partition index
 | 
			
		||||
 * \param[in] stack_ptr      Stack pointer to be stored
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the id of the partition for its index from the db
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \return Partition ID for that partition
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the flags associated with a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \return Flags associated with the partition
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
#ifndef TFM_PSA_API
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the current runtime data of a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \return The runtime data of the specified partition
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
const struct spm_partition_runtime_data_t *
 | 
			
		||||
             tfm_spm_partition_get_runtime_data(uint32_t partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Returns the index of the partition that has running state
 | 
			
		||||
 *
 | 
			
		||||
 * \return The index of the partition with the running state, if there is any
 | 
			
		||||
 *         set. 0 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t tfm_spm_partition_get_running_partition_idx(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Save stack pointer and link register for partition in database
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx  Partition index
 | 
			
		||||
 * \param[in] stack_ptr      Stack pointer to be stored
 | 
			
		||||
 * \param[in] lr             Link register to be stored
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_partition_store_context(uint32_t partition_idx,
 | 
			
		||||
        uint32_t stack_ptr, uint32_t lr);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Set the current state of a partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx  Partition index
 | 
			
		||||
 * \param[in] state          The state to be set
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 * \note The state has to have the value set of \ref spm_part_state_t.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Set the caller partition index for a given partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx        Partition index
 | 
			
		||||
 * \param[in] caller_partition_idx The index of the caller partition
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if any of the partition_idxs are valid.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
 | 
			
		||||
                                                uint32_t caller_partition_idx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* \brief Set the caller client ID for a given partition
 | 
			
		||||
*
 | 
			
		||||
* \param[in] partition_idx        Partition index
 | 
			
		||||
* \param[in] caller_client_id     The ID of the calling client
 | 
			
		||||
*
 | 
			
		||||
* \note This function doesn't check if any of the partition_idxs are valid.
 | 
			
		||||
*/
 | 
			
		||||
void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
 | 
			
		||||
                                            int32_t caller_client_id);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Set the buffer share region of the partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx  Partition index
 | 
			
		||||
 * \param[in] share          The buffer share region to be set
 | 
			
		||||
 *
 | 
			
		||||
 * \return Error code \ref spm_err_t
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 * \note share has to have the value set of \ref tfm_buffer_share_region_e
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
 | 
			
		||||
                                           uint32_t share);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Set the iovec parameters for the partition
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx  Partition index
 | 
			
		||||
 * \param[in] args           The arguments of the secure function
 | 
			
		||||
 *
 | 
			
		||||
 * args is expected to be of type int32_t[4] where:
 | 
			
		||||
 *   args[0] is in_vec
 | 
			
		||||
 *   args[1] is in_len
 | 
			
		||||
 *   args[2] is out_vec
 | 
			
		||||
 *   args[3] is out_len
 | 
			
		||||
 *
 | 
			
		||||
 * \return Error code \ref spm_err_t
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 * \note This function assumes that the iovecs that are passed in args are
 | 
			
		||||
 *       valid, and does no sanity check on them at all.
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
 | 
			
		||||
                                           const int32_t *args);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Execute partition init function
 | 
			
		||||
 *
 | 
			
		||||
 * \return Error code \ref spm_err_t
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_partition_init(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Clears the context info from the database for a partition.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx     Partition index
 | 
			
		||||
 *
 | 
			
		||||
 * \note This function doesn't check if partition_idx is valid.
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_partition_cleanup_context(uint32_t partition_idx);
 | 
			
		||||
#endif /* !defined(TFM_PSA_API) */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Initialize partition database
 | 
			
		||||
 *
 | 
			
		||||
 * \return Error code \ref spm_err_t
 | 
			
		||||
 */
 | 
			
		||||
enum spm_err_t tfm_spm_db_init(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Change the privilege mode for partition thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] privileged        Privileged mode,
 | 
			
		||||
 *                                \ref TFM_PARTITION_PRIVILEGED_MODE
 | 
			
		||||
 *                                and \ref TFM_PARTITION_UNPRIVILEGED_MODE
 | 
			
		||||
 *
 | 
			
		||||
 * \note Barrier instructions are not called by this function, and if
 | 
			
		||||
 *       it is called in thread mode, it might be necessary to call
 | 
			
		||||
 *       them after this function returns (just like it is done in
 | 
			
		||||
 *       jump_to_ns_code()).
 | 
			
		||||
 */
 | 
			
		||||
void tfm_spm_partition_change_privilege(uint32_t privileged);
 | 
			
		||||
 | 
			
		||||
#endif /*__SPM_API_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,83 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPM_DB_H__
 | 
			
		||||
#define __SPM_DB_H__
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
#include "tfm_thread.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct spm_partition_desc_t;
 | 
			
		||||
struct spm_partition_db_t;
 | 
			
		||||
 | 
			
		||||
typedef psa_status_t(*sp_init_function)(void);
 | 
			
		||||
 | 
			
		||||
#define TFM_PARTITION_TYPE_APP   "APPLICATION-ROT"
 | 
			
		||||
#define TFM_PARTITION_TYPE_PSA   "PSA-ROT"
 | 
			
		||||
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
enum tfm_partition_priority {
 | 
			
		||||
    TFM_PRIORITY_LOW = THRD_PRIOR_LOWEST,
 | 
			
		||||
    TFM_PRIORITY_NORMAL = THRD_PRIOR_MEDIUM,
 | 
			
		||||
    TFM_PRIORITY_HIGH = THRD_PRIOR_HIGHEST,
 | 
			
		||||
};
 | 
			
		||||
#else
 | 
			
		||||
enum tfm_partition_priority {
 | 
			
		||||
    TFM_PRIORITY_LOW = 0xFF,
 | 
			
		||||
    TFM_PRIORITY_NORMAL = 0x7F,
 | 
			
		||||
    TFM_PRIORITY_HIGH = 0,
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define TFM_PRIORITY(LEVEL)      TFM_PRIORITY_##LEVEL
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Holds the fields of the partition DB used by the SPM code. The values of
 | 
			
		||||
 * these fields are calculated at compile time, and set during initialisation
 | 
			
		||||
 * phase.
 | 
			
		||||
 */
 | 
			
		||||
struct spm_partition_static_data_t {
 | 
			
		||||
    uint32_t partition_id;
 | 
			
		||||
    uint32_t partition_flags;
 | 
			
		||||
    uint32_t partition_priority;
 | 
			
		||||
    sp_init_function partition_init;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Holds the fields that define a partition for SPM. The fields are further
 | 
			
		||||
 * divided to structures, to keep the related fields close to each other.
 | 
			
		||||
 */
 | 
			
		||||
struct spm_partition_desc_t {
 | 
			
		||||
    struct spm_partition_static_data_t static_data;
 | 
			
		||||
    struct spm_partition_runtime_data_t runtime_data;
 | 
			
		||||
    struct tfm_spm_partition_platform_data_t *platform_data;
 | 
			
		||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
 | 
			
		||||
    struct tfm_spm_partition_memory_data_t memory_data;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef TFM_PSA_API
 | 
			
		||||
    struct tfm_thrd_ctx sp_thrd;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Macros to pick linker symbols and allow to form the partition data base */
 | 
			
		||||
#define REGION(a, b, c) a##b##c
 | 
			
		||||
#define REGION_NAME(a, b, c) REGION(a, b, c)
 | 
			
		||||
/* Changed from #if (TFM_LVL == 1) && !defined(TFM_PSA_API) to #if (TFM_LVL == 1) to avoid linker error.
 | 
			
		||||
   TF-M build autogenerates region details (code, ro, rw, zi and stack ) using linker scripts. We do not
 | 
			
		||||
   hve that in mbed-os build yet.
 | 
			
		||||
*/
 | 
			
		||||
#if (TFM_LVL == 1)
 | 
			
		||||
#define REGION_DECLARE(a, b, c)
 | 
			
		||||
#else
 | 
			
		||||
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
 | 
			
		||||
#define PART_REGION_ADDR(partition, region) \
 | 
			
		||||
    (uint32_t)®ION_NAME(Image$$, partition, region)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __SPM_DB_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,138 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPM_DB_SETUP_H__
 | 
			
		||||
#define __SPM_DB_SETUP_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "spm_db.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Get the index of a partition.
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the index of a partition in the partition db based on the partition ID
 | 
			
		||||
 * provided as a parameter.
 | 
			
		||||
 *
 | 
			
		||||
 * \param[in] partition_idx    The index of the partition
 | 
			
		||||
 *
 | 
			
		||||
 * \return \ref INVALID_PARTITION_IDX if the provided index is invalid. The
 | 
			
		||||
 *         index of the partition otherwise.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t get_partition_idx(uint32_t partition_id);
 | 
			
		||||
 | 
			
		||||
struct spm_partition_db_t {
 | 
			
		||||
    uint32_t is_init;
 | 
			
		||||
    uint32_t partition_count;
 | 
			
		||||
    uint32_t running_partition_idx;
 | 
			
		||||
    struct spm_partition_desc_t partitions[SPM_MAX_PARTITIONS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PARTITION_INIT_STATIC_DATA(data, partition, flags, id, priority)      \
 | 
			
		||||
    do {                                                                      \
 | 
			
		||||
        data.partition_id    = partition##_ID;                                \
 | 
			
		||||
        data.partition_flags = flags;                                         \
 | 
			
		||||
        data.partition_priority = TFM_PRIORITY(priority);                     \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/* Changed from #if (TFM_LVL == 1) && !defined(TFM_PSA_API) to #if (TFM_LVL == 1) to avoid linker error.
 | 
			
		||||
   TF-M build autogenerates region details (code, ro, rw, zi and stack ) using linker scripts. We do not
 | 
			
		||||
   hve that in mbed-os build yet.
 | 
			
		||||
*/
 | 
			
		||||
#if (TFM_LVL == 1)
 | 
			
		||||
#define PARTITION_INIT_MEMORY_DATA(data, partition)
 | 
			
		||||
#else
 | 
			
		||||
#define PARTITION_INIT_MEMORY_DATA(data, partition)                            \
 | 
			
		||||
    do {                                                                       \
 | 
			
		||||
        data.code_start      = PART_REGION_ADDR(partition, $$Base);            \
 | 
			
		||||
        data.code_limit      = PART_REGION_ADDR(partition, $$Limit);           \
 | 
			
		||||
        data.ro_start        = PART_REGION_ADDR(partition, $$RO$$Base);        \
 | 
			
		||||
        data.ro_limit        = PART_REGION_ADDR(partition, $$RO$$Limit);       \
 | 
			
		||||
        data.rw_start        = PART_REGION_ADDR(partition, _DATA$$RW$$Base);   \
 | 
			
		||||
        data.rw_limit        = PART_REGION_ADDR(partition, _DATA$$RW$$Limit);  \
 | 
			
		||||
        data.zi_start        = PART_REGION_ADDR(partition, _DATA$$ZI$$Base);   \
 | 
			
		||||
        data.zi_limit        = PART_REGION_ADDR(partition, _DATA$$ZI$$Limit);  \
 | 
			
		||||
        data.stack_bottom    = PART_REGION_ADDR(partition, _STACK$$ZI$$Base);  \
 | 
			
		||||
        data.stack_top       = PART_REGION_ADDR(partition, _STACK$$ZI$$Limit); \
 | 
			
		||||
    } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if TFM_LVL == 1
 | 
			
		||||
#define PARTITION_INIT_RUNTIME_DATA(data, partition)            \
 | 
			
		||||
    do {                                                        \
 | 
			
		||||
        data.partition_state      = SPM_PARTITION_STATE_UNINIT; \
 | 
			
		||||
    } while (0)
 | 
			
		||||
#else
 | 
			
		||||
#define PARTITION_INIT_RUNTIME_DATA(data, partition)                \
 | 
			
		||||
    do {                                                            \
 | 
			
		||||
        data.partition_state      = SPM_PARTITION_STATE_UNINIT;     \
 | 
			
		||||
        /* The top of the stack is reserved for the iovec        */ \
 | 
			
		||||
        /* parameters of the service called. That's why in       */ \
 | 
			
		||||
        /* data.stack_ptr we extract sizeof(struct iovec_args_t) */ \
 | 
			
		||||
        /* from the limit.                                       */ \
 | 
			
		||||
        data.stack_ptr            =                                 \
 | 
			
		||||
                PART_REGION_ADDR(partition, _STACK$$ZI$$Limit -     \
 | 
			
		||||
                                  sizeof(struct iovec_args_t));     \
 | 
			
		||||
    } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define PARTITION_DECLARE(partition, flag, type, id, priority, part_stack_size)                     \
 | 
			
		||||
    do {                                                                                            \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, $$Base);                                                 \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, $$Limit);                                                \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, $$RO$$Base);                                             \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, $$RO$$Limit);                                            \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, _DATA$$RW$$Base);                                        \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, _DATA$$RW$$Limit);                                       \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Base);                                        \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Limit);                                       \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Base);                                       \
 | 
			
		||||
        REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Limit);                                      \
 | 
			
		||||
        int32_t flags = flag;                                                                       \
 | 
			
		||||
        if (tfm_memcmp(type, TFM_PARTITION_TYPE_APP,                                                \
 | 
			
		||||
            strlen(TFM_PARTITION_TYPE_APP)) == 0) {                                                 \
 | 
			
		||||
            flags |= SPM_PART_FLAG_APP_ROT;                                                         \
 | 
			
		||||
        } else if (tfm_memcmp(type, TFM_PARTITION_TYPE_PSA,                                         \
 | 
			
		||||
                   strlen(TFM_PARTITION_TYPE_PSA)) == 0) {                                          \
 | 
			
		||||
            flags |= SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT;                                 \
 | 
			
		||||
        } else {                                                                                    \
 | 
			
		||||
            return SPM_ERR_INVALID_CONFIG;                                                          \
 | 
			
		||||
        }                                                                                           \
 | 
			
		||||
        struct spm_partition_desc_t *part_ptr;                                                      \
 | 
			
		||||
        if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) {                             \
 | 
			
		||||
            return SPM_ERR_INVALID_CONFIG;                                                          \
 | 
			
		||||
        }                                                                                           \
 | 
			
		||||
        __attribute__((section(".data.partitions_stacks")))                                         \
 | 
			
		||||
        static uint8_t partition##_stack[part_stack_size] __attribute__((aligned(8)));              \
 | 
			
		||||
        part_ptr = &(g_spm_partition_db.partitions[                                                 \
 | 
			
		||||
            g_spm_partition_db.partition_count]);                                                   \
 | 
			
		||||
        part_ptr->memory_data.stack_bottom = (uint32_t)partition##_stack;                           \
 | 
			
		||||
        part_ptr->memory_data.stack_top = part_ptr->memory_data.stack_bottom + part_stack_size;     \
 | 
			
		||||
        PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags,                         \
 | 
			
		||||
                                   id, priority);                                                   \
 | 
			
		||||
        PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition);                             \
 | 
			
		||||
        PARTITION_INIT_MEMORY_DATA(part_ptr->memory_data, partition);                               \
 | 
			
		||||
        ++g_spm_partition_db.partition_count;                                                       \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#define PARTITION_ADD_INIT_FUNC(partition, init_func)                                               \
 | 
			
		||||
    do {                                                                                            \
 | 
			
		||||
        extern int32_t init_func(void);                                                             \
 | 
			
		||||
        uint32_t partition_idx = get_partition_idx(partition##_ID);                                 \
 | 
			
		||||
        struct spm_partition_desc_t *part_ptr =                                                     \
 | 
			
		||||
            &(g_spm_partition_db.partitions[partition_idx]);                                        \
 | 
			
		||||
        part_ptr->static_data.partition_init = init_func;                                           \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#define PARTITION_ADD_PERIPHERAL(partition, peripheral)                                             \
 | 
			
		||||
    do {                                                                                            \
 | 
			
		||||
        uint32_t partition_idx = get_partition_idx(partition##_ID);                                 \
 | 
			
		||||
        struct spm_partition_desc_t *part_ptr =                                                     \
 | 
			
		||||
            &(g_spm_partition_db.partitions[partition_idx]);                                        \
 | 
			
		||||
        part_ptr->platform_data = peripheral;                                                       \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#endif /* __SPM_DB_SETUP_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,40 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPM_PARTITION_DEFS_H__
 | 
			
		||||
#define __SPM_PARTITION_DEFS_H__
 | 
			
		||||
 | 
			
		||||
/* FixMe: allocations to be settled.
 | 
			
		||||
 * 8 bits reserved by TFM for secure partition Id in this prototype
 | 
			
		||||
 */
 | 
			
		||||
#define TFM_SP_BASE 256
 | 
			
		||||
 | 
			
		||||
/* A reserved partition ID that is used for uninitialised data */
 | 
			
		||||
#define INVALID_PARTITION_ID (~0U)
 | 
			
		||||
 | 
			
		||||
/* ***** partition ID-s internal to the TFM ***** */
 | 
			
		||||
#define TFM_INTERNAL_PARTITIONS (2)
 | 
			
		||||
 | 
			
		||||
/* From the SPM point of view the non secure processing environment is handled
 | 
			
		||||
 * as a special secure partition. This simplifies the context switch
 | 
			
		||||
 * operations.
 | 
			
		||||
 */
 | 
			
		||||
#define TFM_SP_NON_SECURE_ID (0)
 | 
			
		||||
/* A dummy partition for TFM_SP_CORE is created to handle secure partition
 | 
			
		||||
 * calls done directly from the core, before NS execution started.
 | 
			
		||||
 */
 | 
			
		||||
#define TFM_SP_CORE_ID (1)
 | 
			
		||||
 | 
			
		||||
#include "tfm_partition_defs.inc"
 | 
			
		||||
 | 
			
		||||
/* This limit is only used to define the size of the database reserved for
 | 
			
		||||
 * partitions. There's no requirement that it match the number of partitions
 | 
			
		||||
 * that get registered in a specific build
 | 
			
		||||
 */
 | 
			
		||||
#define SPM_MAX_PARTITIONS (TFM_MAX_USER_PARTITIONS + TFM_INTERNAL_PARTITIONS)
 | 
			
		||||
 | 
			
		||||
#endif /* __SPM_PARTITION_DEFS_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,111 +0,0 @@
 | 
			
		|||
# TF-M integration to Mbed-OS
 | 
			
		||||
This document is an initial draft for TF-M for Mbed-OS porting guide .
 | 
			
		||||
 | 
			
		||||
## Audience
 | 
			
		||||
This guide is intended for developers wishing to port Mbed-OS with TF-M used as a secure kernel for ARMv8-M targets.
 | 
			
		||||
 | 
			
		||||
Prior knowledge with both TF-M & Mbed-OS concepts is assumed.
 | 
			
		||||
 | 
			
		||||
## Build system concepts:
 | 
			
		||||
 | 
			
		||||
Mbed-OS build system is based on [Mbed-CLI](https://github.com/ARMmbed/mbed-cli).
 | 
			
		||||
Mbed-CLI build system performs lookup for source and header files within project directory and adds them all to a build. All folders will be scanned for sources except for:
 | 
			
		||||
- folders starting with `TARGET_*`
 | 
			
		||||
- folders starting with `COMPONENT_*`
 | 
			
		||||
- folders starting with `FEATURE_*`
 | 
			
		||||
- folders starting with `TESTS_*` (not true for `mbed test` builds)
 | 
			
		||||
- files and folders listed in `.mbedignore`
 | 
			
		||||
 | 
			
		||||
The ignored folders listed above can be explicitly added to a compilation by adding following keys to a target description in `targets.json`:
 | 
			
		||||
- adding `extra_labels_add`, `inherits` and `sub_target` for adding `TARGET_*`
 | 
			
		||||
- adding `components_add` for adding `COMPONENT_*`
 | 
			
		||||
- `features_add` for adding `FEATURE_*`
 | 
			
		||||
 | 
			
		||||
TF-M is built as bare-metal in a secure target, in order to build a secure target with TF-M as its' kernel need to add `--app-config <MBED-OS-ROOT>/tools/psa/tfm/mbed_app.json` to the build command of the secure target.
 | 
			
		||||
 | 
			
		||||
## Build hooks
 | 
			
		||||
 | 
			
		||||
Mbed-OS testing tools are designed to work with a single image (`.bin` or `.hex`).
 | 
			
		||||
When building mbed-os for TF-M targets two images are created. One for normal world(NW) and one for TrustZone(TZ).
 | 
			
		||||
Mbed-OS build system provides `post_binary_hook` that allows executing arbitrary Python script for merging NW and TZ images. Typically `post_binary_hook` is added to NW target and assumes TZ target images as a prerequisite.
 | 
			
		||||
 | 
			
		||||
## Porting TF-M targets
 | 
			
		||||
 | 
			
		||||
Typically firmware for TF-M targets consist of 2 or more images: normal world and TrustZone image. More images can be present in case boot loaders are used.
 | 
			
		||||
Two images must be built and linked separately. TrustZone image must be built first.
 | 
			
		||||
 | 
			
		||||
There may be code and/or header files sharing between the two targets.
 | 
			
		||||
Nested folder layout typically provides more easy code reuse between two targets:
 | 
			
		||||
Example:
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
└── tragets
 | 
			
		||||
    └── TARGET_<VENDOR>
 | 
			
		||||
        └── TARGET_<BOARD>
 | 
			
		||||
            ├── common_files            <-- files shared between NW and TZ images
 | 
			
		||||
            ├── TARGET_<BOARD>_NS
 | 
			
		||||
            │   └── normal_world_files  <-- files only to be included for NW build
 | 
			
		||||
            └── TARGET_<BOARD>_S
 | 
			
		||||
                └── trustzone_files     <-- files only to be included for TZ build
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The target should be represented in a following way in `target.json` (`MUSCA_A1` is taken for example and should be substituted):
 | 
			
		||||
```json
 | 
			
		||||
...
 | 
			
		||||
"ARM_MUSCA_A1": {
 | 
			
		||||
        "public": false,
 | 
			
		||||
        "inherits": ["Target"],
 | 
			
		||||
        "supported_toolchains": ["ARMC6", "GCC_ARM"],
 | 
			
		||||
        "default_toolchain": "ARMC6",
 | 
			
		||||
        "extra_labels": ["ARM_SSG", "MUSCA_A1"],
 | 
			
		||||
    },
 | 
			
		||||
    "ARM_MUSCA_A1_NS": {
 | 
			
		||||
        "inherits": ["NSPE_Target", "ARM_MUSCA_A1"],
 | 
			
		||||
        "core": "Cortex-M33-NS",
 | 
			
		||||
        "device_has_add": ["INTERRUPTIN", "LPTICKER", "SERIAL", "SLEEP", "USTICKER"],
 | 
			
		||||
        "macros": [
 | 
			
		||||
            "MBED_FAULT_HANDLER_DISABLED",
 | 
			
		||||
            "MBEDTLS_PSA_CRYPTO_C"
 | 
			
		||||
        ],
 | 
			
		||||
        "extra_labels_add": ["MUSCA_A1_NS", "PSA", "TFM"],
 | 
			
		||||
        "post_binary_hook": {"function": "ArmMuscaA1Code.binary_hook"}
 | 
			
		||||
    },
 | 
			
		||||
    "ARM_MUSCA_A1_S": {
 | 
			
		||||
        "inherits": ["SPE_Target", "ARM_MUSCA_A1"],
 | 
			
		||||
        "core": "Cortex-M33",
 | 
			
		||||
        "device_has_add": ["FLASH"],
 | 
			
		||||
        "macros": [
 | 
			
		||||
            "MBED_MPU_CUSTOM",
 | 
			
		||||
            "MBEDTLS_PSA_CRYPTO_SPM",
 | 
			
		||||
            "MBEDTLS_PSA_CRYPTO_C",
 | 
			
		||||
            "MBEDTLS_ENTROPY_NV_SEED"
 | 
			
		||||
        ],
 | 
			
		||||
        "components_add": ["FLASHIAP"],
 | 
			
		||||
        "extra_labels_add": ["MUSCA_A1_S", "PSA", "TFM"]
 | 
			
		||||
    },
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Example details:
 | 
			
		||||
- Secure target:
 | 
			
		||||
  - `"device_has_add": ["FLASH"]` and `"components_add": ["FLASHIAP"]` for enabling storage stack. Required by PSA Internal storage service.
 | 
			
		||||
  - `"extra_labels_add": ["PSA", "TFM"]` are required to add PSA services and TF-M SPM implementation sources to a compilation
 | 
			
		||||
  - all the macros from the example above are required
 | 
			
		||||
  - must inherit from `SPE_Target`
 | 
			
		||||
- Nonsecure target:
 | 
			
		||||
  -  must inherit from `NSPE_Target`
 | 
			
		||||
  - `"extra_labels_add": ["PSA", "TFM"]` are required to add PSA services and TF-M SPM implementation sources to a compilation
 | 
			
		||||
  - all the macros from the example above are required
 | 
			
		||||
  -  `post_binary_hook` is used to combine secure and non-secure images
 | 
			
		||||
 | 
			
		||||
### HAL
 | 
			
		||||
For porting Mbed-OS & TF-M both Mbed-OS and TF-M HAL layers should be created.
 | 
			
		||||
 | 
			
		||||
#### Mbed-OS HAL:
 | 
			
		||||
Follow instructions for [Mbed-OS HAL porting](https://os.mbed.com/docs/mbed-os/v5.11/porting/porting-hal-modules.html)
 | 
			
		||||
 | 
			
		||||
#### TF-M:
 | 
			
		||||
Mbed-OS contains customized TF-M version. TF-M services reference implementation was replaced by Mbed-OS version. Thus TF-M has different HAL layer comparing to vanilla [TF-M reference implementation](https://git.trustedfirmware.org/trusted-firmware-m.git/about/).
 | 
			
		||||
 | 
			
		||||
The porting layer consists of:
 | 
			
		||||
- All functions listed in: `components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/platform/include/tfm_spm_hal.h`
 | 
			
		||||
- Flash API `mbed-os/hal/flash_api.h` implementation is required for TZ image. It is used by PSA Internal trusted storage implementation.
 | 
			
		||||
| 
						 | 
				
			
			@ -1,253 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2018-2019 ARM Limited. All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
*
 | 
			
		||||
* Licensed under the Apache License, Version 2.0 (the License); you may
 | 
			
		||||
* not use this file except in compliance with the License.
 | 
			
		||||
* You may obtain a copy of the License at
 | 
			
		||||
*
 | 
			
		||||
* http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
*
 | 
			
		||||
* Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
 | 
			
		||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
* See the License for the specific language governing permissions and
 | 
			
		||||
* limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// ---------------------------------- Includes ---------------------------------
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
#include "psa_initial_attestation_api.h"
 | 
			
		||||
#include "psa_attest_inject_key.h"
 | 
			
		||||
#include "psa_inject_attestation_key_impl.h"
 | 
			
		||||
#include "attestation.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "psa/crypto.h"
 | 
			
		||||
 | 
			
		||||
int32_t g_caller_id = 0;
 | 
			
		||||
 | 
			
		||||
static void set_caller_id(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    g_caller_id = msg->client_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------- Partition's Main Thread ---------------------------
 | 
			
		||||
 | 
			
		||||
static void psa_attest_get_token(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_msg_t msg = { 0 };
 | 
			
		||||
    enum psa_attest_err_t status = PSA_ATTEST_ERR_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(PSA_ATTEST_GET_TOKEN, &msg)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    switch (msg.type) {
 | 
			
		||||
        case PSA_IPC_CONNECT:
 | 
			
		||||
        case PSA_IPC_DISCONNECT: {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_CALL: {
 | 
			
		||||
            uint8_t *challenge_buff = NULL;
 | 
			
		||||
            uint8_t *token_buff = NULL;
 | 
			
		||||
            uint32_t bytes_read = 0;
 | 
			
		||||
 | 
			
		||||
            challenge_buff = calloc(1, msg.in_size[0]);
 | 
			
		||||
            if (challenge_buff == NULL) {
 | 
			
		||||
                status = PSA_ATTEST_ERR_GENERAL;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            bytes_read = psa_read(msg.handle, 0,
 | 
			
		||||
                                  challenge_buff, msg.in_size[0]);
 | 
			
		||||
            if (bytes_read != msg.in_size[0]) {
 | 
			
		||||
                free(challenge_buff);
 | 
			
		||||
                SPM_PANIC("SPM read length mismatch");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            token_buff = calloc(1, msg.out_size[0]);
 | 
			
		||||
            if (token_buff == NULL) {
 | 
			
		||||
                status = PSA_ATTEST_ERR_GENERAL;
 | 
			
		||||
                free(challenge_buff);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_invec in_vec[1] = { { challenge_buff, msg.in_size[0] } };
 | 
			
		||||
            psa_outvec out_vec[1] = { { token_buff, msg.out_size[0] } };
 | 
			
		||||
 | 
			
		||||
            status = attest_init();
 | 
			
		||||
            if (status != PSA_ATTEST_ERR_SUCCESS) {
 | 
			
		||||
                free(challenge_buff);
 | 
			
		||||
                free(token_buff);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            set_caller_id(&msg);
 | 
			
		||||
            status = initial_attest_get_token(in_vec, 1, out_vec, 1);
 | 
			
		||||
            if (status == PSA_ATTEST_ERR_SUCCESS) {
 | 
			
		||||
                psa_write(msg.handle, 0, out_vec[0].base, out_vec[0].len);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            free(challenge_buff);
 | 
			
		||||
            free(token_buff);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        default: {
 | 
			
		||||
            SPM_PANIC("Unexpected message type %d!", (int)(msg.type));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void psa_attest_get_token_size(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_msg_t msg = { 0 };
 | 
			
		||||
    enum psa_attest_err_t status = PSA_ATTEST_ERR_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(PSA_ATTEST_GET_TOKEN_SIZE, &msg)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    switch (msg.type) {
 | 
			
		||||
        case PSA_IPC_CONNECT:
 | 
			
		||||
        case PSA_IPC_DISCONNECT: {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_CALL: {
 | 
			
		||||
            uint32_t challenge_size;
 | 
			
		||||
            uint32_t token_size;
 | 
			
		||||
            uint32_t bytes_read = 0;
 | 
			
		||||
 | 
			
		||||
            bytes_read = psa_read(msg.handle, 0,
 | 
			
		||||
                                  &challenge_size, msg.in_size[0]);
 | 
			
		||||
            if (bytes_read != msg.in_size[0]) {
 | 
			
		||||
                SPM_PANIC("SPM read length mismatch");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_invec in_vec[1] = { { &challenge_size, msg.in_size[0] } };
 | 
			
		||||
            psa_outvec out_vec[1] = { { &token_size, msg.out_size[0] } };
 | 
			
		||||
 | 
			
		||||
            status = attest_init();
 | 
			
		||||
            if (status != PSA_ATTEST_ERR_SUCCESS) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            set_caller_id(&msg);
 | 
			
		||||
            status = initial_attest_get_token_size(in_vec, 1, out_vec, 1);
 | 
			
		||||
            if (status == PSA_ATTEST_ERR_SUCCESS) {
 | 
			
		||||
                psa_write(msg.handle, 0, out_vec[0].base, out_vec[0].len);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        default: {
 | 
			
		||||
            SPM_PANIC("Unexpected message type %d!", (int)(msg.type));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void psa_attest_inject_key(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_msg_t msg = { 0 };
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    if (PSA_SUCCESS != psa_get(PSA_ATTEST_INJECT_KEY, &msg)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    switch (msg.type) {
 | 
			
		||||
        case PSA_IPC_CONNECT:
 | 
			
		||||
        case PSA_IPC_DISCONNECT: {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_CALL: {
 | 
			
		||||
            uint8_t *public_key_data = NULL;
 | 
			
		||||
            size_t public_key_data_length = 0;
 | 
			
		||||
            uint8_t *key_data = NULL;
 | 
			
		||||
            psa_key_type_t type;
 | 
			
		||||
            uint32_t bytes_read = 0;
 | 
			
		||||
 | 
			
		||||
            if (msg.in_size[0] != sizeof(psa_key_type_t)) {
 | 
			
		||||
                status = PSA_ERROR_INVALID_ARGUMENT;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            bytes_read = psa_read(msg.handle, 0, &type, msg.in_size[0]);
 | 
			
		||||
            if (bytes_read != msg.in_size[0]) {
 | 
			
		||||
                SPM_PANIC("SPM read length mismatch");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public_key_data = calloc(1, msg.out_size[0]);
 | 
			
		||||
            if (public_key_data == NULL) {
 | 
			
		||||
                status = PSA_ERROR_INSUFFICIENT_MEMORY;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (msg.in_size[1] != 0) {
 | 
			
		||||
                key_data = calloc(1, msg.in_size[1]);
 | 
			
		||||
                if (key_data == NULL) {
 | 
			
		||||
                    status = PSA_ERROR_INSUFFICIENT_MEMORY;
 | 
			
		||||
                    free(public_key_data);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                bytes_read = psa_read(msg.handle, 1,
 | 
			
		||||
                                      key_data, msg.in_size[1]);
 | 
			
		||||
                if (bytes_read != msg.in_size[1]) {
 | 
			
		||||
                    free(public_key_data);
 | 
			
		||||
                    free(key_data);
 | 
			
		||||
                    SPM_PANIC("SPM read length mismatch");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            status = psa_attestation_inject_key_impl(key_data,
 | 
			
		||||
                                                     msg.in_size[1],
 | 
			
		||||
                                                     type,
 | 
			
		||||
                                                     public_key_data,
 | 
			
		||||
                                                     msg.out_size[0],
 | 
			
		||||
                                                     &public_key_data_length);
 | 
			
		||||
 | 
			
		||||
            if (status == PSA_SUCCESS) {
 | 
			
		||||
                psa_write(msg.handle, 0, public_key_data, public_key_data_length);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_write(msg.handle, 1,
 | 
			
		||||
                      &public_key_data_length, sizeof(public_key_data_length));
 | 
			
		||||
            free(public_key_data);
 | 
			
		||||
            if (key_data != NULL) {
 | 
			
		||||
                free(key_data);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        default: {
 | 
			
		||||
            SPM_PANIC("Unexpected message type %d!", (int)(msg.type));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_reply(msg.handle, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void attest_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    while (1) {
 | 
			
		||||
        uint32_t signals = psa_wait(ATTEST_SRV_WAIT_ANY_SID_MSK, PSA_BLOCK);
 | 
			
		||||
        if (signals & PSA_ATTEST_GET_TOKEN) {
 | 
			
		||||
            psa_attest_get_token();
 | 
			
		||||
        }
 | 
			
		||||
        if (signals & PSA_ATTEST_GET_TOKEN_SIZE) {
 | 
			
		||||
            psa_attest_get_token_size();
 | 
			
		||||
        }
 | 
			
		||||
        if (signals & PSA_ATTEST_INJECT_KEY) {
 | 
			
		||||
            psa_attest_inject_key();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,47 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "ATTEST_SRV",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000025",
 | 
			
		||||
  "entry_point": "attest_main",
 | 
			
		||||
  "stack_size": "0x2000",
 | 
			
		||||
  "heap_size": "0x2000",
 | 
			
		||||
  "services": [
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_ATTEST_GET_TOKEN_ID",
 | 
			
		||||
      "identifier": "0x00000F10",
 | 
			
		||||
      "signal": "PSA_ATTEST_GET_TOKEN",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_ATTEST_GET_TOKEN_SIZE_ID",
 | 
			
		||||
      "identifier": "0x00000F11",
 | 
			
		||||
      "signal": "PSA_ATTEST_GET_TOKEN_SIZE",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_ATTEST_INJECT_KEY_ID",
 | 
			
		||||
      "identifier": "0x00000F12",
 | 
			
		||||
      "signal": "PSA_ATTEST_INJECT_KEY",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "extern_sids": [
 | 
			
		||||
    "PSA_CRYPTO_INIT_ID",
 | 
			
		||||
    "PSA_HASH_ID",
 | 
			
		||||
    "PSA_ASYMMETRIC_ID",
 | 
			
		||||
    "PSA_KEY_MNG_ID",
 | 
			
		||||
    "PSA_CRYPTO_FREE_ID",
 | 
			
		||||
    "PSA_KEY_DERIVATION_ID",
 | 
			
		||||
    "PSA_PLATFORM_LC_GET"
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/psa_attestation_partition.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -14,9 +14,4 @@
 | 
			
		|||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef PSA_CRYPTO_SECURE
 | 
			
		||||
#include "crypto_struct_spe.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "crypto_struct_ipc.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,112 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020, Arm Limited and affiliates.
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/**
 | 
			
		||||
 * \file psa/crypto_spe.h
 | 
			
		||||
 * \brief Platform Security Architecture cryptography module
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_CRYPTO_SPE_H
 | 
			
		||||
#define PSA_CRYPTO_SPE_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define psa_crypto_init  psa_sec_crypto_init
 | 
			
		||||
#define psa_get_key_attributes  psa_sec_get_key_attributes
 | 
			
		||||
#define psa_reset_key_attributes psa_sec_reset_key_attributes
 | 
			
		||||
#define psa_open_key  psa_sec_open_key
 | 
			
		||||
#define psa_close_key  psa_sec_close_key
 | 
			
		||||
#define psa_import_key  psa_sec_import_key
 | 
			
		||||
#define psa_destroy_key  psa_sec_destroy_key
 | 
			
		||||
#define psa_export_key  psa_sec_export_key
 | 
			
		||||
#define psa_export_public_key  psa_sec_export_public_key
 | 
			
		||||
#define psa_copy_key psa_sec_copy_key
 | 
			
		||||
#define psa_hash_compute  psa_sec_hash_compute
 | 
			
		||||
#define psa_hash_compare  psa_sec_hash_compare
 | 
			
		||||
#define psa_hash_setup  psa_sec_hash_setup
 | 
			
		||||
#define psa_hash_update  psa_sec_hash_update
 | 
			
		||||
#define psa_hash_finish  psa_sec_hash_finish
 | 
			
		||||
#define psa_hash_verify  psa_sec_hash_verify
 | 
			
		||||
#define psa_hash_abort  psa_sec_hash_abort
 | 
			
		||||
#define psa_hash_clone  psa_sec_hash_clone
 | 
			
		||||
#define psa_mac_compute  psa_sec_mac_compute
 | 
			
		||||
#define psa_mac_verify  psa_sec_mac_verify
 | 
			
		||||
#define psa_mac_sign_setup  psa_sec_mac_sign_setup
 | 
			
		||||
#define psa_mac_verify_setup  psa_sec_mac_verify_setup
 | 
			
		||||
#define psa_mac_update  psa_sec_mac_update
 | 
			
		||||
#define psa_mac_sign_finish  psa_sec_mac_sign_finish
 | 
			
		||||
#define psa_mac_verify_finish  psa_sec_mac_verify_finish
 | 
			
		||||
#define psa_mac_abort  psa_sec_mac_abort
 | 
			
		||||
#define psa_cipher_encrypt  psa_sec_cipher_encrypt
 | 
			
		||||
#define psa_cipher_decrypt  psa_sec_cipher_decrypt
 | 
			
		||||
#define psa_cipher_encrypt_setup  psa_sec_cipher_encrypt_setup
 | 
			
		||||
#define psa_cipher_decrypt_setup  psa_sec_cipher_decrypt_setup
 | 
			
		||||
#define psa_cipher_generate_iv  psa_sec_cipher_generate_iv
 | 
			
		||||
#define psa_cipher_set_iv  psa_sec_cipher_set_iv
 | 
			
		||||
#define psa_cipher_update  psa_sec_cipher_update
 | 
			
		||||
#define psa_cipher_finish  psa_sec_cipher_finish
 | 
			
		||||
#define psa_cipher_abort  psa_sec_cipher_abort
 | 
			
		||||
#define psa_aead_encrypt  psa_sec_aead_encrypt
 | 
			
		||||
#define psa_aead_decrypt  psa_sec_aead_decrypt
 | 
			
		||||
#define psa_aead_encrypt_setup  psa_sec_aead_encrypt_setup
 | 
			
		||||
#define psa_aead_decrypt_setup  psa_sec_aead_decrypt_setup
 | 
			
		||||
#define psa_aead_generate_nonce  psa_sec_aead_generate_nonce
 | 
			
		||||
#define psa_aead_set_nonce  psa_sec_aead_set_nonce
 | 
			
		||||
#define psa_aead_set_lengths  psa_sec_aead_set_lengths
 | 
			
		||||
#define psa_aead_update_ad  psa_sec_aead_update_ad
 | 
			
		||||
#define psa_aead_update  psa_sec_aead_update
 | 
			
		||||
#define psa_aead_finish  psa_sec_aead_finish
 | 
			
		||||
#define psa_aead_verify  psa_sec_aead_verify
 | 
			
		||||
#define psa_aead_abort  psa_sec_aead_abort
 | 
			
		||||
#define psa_sign_hash  psa_sec_sign_hash
 | 
			
		||||
#define psa_verify_hash  psa_sec_verify_hash
 | 
			
		||||
#define psa_asymmetric_encrypt  psa_sec_asymmetric_encrypt
 | 
			
		||||
#define psa_asymmetric_decrypt  psa_sec_asymmetric_decrypt
 | 
			
		||||
#define psa_key_derivation_setup  psa_sec_key_derivation_setup
 | 
			
		||||
#define psa_key_derivation_get_capacity  psa_sec_key_derivation_get_capacity
 | 
			
		||||
#define psa_key_derivation_set_capacity  psa_sec_key_derivation_set_capacity
 | 
			
		||||
#define psa_key_derivation_input_bytes  psa_sec_key_derivation_input_bytes
 | 
			
		||||
#define psa_key_derivation_input_key  psa_sec_key_derivation_input_key
 | 
			
		||||
#define psa_key_derivation_key_agreement  psa_sec_key_derivation_key_agreement
 | 
			
		||||
#define psa_key_derivation_output_bytes  psa_sec_key_derivation_output_bytes
 | 
			
		||||
#define psa_key_derivation_output_key  psa_sec_key_derivation_output_key
 | 
			
		||||
#define psa_key_derivation_abort  psa_sec_key_derivation_abort
 | 
			
		||||
#define psa_raw_key_agreement  psa_sec_raw_key_agreement
 | 
			
		||||
#define psa_generate_random  psa_sec_generate_random
 | 
			
		||||
#define psa_generate_key  psa_sec_generate_key
 | 
			
		||||
 | 
			
		||||
#define mbedtls_psa_crypto_free  mbedtls_psa_sec_crypto_free
 | 
			
		||||
#define mbedtls_psa_inject_entropy  mbedtls_psa_sec_inject_entropy
 | 
			
		||||
#define psa_set_key_domain_parameters psa_sec_set_key_domain_parameters
 | 
			
		||||
#define psa_get_key_domain_parameters psa_sec_get_key_domain_parameters
 | 
			
		||||
 | 
			
		||||
#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER 1
 | 
			
		||||
 | 
			
		||||
#include "crypto.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The file "crypto_extra.h" contains vendor-specific definitions. This
 | 
			
		||||
 * can include vendor-defined algorithms, extra functions, etc. */
 | 
			
		||||
#include "crypto_extra.h"
 | 
			
		||||
 | 
			
		||||
#endif /* PSA_CRYPTO_SPE_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,85 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited and affiliates
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "psa_crypto_access_control.h"
 | 
			
		||||
#include "psa_crypto_core.h"
 | 
			
		||||
#include "psa_crypto_slot_management.h"
 | 
			
		||||
 | 
			
		||||
typedef struct psa_crypto_access_control_s {
 | 
			
		||||
    psa_key_handle_t key_handle;
 | 
			
		||||
    int32_t partition_id;
 | 
			
		||||
} psa_crypto_access_control_t;
 | 
			
		||||
 | 
			
		||||
static psa_crypto_access_control_t crypto_access_control_arr[PSA_KEY_SLOT_COUNT];
 | 
			
		||||
 | 
			
		||||
static inline void psa_crypto_access_control_reset()
 | 
			
		||||
{
 | 
			
		||||
    memset(crypto_access_control_arr, 0, sizeof(crypto_access_control_arr));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_crypto_access_control_init(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_crypto_access_control_reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_crypto_access_control_destroy(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_crypto_access_control_reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_crypto_access_control_register_handle(psa_key_handle_t key_handle, int32_t partition_id)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < PSA_KEY_SLOT_COUNT; i++) {
 | 
			
		||||
        if (crypto_access_control_arr[i].key_handle == 0 &&
 | 
			
		||||
                crypto_access_control_arr[i].partition_id == 0) {
 | 
			
		||||
            crypto_access_control_arr[i].key_handle = key_handle;
 | 
			
		||||
            crypto_access_control_arr[i].partition_id = partition_id;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SPM_PANIC("psa_crypto_access_control_register_handle failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_crypto_access_control_unregister_handle(psa_key_handle_t key_handle)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < PSA_KEY_SLOT_COUNT; i++) {
 | 
			
		||||
        if (crypto_access_control_arr[i].key_handle == key_handle) {
 | 
			
		||||
            crypto_access_control_arr[i].key_handle = 0;
 | 
			
		||||
            crypto_access_control_arr[i].partition_id = 0;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SPM_PANIC("psa_crypto_access_control_unregister_handle failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t psa_crypto_access_control_is_handle_permitted(psa_key_handle_t key_handle, int32_t partition_id)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < PSA_KEY_SLOT_COUNT; i++) {
 | 
			
		||||
        if (crypto_access_control_arr[i].key_handle == key_handle &&
 | 
			
		||||
                crypto_access_control_arr[i].partition_id == partition_id) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,40 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2019, Arm Limited and affiliates
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_CRYPTO_ACCESS_CONTROL_H
 | 
			
		||||
#define PSA_CRYPTO_ACCESS_CONTROL_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include "crypto_platform.h"
 | 
			
		||||
 | 
			
		||||
/* initialize the module, resets all tracked information */
 | 
			
		||||
void psa_crypto_access_control_init(void);
 | 
			
		||||
 | 
			
		||||
/* deinitialize the module, resets all tracked information */
 | 
			
		||||
void psa_crypto_access_control_destroy(void);
 | 
			
		||||
 | 
			
		||||
/* tracks and associates the key_handle with partition_id */
 | 
			
		||||
void psa_crypto_access_control_register_handle(psa_key_handle_t key_handle, int32_t partition_id);
 | 
			
		||||
 | 
			
		||||
/* removes tracking of the key_handle */
 | 
			
		||||
void psa_crypto_access_control_unregister_handle(psa_key_handle_t key_handle);
 | 
			
		||||
 | 
			
		||||
/* checks if the key_handle is associated with the partition_id, returns 0 is false otherwise 1 */
 | 
			
		||||
uint8_t psa_crypto_access_control_is_handle_permitted(psa_key_handle_t key_handle, int32_t partition_id);
 | 
			
		||||
 | 
			
		||||
#endif /* PSA_CRYPTO_ACCESS_CONTROL_H */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,108 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "CRYPTO_SRV",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000023",
 | 
			
		||||
  "entry_point": "crypto_main",
 | 
			
		||||
  "stack_size": "0x4000",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_CRYPTO_INIT_ID",
 | 
			
		||||
      "identifier": "0x00000F00",
 | 
			
		||||
      "signal": "PSA_CRYPTO_INIT",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_MAC_ID",
 | 
			
		||||
      "identifier": "0x00000F01",
 | 
			
		||||
      "signal": "PSA_MAC",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_HASH_ID",
 | 
			
		||||
      "identifier": "0x00000F02",
 | 
			
		||||
      "signal": "PSA_HASH",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_ASYMMETRIC_ID",
 | 
			
		||||
      "identifier": "0x00000F03",
 | 
			
		||||
      "signal": "PSA_ASYMMETRIC",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_SYMMETRIC_ID",
 | 
			
		||||
      "identifier": "0x00000F04",
 | 
			
		||||
      "signal": "PSA_SYMMETRIC",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_AEAD_ID",
 | 
			
		||||
      "identifier": "0x00000F05",
 | 
			
		||||
      "signal": "PSA_AEAD",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_KEY_MNG_ID",
 | 
			
		||||
      "identifier": "0x00000F06",
 | 
			
		||||
      "signal": "PSA_KEY_MNG",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_RNG_ID",
 | 
			
		||||
      "identifier": "0x00000F07",
 | 
			
		||||
      "signal": "PSA_RNG",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_CRYPTO_FREE_ID",
 | 
			
		||||
      "identifier": "0x00000F08",
 | 
			
		||||
      "signal": "PSA_CRYPTO_FREE",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_KEY_DERIVATION_ID",
 | 
			
		||||
      "identifier": "0x00000F09",
 | 
			
		||||
      "signal": "PSA_KEY_DERIVATION",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PSA_ENTROPY_ID",
 | 
			
		||||
      "identifier": "0x00000F0A",
 | 
			
		||||
      "signal": "PSA_ENTROPY_INJECT",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 1,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "extern_sids": [
 | 
			
		||||
    "PSA_ITS_GET",
 | 
			
		||||
    "PSA_ITS_SET",
 | 
			
		||||
    "PSA_ITS_INFO",
 | 
			
		||||
    "PSA_ITS_REMOVE"
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/psa_crypto_partition.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,202 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2019-2020 Arm Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
#include "platform_srv_impl.h"
 | 
			
		||||
#include "psa/lifecycle.h"
 | 
			
		||||
#include "psa/internal_trusted_storage.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
 | 
			
		||||
#define INPUT_BUFFER_SIZE  64
 | 
			
		||||
#define OUTPUT_BUFFER_SIZE 64
 | 
			
		||||
 | 
			
		||||
typedef psa_status_t (*SignalHandler)(psa_msg_t *);
 | 
			
		||||
 | 
			
		||||
static psa_status_t lifecycle_get(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t lc_state;
 | 
			
		||||
 | 
			
		||||
    if (msg->out_size[0] != sizeof(lc_state)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_status_t status = psa_platfrom_lifecycle_get_impl(&lc_state);
 | 
			
		||||
    if (status == PSA_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, &lc_state, sizeof(lc_state));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t lifecycle_change_request(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t lc_state;
 | 
			
		||||
 | 
			
		||||
    if (msg->in_size[0] != sizeof(lc_state)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
    if (psa_read(msg->handle, 0, &lc_state, sizeof(lc_state)) != sizeof(lc_state)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
    return psa_platfrom_lifecycle_change_request_impl(lc_state);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MBED_NORETURN psa_status_t system_reset_request(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    (void)msg;
 | 
			
		||||
    mbed_psa_system_reset_impl();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum tfm_platform_err_t
 | 
			
		||||
platform_sp_ioctl_ipc(const psa_msg_t *msg) {
 | 
			
		||||
    void *input = NULL;
 | 
			
		||||
    void *output = NULL;
 | 
			
		||||
    psa_invec invec = {0};
 | 
			
		||||
    psa_outvec outvec = {0};
 | 
			
		||||
    uint8_t input_buffer[INPUT_BUFFER_SIZE] = {0};
 | 
			
		||||
    uint8_t output_buffer[OUTPUT_BUFFER_SIZE] = {0};
 | 
			
		||||
    tfm_platform_ioctl_req_t request = 0;
 | 
			
		||||
    enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SYSTEM_ERROR;
 | 
			
		||||
    size_t num = 0;
 | 
			
		||||
    uint32_t in_len = PSA_MAX_IOVEC;
 | 
			
		||||
    uint32_t out_len = PSA_MAX_IOVEC;
 | 
			
		||||
 | 
			
		||||
    while ((in_len > 0) && (msg->in_size[in_len - 1] == 0))
 | 
			
		||||
    {
 | 
			
		||||
        in_len--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((out_len > 0) && (msg->out_size[out_len - 1] == 0))
 | 
			
		||||
    {
 | 
			
		||||
        out_len--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((in_len < 1) || (in_len > 2) ||
 | 
			
		||||
            (out_len > 1))
 | 
			
		||||
    {
 | 
			
		||||
        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    num = psa_read(msg->handle, 0, &request, sizeof(request));
 | 
			
		||||
    if (num != sizeof(request))
 | 
			
		||||
    {
 | 
			
		||||
        return PSA_ERROR_PROGRAMMER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (in_len > 1)
 | 
			
		||||
    {
 | 
			
		||||
        if (msg->in_size[1] > INPUT_BUFFER_SIZE) {
 | 
			
		||||
            return PSA_ERROR_PROGRAMMER_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
        num = psa_read(msg->handle, 1, &input_buffer, msg->in_size[1]);
 | 
			
		||||
        if (num != msg->in_size[1]) {
 | 
			
		||||
            return PSA_ERROR_PROGRAMMER_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
        invec.base = input_buffer;
 | 
			
		||||
        invec.len = msg->in_size[1];
 | 
			
		||||
        input = &invec;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (out_len > 0)
 | 
			
		||||
    {
 | 
			
		||||
        if (msg->out_size[0] > OUTPUT_BUFFER_SIZE) {
 | 
			
		||||
            return PSA_ERROR_PROGRAMMER_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
        outvec.base = output_buffer;
 | 
			
		||||
        outvec.len = msg->out_size[0];
 | 
			
		||||
        output = &outvec;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = tfm_platform_hal_ioctl(request, input, output);
 | 
			
		||||
 | 
			
		||||
    if (output != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        psa_write(msg->handle, 0, outvec.base, outvec.len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t platform_ioctl(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    /*  platform_sp_ioctl_ipc returns either psa_status_t or one of the
 | 
			
		||||
     *  following errorcodes:
 | 
			
		||||
     *  enum tfm_platform_err_t {
 | 
			
		||||
     *      TFM_PLATFORM_ERR_SUCCESS = 0,
 | 
			
		||||
     *      TFM_PLATFORM_ERR_SYSTEM_ERROR,
 | 
			
		||||
     *      TFM_PLATFORM_ERR_INVALID_PARAM,
 | 
			
		||||
     *      TFM_PLATFORM_ERR_NOT_SUPPORTED,
 | 
			
		||||
     *
 | 
			
		||||
     *      TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX
 | 
			
		||||
     *  };
 | 
			
		||||
     */
 | 
			
		||||
    return platform_sp_ioctl_ipc(msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void message_handler(psa_msg_t *msg, SignalHandler handler)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    switch (msg->type) {
 | 
			
		||||
        case PSA_IPC_CONNECT: //fallthrough
 | 
			
		||||
        case PSA_IPC_DISCONNECT: {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_CALL: {
 | 
			
		||||
            status = handler(msg);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
            SPM_PANIC("Unexpected message type %lu!", msg->type);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    psa_reply(msg->handle, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void platform_partition_entry(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait(PLATFORM_WAIT_ANY_SID_MSK, PSA_BLOCK);
 | 
			
		||||
        if ((signals & PSA_PLATFORM_LC_GET_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_PLATFORM_LC_GET_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, lifecycle_get);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_PLATFORM_LC_SET_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_PLATFORM_LC_SET_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, lifecycle_change_request);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_PLATFORM_SYSTEM_RESET_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_PLATFORM_SYSTEM_RESET_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, system_reset_request);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_PLATFORM_IOCTL_MSK)  != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_PLATFORM_IOCTL_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, platform_ioctl);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,48 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "PLATFORM",
 | 
			
		||||
    "type": "APPLICATION-ROT",
 | 
			
		||||
    "priority": "NORMAL",
 | 
			
		||||
    "id": "0x00000008",
 | 
			
		||||
    "entry_point": "platform_partition_entry",
 | 
			
		||||
    "stack_size": "0x400",
 | 
			
		||||
    "heap_size": "0x400",
 | 
			
		||||
    "services": [{
 | 
			
		||||
        "name": "PSA_PLATFORM_LC_GET",
 | 
			
		||||
        "identifier": "0x00011000",
 | 
			
		||||
        "signal": "PSA_PLATFORM_LC_GET_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "name": "PSA_PLATFORM_LC_SET",
 | 
			
		||||
        "identifier": "0x00011001",
 | 
			
		||||
        "signal": "PSA_PLATFORM_LC_SET_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "name": "PSA_PLATFORM_SYSTEM_RESET",
 | 
			
		||||
        "identifier": "0x00011002",
 | 
			
		||||
        "signal": "PSA_PLATFORM_SYSTEM_RESET_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "name": "PSA_PLATFORM_IOCTL",
 | 
			
		||||
        "identifier": "0x00011003",
 | 
			
		||||
        "signal": "PSA_PLATFORM_IOCTL_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    "extern_sids": [
 | 
			
		||||
      "PSA_ITS_RESET"
 | 
			
		||||
    ],
 | 
			
		||||
    "source_files": [
 | 
			
		||||
      "COMPONENT_SPE/platform_partition.c"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,221 +0,0 @@
 | 
			
		|||
/* Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "psa/client.h"
 | 
			
		||||
#include "psa/service.h"
 | 
			
		||||
#include "mbed_spm_partitions.h"
 | 
			
		||||
#include "psa/internal_trusted_storage.h"
 | 
			
		||||
#include "pits_impl.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
 | 
			
		||||
int kv_init_storage_config();
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef psa_status_t (*SignalHandler)(psa_msg_t *);
 | 
			
		||||
 | 
			
		||||
static psa_status_t storage_set(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_storage_uid_t key = 0;
 | 
			
		||||
    void *data = NULL;
 | 
			
		||||
    uint32_t alloc_size = msg->in_size[1];
 | 
			
		||||
    psa_storage_create_flags_t flags = 0;
 | 
			
		||||
 | 
			
		||||
    if ((msg->in_size[0] != sizeof(key)) || (msg->in_size[2] != sizeof(flags))) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 2, &flags, sizeof(flags)) != sizeof(flags)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data = malloc(alloc_size);
 | 
			
		||||
    if (data == NULL) {
 | 
			
		||||
        return PSA_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 1, data, msg->in_size[1]) != msg->in_size[1]) {
 | 
			
		||||
        free(data);
 | 
			
		||||
        return PSA_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_status_t status = psa_its_set_impl(msg->client_id, key, alloc_size, data, flags);
 | 
			
		||||
    memset(data, 0, alloc_size);
 | 
			
		||||
    free(data);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t storage_get(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_storage_uid_t key = 0;
 | 
			
		||||
    uint32_t offset = 0;
 | 
			
		||||
    size_t actual_size;
 | 
			
		||||
 | 
			
		||||
    if ((msg->in_size[0] != sizeof(key)) ||
 | 
			
		||||
            (msg->in_size[1] != sizeof(offset)) ||
 | 
			
		||||
            (msg->out_size[1] != sizeof(actual_size))) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 1, &offset, sizeof(offset)) != sizeof(offset)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t *data = (uint8_t *)malloc(msg->out_size[0]);
 | 
			
		||||
    if (data == NULL) {
 | 
			
		||||
        return PSA_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_status_t status = psa_its_get_impl(msg->client_id, key, offset, msg->out_size[0], data, &actual_size);
 | 
			
		||||
    if (status == PSA_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, data, actual_size);
 | 
			
		||||
        psa_write(msg->handle, 1, &actual_size, sizeof(actual_size));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(data, 0, msg->out_size[0]);
 | 
			
		||||
    free(data);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t storage_info(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    struct psa_storage_info_t info = { 0 };
 | 
			
		||||
    psa_storage_uid_t key = 0;
 | 
			
		||||
 | 
			
		||||
    if ((msg->in_size[0] != sizeof(key)) || (msg->out_size[0] != sizeof(info))) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_status_t status = psa_its_get_info_impl(msg->client_id, key, &info);
 | 
			
		||||
    if (status == PSA_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, &info, msg->out_size[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_status_t storage_remove(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    psa_storage_uid_t key = 0;
 | 
			
		||||
 | 
			
		||||
    if (msg->in_size[0] != sizeof(key)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
 | 
			
		||||
        return PSA_DROP_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return psa_its_remove_impl(msg->client_id, key);
 | 
			
		||||
}
 | 
			
		||||
static psa_status_t storage_reset(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    (void)msg;
 | 
			
		||||
    return psa_its_reset_impl();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void message_handler(psa_msg_t *msg, SignalHandler handler)
 | 
			
		||||
{
 | 
			
		||||
    psa_status_t status = PSA_SUCCESS;
 | 
			
		||||
    switch (msg->type) {
 | 
			
		||||
        case PSA_IPC_CONNECT: //fallthrough
 | 
			
		||||
        case PSA_IPC_DISCONNECT: {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_CALL: {
 | 
			
		||||
            status = handler(msg);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
            SPM_PANIC("Unexpected message type %lu!", msg->type);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    psa_reply(msg->handle, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void its_entry(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    psa_signal_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait(ITS_WAIT_ANY_SID_MSK, PSA_BLOCK);
 | 
			
		||||
        // KVStore initiation:
 | 
			
		||||
        // - Must be done after the psa_wait() call since only now we know OS initialization is done
 | 
			
		||||
        // - Repeating calls has no effect
 | 
			
		||||
        int kv_status = kv_init_storage_config();
 | 
			
		||||
        if (kv_status != MBED_SUCCESS) {
 | 
			
		||||
            SPM_PANIC("KVStore initiation failed with status %d!", kv_status);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ((signals & PSA_ITS_SET_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_ITS_SET_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, storage_set);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_ITS_GET_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_ITS_GET_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, storage_get);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_ITS_INFO_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_ITS_INFO_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, storage_info);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_ITS_REMOVE_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_ITS_REMOVE_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, storage_remove);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_ITS_RESET_MSK) != 0) {
 | 
			
		||||
            if (PSA_SUCCESS != psa_get(PSA_ITS_RESET_MSK, &msg)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            message_handler(&msg, storage_reset);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,53 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "ITS",
 | 
			
		||||
    "type": "APPLICATION-ROT",
 | 
			
		||||
    "priority": "NORMAL",
 | 
			
		||||
    "id": "0x0000000A",
 | 
			
		||||
    "entry_point": "its_entry",
 | 
			
		||||
    "stack_size": "0x800",
 | 
			
		||||
    "heap_size": "0x400",
 | 
			
		||||
    "services": [{
 | 
			
		||||
        "name": "PSA_ITS_GET",
 | 
			
		||||
        "identifier": "0x00011A00",
 | 
			
		||||
        "signal": "PSA_ITS_GET_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "name": "PSA_ITS_SET",
 | 
			
		||||
        "identifier": "0x00011A01",
 | 
			
		||||
        "signal": "PSA_ITS_SET_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "name": "PSA_ITS_INFO",
 | 
			
		||||
        "identifier": "0x00011A02",
 | 
			
		||||
        "signal": "PSA_ITS_INFO_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "name": "PSA_ITS_REMOVE",
 | 
			
		||||
        "identifier": "0x00011A03",
 | 
			
		||||
        "signal": "PSA_ITS_REMOVE_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "name": "PSA_ITS_RESET",
 | 
			
		||||
        "identifier": "0x00011A04",
 | 
			
		||||
        "signal": "PSA_ITS_RESET_MSK",
 | 
			
		||||
        "non_secure_clients": false,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    "source_files": [
 | 
			
		||||
      "COMPONENT_SPE/its_partition.c"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -2102,7 +2102,6 @@ PREDEFINED             = DOXYGEN_ONLY            \
 | 
			
		|||
                         DEVICE_QSPI             \
 | 
			
		||||
                         DEVICE_STORAGE          \
 | 
			
		||||
                         DEVICE_WATCHDOG         \
 | 
			
		||||
                         COMPONENT_SPE           \
 | 
			
		||||
                         "TFM_LVL=1" \
 | 
			
		||||
                         "MBED_DEPRECATED_SINCE(d, m)=" \
 | 
			
		||||
                         "MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=" \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
    "SEARCH_INCLUDES": "YES",
 | 
			
		||||
    "INCLUDE_PATH": "",
 | 
			
		||||
    "INCLUDE_FILE_PATTERNS": "",
 | 
			
		||||
    "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH  DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_MPU DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE DEVICE_WATCHDOG DEVICE_RESET_REASON COMPONENT_SPE \"TFM_LVL=1\" \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\" \"BLE_ROLE_OBSERVER=1\" \"BLE_ROLE_BROADCASTER=1\" \"BLE_ROLE_PERIPHERAL=1\" \"BLE_ROLE_CENTRAL=1\" \"BLE_FEATURE_GATT_CLIENT=1\" \"BLE_FEATURE_GATT_SERVER=1\" \"BLE_FEATURE_SECURITY=1\" \"BLE_FEATURE_SECURE_CONNECTIONS=1\" \"BLE_FEATURE_SIGNING=1\" \"BLE_FEATURE_PHY_MANAGEMENT=1\" \"BLE_FEATURE_WHITELIST=1\" \"BLE_FEATURE_PRIVACY=1\" \"BLE_FEATURE_PERIODIC_ADVERTISING=1\" \"BLE_FEATURE_EXTENDED_ADVERTISING=1\"",
 | 
			
		||||
    "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH  DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_MPU DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE DEVICE_WATCHDOG DEVICE_RESET_REASON \"TFM_LVL=1\" \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\" \"BLE_ROLE_OBSERVER=1\" \"BLE_ROLE_BROADCASTER=1\" \"BLE_ROLE_PERIPHERAL=1\" \"BLE_ROLE_CENTRAL=1\" \"BLE_FEATURE_GATT_CLIENT=1\" \"BLE_FEATURE_GATT_SERVER=1\" \"BLE_FEATURE_SECURITY=1\" \"BLE_FEATURE_SECURE_CONNECTIONS=1\" \"BLE_FEATURE_SIGNING=1\" \"BLE_FEATURE_PHY_MANAGEMENT=1\" \"BLE_FEATURE_WHITELIST=1\" \"BLE_FEATURE_PRIVACY=1\" \"BLE_FEATURE_PERIODIC_ADVERTISING=1\" \"BLE_FEATURE_EXTENDED_ADVERTISING=1\"",
 | 
			
		||||
    "EXPAND_AS_DEFINED": "",
 | 
			
		||||
    "SKIP_FUNCTION_MACROS": "NO",
 | 
			
		||||
    "STRIP_CODE_COMMENTS": "NO",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,13 +89,13 @@ static void reset_storage_for_compliance_test()
 | 
			
		|||
 | 
			
		||||
static void inject_entropy()
 | 
			
		||||
{
 | 
			
		||||
#if defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
#if defined(MBEDTLS_ENTROPY_NV_SEED)
 | 
			
		||||
    uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 };
 | 
			
		||||
    for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) {
 | 
			
		||||
        seed[i] = i;
 | 
			
		||||
    }
 | 
			
		||||
    mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE);
 | 
			
		||||
#endif // defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
#endif // defined(MBEDTLS_ENTROPY_NV_SEED)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,9 +49,6 @@ TLS_SRC := \
 | 
			
		|||
# COMPONENT_PSA_SRV_IMPL - Include secure service implementation code. For
 | 
			
		||||
# example PSA Crypto or PSA Secure Time implementations
 | 
			
		||||
TARGET_SRV_IMPL:=$(TARGET_PREFIX)/platform/COMPONENT_PSA_SRV_IMPL
 | 
			
		||||
# COMPONENT_SPE - Include code that compiles ONLY to the SPE image and never
 | 
			
		||||
# compiles to the NSPE image
 | 
			
		||||
TARGET_SPE:=$(TARGET_PREFIX)/platform/COMPONENT_SPE
 | 
			
		||||
# COMPONENT_NSPE - Include code that compiles ONLY to the NSPE image and never
 | 
			
		||||
# compiles to the SPE image
 | 
			
		||||
TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE
 | 
			
		||||
| 
						 | 
				
			
			@ -88,15 +85,12 @@ rsync:
 | 
			
		|||
	#
 | 
			
		||||
	# Copying Mbed Crypto into Mbed OS...
 | 
			
		||||
	rm -rf $(TARGET_SRV_IMPL)
 | 
			
		||||
	rm -rf $(TARGET_SPE)
 | 
			
		||||
	rm -rf $(TARGET_SRC)
 | 
			
		||||
 | 
			
		||||
	mkdir -p $(TARGET_SRV_IMPL)
 | 
			
		||||
	mkdir -p $(TARGET_SPE)
 | 
			
		||||
	mkdir -p $(TARGET_NSPE)
 | 
			
		||||
 | 
			
		||||
	rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_NSPE)/
 | 
			
		||||
	rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_SPE)/crypto_struct_spe.h
 | 
			
		||||
	rsync -a --delete $(CRYPTO_DIR)/library/psa_*.c $(TARGET_SRV_IMPL)/
 | 
			
		||||
	rsync -a --delete $(CRYPTO_DIR)/library/psa_*.h $(TARGET_SRV_IMPL)/
 | 
			
		||||
	rsync -a --delete $(CRYPTO_DIR)/library/*.c $(TARGET_SRC)/
 | 
			
		||||
| 
						 | 
				
			
			@ -135,4 +129,3 @@ clean:
 | 
			
		|||
	rm -rf $(TARGET_SRC)
 | 
			
		||||
	rm -rf $(CRYPTO_DIR)
 | 
			
		||||
	rm -rf $(TARGET_SRV_IMPL)
 | 
			
		||||
	rm -rf $(TARGET_SPE)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,522 +0,0 @@
 | 
			
		|||
/**
 | 
			
		||||
 * \file psa/crypto_struct.h
 | 
			
		||||
 *
 | 
			
		||||
 * \brief PSA cryptography module: Mbed TLS structured type implementations
 | 
			
		||||
 *
 | 
			
		||||
 * \note This file may not be included directly. Applications must
 | 
			
		||||
 * include psa/crypto.h.
 | 
			
		||||
 *
 | 
			
		||||
 * This file contains the definitions of some data structures with
 | 
			
		||||
 * implementation-specific definitions.
 | 
			
		||||
 *
 | 
			
		||||
 * In implementations with isolation between the application and the
 | 
			
		||||
 * cryptography module, it is expected that the front-end and the back-end
 | 
			
		||||
 * would have different versions of this file.
 | 
			
		||||
 *
 | 
			
		||||
 * <h3>Design notes about multipart operation structures</h3>
 | 
			
		||||
 *
 | 
			
		||||
 * Each multipart operation structure contains a `psa_algorithm_t alg`
 | 
			
		||||
 * field which indicates which specific algorithm the structure is for.
 | 
			
		||||
 * When the structure is not in use, `alg` is 0. Most of the structure
 | 
			
		||||
 * consists of a union which is discriminated by `alg`.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that when `alg` is 0, the content of other fields is undefined.
 | 
			
		||||
 * In particular, it is not guaranteed that a freshly-initialized structure
 | 
			
		||||
 * is all-zero: we initialize structures to something like `{0, 0}`, which
 | 
			
		||||
 * is only guaranteed to initializes the first member of the union;
 | 
			
		||||
 * GCC and Clang initialize the whole structure to 0 (at the time of writing),
 | 
			
		||||
 * but MSVC and CompCert don't.
 | 
			
		||||
 *
 | 
			
		||||
 * In Mbed Crypto, multipart operation structures live independently from
 | 
			
		||||
 * the key. This allows Mbed Crypto to free the key objects when destroying
 | 
			
		||||
 * a key slot. If a multipart operation needs to remember the key after
 | 
			
		||||
 * the setup function returns, the operation structure needs to contain a
 | 
			
		||||
 * copy of the key.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright (C) 2018, ARM Limited, All Rights Reserved
 | 
			
		||||
 *  SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
			
		||||
 *  not use this file except in compliance with the License.
 | 
			
		||||
 *  You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *  http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 *  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 *  See the License for the specific language governing permissions and
 | 
			
		||||
 *  limitations under the License.
 | 
			
		||||
 *
 | 
			
		||||
 *  This file is part of mbed TLS (https://tls.mbed.org)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_CRYPTO_STRUCT_H
 | 
			
		||||
#define PSA_CRYPTO_STRUCT_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
 | 
			
		||||
 * in each of its header files. */
 | 
			
		||||
#if !defined(MBEDTLS_CONFIG_FILE)
 | 
			
		||||
#include "mbedtls/config.h"
 | 
			
		||||
#else
 | 
			
		||||
#include MBEDTLS_CONFIG_FILE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "mbedtls/cipher.h"
 | 
			
		||||
#include "mbedtls/cmac.h"
 | 
			
		||||
#include "mbedtls/gcm.h"
 | 
			
		||||
#include "mbedtls/md.h"
 | 
			
		||||
#include "mbedtls/md2.h"
 | 
			
		||||
#include "mbedtls/md4.h"
 | 
			
		||||
#include "mbedtls/md5.h"
 | 
			
		||||
#include "mbedtls/ripemd160.h"
 | 
			
		||||
#include "mbedtls/sha1.h"
 | 
			
		||||
#include "mbedtls/sha256.h"
 | 
			
		||||
#include "mbedtls/sha512.h"
 | 
			
		||||
 | 
			
		||||
struct psa_hash_operation_s
 | 
			
		||||
{
 | 
			
		||||
    psa_algorithm_t alg;
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
 | 
			
		||||
#if defined(MBEDTLS_MD2_C)
 | 
			
		||||
        mbedtls_md2_context md2;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_MD4_C)
 | 
			
		||||
        mbedtls_md4_context md4;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_MD5_C)
 | 
			
		||||
        mbedtls_md5_context md5;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_RIPEMD160_C)
 | 
			
		||||
        mbedtls_ripemd160_context ripemd160;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_SHA1_C)
 | 
			
		||||
        mbedtls_sha1_context sha1;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_SHA256_C)
 | 
			
		||||
        mbedtls_sha256_context sha256;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_SHA512_C)
 | 
			
		||||
        mbedtls_sha512_context sha512;
 | 
			
		||||
#endif
 | 
			
		||||
    } ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PSA_HASH_OPERATION_INIT {0, {0}}
 | 
			
		||||
static inline struct psa_hash_operation_s psa_hash_operation_init( void )
 | 
			
		||||
{
 | 
			
		||||
    const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT;
 | 
			
		||||
    return( v );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_MD_C)
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
        /** The hash context. */
 | 
			
		||||
        struct psa_hash_operation_s hash_ctx;
 | 
			
		||||
        /** The HMAC part of the context. */
 | 
			
		||||
        uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
 | 
			
		||||
} psa_hmac_internal_data;
 | 
			
		||||
#endif /* MBEDTLS_MD_C */
 | 
			
		||||
 | 
			
		||||
struct psa_mac_operation_s
 | 
			
		||||
{
 | 
			
		||||
    psa_algorithm_t alg;
 | 
			
		||||
    unsigned int key_set : 1;
 | 
			
		||||
    unsigned int iv_required : 1;
 | 
			
		||||
    unsigned int iv_set : 1;
 | 
			
		||||
    unsigned int has_input : 1;
 | 
			
		||||
    unsigned int is_sign : 1;
 | 
			
		||||
    uint8_t mac_size;
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
 | 
			
		||||
#if defined(MBEDTLS_MD_C)
 | 
			
		||||
        psa_hmac_internal_data hmac;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_CMAC_C)
 | 
			
		||||
        mbedtls_cipher_context_t cmac;
 | 
			
		||||
#endif
 | 
			
		||||
    } ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}}
 | 
			
		||||
static inline struct psa_mac_operation_s psa_mac_operation_init( void )
 | 
			
		||||
{
 | 
			
		||||
    const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT;
 | 
			
		||||
    return( v );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct psa_cipher_operation_s
 | 
			
		||||
{
 | 
			
		||||
    psa_algorithm_t alg;
 | 
			
		||||
    unsigned int key_set : 1;
 | 
			
		||||
    unsigned int iv_required : 1;
 | 
			
		||||
    unsigned int iv_set : 1;
 | 
			
		||||
    uint8_t iv_size;
 | 
			
		||||
    uint8_t block_size;
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        unsigned dummy; /* Enable easier initializing of the union. */
 | 
			
		||||
        mbedtls_cipher_context_t cipher;
 | 
			
		||||
    } ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}}
 | 
			
		||||
static inline struct psa_cipher_operation_s psa_cipher_operation_init( void )
 | 
			
		||||
{
 | 
			
		||||
    const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;
 | 
			
		||||
    return( v );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct psa_aead_operation_s
 | 
			
		||||
{
 | 
			
		||||
    psa_algorithm_t alg;
 | 
			
		||||
    unsigned int key_set : 1;
 | 
			
		||||
    unsigned int iv_set : 1;
 | 
			
		||||
    uint8_t iv_size;
 | 
			
		||||
    uint8_t block_size;
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        unsigned dummy; /* Enable easier initializing of the union. */
 | 
			
		||||
        mbedtls_cipher_context_t cipher;
 | 
			
		||||
    } ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, {0}}
 | 
			
		||||
static inline struct psa_aead_operation_s psa_aead_operation_init( void )
 | 
			
		||||
{
 | 
			
		||||
    const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT;
 | 
			
		||||
    return( v );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_MD_C)
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *info;
 | 
			
		||||
    size_t info_length;
 | 
			
		||||
    psa_hmac_internal_data hmac;
 | 
			
		||||
    uint8_t prk[PSA_HASH_MAX_SIZE];
 | 
			
		||||
    uint8_t output_block[PSA_HASH_MAX_SIZE];
 | 
			
		||||
#if PSA_HASH_MAX_SIZE > 0xff
 | 
			
		||||
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
 | 
			
		||||
#endif
 | 
			
		||||
    uint8_t offset_in_block;
 | 
			
		||||
    uint8_t block_number;
 | 
			
		||||
    unsigned int state : 2;
 | 
			
		||||
    unsigned int info_set : 1;
 | 
			
		||||
} psa_hkdf_key_derivation_t;
 | 
			
		||||
#endif /* MBEDTLS_MD_C */
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_MD_C)
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    TLS12_PRF_STATE_INIT,       /* no input provided */
 | 
			
		||||
    TLS12_PRF_STATE_SEED_SET,   /* seed has been set */
 | 
			
		||||
    TLS12_PRF_STATE_KEY_SET,    /* key has been set */
 | 
			
		||||
    TLS12_PRF_STATE_LABEL_SET,  /* label has been set */
 | 
			
		||||
    TLS12_PRF_STATE_OUTPUT      /* output has been started */
 | 
			
		||||
} psa_tls12_prf_key_derivation_state_t;
 | 
			
		||||
 | 
			
		||||
typedef struct psa_tls12_prf_key_derivation_s
 | 
			
		||||
{
 | 
			
		||||
#if PSA_HASH_MAX_SIZE > 0xff
 | 
			
		||||
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Indicates how many bytes in the current HMAC block have
 | 
			
		||||
     * not yet been read by the user. */
 | 
			
		||||
    uint8_t left_in_block;
 | 
			
		||||
 | 
			
		||||
    /* The 1-based number of the block. */
 | 
			
		||||
    uint8_t block_number;
 | 
			
		||||
 | 
			
		||||
    psa_tls12_prf_key_derivation_state_t state;
 | 
			
		||||
 | 
			
		||||
    uint8_t *seed;
 | 
			
		||||
    size_t seed_length;
 | 
			
		||||
    uint8_t *label;
 | 
			
		||||
    size_t label_length;
 | 
			
		||||
    psa_hmac_internal_data hmac;
 | 
			
		||||
    uint8_t Ai[PSA_HASH_MAX_SIZE];
 | 
			
		||||
 | 
			
		||||
    /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */
 | 
			
		||||
    uint8_t output_block[PSA_HASH_MAX_SIZE];
 | 
			
		||||
} psa_tls12_prf_key_derivation_t;
 | 
			
		||||
#endif /* MBEDTLS_MD_C */
 | 
			
		||||
 | 
			
		||||
struct psa_key_derivation_s
 | 
			
		||||
{
 | 
			
		||||
    psa_algorithm_t alg;
 | 
			
		||||
    unsigned int can_output_key : 1;
 | 
			
		||||
    size_t capacity;
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        /* Make the union non-empty even with no supported algorithms. */
 | 
			
		||||
        uint8_t dummy;
 | 
			
		||||
#if defined(MBEDTLS_MD_C)
 | 
			
		||||
        psa_hkdf_key_derivation_t hkdf;
 | 
			
		||||
        psa_tls12_prf_key_derivation_t tls12_prf;
 | 
			
		||||
#endif
 | 
			
		||||
    } ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* This only zeroes out the first byte in the union, the rest is unspecified. */
 | 
			
		||||
#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}}
 | 
			
		||||
static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void )
 | 
			
		||||
{
 | 
			
		||||
    const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT;
 | 
			
		||||
    return( v );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct psa_key_policy_s
 | 
			
		||||
{
 | 
			
		||||
    psa_key_usage_t usage;
 | 
			
		||||
    psa_algorithm_t alg;
 | 
			
		||||
    psa_algorithm_t alg2;
 | 
			
		||||
};
 | 
			
		||||
typedef struct psa_key_policy_s psa_key_policy_t;
 | 
			
		||||
 | 
			
		||||
#define PSA_KEY_POLICY_INIT {0, 0, 0}
 | 
			
		||||
static inline struct psa_key_policy_s psa_key_policy_init( void )
 | 
			
		||||
{
 | 
			
		||||
    const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT;
 | 
			
		||||
    return( v );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The type used internally for key sizes.
 | 
			
		||||
 * Public interfaces use size_t, but internally we use a smaller type. */
 | 
			
		||||
typedef uint16_t psa_key_bits_t;
 | 
			
		||||
/* The maximum value of the type used to represent bit-sizes.
 | 
			
		||||
 * This is used to mark an invalid key size. */
 | 
			
		||||
#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) )
 | 
			
		||||
/* The maximum size of a key in bits.
 | 
			
		||||
 * Currently defined as the maximum that can be represented, rounded down
 | 
			
		||||
 * to a whole number of bytes.
 | 
			
		||||
 * This is an uncast value so that it can be used in preprocessor
 | 
			
		||||
 * conditionals. */
 | 
			
		||||
#define PSA_MAX_KEY_BITS 0xfff8
 | 
			
		||||
 | 
			
		||||
/** A mask of flags that can be stored in key attributes.
 | 
			
		||||
 *
 | 
			
		||||
 * This type is also used internally to store flags in slots. Internal
 | 
			
		||||
 * flags are defined in library/psa_crypto_core.h. Internal flags may have
 | 
			
		||||
 * the same value as external flags if they are properly handled during
 | 
			
		||||
 * key creation and in psa_get_key_attributes.
 | 
			
		||||
 */
 | 
			
		||||
typedef uint16_t psa_key_attributes_flag_t;
 | 
			
		||||
 | 
			
		||||
#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER     \
 | 
			
		||||
    ( (psa_key_attributes_flag_t) 0x0001 )
 | 
			
		||||
 | 
			
		||||
/* A mask of key attribute flags used externally only.
 | 
			
		||||
 * Only meant for internal checks inside the library. */
 | 
			
		||||
#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY (      \
 | 
			
		||||
        MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER |    \
 | 
			
		||||
        0 )
 | 
			
		||||
 | 
			
		||||
/* A mask of key attribute flags used both internally and externally.
 | 
			
		||||
 * Currently there aren't any. */
 | 
			
		||||
#define MBEDTLS_PSA_KA_MASK_DUAL_USE (          \
 | 
			
		||||
        0 )
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    psa_key_type_t type;
 | 
			
		||||
    psa_key_lifetime_t lifetime;
 | 
			
		||||
    psa_key_id_t id;
 | 
			
		||||
    psa_key_policy_t policy;
 | 
			
		||||
    psa_key_bits_t bits;
 | 
			
		||||
    psa_key_attributes_flag_t flags;
 | 
			
		||||
} psa_core_key_attributes_t;
 | 
			
		||||
 | 
			
		||||
/* The server must be able to interpret the attributes as specified by the
 | 
			
		||||
 * client. The server works with the psa_key_id_t encoding the key owner, but
 | 
			
		||||
 * the client works with the psa_key_id_t not containing the key owner (pure
 | 
			
		||||
 * psa_app_key_id_t. */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    psa_key_type_t type;
 | 
			
		||||
    psa_key_lifetime_t lifetime;
 | 
			
		||||
    psa_app_key_id_t id;
 | 
			
		||||
    psa_key_policy_t policy;
 | 
			
		||||
    psa_key_bits_t bits;
 | 
			
		||||
    psa_key_attributes_flag_t flags;
 | 
			
		||||
} psa_client_core_key_attributes_t;
 | 
			
		||||
 | 
			
		||||
#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0}
 | 
			
		||||
 | 
			
		||||
struct psa_key_attributes_s
 | 
			
		||||
{
 | 
			
		||||
    psa_core_key_attributes_t core;
 | 
			
		||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 | 
			
		||||
    psa_key_slot_number_t slot_number;
 | 
			
		||||
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 | 
			
		||||
    void *domain_parameters;
 | 
			
		||||
    size_t domain_parameters_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 | 
			
		||||
#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0}
 | 
			
		||||
#else
 | 
			
		||||
#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0}
 | 
			
		||||
#endif
 | 
			
		||||
typedef struct psa_client_key_attributes_s
 | 
			
		||||
{
 | 
			
		||||
    psa_client_core_key_attributes_t core;
 | 
			
		||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 | 
			
		||||
    psa_key_slot_number_t slot_number;
 | 
			
		||||
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 | 
			
		||||
    void *domain_parameters;
 | 
			
		||||
    size_t domain_parameters_size;
 | 
			
		||||
} psa_client_key_attributes_t;
 | 
			
		||||
 | 
			
		||||
static inline struct psa_key_attributes_s psa_key_attributes_init( void )
 | 
			
		||||
{
 | 
			
		||||
    const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
    return( v );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void psa_core_attributes_to_client(
 | 
			
		||||
    const psa_core_key_attributes_t *server,
 | 
			
		||||
    psa_client_core_key_attributes_t *client)
 | 
			
		||||
{
 | 
			
		||||
    client->type = server->type;
 | 
			
		||||
    client->lifetime = server->lifetime;
 | 
			
		||||
    client->id = server->id.key_id;
 | 
			
		||||
    client->policy = server->policy;
 | 
			
		||||
    client->bits = server->bits;
 | 
			
		||||
    client->flags = server->flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void psa_core_attributes_to_server(
 | 
			
		||||
    const psa_client_core_key_attributes_t *client,
 | 
			
		||||
    psa_key_owner_id_t owner,
 | 
			
		||||
    psa_core_key_attributes_t *server)
 | 
			
		||||
{
 | 
			
		||||
    server->type = client->type;
 | 
			
		||||
    server->lifetime = client->lifetime;
 | 
			
		||||
    server->id.key_id = client->id;
 | 
			
		||||
    server->id.owner = owner;
 | 
			
		||||
    server->policy = client->policy;
 | 
			
		||||
    server->bits = client->bits;
 | 
			
		||||
    server->flags = client->flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void psa_set_key_id(psa_key_attributes_t *attributes,
 | 
			
		||||
                                  psa_key_id_t id)
 | 
			
		||||
{
 | 
			
		||||
    attributes->core.id = id;
 | 
			
		||||
    if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE )
 | 
			
		||||
        attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline psa_key_id_t psa_get_key_id(
 | 
			
		||||
    const psa_key_attributes_t *attributes)
 | 
			
		||||
{
 | 
			
		||||
    return( attributes->core.id );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,
 | 
			
		||||
                                        psa_key_lifetime_t lifetime)
 | 
			
		||||
{
 | 
			
		||||
    attributes->core.lifetime = lifetime;
 | 
			
		||||
    if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
 | 
			
		||||
    {
 | 
			
		||||
#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
 | 
			
		||||
        attributes->core.id.key_id = 0;
 | 
			
		||||
        attributes->core.id.owner = 0;
 | 
			
		||||
#else
 | 
			
		||||
        attributes->core.id = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline psa_key_lifetime_t psa_get_key_lifetime(
 | 
			
		||||
    const psa_key_attributes_t *attributes)
 | 
			
		||||
{
 | 
			
		||||
    return( attributes->core.lifetime );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes,
 | 
			
		||||
                                           psa_key_usage_t usage_flags)
 | 
			
		||||
{
 | 
			
		||||
    attributes->core.policy.usage = usage_flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline psa_key_usage_t psa_get_key_usage_flags(
 | 
			
		||||
    const psa_key_attributes_t *attributes)
 | 
			
		||||
{
 | 
			
		||||
    return( attributes->core.policy.usage );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes,
 | 
			
		||||
                                         psa_algorithm_t alg)
 | 
			
		||||
{
 | 
			
		||||
    attributes->core.policy.alg = alg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline psa_algorithm_t psa_get_key_algorithm(
 | 
			
		||||
    const psa_key_attributes_t *attributes)
 | 
			
		||||
{
 | 
			
		||||
    return( attributes->core.policy.alg );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This function is declared in crypto_extra.h, which comes after this
 | 
			
		||||
 * header file, but we need the function here, so repeat the declaration. */
 | 
			
		||||
psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
 | 
			
		||||
                                           psa_key_type_t type,
 | 
			
		||||
                                           const uint8_t *data,
 | 
			
		||||
                                           size_t data_length);
 | 
			
		||||
 | 
			
		||||
static inline void psa_set_key_type(psa_key_attributes_t *attributes,
 | 
			
		||||
                                    psa_key_type_t type)
 | 
			
		||||
{
 | 
			
		||||
    if( attributes->domain_parameters == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        /* Common case: quick path */
 | 
			
		||||
        attributes->core.type = type;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        /* Call the bigger function to free the old domain paramteres.
 | 
			
		||||
         * Ignore any errors which may arise due to type requiring
 | 
			
		||||
         * non-default domain parameters, since this function can't
 | 
			
		||||
         * report errors. */
 | 
			
		||||
        (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline psa_key_type_t psa_get_key_type(
 | 
			
		||||
    const psa_key_attributes_t *attributes)
 | 
			
		||||
{
 | 
			
		||||
    return( attributes->core.type );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void psa_set_key_bits(psa_key_attributes_t *attributes,
 | 
			
		||||
                                    size_t bits)
 | 
			
		||||
{
 | 
			
		||||
    if( bits > PSA_MAX_KEY_BITS )
 | 
			
		||||
        attributes->core.bits = PSA_KEY_BITS_TOO_LARGE;
 | 
			
		||||
    else
 | 
			
		||||
        attributes->core.bits = (psa_key_bits_t) bits;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline size_t psa_get_key_bits(
 | 
			
		||||
    const psa_key_attributes_t *attributes)
 | 
			
		||||
{
 | 
			
		||||
    return( attributes->core.bits );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* PSA_CRYPTO_STRUCT_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,73 +0,0 @@
 | 
			
		|||
 | 
			
		||||
/** \addtogroup hal */
 | 
			
		||||
/** @{*/
 | 
			
		||||
/* Copyright (c) 2017-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPM_API_H__
 | 
			
		||||
#define __SPM_API_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** @defgroup SPM-HAL SPM HAL API
 | 
			
		||||
 *  The HAL functions for PSA SPM
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------ HAL-SPE API ------------------------- */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(COMPONENT_SPE)
 | 
			
		||||
/**
 | 
			
		||||
 * Start running the NSPE.
 | 
			
		||||
 *
 | 
			
		||||
 * Secure Processing Environment (SPE) expected to boot first. Once all
 | 
			
		||||
 * the initializations are done, Nonsecure Processing Environment (NSPE)
 | 
			
		||||
 * should be booted.
 | 
			
		||||
 *
 | 
			
		||||
 * @note The function must be implemented by target specific code.
 | 
			
		||||
 */
 | 
			
		||||
void spm_hal_start_nspe(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Configure memory protection mechanism.
 | 
			
		||||
 *
 | 
			
		||||
 * Apply memory protection schemes to ensure secure memory can only be accessed
 | 
			
		||||
 * from secure-state.
 | 
			
		||||
 *
 | 
			
		||||
 * @note The function must be implemented by target specific code.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void spm_hal_memory_protection_init(void);
 | 
			
		||||
 | 
			
		||||
#endif // defined(COMPONENT_SPE)
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // __SPM_API_H__
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
| 
						 | 
				
			
			@ -1077,7 +1077,7 @@ extern "C" long PREFIX(_flen)(FILEHANDLE fh)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Do not compile this code for TFM secure target
 | 
			
		||||
#if !defined(COMPONENT_SPE) || !defined(TARGET_TFM)
 | 
			
		||||
#if !defined(TARGET_TFM)
 | 
			
		||||
 | 
			
		||||
#if !defined(__MICROLIB)
 | 
			
		||||
__asm(".global __use_two_region_memory\n\t");
 | 
			
		||||
| 
						 | 
				
			
			@ -1138,7 +1138,7 @@ MBED_USED extern "C" __value_in_regs struct __initial_stackheap __user_setup_sta
 | 
			
		|||
    return _mbed_user_setup_stackheap(R0, R1, R2, R3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !defined(COMPONENT_SPE) || !defined(TARGET_TFM)
 | 
			
		||||
#endif // !defined(TARGET_TFM)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,124 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019 Arm Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 * 
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
 | 
			
		||||
 | 
			
		||||
#ifndef __RTE_DEVICE_H
 | 
			
		||||
#define __RTE_DEVICE_H
 | 
			
		||||
 | 
			
		||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
 | 
			
		||||
// <i> Configuration settings for Driver_ISRAM0_MPC in component ::Drivers:MPC
 | 
			
		||||
#define   RTE_ISRAM0_MPC                  1
 | 
			
		||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
 | 
			
		||||
 | 
			
		||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
 | 
			
		||||
// <i> Configuration settings for Driver_SRAM1_MPC in component ::Drivers:MPC
 | 
			
		||||
#define   RTE_ISRAM1_MPC                  1
 | 
			
		||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
 | 
			
		||||
 | 
			
		||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
 | 
			
		||||
// <i> Configuration settings for Driver_ISRAM2_MPC in component ::Drivers:MPC
 | 
			
		||||
#define   RTE_ISRAM2_MPC                  1
 | 
			
		||||
// </e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
 | 
			
		||||
 | 
			
		||||
// <e> MPC (Memory Protection Controller) [Driver_ISRAM3_MPC]
 | 
			
		||||
// <i> Configuration settings for Driver_SRAM2_MPC in component ::Drivers:MPC
 | 
			
		||||
#define   RTE_ISRAM3_MPC                  1
 | 
			
		||||
// </e> MPC (Memory Protection Controller) [Driver_SRAM3_MPC]
 | 
			
		||||
 | 
			
		||||
// <e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
 | 
			
		||||
// <i> Configuration settings for Driver_CODE_SRAM_MPC in component ::Drivers:MPC
 | 
			
		||||
#define   RTE_CODE_SRAM_MPC               1
 | 
			
		||||
// </e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
 | 
			
		||||
 | 
			
		||||
// <e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
 | 
			
		||||
// <i> Configuration settings for Driver_QSPI_MPC in component ::Drivers:MPC
 | 
			
		||||
#define   RTE_QSPI_MPC                    1
 | 
			
		||||
// </e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
 | 
			
		||||
 | 
			
		||||
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
 | 
			
		||||
// <i> Configuration settings for Driver_USART0 in component ::Drivers:USART
 | 
			
		||||
#define   RTE_USART0                      1
 | 
			
		||||
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
 | 
			
		||||
 | 
			
		||||
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
 | 
			
		||||
// <i> Configuration settings for Driver_USART1 in component ::Drivers:USART
 | 
			
		||||
#define   RTE_USART1                      1
 | 
			
		||||
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
 | 
			
		||||
// <i> Configuration settings for Driver_AHB_PPC0 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_AHB_PPC0                    1
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
 | 
			
		||||
// <i> Configuration settings for Driver_AHB_PPCEXP0 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_AHB_PPCEXP0                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
 | 
			
		||||
// <i> Configuration settings for Driver_AHB_PPCEXP1 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_AHB_PPCEXP1                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
 | 
			
		||||
// <i> Configuration settings for Driver_AHB_PPCEXP2 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_AHB_PPCEXP2                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
 | 
			
		||||
// <i> Configuration settings for Driver_AHB_PPCEXP3 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_AHB_PPCEXP3                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
 | 
			
		||||
// <i> Configuration settings for Driver_APB_PPC0 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_APB_PPC0                    1
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
 | 
			
		||||
// <i> Configuration settings for Driver_APB_PPC1 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_APB_PPC1                    1
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
 | 
			
		||||
// <i> Configuration settings for Driver_APB_PPCEXP0 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_APB_PPCEXP0                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
 | 
			
		||||
// <i> Configuration settings for Driver_APB_PPCEXP1 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_APB_PPCEXP1                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
 | 
			
		||||
// <i> Configuration settings for Driver_APB_PPCEXP2 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_APB_PPCEXP2                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
 | 
			
		||||
 | 
			
		||||
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
 | 
			
		||||
// <i> Configuration settings for Driver_APB_PPCEXP3 in component ::Drivers:PPC
 | 
			
		||||
#define   RTE_APB_PPCEXP3                 0
 | 
			
		||||
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
 | 
			
		||||
 | 
			
		||||
// <e> FLASH (Flash Memory) [Driver_FLASH0]
 | 
			
		||||
// <i> Configuration settings for Driver_FLASH0 in component ::Drivers:FLASH
 | 
			
		||||
#define   RTE_FLASH0                     1
 | 
			
		||||
// </e> FLASH (Flash Memory) [Driver_FLASH0]
 | 
			
		||||
 | 
			
		||||
#endif  /* __RTE_DEVICE_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,54 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018-2019 Arm Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __CMSIS_DRIVER_CONFIG_H__
 | 
			
		||||
#define __CMSIS_DRIVER_CONFIG_H__
 | 
			
		||||
 | 
			
		||||
#include "device_cfg.h"
 | 
			
		||||
#include "platform_retarget_dev.h"
 | 
			
		||||
#include "platform_retarget_pins.h"
 | 
			
		||||
#include "RTE_Device.h"
 | 
			
		||||
#include "target_cfg.h"
 | 
			
		||||
 | 
			
		||||
#define UART0_DEV           UART0_PL011_DEV_NS
 | 
			
		||||
#define UART1_DEV           UART1_PL011_DEV_NS
 | 
			
		||||
 | 
			
		||||
#define FLASH0_DEV          MT25QL_DEV_NS
 | 
			
		||||
 | 
			
		||||
#define MPC_ISRAM0_DEV      MPC_ISRAM0_DEV_S
 | 
			
		||||
#define MPC_ISRAM1_DEV      MPC_ISRAM1_DEV_S
 | 
			
		||||
#define MPC_ISRAM2_DEV      MPC_ISRAM2_DEV_S
 | 
			
		||||
#define MPC_ISRAM3_DEV      MPC_ISRAM3_DEV_S
 | 
			
		||||
#define MPC_CODE_SRAM_DEV   MPC_CODE_SRAM_DEV_S
 | 
			
		||||
#define MPC_QSPI_DEV        MPC_QSPI_DEV_S
 | 
			
		||||
 | 
			
		||||
#define AHB_PPC0_DEV        AHB_PPC0_DEV_S
 | 
			
		||||
#define AHB_PPCEXP0_DEV     AHB_PPCEXP0_DEV_S
 | 
			
		||||
#define AHB_PPCEXP1_DEV     AHB_PPCEXP1_DEV_S
 | 
			
		||||
#define AHB_PPCEXP2_DEV     AHB_PPCEXP2_DEV_S
 | 
			
		||||
#define AHB_PPCEXP3_DEV     AHB_PPCEXP3_DEV_S
 | 
			
		||||
#define APB_PPC0_DEV        APB_PPC0_DEV_S
 | 
			
		||||
#define APB_PPC1_DEV        APB_PPC1_DEV_S
 | 
			
		||||
#define APB_PPCEXP0_DEV     APB_PPCEXP0_DEV_S
 | 
			
		||||
#define APB_PPCEXP1_DEV     APB_PPCEXP1_DEV_S
 | 
			
		||||
#define APB_PPCEXP2_DEV     APB_PPCEXP2_DEV_S
 | 
			
		||||
#define APB_PPCEXP3_DEV     APB_PPCEXP3_DEV_S
 | 
			
		||||
 | 
			
		||||
#define MUSCA_A1_SCC_DEV    MUSCA_A1_SCC_DEV_S
 | 
			
		||||
 | 
			
		||||
#endif  /* __CMSIS_DRIVER_CONFIG_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,69 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the License); you may
 | 
			
		||||
 * not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * $Date:        2. Jan 2014
 | 
			
		||||
 * $Revision:    V2.00
 | 
			
		||||
 *
 | 
			
		||||
 * Project:      Common Driver definitions
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* History:
 | 
			
		||||
 *  Version 2.00
 | 
			
		||||
 *    Changed prefix ARM_DRV -> ARM_DRIVER
 | 
			
		||||
 *    Added General return codes definitions
 | 
			
		||||
 *  Version 1.10
 | 
			
		||||
 *    Namespace prefix ARM_ added
 | 
			
		||||
 *  Version 1.00
 | 
			
		||||
 *    Initial release
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DRIVER_COMMON_H
 | 
			
		||||
#define __DRIVER_COMMON_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#define ARM_DRIVER_VERSION_MAJOR_MINOR(major,minor) (((major) << 8) | (minor))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
\brief Driver Version
 | 
			
		||||
*/
 | 
			
		||||
typedef struct _ARM_DRIVER_VERSION {
 | 
			
		||||
  uint16_t api;                         ///< API version
 | 
			
		||||
  uint16_t drv;                         ///< Driver version
 | 
			
		||||
} ARM_DRIVER_VERSION;
 | 
			
		||||
 | 
			
		||||
/* General return codes */
 | 
			
		||||
#define ARM_DRIVER_OK                 0 ///< Operation succeeded
 | 
			
		||||
#define ARM_DRIVER_ERROR             -1 ///< Unspecified error
 | 
			
		||||
#define ARM_DRIVER_ERROR_BUSY        -2 ///< Driver is busy
 | 
			
		||||
#define ARM_DRIVER_ERROR_TIMEOUT     -3 ///< Timeout occurred
 | 
			
		||||
#define ARM_DRIVER_ERROR_UNSUPPORTED -4 ///< Operation not supported
 | 
			
		||||
#define ARM_DRIVER_ERROR_PARAMETER   -5 ///< Parameter error
 | 
			
		||||
#define ARM_DRIVER_ERROR_SPECIFIC    -6 ///< Start of driver specific errors
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
\brief General power states
 | 
			
		||||
*/
 | 
			
		||||
typedef enum _ARM_POWER_STATE {
 | 
			
		||||
  ARM_POWER_OFF,                        ///< Power off: no operation possible
 | 
			
		||||
  ARM_POWER_LOW,                        ///< Low Power mode: retain state, detect and signal wake-up events
 | 
			
		||||
  ARM_POWER_FULL                        ///< Power on: full operation at maximum performance
 | 
			
		||||
} ARM_POWER_STATE;
 | 
			
		||||
 | 
			
		||||
#endif /* __DRIVER_COMMON_H */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,153 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2016-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __DRIVER_MPC_H
 | 
			
		||||
#define __DRIVER_MPC_H
 | 
			
		||||
 | 
			
		||||
#include "Driver_Common.h"
 | 
			
		||||
 | 
			
		||||
/* API version */
 | 
			
		||||
#define ARM_MPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0)
 | 
			
		||||
 | 
			
		||||
/* Error code returned by the driver functions */
 | 
			
		||||
#define ARM_MPC_ERR_NOT_INIT      (ARM_DRIVER_ERROR_SPECIFIC - 1)  ///< MPC not initialized */
 | 
			
		||||
#define ARM_MPC_ERR_NOT_IN_RANGE  (ARM_DRIVER_ERROR_SPECIFIC - 2)  ///< Address does not belong to a range controlled by the MPC */
 | 
			
		||||
#define ARM_MPC_ERR_NOT_ALIGNED   (ARM_DRIVER_ERROR_SPECIFIC - 3)  ///< Address is not aligned on the block size of this MPC */
 | 
			
		||||
#define ARM_MPC_ERR_INVALID_RANGE (ARM_DRIVER_ERROR_SPECIFIC - 4)  ///< The given address range to configure is invalid
 | 
			
		||||
#define ARM_MPC_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE (ARM_DRIVER_ERROR_SPECIFIC - 4)  ///< The given range cannot be accessed with the wanted security attributes */
 | 
			
		||||
#define ARM_MPC_ERR_UNSPECIFIED   (ARM_DRIVER_ERROR_SPECIFIC - 5)  ///< Unspecified error */
 | 
			
		||||
 | 
			
		||||
/* Security attribute used in various place of the API */
 | 
			
		||||
typedef enum _ARM_MPC_SEC_ATTR {
 | 
			
		||||
    ARM_MPC_ATTR_SECURE,     ///< Secure attribute
 | 
			
		||||
    ARM_MPC_ATTR_NONSECURE,  ///< Non-secure attribute
 | 
			
		||||
    /* Used when getting the configuration of a memory range and some blocks are
 | 
			
		||||
     * secure whereas some other are non secure */
 | 
			
		||||
    ARM_MPC_ATTR_MIXED,      ///< Mixed attribute
 | 
			
		||||
} ARM_MPC_SEC_ATTR;
 | 
			
		||||
 | 
			
		||||
/* Function documentation */
 | 
			
		||||
/**
 | 
			
		||||
  \fn          ARM_DRIVER_VERSION ARM_MPC_GetVersion (void)
 | 
			
		||||
  \brief       Get driver version.
 | 
			
		||||
  \return      \ref ARM_DRIVER_VERSION
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_Initialize (void)
 | 
			
		||||
  \brief       Initialize MPC Interface.
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_Uninitialize (void)
 | 
			
		||||
  \brief       De-initialize MPC Interface. The controlled memory region
 | 
			
		||||
               should not be accessed after a call to this function, as
 | 
			
		||||
               it is allowed to configure everything to be secure (to
 | 
			
		||||
               prevent information leak for example).
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_GetBlockSize (uint32_t* blk_size)
 | 
			
		||||
  \brief       Get the block size of the MPC. All regions must be aligned
 | 
			
		||||
               on this block size (base address and limit+1 address).
 | 
			
		||||
  \param[out]  blk_size:  The block size in bytes.
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_GetCtrlConfig (uint32_t* ctrl_val)
 | 
			
		||||
  \brief       Get some information on how the MPC IP is configured.
 | 
			
		||||
  \param[out]  ctrl_val:  MPC control configuration
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_SetCtrlConfig (uint32_t ctrl)
 | 
			
		||||
  \brief       Set new control configuration for the MPC IP.
 | 
			
		||||
  \param[in]   ctrl:  New control configuration.
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_ConfigRegion (uintptr_t base,
 | 
			
		||||
                                             uintptr_t limit,
 | 
			
		||||
                                             ARM_MPC_SEC_ATTR attr)
 | 
			
		||||
  \brief       Configure a memory region (base and limit included).
 | 
			
		||||
               Both base and limit addresses must belong to the same
 | 
			
		||||
               memory range, and this range must be managed by this MPC.
 | 
			
		||||
               Also, some ranges are only allowed to be configured as
 | 
			
		||||
               secure/non-secure, because of hardware requirements
 | 
			
		||||
               (security aliases), and only a relevant security attribute
 | 
			
		||||
               is therefore allowed for such ranges.
 | 
			
		||||
  \param[in]   base:  Base address of the region to configure. This
 | 
			
		||||
                      bound is included in the configured region.
 | 
			
		||||
                      This must be aligned on the block size of this MPC.
 | 
			
		||||
  \param[in]   limit: Limit address of the region to configure. This
 | 
			
		||||
                      bound is included in the configured region.
 | 
			
		||||
                      Limit+1 must be aligned on the block size of this MPC.
 | 
			
		||||
  \param[in]   attr:  Wanted security attribute of the region.
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_GetRegionConfig (uintptr_t base,
 | 
			
		||||
                                                uintptr_t limit,
 | 
			
		||||
                                                ARM_MPC_SEC_ATTR *attr)
 | 
			
		||||
  \brief       Gets a memory region (base and limit included).
 | 
			
		||||
  \param[in]   base:  Base address of the region to poll. This
 | 
			
		||||
                      bound is included. It does not need to be aligned
 | 
			
		||||
                      in any way.
 | 
			
		||||
  \param[in]   limit: Limit address of the region to poll. This
 | 
			
		||||
                      bound is included. (limit+1) does not need to be aligned
 | 
			
		||||
                      in any way.
 | 
			
		||||
  \param[out]  attr:  Security attribute of the region.
 | 
			
		||||
                      If the region has mixed secure/non-secure,
 | 
			
		||||
                      a special value is returned (\ref ARM_MPC_SEC_ATTR).
 | 
			
		||||
 | 
			
		||||
               In case base and limit+1 addresses are not aligned on
 | 
			
		||||
               the block size, the enclosing region with base and
 | 
			
		||||
               limit+1 aligned on block size will be queried.
 | 
			
		||||
               In case of early termination of the function (error), the
 | 
			
		||||
               security attribute will be set to ARM_MPC_ATTR_MIXED.
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_EnableInterrupt (void)
 | 
			
		||||
  \brief       Enable MPC interrupt.
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
 | 
			
		||||
  \fn          void ARM_MPC_DisableInterrupt (void)
 | 
			
		||||
  \brief       Disable MPC interrupt.
 | 
			
		||||
 | 
			
		||||
  \fn          void ARM_MPC_ClearInterrupt (void)
 | 
			
		||||
  \brief       Clear MPC interrupt.
 | 
			
		||||
 | 
			
		||||
  \fn          uint32_t ARM_MPC_InterruptState (void)
 | 
			
		||||
  \brief       MPC interrupt state.
 | 
			
		||||
  \return      Returns 1 if the interrupt is active, 0 otherwise.
 | 
			
		||||
 | 
			
		||||
  \fn          int32_t ARM_MPC_LockDown (void)
 | 
			
		||||
  \brief       Lock down the MPC configuration.
 | 
			
		||||
  \return      Returns error code.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Access structure of the MPC Driver.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _ARM_DRIVER_MPC {
 | 
			
		||||
  ARM_DRIVER_VERSION (*GetVersion)       (void);                                                     ///< Pointer to \ref ARM_MPC_GetVersion    : Get driver version.
 | 
			
		||||
  int32_t            (*Initialize)       (void);                                                     ///< Pointer to \ref ARM_MPC_Initialize    : Initialize the MPC Interface.
 | 
			
		||||
  int32_t            (*Uninitialize)     (void);                                                     ///< Pointer to \ref ARM_MPC_Uninitialize  : De-initialize the MPC Interface.
 | 
			
		||||
  int32_t            (*GetBlockSize)     (uint32_t* blk_size);                                       ///< Pointer to \ref ARM_MPC_GetBlockSize  : Get MPC block size
 | 
			
		||||
  int32_t            (*GetCtrlConfig)    (uint32_t* ctrl_val);                                       ///< Pointer to \ref ARM_MPC_GetCtrlConfig : Get the MPC control configuration flags.
 | 
			
		||||
  int32_t            (*SetCtrlConfig)    (uint32_t ctrl);                                            ///< Pointer to \ref ARM_MPC_SetCtrlConfig : Set the MPC control configuration flags.
 | 
			
		||||
  int32_t            (*ConfigRegion)     (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR attr);   ///< Pointer to \ref ARM_MPC_ConfigRegion  : Configure a region using the driver for the specific MPC.
 | 
			
		||||
  int32_t            (*GetRegionConfig)  (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR *attr);  ///< Pointer to \ref ARM_MPC_GetRegionConfig  : Get the configuration of a specific region on this MPC.
 | 
			
		||||
  int32_t            (*EnableInterrupt)  (void);                                                     ///< Pointer to \ref ARM_MPC_EnableInterrupt  : Enable MPC interrupt.
 | 
			
		||||
  void               (*DisableInterrupt) (void);                                                     ///< Pointer to \ref ARM_MPC_DisableInterrupt : Disable MPC interrupt.
 | 
			
		||||
  void               (*ClearInterrupt)   (void);                                                     ///< Pointer to \ref ARM_MPC_ClearInterrupt   : Clear MPC interrupt.
 | 
			
		||||
  uint32_t           (*InterruptState)   (void);                                                     ///< Pointer to \ref ARM_MPC_InterruptState   : MPC interrupt State.
 | 
			
		||||
  int32_t            (*LockDown)         (void);                                                     ///< Pointer to \ref ARM_MPC_LockDown         : Lock down the MPC configuration.
 | 
			
		||||
} const ARM_DRIVER_MPC;
 | 
			
		||||
 | 
			
		||||
#endif /* __DRIVER_MPC_H */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,969 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2016-2019 Arm Limited
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "Driver_PPC.h"
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "cmsis_driver_config.h"
 | 
			
		||||
#include "RTE_Device.h"
 | 
			
		||||
 | 
			
		||||
/* Driver version */
 | 
			
		||||
#define ARM_PPC_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0)
 | 
			
		||||
 | 
			
		||||
/* Driver Version */
 | 
			
		||||
static const ARM_DRIVER_VERSION DriverVersion = {
 | 
			
		||||
    ARM_PPC_API_VERSION,
 | 
			
		||||
    ARM_PPC_DRV_VERSION
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static ARM_DRIVER_VERSION ARM_PPC_GetVersion(void)
 | 
			
		||||
{
 | 
			
		||||
    return DriverVersion;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if (RTE_AHB_PPC0)
 | 
			
		||||
/* AHB PPC0 Driver wrapper functions */
 | 
			
		||||
static int32_t AHB_PPC0_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&AHB_PPC0_DEV, AHB_PPC0);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPC0_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done*/
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                     ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&AHB_PPC0_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPC0_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&AHB_PPC0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPC0_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&AHB_PPC0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPC0_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&AHB_PPC0_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPC0_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&AHB_PPC0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPC0_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&AHB_PPC0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPC0_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&AHB_PPC0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* AHB PPC0 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_AHB_PPC0;
 | 
			
		||||
ARM_DRIVER_PPC Driver_AHB_PPC0 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = AHB_PPC0_Initialize,
 | 
			
		||||
    .Uninitialize      = AHB_PPC0_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = AHB_PPC0_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = AHB_PPC0_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = AHB_PPC0_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = AHB_PPC0_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = AHB_PPC0_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = AHB_PPC0_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = AHB_PPC0_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_AHB_PPC0 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_AHB_PPCEXP0)
 | 
			
		||||
/* AHB PPCEXP0 Driver wrapper functions */
 | 
			
		||||
static int32_t AHB_PPCEXP0_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&AHB_PPCEXP0_DEV, AHB_PPC_EXP0);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP0_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP0_ConfigPeriph(uint8_t periph,
 | 
			
		||||
                                        ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                        ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&AHB_PPCEXP0_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP0_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&AHB_PPCEXP0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP0_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&AHB_PPCEXP0_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP0_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&AHB_PPCEXP0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP0_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&AHB_PPCEXP0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP0_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&AHB_PPCEXP0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* AHB PPCEXP0 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP0;
 | 
			
		||||
ARM_DRIVER_PPC Driver_AHB_PPCEXP0 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = AHB_PPCEXP0_Initialize,
 | 
			
		||||
    .Uninitialize      = AHB_PPCEXP0_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = AHB_PPCEXP0_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = AHB_PPCEXP0_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = AHB_PPCEXP0_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = AHB_PPCEXP0_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = AHB_PPCEXP0_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = AHB_PPCEXP0_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = AHB_PPCEXP0_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_AHB_PPCEXP0 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_AHB_PPCEXP1)
 | 
			
		||||
/* AHB PPCEXP1 Driver wrapper functions */
 | 
			
		||||
static int32_t AHB_PPCEXP1_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&AHB_PPCEXP1_DEV, AHB_PPC_EXP1);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP1_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP1_ConfigPeriph(uint8_t periph,
 | 
			
		||||
                                        ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                        ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&AHB_PPCEXP1_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP1_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&AHB_PPCEXP1_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP1_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP1_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&AHB_PPCEXP1_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP1_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&AHB_PPCEXP1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP1_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&AHB_PPCEXP1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP1_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&AHB_PPCEXP1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* AHB PPCEXP1 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP1;
 | 
			
		||||
ARM_DRIVER_PPC Driver_AHB_PPCEXP1 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = AHB_PPCEXP1_Initialize,
 | 
			
		||||
    .Uninitialize      = AHB_PPCEXP1_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = AHB_PPCEXP1_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = AHB_PPCEXP1_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = AHB_PPCEXP1_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = AHB_PPCEXP1_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = AHB_PPCEXP1_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = AHB_PPCEXP1_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = AHB_PPCEXP1_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_AHB_PPCEXP1 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_AHB_PPCEXP2)
 | 
			
		||||
/* AHB PPCEXP2 Driver wrapper functions */
 | 
			
		||||
static int32_t AHB_PPCEXP2_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&AHB_PPCEXP2_DEV, AHB_PPC_EXP2);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP2_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP2_ConfigPeriph(uint8_t periph,
 | 
			
		||||
                                        ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                        ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&AHB_PPCEXP2_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP2_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&AHB_PPCEXP2_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP2_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP2_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&AHB_PPCEXP2_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP2_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&AHB_PPCEXP2_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP2_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&AHB_PPCEXP2_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP2_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&AHB_PPCEXP2_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* AHB PPCEXP2 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP2;
 | 
			
		||||
ARM_DRIVER_PPC Driver_AHB_PPCEXP2 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = AHB_PPCEXP2_Initialize,
 | 
			
		||||
    .Uninitialize      = AHB_PPCEXP2_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = AHB_PPCEXP2_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = AHB_PPCEXP2_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = AHB_PPCEXP2_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = AHB_PPCEXP2_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = AHB_PPCEXP2_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = AHB_PPCEXP2_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = AHB_PPCEXP2_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_AHB_PPCEXP2 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_AHB_PPCEXP3)
 | 
			
		||||
/* AHB PPCEXP3 Driver wrapper functions */
 | 
			
		||||
static int32_t AHB_PPCEXP3_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&AHB_PPCEXP3_DEV, AHB_PPC_EXP3);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP3_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP3_ConfigPeriph(uint8_t periph,
 | 
			
		||||
                                        ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                        ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&AHB_PPCEXP3_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP3_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&AHB_PPCEXP3_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP3_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t AHB_PPCEXP3_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&AHB_PPCEXP3_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP3_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&AHB_PPCEXP3_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AHB_PPCEXP3_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&AHB_PPCEXP3_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t AHB_PPCEXP3_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&AHB_PPCEXP3_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* AHB PPCEXP3 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP3;
 | 
			
		||||
ARM_DRIVER_PPC Driver_AHB_PPCEXP3 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = AHB_PPCEXP3_Initialize,
 | 
			
		||||
    .Uninitialize      = AHB_PPCEXP3_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = AHB_PPCEXP3_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = AHB_PPCEXP3_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = AHB_PPCEXP3_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = AHB_PPCEXP3_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = AHB_PPCEXP3_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = AHB_PPCEXP3_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = AHB_PPCEXP3_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_AHB_PPCEXP3 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_APB_PPC0)
 | 
			
		||||
/* APB PPC0 Driver wrapper functions */
 | 
			
		||||
static int32_t APB_PPC0_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&APB_PPC0_DEV, APB_PPC0);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPC0_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done*/
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                     ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&APB_PPC0_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPC0_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&APB_PPC0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPC0_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&APB_PPC0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPC0_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&APB_PPC0_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPC0_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&APB_PPC0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPC0_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&APB_PPC0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPC0_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&APB_PPC0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* APB PPC0 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_APB_PPC0;
 | 
			
		||||
ARM_DRIVER_PPC Driver_APB_PPC0 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = APB_PPC0_Initialize,
 | 
			
		||||
    .Uninitialize      = APB_PPC0_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = APB_PPC0_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = APB_PPC0_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = APB_PPC0_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = APB_PPC0_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = APB_PPC0_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = APB_PPC0_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = APB_PPC0_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_APB_PPC0 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_APB_PPC1)
 | 
			
		||||
/* APB PPC1 Driver wrapper functions */
 | 
			
		||||
static int32_t APB_PPC1_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&APB_PPC1_DEV, APB_PPC1);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPC1_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done*/
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPC1_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                     ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&APB_PPC1_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPC1_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&APB_PPC1_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPC1_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&APB_PPC1_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
static int32_t APB_PPC1_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&APB_PPC1_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPC1_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&APB_PPC1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPC1_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&APB_PPC1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPC1_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&APB_PPC1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* APB PPC1 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_APB_PPC1;
 | 
			
		||||
ARM_DRIVER_PPC Driver_APB_PPC1 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = APB_PPC1_Initialize,
 | 
			
		||||
    .Uninitialize      = APB_PPC1_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = APB_PPC1_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = APB_PPC1_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = APB_PPC1_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = APB_PPC1_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = APB_PPC1_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = APB_PPC1_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = APB_PPC1_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_APB_PPC1 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_APB_PPCEXP0)
 | 
			
		||||
/* APB PPCEXP0 Driver wrapper functions */
 | 
			
		||||
static int32_t APB_PPCEXP0_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&APB_PPCEXP0_DEV, APB_PPC_EXP0);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP0_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP0_ConfigPeriph(uint8_t periph,
 | 
			
		||||
                                        ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                        ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&APB_PPCEXP0_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP0_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&APB_PPCEXP0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&APB_PPCEXP0_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP0_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&APB_PPCEXP0_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP0_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&APB_PPCEXP0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP0_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&APB_PPCEXP0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP0_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&APB_PPCEXP0_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* APB PPCEXP0 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_APB_PPCEXP0;
 | 
			
		||||
ARM_DRIVER_PPC Driver_APB_PPCEXP0 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = APB_PPCEXP0_Initialize,
 | 
			
		||||
    .Uninitialize      = APB_PPCEXP0_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = APB_PPCEXP0_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = APB_PPCEXP0_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = APB_PPCEXP0_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = APB_PPCEXP0_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = APB_PPCEXP0_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = APB_PPCEXP0_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = APB_PPCEXP0_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_APB_PPCEXP0 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_APB_PPCEXP1)
 | 
			
		||||
/* APB PPCEXP1 Driver wrapper functions */
 | 
			
		||||
static int32_t APB_PPCEXP1_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&APB_PPCEXP1_DEV, APB_PPC_EXP1);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP1_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP1_ConfigPeriph(uint8_t periph,
 | 
			
		||||
                                        ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                        ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&APB_PPCEXP1_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP1_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&APB_PPCEXP1_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&APB_PPCEXP1_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP1_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&APB_PPCEXP1_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP1_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&APB_PPCEXP1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP1_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&APB_PPCEXP1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP1_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&APB_PPCEXP1_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* APB PPCEXP1 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_APB_PPCEXP1;
 | 
			
		||||
ARM_DRIVER_PPC Driver_APB_PPCEXP1 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = APB_PPCEXP1_Initialize,
 | 
			
		||||
    .Uninitialize      = APB_PPCEXP1_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = APB_PPCEXP1_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = APB_PPCEXP1_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = APB_PPCEXP1_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = APB_PPCEXP1_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = APB_PPCEXP1_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = APB_PPCEXP1_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = APB_PPCEXP1_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_APB_PPCEXP1 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_APB_PPCEXP2)
 | 
			
		||||
/* APB PPCEXP2 Driver wrapper functions */
 | 
			
		||||
static int32_t APB_PPCEXP2_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&APB_PPCEXP2_DEV, APB_PPC_EXP2);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP2_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP2_ConfigPeriph(uint8_t periph,
 | 
			
		||||
                                        ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                        ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&APB_PPCEXP2_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP2_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&APB_PPCEXP2_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&APB_PPCEXP2_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP2_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&APB_PPCEXP2_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP2_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&APB_PPCEXP2_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP2_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&APB_PPCEXP2_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP2_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&APB_PPCEXP2_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* APB PPCEXP2 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_APB_PPCEXP2;
 | 
			
		||||
ARM_DRIVER_PPC Driver_APB_PPCEXP2 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = APB_PPCEXP2_Initialize,
 | 
			
		||||
    .Uninitialize      = APB_PPCEXP2_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = APB_PPCEXP2_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = APB_PPCEXP2_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = APB_PPCEXP2_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = APB_PPCEXP2_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = APB_PPCEXP2_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = APB_PPCEXP2_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = APB_PPCEXP2_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_APB_PPCEXP2 */
 | 
			
		||||
 | 
			
		||||
#if (RTE_APB_PPCEXP3)
 | 
			
		||||
/* APB PPCEXP3 Driver wrapper functions */
 | 
			
		||||
static int32_t APB_PPCEXP3_Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_init(&APB_PPCEXP3_DEV, APB_PPC_EXP3);
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP3_Uninitialize(void)
 | 
			
		||||
{
 | 
			
		||||
    /* Nothing to be done */
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP3_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
 | 
			
		||||
                                       ARM_PPC_PrivAttr priv_attr)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_config_peripheral(&APB_PPCEXP3_DEV, periph,
 | 
			
		||||
                                       (enum ppc_sse200_sec_attr_t)sec_attr,
 | 
			
		||||
                                       (enum ppc_sse200_priv_attr_t)priv_attr);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP3_IsPeriphSecure(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_secure(&APB_PPCEXP3_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_is_periph_priv_only(&APB_PPCEXP3_DEV, periph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32_t APB_PPCEXP3_EnableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    enum ppc_sse200_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = ppc_sse200_irq_enable(&APB_PPCEXP3_DEV);
 | 
			
		||||
 | 
			
		||||
    if( ret != PPC_SSE200_ERR_NONE) {
 | 
			
		||||
        return ARM_DRIVER_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ARM_DRIVER_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP3_DisableInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_irq_disable(&APB_PPCEXP3_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void APB_PPCEXP3_ClearInterrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    ppc_sse200_clear_irq(&APB_PPCEXP3_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t APB_PPCEXP3_InterruptState(void)
 | 
			
		||||
{
 | 
			
		||||
    return ppc_sse200_irq_state(&APB_PPCEXP3_DEV);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* APB PPCEXP3 Driver CMSIS access structure */
 | 
			
		||||
extern ARM_DRIVER_PPC Driver_APB_PPCEXP3;
 | 
			
		||||
ARM_DRIVER_PPC Driver_APB_PPCEXP3 = {
 | 
			
		||||
    .GetVersion        = ARM_PPC_GetVersion,
 | 
			
		||||
    .Initialize        = APB_PPCEXP3_Initialize,
 | 
			
		||||
    .Uninitialize      = APB_PPCEXP3_Uninitialize,
 | 
			
		||||
    .ConfigPeriph      = APB_PPCEXP3_ConfigPeriph,
 | 
			
		||||
    .IsPeriphSecure    = APB_PPCEXP3_IsPeriphSecure,
 | 
			
		||||
    .IsPeriphPrivOnly  = APB_PPCEXP3_IsPeriphPrivOnly,
 | 
			
		||||
    .EnableInterrupt   = APB_PPCEXP3_EnableInterrupt,
 | 
			
		||||
    .DisableInterrupt  = APB_PPCEXP3_DisableInterrupt,
 | 
			
		||||
    .ClearInterrupt    = APB_PPCEXP3_ClearInterrupt,
 | 
			
		||||
    .InterruptState    = APB_PPCEXP3_InterruptState
 | 
			
		||||
};
 | 
			
		||||
#endif /* RTE_APB_PPCEXP3 */
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue