mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			PSA SPM
* Intorduce PSA-SPM to mbed-os * Add SPM tests (for PSA targets) * Add PSA PRoT internal storage Secure implementation * Integrate SPM into the boot proccess * PSA manifest data generator * Introduce PSA targets skeleton to mbed-os * Add artifact delivery to the toolspull/8744/head
							parent
							
								
									1c1638342d
								
							
						
					
					
						commit
						dd73fa689c
					
				| 
						 | 
				
			
			@ -94,3 +94,6 @@ log
 | 
			
		|||
 | 
			
		||||
# Icetea related file
 | 
			
		||||
test_suite.json
 | 
			
		||||
 | 
			
		||||
# default delivery dir
 | 
			
		||||
DELIVERY/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,163 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "utest/utest.h"
 | 
			
		||||
#include "unity/unity.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
#if !defined(COMPONENT_PSA_SRV_IPC)
 | 
			
		||||
#error [NOT_SUPPORTED] Test supported only on PSA targets
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined ( __GNUC__ )
 | 
			
		||||
#error [NOT_SUPPORTED] this test is supported on GCC only
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
#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;
 | 
			
		||||
 | 
			
		||||
__attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void)
 | 
			
		||||
{
 | 
			
		||||
    register uint32_t result;
 | 
			
		||||
 | 
			
		||||
    __ASM volatile ("MOV %0, LR\n" : "=r" (result));
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function is required as we need a symbol/address
 | 
			
		||||
// to jump to from fault handler.
 | 
			
		||||
void do_nothing(void)
 | 
			
		||||
{
 | 
			
		||||
    __NOP();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test exception handler
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
{
 | 
			
		||||
    // 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     r1, [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 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),
 | 
			
		||||
    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),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
#ifndef NO_GREENTEA
 | 
			
		||||
    GREENTEA_SETUP(20, "default_auto");
 | 
			
		||||
#endif
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_test_its_reset_partition.h"
 | 
			
		||||
#include "psa_its_partition.h"
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
spm_partition_t g_partitions[2] = {
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = TEST_ITS_RESET_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = TEST_ITS_RESET_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = TEST_ITS_RESET_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = TEST_ITS_RESET_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = ITS_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = ITS_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = ITS_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = ITS_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Check all the defined memory regions for overlapping. */
 | 
			
		||||
 | 
			
		||||
/* A list of all the memory regions. */
 | 
			
		||||
const mem_region_t *mem_regions = NULL;
 | 
			
		||||
 | 
			
		||||
const uint32_t mem_region_count = 0;
 | 
			
		||||
 | 
			
		||||
// forward declaration of partition initializers
 | 
			
		||||
void test_its_reset_init(spm_partition_t *partition);
 | 
			
		||||
void its_init(spm_partition_t *partition);
 | 
			
		||||
 
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partitions) {
 | 
			
		||||
        SPM_PANIC("partitions is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    test_its_reset_init(&(g_partitions[0]));
 | 
			
		||||
    its_init(&(g_partitions[1]));
 | 
			
		||||
 
 | 
			
		||||
    *partitions = g_partitions;
 | 
			
		||||
    return 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
#include "spm_client.h"
 | 
			
		||||
#include "psa_prot_internal_storage.h"
 | 
			
		||||
#include "test_pits.h"
 | 
			
		||||
#include "psa_test_its_reset_ifs.h"
 | 
			
		||||
 | 
			
		||||
psa_its_status_t test_psa_its_reset(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t conn = psa_connect(TEST_PSA_ITS_RESET, 1);
 | 
			
		||||
    if (conn <= PSA_NULL_HANDLE) {
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_error_t status = psa_call(conn, NULL, 0, NULL, 0);
 | 
			
		||||
    if (status == PSA_DROP_CONNECTION) {
 | 
			
		||||
        status = PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_close(conn);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,97 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_test_its_reset_partition.h"
 | 
			
		||||
#include "psa_test_its_reset_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t test_its_reset_thread_stack[1024] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t test_its_reset_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t test_its_reset_thread_attr = {
 | 
			
		||||
    .name = "test_its_reset",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &test_its_reset_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(test_its_reset_thread_cb),
 | 
			
		||||
    .stack_mem = test_its_reset_thread_stack,
 | 
			
		||||
    .stack_size = 1024,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t test_its_reset_rot_services[TEST_ITS_RESET_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = TEST_PSA_ITS_RESET,
 | 
			
		||||
        .mask = TEST_PSA_ITS_RESET_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 1,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t test_its_reset_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t test_its_reset_mutex_attr = {
 | 
			
		||||
    .name = "test_its_reset_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &test_its_reset_mutex,
 | 
			
		||||
    .cb_size = sizeof(test_its_reset_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void test_pits_entry(void *ptr);
 | 
			
		||||
 | 
			
		||||
void test_its_reset_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&test_its_reset_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition test_its_reset!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < TEST_ITS_RESET_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        test_its_reset_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = test_its_reset_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(test_pits_entry, NULL, &test_its_reset_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition test_its_reset!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_TEST_ITS_RESET_PARTITION_H
 | 
			
		||||
#define PSA_TEST_ITS_RESET_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define TEST_ITS_RESET_ID 11
 | 
			
		||||
 | 
			
		||||
#define TEST_ITS_RESET_ROT_SRV_COUNT (1UL)
 | 
			
		||||
#define TEST_ITS_RESET_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* TEST_ITS_RESET event flags */
 | 
			
		||||
#define TEST_ITS_RESET_RESERVED1_POS (1UL)
 | 
			
		||||
#define TEST_ITS_RESET_RESERVED1_MSK (1UL << TEST_ITS_RESET_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define TEST_ITS_RESET_RESERVED2_POS (2UL)
 | 
			
		||||
#define TEST_ITS_RESET_RESERVED2_MSK (1UL << TEST_ITS_RESET_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define TEST_PSA_ITS_RESET_MSK_POS (4UL)
 | 
			
		||||
#define TEST_PSA_ITS_RESET_MSK (1UL << TEST_PSA_ITS_RESET_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define TEST_ITS_RESET_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    TEST_PSA_ITS_RESET_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define TEST_ITS_RESET_WAIT_ANY_MSK (\
 | 
			
		||||
    TEST_ITS_RESET_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_TEST_ITS_RESET_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
/* Copyright (c) 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.
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "psa_prot_internal_storage.h"
 | 
			
		||||
#include "test_pits_impl.h"
 | 
			
		||||
#include "kv_config.h"
 | 
			
		||||
#include "KVMap.h"
 | 
			
		||||
#include "KVStore.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
 | 
			
		||||
#define STR_EXPAND(tok)     #tok
 | 
			
		||||
 | 
			
		||||
psa_its_status_t test_psa_its_reset_impl(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_its_status_t status = PSA_ITS_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    int kv_status = kv_init_storage_config();
 | 
			
		||||
    if (kv_status != MBED_SUCCESS) {
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KVMap &kv_map = KVMap::get_instance();
 | 
			
		||||
    KVStore *kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV));
 | 
			
		||||
    if (!kvstore) {
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvstore->reset() != MBED_SUCCESS) {
 | 
			
		||||
        status = PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
// -------------------------------------- Includes -----------------------------------
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_test_its_reset_partition.h"
 | 
			
		||||
#include "psa_prot_internal_storage.h"
 | 
			
		||||
#include "test_pits_impl.h"
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void test_pits_entry(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_error_t status = PSA_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
        if ((signals & TEST_PSA_ITS_RESET_MSK) != 0) {
 | 
			
		||||
            psa_get(TEST_PSA_ITS_RESET_MSK, &msg);
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CONNECT: //fallthrough
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case PSA_IPC_CALL:
 | 
			
		||||
                {
 | 
			
		||||
                    status = test_psa_its_reset_impl();
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                default:
 | 
			
		||||
                {
 | 
			
		||||
                    SPM_PANIC("Unexpected message type %d!", (int)(msg.type));
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_reply(msg.handle, status);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_TEST_ITS_RESET_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_TEST_ITS_RESET_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define TEST_PSA_ITS_RESET 0x00011A04
 | 
			
		||||
 | 
			
		||||
#endif // PSA_TEST_ITS_RESET_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "TEST_ITS_RESET",
 | 
			
		||||
    "type": "APPLICATION-ROT",
 | 
			
		||||
    "priority": "NORMAL",
 | 
			
		||||
    "id": "0x0000000B",
 | 
			
		||||
    "entry_point": "test_pits_entry",
 | 
			
		||||
    "stack_size": "0x400",
 | 
			
		||||
    "heap_size": "0x400",
 | 
			
		||||
    "services": [{
 | 
			
		||||
        "name": "TEST_PSA_ITS_RESET",
 | 
			
		||||
        "identifier": "0x00011A04",
 | 
			
		||||
        "signal": "TEST_PSA_ITS_RESET_MSK",
 | 
			
		||||
        "non_secure_clients": true,
 | 
			
		||||
        "minor_version": 1,
 | 
			
		||||
        "minor_policy": "RELAXED"
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    "source_files": [
 | 
			
		||||
      "COMPONENT_SPE/test_pits_reset_partition.c"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +38,9 @@ static void pits_test()
 | 
			
		|||
    struct psa_its_info_t info = {0, PSA_ITS_WRITE_ONCE_FLAG};
 | 
			
		||||
    memset(read_buff, 0, TEST_BUFF_SIZE);
 | 
			
		||||
 | 
			
		||||
    status = test_psa_its_reset();
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status);
 | 
			
		||||
 | 
			
		||||
    status = psa_its_get_info(5, &info);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_ITS_ERROR_KEY_NOT_FOUND, status);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,473 @@
 | 
			
		|||
/* Copyright (c) 2017 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 COMPONENT_PSA_SRV_IPC
 | 
			
		||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
 | 
			
		||||
#endif // COMPONENT_PSA_SRV_IPC
 | 
			
		||||
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "psa_client_tests_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
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_t *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_t *iovec_temp,
 | 
			
		||||
        size_t tx_len,
 | 
			
		||||
        size_t rx_len,
 | 
			
		||||
        uint8_t *expected,
 | 
			
		||||
        uint8_t expected_size
 | 
			
		||||
        )
 | 
			
		||||
{
 | 
			
		||||
    error_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_t 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);
 | 
			
		||||
 | 
			
		||||
    // Wait for psa_close to finish on server side
 | 
			
		||||
    osDelay(50);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing iovec 0 sent as NULL
 | 
			
		||||
void iovec_0_NULL()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(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_t 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(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_t 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(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_t 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_t iovec_temp[1] = { {dummy_buff, 0} };
 | 
			
		||||
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(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_t iovec_temp[1] = { {dummy_buff, sizeof(dummy_buff)} };
 | 
			
		||||
 | 
			
		||||
    psa_handle_t handle = client_ipc_tests_connect(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()
 | 
			
		||||
{
 | 
			
		||||
    error_t status = PSA_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    uint8_t      dummy_res[10]  = {0};
 | 
			
		||||
    psa_outvec_t 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(PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    psa_invec_t 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(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_t 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(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(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(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_t 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_t *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(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, T2, T3;
 | 
			
		||||
    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_t 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_t 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_t 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(PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            handle[i] = psa_connect(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(DROP_CONN, DROP_CONN_MINOR_VER);
 | 
			
		||||
    psa_error_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(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(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 multiple calls on different channels to the same SID", multi_thread_diff_handles),
 | 
			
		||||
    Case("Testing client exceed num of max channels allowed", exceed_num_of_max_channels),
 | 
			
		||||
    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),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    // Setup Greentea using a reasonable timeout in seconds
 | 
			
		||||
#ifndef NO_GREENTEA
 | 
			
		||||
    GREENTEA_SETUP(60, "default_auto");
 | 
			
		||||
#endif
 | 
			
		||||
    return verbose_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(test_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_CLIENT_TESTS_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_CLIENT_TESTS_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define PART1_ROT_SRV1 0x00001A05
 | 
			
		||||
#define DROP_CONN 0x00001A06
 | 
			
		||||
#define SECURE_CLIENTS_ONLY 0x00001A07
 | 
			
		||||
 | 
			
		||||
#endif // PSA_CLIENT_TESTS_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,121 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_client_tests_part1_partition.h"
 | 
			
		||||
#include "psa_client_tests_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t client_tests_part1_thread_stack[1024] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t client_tests_part1_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t client_tests_part1_thread_attr = {
 | 
			
		||||
    .name = "client_tests_part1",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &client_tests_part1_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(client_tests_part1_thread_cb),
 | 
			
		||||
    .stack_mem = client_tests_part1_thread_stack,
 | 
			
		||||
    .stack_size = 1024,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t client_tests_part1_rot_services[CLIENT_TESTS_PART1_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART1_ROT_SRV1,
 | 
			
		||||
        .mask = PART1_ROT_SRV1_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = DROP_CONN,
 | 
			
		||||
        .mask = DROP_CONN_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = SECURE_CLIENTS_ONLY,
 | 
			
		||||
        .mask = SECURE_CLIENTS_ONLY_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = false,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t client_tests_part1_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t client_tests_part1_mutex_attr = {
 | 
			
		||||
    .name = "client_tests_part1_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &client_tests_part1_mutex,
 | 
			
		||||
    .cb_size = sizeof(client_tests_part1_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void server_main(void *ptr);
 | 
			
		||||
 | 
			
		||||
void client_tests_part1_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&client_tests_part1_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition client_tests_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < CLIENT_TESTS_PART1_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        client_tests_part1_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = client_tests_part1_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(server_main, NULL, &client_tests_part1_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition client_tests_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_CLIENT_TESTS_PART1_PARTITION_H
 | 
			
		||||
#define PSA_CLIENT_TESTS_PART1_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define CLIENT_TESTS_PART1_ID 1
 | 
			
		||||
 | 
			
		||||
#define CLIENT_TESTS_PART1_ROT_SRV_COUNT (3UL)
 | 
			
		||||
#define CLIENT_TESTS_PART1_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* CLIENT_TESTS_PART1 event flags */
 | 
			
		||||
#define CLIENT_TESTS_PART1_RESERVED1_POS (1UL)
 | 
			
		||||
#define CLIENT_TESTS_PART1_RESERVED1_MSK (1UL << CLIENT_TESTS_PART1_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define CLIENT_TESTS_PART1_RESERVED2_POS (2UL)
 | 
			
		||||
#define CLIENT_TESTS_PART1_RESERVED2_MSK (1UL << CLIENT_TESTS_PART1_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
#define CLIENT_TESTS_PART1_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    PART1_ROT_SRV1_MSK | \
 | 
			
		||||
    DROP_CONN_MSK | \
 | 
			
		||||
    SECURE_CLIENTS_ONLY_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define CLIENT_TESTS_PART1_WAIT_ANY_MSK (\
 | 
			
		||||
    CLIENT_TESTS_PART1_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_CLIENT_TESTS_PART1_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_client_tests_part1_partition.h"
 | 
			
		||||
#include "psa_its_partition.h"
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
spm_partition_t g_partitions[2] = {
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = CLIENT_TESTS_PART1_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = CLIENT_TESTS_PART1_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = CLIENT_TESTS_PART1_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = CLIENT_TESTS_PART1_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = ITS_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = ITS_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = ITS_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = ITS_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Check all the defined memory regions for overlapping. */
 | 
			
		||||
 | 
			
		||||
/* A list of all the memory regions. */
 | 
			
		||||
const mem_region_t *mem_regions = NULL;
 | 
			
		||||
 | 
			
		||||
const uint32_t mem_region_count = 0;
 | 
			
		||||
 | 
			
		||||
// forward declaration of partition initializers
 | 
			
		||||
void client_tests_part1_init(spm_partition_t *partition);
 | 
			
		||||
void its_init(spm_partition_t *partition);
 | 
			
		||||
 
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partitions) {
 | 
			
		||||
        SPM_PANIC("partitions is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    client_tests_part1_init(&(g_partitions[0]));
 | 
			
		||||
    its_init(&(g_partitions[1]));
 | 
			
		||||
 
 | 
			
		||||
    *partitions = g_partitions;
 | 
			
		||||
    return 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_client_tests_part1_partition.h"
 | 
			
		||||
 | 
			
		||||
#define MSG_BUF_SIZE 128
 | 
			
		||||
uint8_t data[MSG_BUF_SIZE] = {0};
 | 
			
		||||
 | 
			
		||||
void server_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
        if (signals & PART1_ROT_SRV1_MSK) {
 | 
			
		||||
            psa_get(PART1_ROT_SRV1_MSK, &msg);
 | 
			
		||||
            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) {
 | 
			
		||||
            psa_get(DROP_CONN_MSK, &msg);
 | 
			
		||||
            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){
 | 
			
		||||
            psa_get(SECURE_CLIENTS_ONLY_MSK, &msg);
 | 
			
		||||
            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 %d", signals);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "CLIENT_TESTS_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000001",
 | 
			
		||||
  "entry_point": "server_main",
 | 
			
		||||
  "stack_size": "0x400",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "PART1_ROT_SRV1",
 | 
			
		||||
      "identifier": "0x00001A05",
 | 
			
		||||
      "signal": "PART1_ROT_SRV1_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "DROP_CONN",
 | 
			
		||||
      "identifier": "0x00001A06",
 | 
			
		||||
      "signal": "DROP_CONN_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "SECURE_CLIENTS_ONLY",
 | 
			
		||||
      "identifier": "0x00001A07",
 | 
			
		||||
      "signal": "SECURE_CLIENTS_ONLY_MSK",
 | 
			
		||||
      "non_secure_clients": false,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/server.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_CLIENT_TESTS_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_CLIENT_TESTS_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define PART1_ROT_SRV1 0x00001A05
 | 
			
		||||
#define DROP_CONN 0x00001A06
 | 
			
		||||
#define SECURE_CLIENTS_ONLY 0x00001A07
 | 
			
		||||
 | 
			
		||||
#endif // PSA_CLIENT_TESTS_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,284 @@
 | 
			
		|||
/* Copyright (c) 2017 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 COMPONENT_PSA_SRV_IPC
 | 
			
		||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
 | 
			
		||||
#endif // COMPONENT_PSA_SRV_IPC
 | 
			
		||||
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "psa_server_test_part1_ifs.h"
 | 
			
		||||
#include "server_tests.h"
 | 
			
		||||
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(wait_timeout)
 | 
			
		||||
{
 | 
			
		||||
    osDelay(50);
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(identity_during_connect)
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT(test_handle > 0);
 | 
			
		||||
 | 
			
		||||
    psa_close(test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(identity_during_call)
 | 
			
		||||
{
 | 
			
		||||
    psa_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec_t data[PSA_MAX_IOVEC] = {
 | 
			
		||||
        {test_str, 4},
 | 
			
		||||
        {test_str + 5, 6},
 | 
			
		||||
        {test_str + 13, 1},
 | 
			
		||||
        {NULL, 0}
 | 
			
		||||
    };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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(TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_CONNECTION_REFUSED, test_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_CLIENT(read_at_outofboud_offset)
 | 
			
		||||
{
 | 
			
		||||
    psa_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec_t data = { test_str, sizeof(test_str) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec_t data[3] = {
 | 
			
		||||
        {test_str, 4},
 | 
			
		||||
        {test_str + 5, 6},
 | 
			
		||||
        {test_str + 13, 1}
 | 
			
		||||
    };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec_t data = { test_str, sizeof(test_str) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec_t data = { test_str, sizeof(test_str) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_invec_t data = { test_str, 8 };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_outvec_t resp = { &secure_value, sizeof(secure_value) };
 | 
			
		||||
    psa_handle_t test_handle = psa_connect(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(TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    size_t in_len = strlen(cross_part_buf);
 | 
			
		||||
    TEST_ASSERT_MESSAGE(test_handle > 0, "psa_connect() failed");
 | 
			
		||||
 | 
			
		||||
    psa_invec_t 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_t resp = { response_buf, OUT_BUFFER_SIZE };
 | 
			
		||||
 | 
			
		||||
    psa_error_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(TEST, TEST_ROT_SRV_MINOR);
 | 
			
		||||
    TEST_ASSERT_MESSAGE(test_handle > 0, "psa_connect() failed");
 | 
			
		||||
 | 
			
		||||
    psa_error_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(CONTROL, 0);
 | 
			
		||||
    if (control_handle < 0) {
 | 
			
		||||
        error("Could not open a connection with CONTROL ROT_SRV");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef NO_GREENTEA
 | 
			
		||||
    GREENTEA_SETUP(60, "default_auto");
 | 
			
		||||
#endif
 | 
			
		||||
    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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    test_action_t action = START_TEST;
 | 
			
		||||
    psa_invec_t data = {&action, sizeof(action)};
 | 
			
		||||
 | 
			
		||||
    status = psa_call(control_handle, &data, 1, NULL, 0);
 | 
			
		||||
    TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
 | 
			
		||||
    osDelay(50);
 | 
			
		||||
    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_error_t status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    test_action_t action = GET_TEST_RESULT;
 | 
			
		||||
    psa_invec_t data = {&action, sizeof(action)};
 | 
			
		||||
    psa_outvec_t resp = {&test_status, sizeof(test_status)};
 | 
			
		||||
 | 
			
		||||
    // Wait for psa_close to finish on server side
 | 
			
		||||
    osDelay(50);
 | 
			
		||||
 | 
			
		||||
    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("Wait invalid time", wait_timeout),
 | 
			
		||||
    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),
 | 
			
		||||
    SPM_UTEST_CASE("Test a common DOORBELL scenario", doorbell_test),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,88 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "string.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_server_test_part1_partition.h"
 | 
			
		||||
#include "server_tests.h"
 | 
			
		||||
 | 
			
		||||
extern psa_test_server_side_func test_list[];
 | 
			
		||||
static size_t num_of_tests = 0;
 | 
			
		||||
static psa_msg_t msg = {0};
 | 
			
		||||
static void init_num_of_tests()
 | 
			
		||||
{
 | 
			
		||||
    size_t i = 0;
 | 
			
		||||
    while(test_list[i] != NULL) {
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    num_of_tests = i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void part1_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    psa_error_t test_status = PSA_SUCCESS; // status of the api calls during the test
 | 
			
		||||
    psa_error_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_any(PSA_BLOCK);
 | 
			
		||||
        if (0 == (signals & CONTROL_MSK)) {
 | 
			
		||||
            SPM_PANIC("returned from psa_wait_any without CONTROL_ROT_SRV bit on signals=(0x%08x)\n", signals);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        psa_get(CONTROL_MSK, &msg);
 | 
			
		||||
        switch (msg.type) {
 | 
			
		||||
        case PSA_IPC_CALL:
 | 
			
		||||
            if (msg.in_size[0] == 0) {
 | 
			
		||||
                SPM_PANIC("got a zero message size to 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 %d!", (int)(msg.type));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,100 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_server_test_part2_partition.h"
 | 
			
		||||
 | 
			
		||||
static psa_msg_t msg = {0};
 | 
			
		||||
 | 
			
		||||
void part2_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
    char *str = NULL;
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
        if (0 == (signals & (ROT_SRV_REVERSE_MSK | ROT_SRV_DB_TST_MSK))) {
 | 
			
		||||
            SPM_PANIC("returned from psa_wait_any without ROT_SRV_REVERSE_MSK or ROT_SRV_DB_TST_MSK bit on\n");
 | 
			
		||||
        }
 | 
			
		||||
        if(signals & ROT_SRV_REVERSE_MSK) {
 | 
			
		||||
            psa_get(ROT_SRV_REVERSE_MSK, &msg);
 | 
			
		||||
            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 %d!", (int)(msg.type));
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
        }
 | 
			
		||||
        else {  // -- Doorbell test
 | 
			
		||||
 | 
			
		||||
            psa_get(ROT_SRV_DB_TST_MSK, &msg);
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CALL:
 | 
			
		||||
                {
 | 
			
		||||
                    int32_t caller_part_id = psa_identity(msg.handle);
 | 
			
		||||
                    // Doorbell contract is valid only between secure partitions
 | 
			
		||||
                    if (PSA_NSPE_IDENTIFIER == caller_part_id) {
 | 
			
		||||
                        SPM_PANIC("Caller partition is non secure\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    // In doorbell scenario the server first calls psa_reply()
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    // Then the servers waits to some driver making long calculations - imitate using osDelay()
 | 
			
		||||
                    osDelay(20);
 | 
			
		||||
                    // 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 %d!", (int)(msg.type));
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SERVER_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_SERVER_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define CONTROL 0x00001A01
 | 
			
		||||
#define TEST 0x00001A02
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SERVER_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,116 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_server_test_part1_partition.h"
 | 
			
		||||
#include "psa_server_test_part1_ifs.h"
 | 
			
		||||
#include "psa_server_test_part2_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t server_test_part1_thread_stack[1024] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t server_test_part1_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t server_test_part1_thread_attr = {
 | 
			
		||||
    .name = "server_test_part1",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &server_test_part1_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(server_test_part1_thread_cb),
 | 
			
		||||
    .stack_mem = server_test_part1_thread_stack,
 | 
			
		||||
    .stack_size = 1024,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t server_test_part1_rot_services[SERVER_TEST_PART1_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = CONTROL,
 | 
			
		||||
        .mask = CONTROL_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = TEST,
 | 
			
		||||
        .mask = TEST_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 12,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_STRICT,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* External SIDs used by SERVER_TEST_PART1 */
 | 
			
		||||
const uint32_t server_test_part1_external_sids[2] =
 | 
			
		||||
{
 | 
			
		||||
    ROT_SRV_REVERSE,
 | 
			
		||||
    ROT_SRV_DB_TST,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t server_test_part1_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t server_test_part1_mutex_attr = {
 | 
			
		||||
    .name = "server_test_part1_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &server_test_part1_mutex,
 | 
			
		||||
    .cb_size = sizeof(server_test_part1_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void part1_main(void *ptr);
 | 
			
		||||
 | 
			
		||||
void server_test_part1_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&server_test_part1_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition server_test_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < SERVER_TEST_PART1_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        server_test_part1_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = server_test_part1_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(part1_main, NULL, &server_test_part1_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition server_test_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SERVER_TEST_PART1_PARTITION_H
 | 
			
		||||
#define PSA_SERVER_TEST_PART1_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART1_ID 2
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART1_ROT_SRV_COUNT (2UL)
 | 
			
		||||
#define SERVER_TEST_PART1_EXT_ROT_SRV_COUNT (2UL)
 | 
			
		||||
 | 
			
		||||
/* SERVER_TEST_PART1 event flags */
 | 
			
		||||
#define SERVER_TEST_PART1_RESERVED1_POS (1UL)
 | 
			
		||||
#define SERVER_TEST_PART1_RESERVED1_MSK (1UL << SERVER_TEST_PART1_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART1_RESERVED2_POS (2UL)
 | 
			
		||||
#define SERVER_TEST_PART1_RESERVED2_MSK (1UL << SERVER_TEST_PART1_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define CONTROL_MSK_POS (4UL)
 | 
			
		||||
#define CONTROL_MSK (1UL << CONTROL_MSK_POS)
 | 
			
		||||
#define TEST_MSK_POS (5UL)
 | 
			
		||||
#define TEST_MSK (1UL << TEST_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART1_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    CONTROL_MSK | \
 | 
			
		||||
    TEST_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define SERVER_TEST_PART1_WAIT_ANY_MSK (\
 | 
			
		||||
    SERVER_TEST_PART1_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SERVER_TEST_PART1_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SERVER_TEST_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_SERVER_TEST_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define ROT_SRV_REVERSE 0x00001A03
 | 
			
		||||
#define ROT_SRV_DB_TST 0x00001A04
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SERVER_TEST_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_server_test_part2_partition.h"
 | 
			
		||||
#include "psa_server_test_part2_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t server_test_part2_thread_stack[1024] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t server_test_part2_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t server_test_part2_thread_attr = {
 | 
			
		||||
    .name = "server_test_part2",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &server_test_part2_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(server_test_part2_thread_cb),
 | 
			
		||||
    .stack_mem = server_test_part2_thread_stack,
 | 
			
		||||
    .stack_size = 1024,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t server_test_part2_rot_services[SERVER_TEST_PART2_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = ROT_SRV_REVERSE,
 | 
			
		||||
        .mask = ROT_SRV_REVERSE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_STRICT,
 | 
			
		||||
        .allow_nspe = false,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = ROT_SRV_DB_TST,
 | 
			
		||||
        .mask = ROT_SRV_DB_TST_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_STRICT,
 | 
			
		||||
        .allow_nspe = false,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t server_test_part2_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t server_test_part2_mutex_attr = {
 | 
			
		||||
    .name = "server_test_part2_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &server_test_part2_mutex,
 | 
			
		||||
    .cb_size = sizeof(server_test_part2_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void part2_main(void *ptr);
 | 
			
		||||
 | 
			
		||||
void server_test_part2_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&server_test_part2_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition server_test_part2!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < SERVER_TEST_PART2_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        server_test_part2_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = server_test_part2_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(part2_main, NULL, &server_test_part2_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition server_test_part2!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SERVER_TEST_PART2_PARTITION_H
 | 
			
		||||
#define PSA_SERVER_TEST_PART2_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART2_ID 3
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART2_ROT_SRV_COUNT (2UL)
 | 
			
		||||
#define SERVER_TEST_PART2_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* SERVER_TEST_PART2 event flags */
 | 
			
		||||
#define SERVER_TEST_PART2_RESERVED1_POS (1UL)
 | 
			
		||||
#define SERVER_TEST_PART2_RESERVED1_MSK (1UL << SERVER_TEST_PART2_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART2_RESERVED2_POS (2UL)
 | 
			
		||||
#define SERVER_TEST_PART2_RESERVED2_MSK (1UL << SERVER_TEST_PART2_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
#define SERVER_TEST_PART2_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    ROT_SRV_REVERSE_MSK | \
 | 
			
		||||
    ROT_SRV_DB_TST_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define SERVER_TEST_PART2_WAIT_ANY_MSK (\
 | 
			
		||||
    SERVER_TEST_PART2_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SERVER_TEST_PART2_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,93 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_server_test_part1_partition.h"
 | 
			
		||||
#include "psa_server_test_part2_partition.h"
 | 
			
		||||
#include "psa_its_partition.h"
 | 
			
		||||
 
 | 
			
		||||
extern const uint32_t server_test_part1_external_sids[2];
 | 
			
		||||
 
 | 
			
		||||
spm_partition_t g_partitions[3] = {
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = SERVER_TEST_PART1_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = SERVER_TEST_PART1_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = SERVER_TEST_PART1_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = server_test_part1_external_sids,
 | 
			
		||||
        .extern_sids_count = SERVER_TEST_PART1_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = SERVER_TEST_PART2_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = SERVER_TEST_PART2_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = SERVER_TEST_PART2_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = SERVER_TEST_PART2_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = ITS_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = ITS_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = ITS_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = ITS_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Check all the defined memory regions for overlapping. */
 | 
			
		||||
 | 
			
		||||
/* A list of all the memory regions. */
 | 
			
		||||
const mem_region_t *mem_regions = NULL;
 | 
			
		||||
 | 
			
		||||
const uint32_t mem_region_count = 0;
 | 
			
		||||
 | 
			
		||||
// forward declaration of partition initializers
 | 
			
		||||
void server_test_part1_init(spm_partition_t *partition);
 | 
			
		||||
void server_test_part2_init(spm_partition_t *partition);
 | 
			
		||||
void its_init(spm_partition_t *partition);
 | 
			
		||||
 
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partitions) {
 | 
			
		||||
        SPM_PANIC("partitions is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    server_test_part1_init(&(g_partitions[0]));
 | 
			
		||||
    server_test_part2_init(&(g_partitions[1]));
 | 
			
		||||
    its_init(&(g_partitions[2]));
 | 
			
		||||
 
 | 
			
		||||
    *partitions = g_partitions;
 | 
			
		||||
    return 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
/* Copyright (c) 2017 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 __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_error_t (*psa_test_server_side_func)(psa_error_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_error_t PSA_TEST_SERVER_NAME(name) (psa_error_t* status_ptr)
 | 
			
		||||
 | 
			
		||||
#define PSA_TEST(name) \
 | 
			
		||||
    PSA_TEST_CLIENT(name); \
 | 
			
		||||
    PSA_TEST_SERVER(name); \
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST(wait_timeout)
 | 
			
		||||
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__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,679 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "string.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_server_test_part1_partition.h"
 | 
			
		||||
#include "psa_server_test_part2_ifs.h"
 | 
			
		||||
#include "server_tests.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Process a generic connect message to TEST ROT_SRV.
 | 
			
		||||
 * @return PSA_SUCCESS or negative error code if failed.
 | 
			
		||||
 */
 | 
			
		||||
static psa_error_t process_connect_request(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_error_t res = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_t signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        res = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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 TEST ROT_SRV.
 | 
			
		||||
 * @return PSA_SUCCESS or negative error code if failed.
 | 
			
		||||
 */
 | 
			
		||||
static psa_error_t process_disconnect_request(void)
 | 
			
		||||
{
 | 
			
		||||
    psa_error_t res = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_t signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        res = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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(wait_timeout)
 | 
			
		||||
{
 | 
			
		||||
    psa_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    uint32_t signals = psa_wait_any(7);
 | 
			
		||||
    *status_ptr = ((signals & TEST_MSK) == 0) ? PSA_SUCCESS : PSA_TEST_ERROR;;
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
    test_status = process_disconnect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ((signals & TEST_MSK) == 0) ? PSA_SUCCESS : PSA_TEST_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_TEST_SERVER(identity_during_connect)
 | 
			
		||||
{
 | 
			
		||||
    psa_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    int32_t identity = 0;
 | 
			
		||||
 | 
			
		||||
    uint32_t signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    if (msg.type != PSA_IPC_CONNECT) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    identity = psa_identity(msg.handle);
 | 
			
		||||
    *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_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    int32_t identity = 0;
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    if (msg.type != PSA_IPC_CALL) {
 | 
			
		||||
        test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    identity = psa_identity(msg.handle);
 | 
			
		||||
    *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_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_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_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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_error_t res = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_t signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        res = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_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_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_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_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_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_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_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_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_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_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    uint32_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_any(PSA_BLOCK);
 | 
			
		||||
        if (0 == (signals & TEST_MSK)) {
 | 
			
		||||
            SPM_PANIC("returned from psa_wait_any without ROT_SRV_FACTORIAL bit on\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        psa_get(TEST_MSK, &msg);
 | 
			
		||||
        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 %d!", (int)(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)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_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_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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_t data = { buff, data_read };
 | 
			
		||||
 | 
			
		||||
    psa_outvec_t resp = { buff, data_read };
 | 
			
		||||
    psa_handle_t conn_handle = psa_connect(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)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    psa_error_t test_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t disconnect_status = PSA_SUCCESS;
 | 
			
		||||
    psa_error_t partition_call_status = PSA_SUCCESS;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    test_status = process_connect_request();
 | 
			
		||||
    if (test_status != PSA_SUCCESS) {
 | 
			
		||||
        return test_status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
    if ((signals & TEST_MSK) == 0) {
 | 
			
		||||
        test_status = PSA_TEST_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_get(TEST_MSK, &msg);
 | 
			
		||||
    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(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_interrupt(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(wait_timeout),
 | 
			
		||||
    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),
 | 
			
		||||
    PSA_TEST_SERVER_NAME(doorbell_test),
 | 
			
		||||
    NULL
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "SERVER_TEST_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000002",
 | 
			
		||||
  "entry_point": "part1_main",
 | 
			
		||||
  "stack_size": "0x400",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "CONTROL",
 | 
			
		||||
      "identifier": "0x00001A01",
 | 
			
		||||
      "signal": "CONTROL_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "TEST",
 | 
			
		||||
      "identifier": "0x00001A02",
 | 
			
		||||
      "signal": "TEST_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 12,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "extern_sids": [
 | 
			
		||||
    "ROT_SRV_REVERSE",
 | 
			
		||||
    "ROT_SRV_DB_TST"
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/partition.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "SERVER_TEST_PART2",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000003",
 | 
			
		||||
  "entry_point": "part2_main",
 | 
			
		||||
  "stack_size": "0x400",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "ROT_SRV_REVERSE",
 | 
			
		||||
      "identifier": "0x00001A03",
 | 
			
		||||
      "signal": "ROT_SRV_REVERSE_MSK",
 | 
			
		||||
      "non_secure_clients": false,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "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/partition2.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SERVER_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_SERVER_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define CONTROL 0x00001A01
 | 
			
		||||
#define TEST 0x00001A02
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SERVER_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SERVER_TEST_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_SERVER_TEST_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define ROT_SRV_REVERSE 0x00001A03
 | 
			
		||||
#define ROT_SRV_DB_TST 0x00001A04
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SERVER_TEST_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
/* Copyright (c) 2017 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 __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_error_t (*psa_test_server_side_func)(psa_error_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_error_t PSA_TEST_SERVER_NAME(name) (psa_error_t* status_ptr)
 | 
			
		||||
 | 
			
		||||
#define PSA_TEST(name) \
 | 
			
		||||
    PSA_TEST_CLIENT(name); \
 | 
			
		||||
    PSA_TEST_SERVER(name); \
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_TEST(wait_timeout)
 | 
			
		||||
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__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,90 @@
 | 
			
		|||
/* Copyright (c) 2017 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 COMPONENT_PSA_SRV_IPC
 | 
			
		||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
 | 
			
		||||
#endif // COMPONENT_PSA_SRV_IPC
 | 
			
		||||
/* -------------------------------------- Includes ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "psa_smoke_test_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
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(ROT_SRV1, CLIENT_MINOR_VERSION);
 | 
			
		||||
    TEST_ASSERT_MESSAGE(conn_handle > 0, "psa_connect() failed");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    psa_invec_t 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_t outvec = {response_buf, CLIENT_RSP_BUF_SIZE};
 | 
			
		||||
 | 
			
		||||
    psa_error_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);
 | 
			
		||||
 | 
			
		||||
    // Wait for psa_close to finish on server side
 | 
			
		||||
    osDelay(50);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --------------------------------- Test Framework ---------------------------------- */
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t greentea_setup(const size_t number_of_cases) {
 | 
			
		||||
#ifndef NO_GREENTEA
 | 
			
		||||
    GREENTEA_SETUP(20, "default_auto");
 | 
			
		||||
#endif
 | 
			
		||||
    // Call the default reporting function
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,107 @@
 | 
			
		|||
// -------------------------------------- Includes -----------------------------------
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_smoke_test_part1_partition.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 part1_main(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t  signals   = 0;
 | 
			
		||||
    int32_t   client_id = 0;
 | 
			
		||||
    psa_msg_t msg       = {0};
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
        if ((signals & ROT_SRV1_MSK) != ROT_SRV1_MSK) {
 | 
			
		||||
            SPM_PANIC("Received unknown signal (0x%08x)\n", signals);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        osDelay(500);
 | 
			
		||||
 | 
			
		||||
        psa_get(ROT_SRV1_MSK, &msg);
 | 
			
		||||
        if (msg.handle != PSA_NULL_HANDLE) {
 | 
			
		||||
            client_id = psa_identity(msg.handle);
 | 
			
		||||
            if (client_id != PSA_NSPE_IDENTIFIER) {
 | 
			
		||||
                SPM_PANIC("Received message from unexpected source (0x%08x)\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 %d, got %d", 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 %d!", (int)(msg.type));
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_smoke_test_part1_partition.h"
 | 
			
		||||
#include "psa_its_partition.h"
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
spm_partition_t g_partitions[2] = {
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = SMOKE_TEST_PART1_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = SMOKE_TEST_PART1_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = SMOKE_TEST_PART1_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = SMOKE_TEST_PART1_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = ITS_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = ITS_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = ITS_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = ITS_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Check all the defined memory regions for overlapping. */
 | 
			
		||||
 | 
			
		||||
/* A list of all the memory regions. */
 | 
			
		||||
const mem_region_t *mem_regions = NULL;
 | 
			
		||||
 | 
			
		||||
const uint32_t mem_region_count = 0;
 | 
			
		||||
 | 
			
		||||
// forward declaration of partition initializers
 | 
			
		||||
void smoke_test_part1_init(spm_partition_t *partition);
 | 
			
		||||
void its_init(spm_partition_t *partition);
 | 
			
		||||
 
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partitions) {
 | 
			
		||||
        SPM_PANIC("partitions is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    smoke_test_part1_init(&(g_partitions[0]));
 | 
			
		||||
    its_init(&(g_partitions[1]));
 | 
			
		||||
 
 | 
			
		||||
    *partitions = g_partitions;
 | 
			
		||||
    return 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SMOKE_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_SMOKE_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define ROT_SRV1 0x00001A00
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SMOKE_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,97 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_smoke_test_part1_partition.h"
 | 
			
		||||
#include "psa_smoke_test_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t smoke_test_part1_thread_stack[512] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t smoke_test_part1_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t smoke_test_part1_thread_attr = {
 | 
			
		||||
    .name = "smoke_test_part1",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &smoke_test_part1_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(smoke_test_part1_thread_cb),
 | 
			
		||||
    .stack_mem = smoke_test_part1_thread_stack,
 | 
			
		||||
    .stack_size = 512,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t smoke_test_part1_rot_services[SMOKE_TEST_PART1_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = ROT_SRV1,
 | 
			
		||||
        .mask = ROT_SRV1_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t smoke_test_part1_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t smoke_test_part1_mutex_attr = {
 | 
			
		||||
    .name = "smoke_test_part1_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &smoke_test_part1_mutex,
 | 
			
		||||
    .cb_size = sizeof(smoke_test_part1_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void part1_main(void *ptr);
 | 
			
		||||
 | 
			
		||||
void smoke_test_part1_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&smoke_test_part1_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition smoke_test_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < SMOKE_TEST_PART1_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        smoke_test_part1_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = smoke_test_part1_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(part1_main, NULL, &smoke_test_part1_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition smoke_test_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SMOKE_TEST_PART1_PARTITION_H
 | 
			
		||||
#define PSA_SMOKE_TEST_PART1_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define SMOKE_TEST_PART1_ID 4
 | 
			
		||||
 | 
			
		||||
#define SMOKE_TEST_PART1_ROT_SRV_COUNT (1UL)
 | 
			
		||||
#define SMOKE_TEST_PART1_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* SMOKE_TEST_PART1 event flags */
 | 
			
		||||
#define SMOKE_TEST_PART1_RESERVED1_POS (1UL)
 | 
			
		||||
#define SMOKE_TEST_PART1_RESERVED1_MSK (1UL << SMOKE_TEST_PART1_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define SMOKE_TEST_PART1_RESERVED2_POS (2UL)
 | 
			
		||||
#define SMOKE_TEST_PART1_RESERVED2_MSK (1UL << SMOKE_TEST_PART1_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define ROT_SRV1_MSK_POS (4UL)
 | 
			
		||||
#define ROT_SRV1_MSK (1UL << ROT_SRV1_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define SMOKE_TEST_PART1_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    ROT_SRV1_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define SMOKE_TEST_PART1_WAIT_ANY_MSK (\
 | 
			
		||||
    SMOKE_TEST_PART1_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SMOKE_TEST_PART1_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "SMOKE_TEST_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000004",
 | 
			
		||||
  "entry_point": "part1_main",
 | 
			
		||||
  "stack_size": "0x200",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "ROT_SRV1",
 | 
			
		||||
      "identifier": "0x00001A00",
 | 
			
		||||
      "signal": "ROT_SRV1_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "COMPONENT_SPE/partition1.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_SMOKE_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_SMOKE_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define ROT_SRV1 0x00001A00
 | 
			
		||||
 | 
			
		||||
#endif // PSA_SMOKE_TEST_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,114 @@
 | 
			
		|||
/* Copyright (c) 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "psa_prot_internal_storage.h"
 | 
			
		||||
#include "psa_its_ifs.h"
 | 
			
		||||
 | 
			
		||||
psa_its_status_t psa_its_set(uint32_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags)
 | 
			
		||||
{
 | 
			
		||||
    if (!p_data && data_length) {
 | 
			
		||||
        return PSA_ITS_ERROR_BAD_POINTER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_invec_t msg[3] = {
 | 
			
		||||
        { &uid, sizeof(uid) },
 | 
			
		||||
        { p_data, data_length },
 | 
			
		||||
        { &create_flags, sizeof(create_flags) }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    psa_handle_t conn = psa_connect(PSA_ITS_SET, 1);
 | 
			
		||||
    if (conn <= PSA_NULL_HANDLE) {
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_error_t status = psa_call(conn, msg, 3, NULL, 0);
 | 
			
		||||
    if (status == PSA_DROP_CONNECTION) {
 | 
			
		||||
        status = PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_close(conn);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_its_status_t psa_its_get(uint32_t uid, uint32_t data_offset, uint32_t data_length, void *p_data)
 | 
			
		||||
{
 | 
			
		||||
    if (!p_data && data_length) {
 | 
			
		||||
       return PSA_ITS_ERROR_BAD_POINTER;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
    psa_invec_t msg[2] = {
 | 
			
		||||
        { &uid, sizeof(uid) },
 | 
			
		||||
        { &data_offset, sizeof(data_offset) }
 | 
			
		||||
    };
 | 
			
		||||
    psa_outvec_t resp = { p_data, data_length };
 | 
			
		||||
 | 
			
		||||
    psa_handle_t conn = psa_connect(PSA_ITS_GET, 1);
 | 
			
		||||
    if (conn <= PSA_NULL_HANDLE) {
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_error_t status = psa_call(conn, msg, 2, &resp, 1);
 | 
			
		||||
 | 
			
		||||
    if (status == PSA_DROP_CONNECTION) {
 | 
			
		||||
        status = PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_close(conn);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_its_status_t psa_its_get_info(uint32_t uid, struct psa_its_info_t *p_info)
 | 
			
		||||
{
 | 
			
		||||
    if (!p_info) {
 | 
			
		||||
        return PSA_ITS_ERROR_BAD_POINTER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct psa_its_info_t info = { 0 };
 | 
			
		||||
    psa_invec_t msg = { &uid, sizeof(uid) };
 | 
			
		||||
    psa_outvec_t resp = { &info, sizeof(info) };
 | 
			
		||||
    psa_handle_t conn = psa_connect(PSA_ITS_INFO, 1);
 | 
			
		||||
    if (conn <= PSA_NULL_HANDLE) {
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_error_t status = psa_call(conn, &msg, 1, &resp, 1);
 | 
			
		||||
 | 
			
		||||
    *p_info = info;
 | 
			
		||||
 | 
			
		||||
    if (status == PSA_DROP_CONNECTION) {
 | 
			
		||||
        status = PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_close(conn);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_its_status_t psa_its_remove(uint32_t uid)
 | 
			
		||||
{
 | 
			
		||||
    psa_invec_t msg = { &uid, sizeof(uid) };
 | 
			
		||||
    psa_handle_t conn = psa_connect(PSA_ITS_REMOVE, 1);
 | 
			
		||||
    if (conn <= PSA_NULL_HANDLE) {
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_error_t status = psa_call(conn, &msg, 1, NULL, 0);
 | 
			
		||||
    if (status == PSA_DROP_CONNECTION) {
 | 
			
		||||
        status = PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_close(conn);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,197 @@
 | 
			
		|||
/* Copyright (c) 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_its_partition.h"
 | 
			
		||||
#include "psa_prot_internal_storage.h"
 | 
			
		||||
#include "pits_impl.h"
 | 
			
		||||
#include "kv_config.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef psa_error_t (*SignalHandler)(psa_msg_t *);
 | 
			
		||||
 | 
			
		||||
static psa_error_t storage_set(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t key = 0;
 | 
			
		||||
    void *data = NULL;
 | 
			
		||||
    uint32_t alloc_size = msg->in_size[1];
 | 
			
		||||
    psa_its_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_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (psa_read(msg->handle, 1, data, msg->in_size[1]) != msg->in_size[1]) {
 | 
			
		||||
        free(data);
 | 
			
		||||
        return PSA_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_its_status_t status = psa_its_set_impl(psa_identity(msg->handle), key, alloc_size, data, flags);
 | 
			
		||||
 | 
			
		||||
    memset(data, 0, alloc_size);
 | 
			
		||||
    free(data);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_error_t storage_get(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t key = 0;
 | 
			
		||||
    uint32_t offset = 0;
 | 
			
		||||
 | 
			
		||||
    if ((msg->in_size[0] != sizeof(key)) || (msg->in_size[1] != sizeof(offset))) {
 | 
			
		||||
        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_ITS_ERROR_STORAGE_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_its_status_t status = psa_its_get_impl(psa_identity(msg->handle), key, offset, msg->out_size[0], data);
 | 
			
		||||
    if (status == PSA_ITS_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, data, msg->out_size[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(data, 0, msg->out_size[0]);
 | 
			
		||||
    free(data);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_error_t storage_info(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    struct psa_its_info_t info = { 0 };
 | 
			
		||||
    uint32_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_its_status_t status = psa_its_get_info_impl(psa_identity(msg->handle), key, &info);
 | 
			
		||||
    if (status == PSA_ITS_SUCCESS) {
 | 
			
		||||
        psa_write(msg->handle, 0, &info, msg->out_size[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static psa_error_t storage_remove(psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    uint32_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(psa_identity(msg->handle), key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void message_handler(psa_msg_t *msg, SignalHandler handler)
 | 
			
		||||
{
 | 
			
		||||
    psa_error_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 %d!", (int)(msg->type));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    psa_reply(msg->handle, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pits_entry(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
 | 
			
		||||
        // KVStore initiation:
 | 
			
		||||
        // - Must be done after the psa_wait_any() 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) {
 | 
			
		||||
            psa_get(PSA_ITS_SET_MSK, &msg);
 | 
			
		||||
            message_handler(&msg, storage_set);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_ITS_GET_MSK) != 0) {
 | 
			
		||||
            psa_get(PSA_ITS_GET_MSK, &msg);
 | 
			
		||||
            message_handler(&msg, storage_get);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_ITS_INFO_MSK) != 0) {
 | 
			
		||||
            psa_get(PSA_ITS_INFO_MSK, &msg);
 | 
			
		||||
            message_handler(&msg, storage_info);
 | 
			
		||||
        }
 | 
			
		||||
        if ((signals & PSA_ITS_REMOVE_MSK) != 0) {
 | 
			
		||||
            psa_get(PSA_ITS_REMOVE_MSK, &msg);
 | 
			
		||||
            message_handler(&msg, storage_remove);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef   __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,133 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_its_partition.h"
 | 
			
		||||
#include "psa_its_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t its_thread_stack[1024] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t its_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t its_thread_attr = {
 | 
			
		||||
    .name = "its",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &its_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(its_thread_cb),
 | 
			
		||||
    .stack_mem = its_thread_stack,
 | 
			
		||||
    .stack_size = 1024,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t its_rot_services[ITS_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PSA_ITS_GET,
 | 
			
		||||
        .mask = PSA_ITS_GET_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 1,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PSA_ITS_SET,
 | 
			
		||||
        .mask = PSA_ITS_SET_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 1,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PSA_ITS_INFO,
 | 
			
		||||
        .mask = PSA_ITS_INFO_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 1,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PSA_ITS_REMOVE,
 | 
			
		||||
        .mask = PSA_ITS_REMOVE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 1,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t its_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t its_mutex_attr = {
 | 
			
		||||
    .name = "its_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &its_mutex,
 | 
			
		||||
    .cb_size = sizeof(its_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void pits_entry(void *ptr);
 | 
			
		||||
 | 
			
		||||
void its_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&its_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition its!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < ITS_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        its_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = its_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(pits_entry, NULL, &its_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition its!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_ITS_PARTITION_H
 | 
			
		||||
#define PSA_ITS_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define ITS_ID 10
 | 
			
		||||
 | 
			
		||||
#define ITS_ROT_SRV_COUNT (4UL)
 | 
			
		||||
#define ITS_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* ITS event flags */
 | 
			
		||||
#define ITS_RESERVED1_POS (1UL)
 | 
			
		||||
#define ITS_RESERVED1_MSK (1UL << ITS_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define ITS_RESERVED2_POS (2UL)
 | 
			
		||||
#define ITS_RESERVED2_MSK (1UL << ITS_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#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 ITS_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    PSA_ITS_GET_MSK | \
 | 
			
		||||
    PSA_ITS_SET_MSK | \
 | 
			
		||||
    PSA_ITS_INFO_MSK | \
 | 
			
		||||
    PSA_ITS_REMOVE_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define ITS_WAIT_ANY_MSK (\
 | 
			
		||||
    ITS_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_ITS_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "ITS",
 | 
			
		||||
    "type": "APPLICATION-ROT",
 | 
			
		||||
    "priority": "NORMAL",
 | 
			
		||||
    "id": "0x0000000A",
 | 
			
		||||
    "entry_point": "pits_entry",
 | 
			
		||||
    "stack_size": "0x400",
 | 
			
		||||
    "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"
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    "source_files": [
 | 
			
		||||
      "COMPONENT_SPE/its_partition.c"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_ITS_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_ITS_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define PSA_ITS_GET 0x00011A00
 | 
			
		||||
#define PSA_ITS_SET 0x00011A01
 | 
			
		||||
#define PSA_ITS_INFO 0x00011A02
 | 
			
		||||
#define PSA_ITS_REMOVE 0x00011A03
 | 
			
		||||
 | 
			
		||||
#endif // PSA_ITS_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,227 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017, 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_defs.h"
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "mbed_critical.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------ Definitions ---------------------------------- */
 | 
			
		||||
 | 
			
		||||
#define PSA_HANDLE_MGR_HANDLE_INDEX_POS         16
 | 
			
		||||
#define PSA_HANDLE_MGR_HANDLE_INDEX_MSK         0xFFFF
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* -------------------------------- Handle Manager Module ---------------------------- */
 | 
			
		||||
 | 
			
		||||
/* The Handle Manager Module manages handles.
 | 
			
		||||
 *
 | 
			
		||||
 * It basically generates and exposes a unique handle identifier [handle] per
 | 
			
		||||
 * handle memory [handle_mem] it receives from the user.
 | 
			
		||||
 * Then users can use the exposed handle identifier to relate to the "registered"
 | 
			
		||||
 * handle memory.
 | 
			
		||||
 *
 | 
			
		||||
 * Users can:
 | 
			
		||||
 * - Ask for a unique handle identifier for a given handle memory [handle_create]
 | 
			
		||||
 * - Ask for a pointer to the handle memory corresponding to a
 | 
			
		||||
 *   handle identifier [handle_get_mem]
 | 
			
		||||
 * - Remove a handle from the handle manager module [handle_destroy]
 | 
			
		||||
 *
 | 
			
		||||
 * Note:
 | 
			
		||||
 * Handles generation is done exclusively.
 | 
			
		||||
 * Once we got a handle, removing a handle or getting its memory can be
 | 
			
		||||
 * done non-exclusive.
 | 
			
		||||
 * The assumption is that only one context is dealing with a handle after it was
 | 
			
		||||
 * generated.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------- Functions ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************************************************************
 | 
			
		||||
 * Function   : psa_hndl_mgr_handle_create
 | 
			
		||||
 *
 | 
			
		||||
 * Description: This function generates a unique handle identifier, and "couples" it with the received handle memory.
 | 
			
		||||
 *              If there is no vacant space for the new handle, the function fails.
 | 
			
		||||
 * 
 | 
			
		||||
 * Note:        This function is expected to pass since it is always coupled with memory pool allocation of the same size.
 | 
			
		||||
 *              In case memory pool allocation fails, this function should not be called.
 | 
			
		||||
 *              This function will panic on non vacant space use case.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters : handle_mgr - [IN]  A pointer to the handle manager object
 | 
			
		||||
 *              handle_mem - [IN]  A pointer to a pre-allocated handle memory to get a handle identifier for
 | 
			
		||||
 *              friend_pid - [IN]  The partition id which is allowed to get_mem() and destroy() in addition to the handle owner.
 | 
			
		||||
 *                                 Use PSA_HANDLE_MGR_INVALID_FRIEND_OWNER to denote there is no friend partition.
 | 
			
		||||
 *
 | 
			
		||||
 * Return     : The created handle identifier
 | 
			
		||||
 *********************************************************************************************************************************/
 | 
			
		||||
psa_handle_t psa_hndl_mgr_handle_create(psa_handle_manager_t *handle_mgr, void *handle_mem, int32_t friend_pid)
 | 
			
		||||
{
 | 
			
		||||
    // Make sanity checks on arguments
 | 
			
		||||
    SPM_ASSERT(handle_mgr != NULL);
 | 
			
		||||
    SPM_ASSERT(handle_mem != NULL);
 | 
			
		||||
 | 
			
		||||
    // Get active partition id - Needed for requester identification
 | 
			
		||||
    spm_partition_t *curr_part_ptr = get_active_partition();
 | 
			
		||||
    int32_t          current_pid   = ((curr_part_ptr != NULL) ? curr_part_ptr->partition_id : PSA_NSPE_IDENTIFIER);
 | 
			
		||||
    uint32_t         expected      = UINT16_MAX;
 | 
			
		||||
 | 
			
		||||
    // Avoid passing UINT16_MAX. Start again from 0 if reached.
 | 
			
		||||
    // The reason for this is that we use the 16 upper bits to store the handle's index in the handles pool (for performance reasons)
 | 
			
		||||
    core_util_atomic_cas_u32( (uint32_t *)( &(handle_mgr->handle_generator) ),
 | 
			
		||||
                              &expected,
 | 
			
		||||
                              PSA_HANDLE_MGR_INVALID_HANDLE
 | 
			
		||||
                            );
 | 
			
		||||
 | 
			
		||||
    // Generate a new handle identifier
 | 
			
		||||
    uint32_t tmp_handle = core_util_atomic_incr_u32(&(handle_mgr->handle_generator), 1);
 | 
			
		||||
    uint32_t new_handle = PSA_HANDLE_MGR_INVALID_HANDLE;
 | 
			
		||||
    uint32_t pool_ix    = 0;
 | 
			
		||||
 | 
			
		||||
    // Look for a vacant space in handles pool for the generated handle
 | 
			
		||||
    for(pool_ix = 0; pool_ix < handle_mgr->pool_size; pool_ix++) {
 | 
			
		||||
 | 
			
		||||
        expected = PSA_HANDLE_MGR_INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
        // Write the handles pool index in the upper 16 bits of the handle
 | 
			
		||||
        new_handle = ((pool_ix << PSA_HANDLE_MGR_HANDLE_INDEX_POS) | tmp_handle);
 | 
			
		||||
 | 
			
		||||
        // Store the generated handle in the handles pool
 | 
			
		||||
        if(core_util_atomic_cas_u32( (uint32_t *)( &(handle_mgr->handles_pool[pool_ix].handle) ),
 | 
			
		||||
                                     &expected,
 | 
			
		||||
                                     new_handle
 | 
			
		||||
                                   )) {
 | 
			
		||||
 | 
			
		||||
            // Handle is successfully stored in handles pool
 | 
			
		||||
 | 
			
		||||
            // Store the handle memory in the handles pool, "coupled" with the stored handle
 | 
			
		||||
            handle_mgr->handles_pool[pool_ix].handle_mem    = handle_mem;
 | 
			
		||||
            handle_mgr->handles_pool[pool_ix].handle_owner  = current_pid;
 | 
			
		||||
            handle_mgr->handles_pool[pool_ix].handle_friend = friend_pid;
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Occupied index in handles pool - continue looping
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Handle creation should only occur after a successful memory allocation
 | 
			
		||||
    // and is not expected to fail.
 | 
			
		||||
    SPM_ASSERT(pool_ix != handle_mgr->pool_size);
 | 
			
		||||
    
 | 
			
		||||
    return new_handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************************************************************
 | 
			
		||||
 * Function   : psa_hndl_mgr_handle_destroy
 | 
			
		||||
 *
 | 
			
		||||
 * Description: This function removes a handle from the handle manager.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters : handle_mgr - [IN]  A pointer to the handle manager object
 | 
			
		||||
 *              handle     - [IN]  The handle to be removed
 | 
			
		||||
 *
 | 
			
		||||
 * Return     : Void
 | 
			
		||||
 *********************************************************************************************************************************/
 | 
			
		||||
void psa_hndl_mgr_handle_destroy(psa_handle_manager_t *handle_mgr, psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    // Make sanity checks on arguments
 | 
			
		||||
    SPM_ASSERT(handle_mgr != NULL);
 | 
			
		||||
    SPM_ASSERT(handle != PSA_NULL_HANDLE);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Get the handle's index in the handles pool
 | 
			
		||||
    uint32_t pool_ix = ((handle >> PSA_HANDLE_MGR_HANDLE_INDEX_POS) & PSA_HANDLE_MGR_HANDLE_INDEX_MSK);
 | 
			
		||||
    if(pool_ix >= handle_mgr->pool_size) {
 | 
			
		||||
        SPM_PANIC("[ERROR] Handle's index [%d] is bigger than handles pool size [%d]! \n", (int)pool_ix, (int)(handle_mgr->pool_size));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(handle_mgr->handles_pool[pool_ix].handle != handle) {
 | 
			
		||||
        SPM_PANIC("[ERROR] Handle %d is not found in expected index! \n", (int)handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get active partition id - Needed for requester identification
 | 
			
		||||
    spm_partition_t *curr_part_ptr = get_active_partition();
 | 
			
		||||
    int32_t          current_pid   = ((curr_part_ptr != NULL) ? curr_part_ptr->partition_id : PSA_NSPE_IDENTIFIER);
 | 
			
		||||
 | 
			
		||||
    if( (handle_mgr->handles_pool[pool_ix].handle_owner != current_pid) &&
 | 
			
		||||
        (handle_mgr->handles_pool[pool_ix].handle_friend != current_pid)
 | 
			
		||||
      ) {
 | 
			
		||||
        SPM_PANIC("[ERROR] Request for destroy by non-owner or friend!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handle_mgr->handles_pool[pool_ix].handle        = PSA_NULL_HANDLE;
 | 
			
		||||
    handle_mgr->handles_pool[pool_ix].handle_owner  = PSA_HANDLE_MGR_INVALID_FRIEND_OWNER;
 | 
			
		||||
    handle_mgr->handles_pool[pool_ix].handle_friend = PSA_HANDLE_MGR_INVALID_FRIEND_OWNER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************************************************************
 | 
			
		||||
 * Function   : psa_hndl_mgr_handle_get_mem
 | 
			
		||||
 *
 | 
			
		||||
 * Description: This function looks for the handle memory corresponding to <handle>.
 | 
			
		||||
 *              If it is not found in the expected index in the handles pool, the function fails.
 | 
			
		||||
 *
 | 
			
		||||
 * Parameters : handle_mgr - [IN]  A pointer to the handle manager object.
 | 
			
		||||
 *              handle     - [IN]  The handle for which we request the corresponding memory handle.
 | 
			
		||||
 *
 | 
			
		||||
 * Return     : A pointer to the memory corresponding to the handle.
 | 
			
		||||
 *********************************************************************************************************************************/
 | 
			
		||||
void *psa_hndl_mgr_handle_get_mem(psa_handle_manager_t *handle_mgr, psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    SPM_ASSERT(handle_mgr != NULL);
 | 
			
		||||
 | 
			
		||||
    if(handle == PSA_NULL_HANDLE) {
 | 
			
		||||
        SPM_PANIC("[ERROR] Trying to get memory for an invalid handle! \n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get the handle's index in the handles pool
 | 
			
		||||
    uint32_t pool_ix = ((handle >> PSA_HANDLE_MGR_HANDLE_INDEX_POS) & PSA_HANDLE_MGR_HANDLE_INDEX_MSK);
 | 
			
		||||
    if(pool_ix >= handle_mgr->pool_size) {
 | 
			
		||||
        SPM_PANIC("[ERROR] Handle's index [%d] is bigger than handles pool size [%d]! \n", (int)pool_ix, (int)(handle_mgr->pool_size));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(handle_mgr->handles_pool[pool_ix].handle != handle) {
 | 
			
		||||
        SPM_PANIC("[ERROR] Handle %d is not found in expected index! \n", (int)handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get active partition id - Needed for requester identification
 | 
			
		||||
    spm_partition_t *curr_part_ptr = get_active_partition();
 | 
			
		||||
    int32_t          current_pid   = ((curr_part_ptr != NULL) ? curr_part_ptr->partition_id : PSA_NSPE_IDENTIFIER);
 | 
			
		||||
 | 
			
		||||
    if( (current_pid != handle_mgr->handles_pool[pool_ix].handle_owner) &&
 | 
			
		||||
        (current_pid != handle_mgr->handles_pool[pool_ix].handle_friend)
 | 
			
		||||
      ) {
 | 
			
		||||
        SPM_PANIC("[ERROR] Request for handle memory is not allowed for this partition! \n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If a valid handle is "coupled" with a NULL handle memory then
 | 
			
		||||
    // it is an internal module error or memory was overwritten --> Assert
 | 
			
		||||
    SPM_ASSERT(handle_mgr->handles_pool[pool_ix].handle_mem != NULL);
 | 
			
		||||
 | 
			
		||||
    return handle_mgr->handles_pool[pool_ix].handle_mem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,99 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2017, 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MBED_HANDLE_MANAGER_H__
 | 
			
		||||
#define __MBED_HANDLE_MANAGER_H__
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------- Includes ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
#include "psa_defs.h"
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* --------------------------------- extern "C" wrapper ------------------------------ */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------ Definitions ---------------------------------- */
 | 
			
		||||
 | 
			
		||||
#define PSA_HANDLE_MGR_INVALID_HANDLE           ((uint32_t)PSA_NULL_HANDLE)
 | 
			
		||||
 | 
			
		||||
#define PSA_HANDLE_MGR_INVALID_FRIEND_OWNER     0       // Denoting invalid friend or invalid owner
 | 
			
		||||
 | 
			
		||||
#define PSA_HANDLE_MGR_MAX_HANDLES_NUM          0x8000  // Handles manager pool indexes must be in range 0 - 0x7FFF.
 | 
			
		||||
                                                        // The reason for this limitation is that the index is stored in the upper 16 bits of a handle,
 | 
			
		||||
                                                        // and the most significant bit must be zero to keep handles non negative.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------- Structs ------------------------------------ */
 | 
			
		||||
 | 
			
		||||
typedef struct psa_handle_item_t {
 | 
			
		||||
 | 
			
		||||
    psa_handle_t  handle;           /* The user exposed handle [unique identifier] */
 | 
			
		||||
    int32_t       handle_owner;     /* The partition id of the handle creator - allowed to get_mem() / destroy() */
 | 
			
		||||
    int32_t       handle_friend;    /* The partition id of a "friend" partition - allowed to get_mem() */
 | 
			
		||||
    void         *handle_mem;       /* Points to memory allocated by the user */
 | 
			
		||||
 | 
			
		||||
} psa_handle_item_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct psa_handle_manager_t {
 | 
			
		||||
 | 
			
		||||
    uint32_t           handle_generator;    /* A counter supplying handle numbers  */
 | 
			
		||||
    uint32_t           pool_size;           /* The maximum number of handles that pool can contain */
 | 
			
		||||
    psa_handle_item_t *handles_pool;        /* Holding couples of handles and their memory "blocks" */
 | 
			
		||||
 | 
			
		||||
} psa_handle_manager_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
handles_pool
 | 
			
		||||
    |
 | 
			
		||||
    |
 | 
			
		||||
    |
 | 
			
		||||
    -->  *--------------------------------------------------------------------------*
 | 
			
		||||
         |    handle      |    handle      |    handle      |       |       |  ...  |
 | 
			
		||||
         *--------------------------------------------------------------------------*
 | 
			
		||||
         |  handle_owner  |  handle_owner  |  handle_owner  |       |       |  ...  |
 | 
			
		||||
         *--------------------------------------------------------------------------*
 | 
			
		||||
         |  handle_friend |  handle_friend |  handle_friend |       |       |  ...  |
 | 
			
		||||
         *--------------------------------------------------------------------------*
 | 
			
		||||
         |  handle_mem    |  handle_mem    |  handle_mem    |       |       |  ...  |
 | 
			
		||||
         *--------------------------------------------------------------------------*
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------- Functions ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
psa_handle_t psa_hndl_mgr_handle_create(psa_handle_manager_t *handle_mgr, void *handle_mem, int32_t friend_pid);
 | 
			
		||||
void psa_hndl_mgr_handle_destroy(psa_handle_manager_t *handle_mgr, psa_handle_t handle);
 | 
			
		||||
void *psa_hndl_mgr_handle_get_mem(psa_handle_manager_t *handle_mgr, psa_handle_t handle);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  /* __MBED_HANDLE_MANAGER_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_its_partition.h"
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
spm_partition_t g_partitions[1] = {
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = ITS_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = ITS_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = ITS_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = ITS_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Check all the defined memory regions for overlapping. */
 | 
			
		||||
 | 
			
		||||
/* A list of all the memory regions. */
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
const mem_region_t *mem_regions = NULL;
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
const uint32_t mem_region_count = 0;
 | 
			
		||||
 | 
			
		||||
// forward declaration of partition initializers
 | 
			
		||||
void its_init(spm_partition_t *partition);
 | 
			
		||||
 
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partitions) {
 | 
			
		||||
        SPM_PANIC("partitions is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    its_init(&(g_partitions[0]));
 | 
			
		||||
 
 | 
			
		||||
    *partitions = g_partitions;
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,351 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "mbed_toolchain.h"
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "spm_messages.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
 | 
			
		||||
extern spm_db_t g_spm;
 | 
			
		||||
 | 
			
		||||
static inline spm_rot_service_t *rot_service_in_partition_get_by_sid(spm_partition_t *partition, uint32_t sid)
 | 
			
		||||
{
 | 
			
		||||
    for (uint32_t i = 0; i < partition->rot_services_count; ++i) {
 | 
			
		||||
        spm_rot_service_t *rot_service = &(partition->rot_services[i]);
 | 
			
		||||
        if (rot_service->sid == sid) {
 | 
			
		||||
            return rot_service;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline spm_rot_service_t *rot_service_get(uint32_t sid)
 | 
			
		||||
{
 | 
			
		||||
    for (uint32_t i = 0; i < g_spm.partition_count; ++i) {
 | 
			
		||||
        spm_rot_service_t *rot_service = rot_service_in_partition_get_by_sid(&(g_spm.partitions[i]), sid);
 | 
			
		||||
        if (NULL != rot_service) {
 | 
			
		||||
            return rot_service;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void spm_validate_connection_allowed(spm_rot_service_t *target, spm_partition_t *source)
 | 
			
		||||
{
 | 
			
		||||
    if ((NULL == source) && (false == target->allow_nspe)) {
 | 
			
		||||
        SPM_PANIC("SID 0x%x is not allowed to be called from NSPE\n", target->sid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (NULL != source) {
 | 
			
		||||
        if (NULL == source->extern_sids) {
 | 
			
		||||
            SPM_PANIC("Partition %d did not declare extern functions\n", source->partition_id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (uint32_t i = 0; i < source->extern_sids_count; i++) {
 | 
			
		||||
            if (source->extern_sids[i] == target->sid) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SPM_PANIC("SID 0x%x is not in partition %d extern functions list\n", target->sid, source->partition_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline psa_handle_t create_channel_handle(void *handle_mem, int32_t friend_pid)
 | 
			
		||||
{
 | 
			
		||||
    return psa_hndl_mgr_handle_create(&(g_spm.channels_handle_mgr), handle_mem, friend_pid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline spm_ipc_channel_t *get_channel_from_handle(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    return (spm_ipc_channel_t *)psa_hndl_mgr_handle_get_mem(&(g_spm.channels_handle_mgr), handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void spm_rot_service_queue_enqueue(spm_rot_service_t *rot_service, spm_ipc_channel_t *item)
 | 
			
		||||
{
 | 
			
		||||
    osStatus_t os_status = osMutexAcquire(rot_service->partition->mutex, osWaitForever);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    if (rot_service->queue.tail == NULL) {
 | 
			
		||||
        rot_service->queue.head = item;
 | 
			
		||||
    } else {
 | 
			
		||||
        rot_service->queue.tail->next = item;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rot_service->queue.tail = item;
 | 
			
		||||
 | 
			
		||||
    uint32_t flags = osThreadFlagsSet(rot_service->partition->thread_id, rot_service->mask);
 | 
			
		||||
    // osThreadFlagsSet() sets the msb on failure.
 | 
			
		||||
    // flags is not allowed to be 0 since only dequeue operation can clear the flags,
 | 
			
		||||
    // and both operations (enqueue and dequeue) are mutex protected.
 | 
			
		||||
    SPM_ASSERT((flags & SPM_CMSIS_RTOS_ERROR_BIT_MSK) == 0);
 | 
			
		||||
    SPM_ASSERT(flags & rot_service->mask);
 | 
			
		||||
    PSA_UNUSED(flags);
 | 
			
		||||
 | 
			
		||||
    os_status = osMutexRelease(rot_service->partition->mutex);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_connect_async(uint32_t sid, spm_pending_connect_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    SPM_ASSERT(msg != NULL);
 | 
			
		||||
 | 
			
		||||
    spm_rot_service_t *dst_rot_service = rot_service_get(sid);
 | 
			
		||||
    if (NULL == dst_rot_service) {
 | 
			
		||||
        SPM_PANIC("SID 0x%x is invalid!\n", sid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (((dst_rot_service->min_version_policy == PSA_MINOR_VERSION_POLICY_RELAXED) && (msg->min_version > dst_rot_service->min_version)) ||
 | 
			
		||||
        ((dst_rot_service->min_version_policy == PSA_MINOR_VERSION_POLICY_STRICT) && (msg->min_version != dst_rot_service->min_version))) {
 | 
			
		||||
            SPM_PANIC("minor version %d does not comply with sid %d minor version %d and minor policy %d",
 | 
			
		||||
                    msg->min_version, dst_rot_service->sid, dst_rot_service->min_version, dst_rot_service->min_version_policy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    spm_partition_t *origin_partition = get_active_partition();
 | 
			
		||||
    spm_validate_connection_allowed(dst_rot_service, origin_partition);
 | 
			
		||||
 | 
			
		||||
    if (!is_buffer_accessible(msg, sizeof(*msg), origin_partition)) {
 | 
			
		||||
        SPM_PANIC("Pending connect message is inaccessible\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Allocating from SPM-Core internal memory
 | 
			
		||||
    spm_ipc_channel_t *channel = (spm_ipc_channel_t *)osMemoryPoolAlloc(g_spm.channel_mem_pool, PSA_POLL);
 | 
			
		||||
    if (NULL == channel) {
 | 
			
		||||
        msg->rc = PSA_CONNECTION_REFUSED;
 | 
			
		||||
        if (origin_partition != NULL) {
 | 
			
		||||
            osStatus_t os_status = osSemaphoreRelease(msg->completion_sem_id);
 | 
			
		||||
            SPM_ASSERT(osOK == os_status);
 | 
			
		||||
            PSA_UNUSED(os_status);
 | 
			
		||||
        } else {
 | 
			
		||||
            nspe_done(msg->completion_sem_id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create the handle in the user message so we could destroy it in case of failure.
 | 
			
		||||
    msg->rc = (psa_error_t)create_channel_handle(channel, dst_rot_service->partition->partition_id);
 | 
			
		||||
 | 
			
		||||
    // NOTE: all struct fields must be initialized as the allocated memory is not zeroed.
 | 
			
		||||
    channel->state = SPM_CHANNEL_STATE_CONNECTING;
 | 
			
		||||
    channel->src_partition = origin_partition;
 | 
			
		||||
    channel->dst_rot_service = dst_rot_service;
 | 
			
		||||
    channel->msg_ptr = msg;
 | 
			
		||||
    channel->msg_type = PSA_IPC_CONNECT;
 | 
			
		||||
    channel->rhandle = NULL;
 | 
			
		||||
    channel->next = NULL;
 | 
			
		||||
    channel->is_dropped = FALSE;
 | 
			
		||||
 | 
			
		||||
    spm_rot_service_queue_enqueue(dst_rot_service, channel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
 | 
			
		||||
{
 | 
			
		||||
    osRtxSemaphore_t msg_sem_storage = {0};
 | 
			
		||||
    const osSemaphoreAttr_t msg_sem_attr = {
 | 
			
		||||
        .name = NULL,
 | 
			
		||||
        .attr_bits = 0,
 | 
			
		||||
        .cb_mem = &msg_sem_storage,
 | 
			
		||||
        .cb_size = sizeof(msg_sem_storage),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    spm_pending_connect_msg_t msg = {
 | 
			
		||||
        .min_version = minor_version,
 | 
			
		||||
        .rc = PSA_NULL_HANDLE,
 | 
			
		||||
        .completion_sem_id = osSemaphoreNew(
 | 
			
		||||
            SPM_COMPLETION_SEM_MAX_COUNT,
 | 
			
		||||
            SPM_COMPLETION_SEM_INITIAL_COUNT,
 | 
			
		||||
            &msg_sem_attr)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (NULL == msg.completion_sem_id) {
 | 
			
		||||
        SPM_PANIC("could not create a semaphore for connect message");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_connect_async(sid, &msg);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(msg.completion_sem_id, osWaitForever);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreDelete(msg.completion_sem_id);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    return (psa_handle_t)msg.rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_call_async(psa_handle_t handle, spm_pending_call_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    SPM_ASSERT(msg != NULL);
 | 
			
		||||
    spm_ipc_channel_t *channel = get_channel_from_handle(handle);
 | 
			
		||||
    SPM_ASSERT(channel != NULL);
 | 
			
		||||
 | 
			
		||||
    if (!is_buffer_accessible(msg, sizeof(*msg), channel->src_partition)) {
 | 
			
		||||
        SPM_PANIC("Pending call message is inaccessible\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (channel->is_dropped == TRUE) {
 | 
			
		||||
        msg->rc = PSA_DROP_CONNECTION;
 | 
			
		||||
 | 
			
		||||
        if (channel->src_partition == NULL) {
 | 
			
		||||
            nspe_done(msg->completion_sem_id);
 | 
			
		||||
        } else {
 | 
			
		||||
            osStatus_t os_status = osSemaphoreRelease(msg->completion_sem_id);
 | 
			
		||||
            SPM_ASSERT(osOK == os_status);
 | 
			
		||||
            PSA_UNUSED(os_status);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    channel_state_switch(&channel->state,
 | 
			
		||||
        SPM_CHANNEL_STATE_IDLE, SPM_CHANNEL_STATE_PENDING);
 | 
			
		||||
 | 
			
		||||
    channel->msg_ptr = msg;
 | 
			
		||||
    channel->msg_type = PSA_IPC_CALL;
 | 
			
		||||
 | 
			
		||||
    validate_iovec(msg->in_vec, msg->in_vec_size, msg->out_vec, msg->out_vec_size);
 | 
			
		||||
    spm_rot_service_queue_enqueue(channel->dst_rot_service, channel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_error_t psa_call(
 | 
			
		||||
    psa_handle_t handle,
 | 
			
		||||
    const psa_invec_t *in_vec,
 | 
			
		||||
    size_t in_len,
 | 
			
		||||
    const psa_outvec_t *out_vec,
 | 
			
		||||
    size_t out_len
 | 
			
		||||
    )
 | 
			
		||||
{
 | 
			
		||||
    osRtxSemaphore_t msg_sem_storage = {0};
 | 
			
		||||
    const osSemaphoreAttr_t msg_sem_attr = {
 | 
			
		||||
        .name = NULL,
 | 
			
		||||
        .attr_bits = 0,
 | 
			
		||||
        .cb_mem = &msg_sem_storage,
 | 
			
		||||
        .cb_size = sizeof(msg_sem_storage),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    spm_pending_call_msg_t msg = {
 | 
			
		||||
        .in_vec = in_vec,
 | 
			
		||||
        .in_vec_size = in_len,
 | 
			
		||||
        .out_vec = out_vec,
 | 
			
		||||
        .out_vec_size = out_len,
 | 
			
		||||
        .rc = PSA_SUCCESS,
 | 
			
		||||
        .completion_sem_id = osSemaphoreNew(
 | 
			
		||||
            SPM_COMPLETION_SEM_MAX_COUNT,
 | 
			
		||||
            SPM_COMPLETION_SEM_INITIAL_COUNT,
 | 
			
		||||
            &msg_sem_attr)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (NULL == msg.completion_sem_id) {
 | 
			
		||||
        SPM_PANIC("could not create a semaphore for connect message");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_call_async(handle, &msg);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(msg.completion_sem_id, osWaitForever);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreDelete(msg.completion_sem_id);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    return (psa_error_t)msg.rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_close_async(psa_handle_t handle, spm_pending_close_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    SPM_ASSERT(msg != NULL);
 | 
			
		||||
 | 
			
		||||
    spm_ipc_channel_t *channel = get_channel_from_handle(handle);
 | 
			
		||||
    SPM_ASSERT(channel != NULL);
 | 
			
		||||
 | 
			
		||||
    if (!is_buffer_accessible(msg, sizeof(*msg), channel->src_partition)) {
 | 
			
		||||
        SPM_PANIC("Pending close message is inaccessible\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    channel_state_assert(&(channel->state), SPM_CHANNEL_STATE_IDLE);
 | 
			
		||||
 | 
			
		||||
    channel->msg_ptr  = msg;
 | 
			
		||||
    channel->msg_type = PSA_IPC_DISCONNECT;
 | 
			
		||||
 | 
			
		||||
    spm_rot_service_queue_enqueue(channel->dst_rot_service, channel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_close(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    if (handle == PSA_NULL_HANDLE) {
 | 
			
		||||
        // Invalid handles will fail inside handle manager [called from psa_close_async()]
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    osRtxSemaphore_t msg_sem_storage = {0};
 | 
			
		||||
    const osSemaphoreAttr_t msg_sem_attr = {
 | 
			
		||||
        .name      = NULL,
 | 
			
		||||
        .attr_bits = 0,
 | 
			
		||||
        .cb_mem    = &msg_sem_storage,
 | 
			
		||||
        .cb_size   = sizeof(msg_sem_storage),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    spm_pending_close_msg_t msg = {
 | 
			
		||||
        .handle = handle,
 | 
			
		||||
        .completion_sem_id = osSemaphoreNew( SPM_COMPLETION_SEM_MAX_COUNT,
 | 
			
		||||
                                             SPM_COMPLETION_SEM_INITIAL_COUNT,
 | 
			
		||||
                                             &msg_sem_attr
 | 
			
		||||
                                           ),
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (NULL == msg.completion_sem_id) {
 | 
			
		||||
        SPM_PANIC("Could not create a semaphore for close message");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_close_async(handle, &msg);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(msg.completion_sem_id, osWaitForever);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreDelete(msg.completion_sem_id);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t psa_framework_version(void)
 | 
			
		||||
{
 | 
			
		||||
    return (uint32_t)PSA_FRAMEWORK_VERSION;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t psa_version(uint32_t sid)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t version = PSA_VERSION_NONE;
 | 
			
		||||
    spm_rot_service_t *service = rot_service_get(sid);
 | 
			
		||||
    if (service != NULL) {
 | 
			
		||||
        if ((get_active_partition() != NULL) || (service->allow_nspe)) {
 | 
			
		||||
            version = service->min_version;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return version;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,173 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "psa_defs.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
 | 
			
		||||
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);
 | 
			
		||||
 | 
			
		||||
inline void validate_iovec(
 | 
			
		||||
    const void *in_vec,
 | 
			
		||||
    const uint32_t in_len,
 | 
			
		||||
    const void *out_vec,
 | 
			
		||||
    const uint32_t out_len
 | 
			
		||||
    )
 | 
			
		||||
{
 | 
			
		||||
    if (
 | 
			
		||||
        !(
 | 
			
		||||
            ((in_vec != NULL) || (in_len == 0)) &&
 | 
			
		||||
            ((out_vec != NULL) || (out_len == 0)) &&
 | 
			
		||||
            (in_len + out_len <= PSA_MAX_IOVEC)
 | 
			
		||||
        )
 | 
			
		||||
    ) {
 | 
			
		||||
        SPM_PANIC("Failed iovec Validation invec=(0X%p) inlen=(%d) outvec=(0X%p) outlen=(%d)\n", in_vec, in_len, out_vec, out_len);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void channel_state_switch(uint8_t *current_state, uint8_t expected_state, uint8_t new_state)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t backup_expected = expected_state;
 | 
			
		||||
    if (!core_util_atomic_cas_u8(current_state, &expected_state, new_state)) {
 | 
			
		||||
        SPM_PANIC("channel in incorrect processing state: %d while %d is expected!\n",
 | 
			
		||||
            expected_state, backup_expected);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void channel_state_assert(uint8_t *current_state, uint8_t expected_state)
 | 
			
		||||
{
 | 
			
		||||
    if (*current_state != expected_state) {
 | 
			
		||||
        SPM_PANIC("channel in incorrect processing state: %d while %d is expected!\n",
 | 
			
		||||
            *current_state, expected_state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern const mem_region_t *mem_regions;
 | 
			
		||||
extern const uint32_t mem_region_count;
 | 
			
		||||
 | 
			
		||||
const mem_region_t *get_mem_regions(int32_t partition_id, uint32_t *region_count)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
 | 
			
		||||
    SPM_ASSERT(NULL != region_count);
 | 
			
		||||
    *region_count = 0;
 | 
			
		||||
 | 
			
		||||
    if (partition_id == MEM_PARTITIONS_ALL) {
 | 
			
		||||
        *region_count = mem_region_count;
 | 
			
		||||
        return mem_regions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The entries in the array of memory regions are grouped by partition id.
 | 
			
		||||
    // This is ensured by the way this array is automatically generated from the manifest files.
 | 
			
		||||
    for (i = 0; i < mem_region_count && mem_regions[i].partition_id != partition_id; i++);
 | 
			
		||||
 | 
			
		||||
    if (i == mem_region_count) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const mem_region_t *regions = &mem_regions[i];
 | 
			
		||||
    for (; i < mem_region_count && mem_regions[i].partition_id == partition_id; i++, (*region_count)++);
 | 
			
		||||
 | 
			
		||||
    return regions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern spm_db_t g_spm;
 | 
			
		||||
 | 
			
		||||
spm_partition_t *get_active_partition(void)
 | 
			
		||||
{
 | 
			
		||||
    osThreadId_t active_thread_id = osThreadGetId();
 | 
			
		||||
    SPM_ASSERT(NULL != active_thread_id);
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < g_spm.partition_count; ++i) {
 | 
			
		||||
        if (g_spm.partitions[i].thread_id == active_thread_id) {
 | 
			
		||||
            return &(g_spm.partitions[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL; // Valid in case of NSPE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool is_buffer_accessible(const void *ptr, size_t size, spm_partition_t *accessing_partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == ptr) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (size == 0) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check wrap around of ptr + size
 | 
			
		||||
    if (((uintptr_t)ptr + size - 1) < (uintptr_t)ptr) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Note: Sanity checks on platform addresses and sizes is done in psa_spm_init()
 | 
			
		||||
 | 
			
		||||
    uint32_t secure_ram_base   = PSA_SECURE_RAM_START;
 | 
			
		||||
    size_t   secure_ram_len    = PSA_SECURE_RAM_SIZE;
 | 
			
		||||
    uint32_t secure_rom_base   = PSA_SECURE_ROM_START;
 | 
			
		||||
    size_t   secure_rom_len    = PSA_SECURE_ROM_SIZE;
 | 
			
		||||
 | 
			
		||||
    uint32_t non_secure_ram_base   = PSA_NON_SECURE_RAM_START;
 | 
			
		||||
    size_t   non_secure_ram_len    = PSA_NON_SECURE_RAM_SIZE;
 | 
			
		||||
    uint32_t non_secure_rom_base   = PSA_NON_SECURE_ROM_START;
 | 
			
		||||
    size_t   non_secure_rom_len    = PSA_NON_SECURE_ROM_SIZE;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Check NSPE case
 | 
			
		||||
    if (accessing_partition == NULL) {
 | 
			
		||||
 | 
			
		||||
        // Make sure the NSPE is accessing the non-secure ram range OR the non-secure flash range
 | 
			
		||||
 | 
			
		||||
        // RAM
 | 
			
		||||
        if ( ((uintptr_t)ptr >= (uintptr_t)non_secure_ram_base) && ((uintptr_t)ptr < ((uintptr_t)non_secure_ram_base + non_secure_ram_len)) &&
 | 
			
		||||
             (((uintptr_t)ptr + size) <= ((uintptr_t)non_secure_ram_base + non_secure_ram_len))
 | 
			
		||||
           ) {
 | 
			
		||||
               return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // FLASH
 | 
			
		||||
        if ( ((uintptr_t)ptr >= (uintptr_t)non_secure_rom_base) && ((uintptr_t)ptr < ((uintptr_t)non_secure_rom_base + non_secure_rom_len)) &&
 | 
			
		||||
             (((uintptr_t)ptr + size) <= ((uintptr_t)non_secure_rom_base + non_secure_rom_len))
 | 
			
		||||
           ) {
 | 
			
		||||
               return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else    // Check SPE case
 | 
			
		||||
    {
 | 
			
		||||
        // As we do not expect secure partitions to use SPE addresses for iovecs, we make sure here that the SPE is accessing
 | 
			
		||||
        // the secure ram range OR the secure flash range
 | 
			
		||||
 | 
			
		||||
        // RAM
 | 
			
		||||
        if ( ((uintptr_t)ptr >= (uintptr_t)secure_ram_base) && ((uintptr_t)ptr < ((uintptr_t)secure_ram_base + secure_ram_len)) &&
 | 
			
		||||
             (((uintptr_t)ptr + size) <= ((uintptr_t)secure_ram_base + secure_ram_len))
 | 
			
		||||
           ) {
 | 
			
		||||
               return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // FLASH
 | 
			
		||||
        if ( ((uintptr_t)ptr >= (uintptr_t)secure_rom_base) && ((uintptr_t)ptr < ((uintptr_t)secure_rom_base + secure_rom_len)) &&
 | 
			
		||||
             (((uintptr_t)ptr + size) <= ((uintptr_t)secure_rom_base + secure_rom_len))
 | 
			
		||||
           ) {
 | 
			
		||||
               return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,165 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS <= PSA_HANDLE_MGR_MAX_HANDLES_NUM,
 | 
			
		||||
    "Number of channels exceeds maximum number of handles allowed in handles manager!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES <= PSA_HANDLE_MGR_MAX_HANDLES_NUM,
 | 
			
		||||
    "Number of active messages exceeds maximum number of handles allowed in handles manager!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Sanity check - memory ranges are well formed
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    (PSA_SECURE_RAM_START + PSA_SECURE_RAM_SIZE - 1) > PSA_SECURE_RAM_START,
 | 
			
		||||
    "Illegal secure ram region!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    (PSA_SECURE_ROM_START + PSA_SECURE_ROM_SIZE - 1) > PSA_SECURE_ROM_START,
 | 
			
		||||
    "Illegal secure flash region!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    (PSA_NON_SECURE_RAM_START + PSA_NON_SECURE_RAM_SIZE - 1) > PSA_NON_SECURE_RAM_START,
 | 
			
		||||
    "Illegal non-secure ram region!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    (PSA_NON_SECURE_ROM_START + PSA_NON_SECURE_ROM_SIZE - 1) > PSA_NON_SECURE_ROM_START,
 | 
			
		||||
    "Illegal non-secure flash region!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    (PSA_SHARED_RAM_START + PSA_SHARED_RAM_SIZE - 1) > PSA_SHARED_RAM_START,
 | 
			
		||||
    "Illegal shared ram region!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Sanity check - memory ranges are not overlapping
 | 
			
		||||
 | 
			
		||||
#ifndef MIN
 | 
			
		||||
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef MAX
 | 
			
		||||
#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define OVERLAP_CHECK( name1, start1, size1, name2, start2, size2) \
 | 
			
		||||
    MBED_STATIC_ASSERT( \
 | 
			
		||||
        MAX(start1, start2) >= MIN((start1 + size1), (start2 + size2)), \
 | 
			
		||||
        name1 " and " name2 " are overlapping!!!" \
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
OVERLAP_CHECK(
 | 
			
		||||
    "PSA_SECURE_RAM",     PSA_SECURE_RAM_START,     PSA_SECURE_RAM_SIZE,
 | 
			
		||||
    "PSA_NON_SECURE_RAM", PSA_NON_SECURE_RAM_START, PSA_NON_SECURE_RAM_SIZE
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
OVERLAP_CHECK(
 | 
			
		||||
    "PSA_SECURE_RAM", PSA_SECURE_RAM_START, PSA_SECURE_RAM_SIZE,
 | 
			
		||||
    "PSA_SHARED_RAM", PSA_SHARED_RAM_START, PSA_SHARED_RAM_SIZE
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
OVERLAP_CHECK(
 | 
			
		||||
    "PSA_SHARED_RAM",     PSA_SHARED_RAM_START,     PSA_SHARED_RAM_SIZE,
 | 
			
		||||
    "PSA_NON_SECURE_RAM", PSA_NON_SECURE_RAM_START, PSA_NON_SECURE_RAM_SIZE
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
OVERLAP_CHECK(
 | 
			
		||||
    "PSA_SECURE_FLASH",     PSA_SECURE_ROM_START, PSA_SECURE_ROM_SIZE,
 | 
			
		||||
    "PSA_NON_SECURE_FLASH", PSA_NON_SECURE_ROM_START, PSA_NON_SECURE_ROM_SIZE
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
psa_handle_item_t g_channels_handle_storage[MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS] = {0};
 | 
			
		||||
spm_ipc_channel_t g_channel_data[MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS] = {0};
 | 
			
		||||
osRtxMemoryPool_t g_channel_mem_pool_storage = {0};
 | 
			
		||||
osMemoryPoolAttr_t g_channel_mem_pool_attr = {
 | 
			
		||||
    .name = "SPM_channel_pool",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &g_channel_mem_pool_storage,
 | 
			
		||||
    .cb_size = sizeof(g_channel_mem_pool_storage),
 | 
			
		||||
    .mp_mem = g_channel_data,
 | 
			
		||||
    .mp_size = sizeof(g_channel_data)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
psa_handle_item_t g_messages_handle_storage[MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES] = {0};
 | 
			
		||||
spm_active_msg_t g_active_messages_data[MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES] = {0};
 | 
			
		||||
osRtxMemoryPool_t g_active_messages_mem_pool_storage = {0};
 | 
			
		||||
osMemoryPoolAttr_t g_active_messages_mem_pool_attr = {
 | 
			
		||||
    .name = "SPM_active_messages_pool",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &g_active_messages_mem_pool_storage,
 | 
			
		||||
    .cb_size = sizeof(g_active_messages_mem_pool_storage),
 | 
			
		||||
    .mp_mem = g_active_messages_data,
 | 
			
		||||
    .mp_size = sizeof(g_active_messages_data)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
spm_db_t g_spm = {
 | 
			
		||||
    .partitions = NULL,
 | 
			
		||||
    .partition_count = 0,
 | 
			
		||||
    .channels_handle_mgr = {
 | 
			
		||||
        .handle_generator = PSA_HANDLE_MGR_INVALID_HANDLE,
 | 
			
		||||
        .pool_size        = MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS,
 | 
			
		||||
        .handles_pool     = g_channels_handle_storage
 | 
			
		||||
    },
 | 
			
		||||
    .messages_handle_mgr = {
 | 
			
		||||
        .handle_generator = PSA_HANDLE_MGR_INVALID_HANDLE,
 | 
			
		||||
        .pool_size        = MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES,
 | 
			
		||||
        .handles_pool     = g_messages_handle_storage
 | 
			
		||||
    },
 | 
			
		||||
    .channel_mem_pool = NULL,
 | 
			
		||||
    .active_messages_mem_pool = NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// forward declaration
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions);
 | 
			
		||||
 | 
			
		||||
void psa_spm_init(void)
 | 
			
		||||
{
 | 
			
		||||
    spm_hal_memory_protection_init();
 | 
			
		||||
 | 
			
		||||
    g_spm.channel_mem_pool = osMemoryPoolNew(
 | 
			
		||||
        MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS,
 | 
			
		||||
        sizeof(spm_ipc_channel_t),
 | 
			
		||||
        &g_channel_mem_pool_attr
 | 
			
		||||
        );
 | 
			
		||||
    if (NULL == g_spm.channel_mem_pool) {
 | 
			
		||||
        error("%s - Failed to create channel memory pool!\n", __func__);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_spm.active_messages_mem_pool = osMemoryPoolNew(
 | 
			
		||||
        MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES,
 | 
			
		||||
        sizeof(spm_active_msg_t),
 | 
			
		||||
        &g_active_messages_mem_pool_attr
 | 
			
		||||
        );
 | 
			
		||||
    if (NULL == g_spm.active_messages_mem_pool) {
 | 
			
		||||
        error("%s - Failed to create active messages memory pool!\n", __func__);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_spm.partition_count = init_partitions(&(g_spm.partitions));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,235 @@
 | 
			
		|||
/* Copyright (c) 2017 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 SPM_INTERNAL_H
 | 
			
		||||
#define SPM_INTERNAL_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_defs.h"
 | 
			
		||||
#include "spm_messages.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define SPM_COMPLETION_SEM_MAX_COUNT (1UL) /* Maximum number of available tokens for a completion semaphore. */
 | 
			
		||||
#define SPM_COMPLETION_SEM_INITIAL_COUNT (0UL) /* Initial number of available tokens for a completion semaphore. */
 | 
			
		||||
 | 
			
		||||
#define PSA_MMIO_PERM_READ_ONLY   (0x000000001)
 | 
			
		||||
#define PSA_MMIO_PERM_READ_WRITE  (0x000000003)
 | 
			
		||||
 | 
			
		||||
#define PSA_RESERVED_ERROR_MIN (INT32_MIN + 1)
 | 
			
		||||
#define PSA_RESERVED_ERROR_MAX (INT32_MIN + 127)
 | 
			
		||||
 | 
			
		||||
#define SPM_CHANNEL_STATE_INVALID          (0x01)
 | 
			
		||||
#define SPM_CHANNEL_STATE_CONNECTING       (0x02)
 | 
			
		||||
#define SPM_CHANNEL_STATE_IDLE             (0x03)
 | 
			
		||||
#define SPM_CHANNEL_STATE_PENDING          (0x04)
 | 
			
		||||
#define SPM_CHANNEL_STATE_ACTIVE           (0x05)
 | 
			
		||||
 | 
			
		||||
#define MEM_PARTITIONS_ALL (0) /* A constant to use to retrieve the memory regions for all the partitions at once. */
 | 
			
		||||
 | 
			
		||||
#define SPM_CMSIS_RTOS_ERROR_BIT_MSK (0x80000000)
 | 
			
		||||
 | 
			
		||||
#ifndef TRUE
 | 
			
		||||
#define TRUE (1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef FALSE
 | 
			
		||||
#define FALSE (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct spm_partition;
 | 
			
		||||
struct spm_ipc_channel;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Structure to describe MMIO region along with owning partition.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct mem_region {
 | 
			
		||||
    const uint32_t base;
 | 
			
		||||
    const uint32_t size;
 | 
			
		||||
    const uint32_t permission;
 | 
			
		||||
    const int32_t partition_id;
 | 
			
		||||
} mem_region_t;
 | 
			
		||||
 | 
			
		||||
typedef union spm_iovec {
 | 
			
		||||
    psa_invec_t in;
 | 
			
		||||
    psa_outvec_t out;
 | 
			
		||||
} spm_iovec_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * IRQ signal mapper definition.
 | 
			
		||||
 * The function will not return on invalid signal.
 | 
			
		||||
 */
 | 
			
		||||
typedef IRQn_Type (*spm_signal_to_irq_mapper_t)(uint32_t);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Structure to aggregate channels queue in a Root of Trust Service.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct spm_channel_linked_list {
 | 
			
		||||
    struct spm_ipc_channel *head; /* List's first object*/
 | 
			
		||||
    struct spm_ipc_channel *tail; /* List's last object*/
 | 
			
		||||
} spm_channel_linked_list_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Structure containing resources and attributes of a Root of Trust Service.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct spm_rot_service {
 | 
			
		||||
    const uint32_t sid; /* The Root of Trust Service ID.*/
 | 
			
		||||
    const uint32_t mask; /* The signal for this Root of Trust Service*/
 | 
			
		||||
    struct spm_partition *partition; /* Pointer to the Partition which the Root of Trust Service belongs to.*/
 | 
			
		||||
    const uint32_t min_version; /* Minor version of the Root of Trust Service interface.*/
 | 
			
		||||
    const uint32_t min_version_policy; /* Minor version policy of the Root of Trust Service.*/
 | 
			
		||||
    const bool allow_nspe; /* Whether to allow non-secure clients to connect to the Root of Trust Service.*/
 | 
			
		||||
    spm_channel_linked_list_t queue; /* Queue of channels holding ROT_SRV operations waiting to be served. */
 | 
			
		||||
} spm_rot_service_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Structure containing Partition->RoT-Service channel information.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct spm_ipc_channel {
 | 
			
		||||
    struct spm_partition *src_partition; /* Pointer to the Partition which connects to the Root of Trust Service.*/
 | 
			
		||||
    spm_rot_service_t *dst_rot_service; /* Pointer to the connected Root of Trust Service.*/
 | 
			
		||||
    void *rhandle; /* Reverse handle to be used for this channel.*/
 | 
			
		||||
    void *msg_ptr; /* message data sent from user */
 | 
			
		||||
    struct spm_ipc_channel *next; /* Next channel in the chain  */
 | 
			
		||||
    uint8_t msg_type; /* The message type.*/
 | 
			
		||||
    uint8_t state; /* The current processing state of the channel.*/
 | 
			
		||||
    uint8_t is_dropped;
 | 
			
		||||
} spm_ipc_channel_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Structure containing the currently active message for a Root of Trust Service.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct spm_active_msg {
 | 
			
		||||
    spm_ipc_channel_t *channel; /* Pointer to the channel delivering this message.*/
 | 
			
		||||
    spm_iovec_t iovecs[PSA_MAX_IOVEC]; /* IOvecs sent for message and response.*/
 | 
			
		||||
    uint8_t out_index; /* First index of outvecs in iovecs*/
 | 
			
		||||
} spm_active_msg_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Structure containing resources and attributes of a Secure Partition.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct spm_partition {
 | 
			
		||||
    const int32_t partition_id; /* The Partition ID.*/
 | 
			
		||||
    osThreadId_t thread_id; /* Thread ID of the Partition thread.*/
 | 
			
		||||
    const uint32_t flags_rot_srv; /* Mask of all the ROT_SRV signals the partition supports.*/
 | 
			
		||||
    const uint32_t flags_interrupts; /* Mask of all the IRQs & doorbell which the partition supports.*/
 | 
			
		||||
    spm_rot_service_t *rot_services; /* Array of the Partition's Root of Trust Services.*/
 | 
			
		||||
    const uint32_t rot_services_count; /* Number of the Partition's Root of Trust Services.*/
 | 
			
		||||
    const uint32_t *extern_sids; /* Array of Root of Trust Service IDs which the partition can connect to.*/
 | 
			
		||||
    const uint32_t extern_sids_count; /* Number of Root of Trust Services which the partition can connect to.*/
 | 
			
		||||
    osMutexId_t mutex; /* Mutex for all rot_service's queues operations. */
 | 
			
		||||
    spm_signal_to_irq_mapper_t irq_mapper; /* a function which maps signal to irq number*/
 | 
			
		||||
} spm_partition_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Structure containing the SPM internal data.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct spm_db {
 | 
			
		||||
    spm_partition_t *partitions; /* Array of all the Secure Partitions in the system.*/
 | 
			
		||||
    uint32_t partition_count; /* Number of Secure Partitions in the system.*/
 | 
			
		||||
    psa_handle_manager_t channels_handle_mgr;
 | 
			
		||||
    psa_handle_manager_t messages_handle_mgr;
 | 
			
		||||
    osMemoryPoolId_t channel_mem_pool; /* Channel memory pool identifier.*/
 | 
			
		||||
    osMemoryPoolId_t active_messages_mem_pool; /* Channel memory pool identifier.*/
 | 
			
		||||
} spm_db_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns a pointer to the currently active secure partition or NULL in case called from NSPE.
 | 
			
		||||
 */
 | 
			
		||||
spm_partition_t *get_active_partition(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return an array of memory regions used by a given partition.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] partition_id - a partition ID to find memory regions for, if MEM_PARTITIONS_ALL then
 | 
			
		||||
 *                           memory regions for all the partitions are returned
 | 
			
		||||
 * @param[out] region_count - will be set to the number of memory regions returned
 | 
			
		||||
 */
 | 
			
		||||
const mem_region_t *get_mem_regions(int32_t partition_id, uint32_t *region_count);
 | 
			
		||||
 | 
			
		||||
// Platform dependent APIs
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Validates a memory block is accessable from a specific partition
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ptr pointer to the beggining of the memory block.
 | 
			
		||||
 * @param[in] size size of the memory block in bytes.
 | 
			
		||||
 * @param[in] accessing_partition which partition is trying to access the memory.
 | 
			
		||||
 * @return true if the entire memory block is accessable from given partition.
 | 
			
		||||
 */
 | 
			
		||||
bool is_buffer_accessible(const void *ptr, size_t size, spm_partition_t * accessing_partition);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Alerts NSPE that a proccess (connect or call) has ended.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] completion_sem_id semaphore id in NSPE.
 | 
			
		||||
 */
 | 
			
		||||
void nspe_done(osSemaphoreId_t completion_sem_id);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Validates parameters sent from caller and queues a connect message on the correct ROT_SRV.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] sid - desired RoT service ID
 | 
			
		||||
 * @param[in] msg - pointer to connect message struct
 | 
			
		||||
 */
 | 
			
		||||
void psa_connect_async(uint32_t sid, spm_pending_connect_msg_t *msg);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Validates parameters sent from caller and queues a call message on the correct ROT_SRV.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] handle - channel handle for the connection
 | 
			
		||||
 * @param[in] msg - pointer to call message struct
 | 
			
		||||
 */
 | 
			
		||||
void psa_call_async(psa_handle_t handle, spm_pending_call_msg_t *msg);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Validates parameters sent from caller and queues a disconnect message on the correct ROT_SRV.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] handle - handle of channel to close
 | 
			
		||||
 * @param[in] msg - pointer to close message struct
 | 
			
		||||
 */
 | 
			
		||||
void psa_close_async(psa_handle_t handle, spm_pending_close_msg_t *msg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Validates IOvecs.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] in_vec - psa_invec_t array
 | 
			
		||||
 * @param[in] in_len - number of elements in in_vec
 | 
			
		||||
 * @param[in] out_vec - psa_outvec_t array
 | 
			
		||||
 * @param[in] out_len - number of elements in out_vec
 | 
			
		||||
*/
 | 
			
		||||
void validate_iovec(
 | 
			
		||||
    const void *in_vec,
 | 
			
		||||
    const uint32_t in_len,
 | 
			
		||||
    const void *out_vec,
 | 
			
		||||
    const uint32_t out_len
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
void channel_state_switch(uint8_t *current_state, uint8_t expected_state, uint8_t new_state);
 | 
			
		||||
void channel_state_assert(uint8_t *current_state, uint8_t expected_state);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // SPM_INTERNAL_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
#if defined(COMPONENT_SPM_MAILBOX)
 | 
			
		||||
 | 
			
		||||
#include "ipc_queue.h"
 | 
			
		||||
extern ipc_consumer_queue_t *cons_queue;
 | 
			
		||||
// this is the dispatcher thread for dual-chip systems
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
    while (true) {
 | 
			
		||||
        ipc_queue_drain(cons_queue);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#error "Non dual-chip platforms are not yet supported"
 | 
			
		||||
 | 
			
		||||
#endif // defined(COMPONENT_SPM_MAILBOX)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
/* Copyright (c) 2017 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 __MBED_SPM_PANIC_H__
 | 
			
		||||
#define __MBED_SPM_PANIC_H__
 | 
			
		||||
 | 
			
		||||
/** @addtogroup SPM
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "mbed_toolchain.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef SPM_SPE_BUILD
 | 
			
		||||
 | 
			
		||||
#error "Trying to build for SPE with SPM_SPE_BUILD flag - Not supported"
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generate a system panic
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] format The format string to output on panic
 | 
			
		||||
 * @param[in] ...    (Additional arguments) Depending on the format string
 | 
			
		||||
 */
 | 
			
		||||
#define SPM_PANIC(format, ...)  error("%s %u: " format, __func__, __LINE__, ##__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Assert on condition (debug build only)
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] expr Condition to be asserted
 | 
			
		||||
 */
 | 
			
		||||
#define SPM_ASSERT(expr) MBED_ASSERT(expr)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/ // end of SPM group
 | 
			
		||||
 | 
			
		||||
#endif  // __MBED_SPM_PANIC_H__
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,586 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "mbed_toolchain.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_messages.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
 | 
			
		||||
extern spm_db_t g_spm;
 | 
			
		||||
 | 
			
		||||
static inline spm_partition_t *get_partition_by_pid(int32_t partition_id)
 | 
			
		||||
{
 | 
			
		||||
    for (uint32_t i = 0; i < g_spm.partition_count; ++i) {
 | 
			
		||||
        if (g_spm.partitions[i].partition_id == partition_id) {
 | 
			
		||||
            return &(g_spm.partitions[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline psa_handle_t create_msg_handle(void *handle_mem, int32_t friend_pid)
 | 
			
		||||
{
 | 
			
		||||
    return psa_hndl_mgr_handle_create(&(g_spm.messages_handle_mgr), handle_mem, friend_pid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline spm_active_msg_t *get_msg_from_handle(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    return (spm_active_msg_t *)psa_hndl_mgr_handle_get_mem(&(g_spm.messages_handle_mgr), handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void destroy_msg_handle(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_hndl_mgr_handle_destroy(&(g_spm.messages_handle_mgr), handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void destroy_channel_handle(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_hndl_mgr_handle_destroy(&(g_spm.channels_handle_mgr), handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline spm_rot_service_t *get_rot_service(spm_partition_t *prt, psa_signal_t signal)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < prt->rot_services_count; i++) {
 | 
			
		||||
        if (prt->rot_services[i].mask == signal) {
 | 
			
		||||
            return &prt->rot_services[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function validates the parameters sent from the user and copies it to an active message
 | 
			
		||||
 *
 | 
			
		||||
 * Function assumptions:
 | 
			
		||||
 * * channel is allocated from SPM Core memory
 | 
			
		||||
 * * channel->msg_ptr potentially allocated from nonsecure memory
 | 
			
		||||
 * * user_msg allocated from secure partition memory - not trusted by SPM Core
 | 
			
		||||
*/
 | 
			
		||||
static void copy_message_to_spm(spm_ipc_channel_t *channel, psa_msg_t *user_msg)
 | 
			
		||||
{
 | 
			
		||||
    // Memory allocated from MemoryPool isn't zeroed - thus a temporary variable will make sure we will start from a clear state.
 | 
			
		||||
    spm_active_msg_t temp_active_message = {
 | 
			
		||||
        .channel = channel,
 | 
			
		||||
        .iovecs = {{.in = {0}}},
 | 
			
		||||
        .out_index = 0,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (channel->msg_type == PSA_IPC_CALL) {
 | 
			
		||||
        if (!is_buffer_accessible(channel->msg_ptr, sizeof(spm_pending_call_msg_t), channel->src_partition)) {
 | 
			
		||||
            SPM_PANIC("message data is inaccessible\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        spm_pending_call_msg_t *call_msg_data = (spm_pending_call_msg_t *)channel->msg_ptr;
 | 
			
		||||
 | 
			
		||||
        // Copy pointers and sizes to secure memory to prevent TOCTOU
 | 
			
		||||
        const psa_invec_t *temp_invec = call_msg_data->in_vec;
 | 
			
		||||
        const uint32_t temp_invec_size = call_msg_data->in_vec_size;
 | 
			
		||||
        const psa_outvec_t *temp_outvec = call_msg_data->out_vec;
 | 
			
		||||
        const uint32_t temp_outvec_size = call_msg_data->out_vec_size;
 | 
			
		||||
 | 
			
		||||
        validate_iovec(temp_invec, temp_invec_size, temp_outvec, temp_outvec_size);
 | 
			
		||||
        temp_active_message.out_index = (uint8_t)temp_invec_size;
 | 
			
		||||
 | 
			
		||||
        if (temp_invec_size > 0) {
 | 
			
		||||
            if (!is_buffer_accessible(temp_invec, temp_invec_size * sizeof(*temp_invec), channel->src_partition)) {
 | 
			
		||||
                SPM_PANIC("in_vec is inaccessible\n");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (uint32_t i = 0; i < temp_invec_size; ++i) {
 | 
			
		||||
                if (temp_invec[i].len == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Copy struct
 | 
			
		||||
                temp_active_message.iovecs[i].in = temp_invec[i];
 | 
			
		||||
                user_msg->in_size[i] = temp_invec[i].len;
 | 
			
		||||
 | 
			
		||||
                // Copy then check to prevent TOCTOU
 | 
			
		||||
                if (!is_buffer_accessible(
 | 
			
		||||
                    temp_active_message.iovecs[i].in.base,
 | 
			
		||||
                    temp_active_message.iovecs[i].in.len,
 | 
			
		||||
                    channel->src_partition)) {
 | 
			
		||||
                    SPM_PANIC("in_vec[%d] is inaccessible\n", i);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (temp_outvec_size > 0) {
 | 
			
		||||
            if (!is_buffer_accessible(temp_outvec, temp_outvec_size * sizeof(*temp_outvec), channel->src_partition)) {
 | 
			
		||||
                SPM_PANIC("out_vec is inaccessible\n");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (uint32_t i = 0; i < temp_outvec_size; ++i) {
 | 
			
		||||
                if (temp_outvec[i].len == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Copy struct
 | 
			
		||||
                temp_active_message.iovecs[temp_invec_size + i].out = temp_outvec[i];
 | 
			
		||||
                user_msg->out_size[i] = temp_outvec[i].len;
 | 
			
		||||
 | 
			
		||||
                // Copy then check to prevent TOCTOU
 | 
			
		||||
                if (!is_buffer_accessible(
 | 
			
		||||
                    temp_active_message.iovecs[temp_invec_size + i].out.base,
 | 
			
		||||
                    temp_active_message.iovecs[temp_invec_size + i].out.len,
 | 
			
		||||
                    channel->src_partition)) {
 | 
			
		||||
                    SPM_PANIC("out_vec[%d] is inaccessible\n", i);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Allocating from SPM-Core internal memory
 | 
			
		||||
    spm_active_msg_t *active_msg = (spm_active_msg_t *)osMemoryPoolAlloc(g_spm.active_messages_mem_pool, osWaitForever);
 | 
			
		||||
    if (NULL == active_msg) {
 | 
			
		||||
        SPM_PANIC("Could not allocate active message");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Copy struct
 | 
			
		||||
    *active_msg = temp_active_message;
 | 
			
		||||
 | 
			
		||||
    psa_handle_t handle = create_msg_handle(active_msg, PSA_HANDLE_MGR_INVALID_FRIEND_OWNER);
 | 
			
		||||
 | 
			
		||||
    user_msg->type = channel->msg_type;
 | 
			
		||||
    user_msg->rhandle = channel->rhandle;
 | 
			
		||||
    user_msg->handle = handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static spm_ipc_channel_t *spm_rot_service_queue_dequeue(spm_rot_service_t *rot_service)
 | 
			
		||||
{
 | 
			
		||||
    osStatus_t os_status = osMutexAcquire(rot_service->partition->mutex, osWaitForever);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    spm_ipc_channel_t *ret = rot_service->queue.head;
 | 
			
		||||
 | 
			
		||||
    if (ret == NULL) {
 | 
			
		||||
        SPM_PANIC("Dequeue from empty queue");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rot_service->queue.head = ret->next;
 | 
			
		||||
    ret->next = NULL;
 | 
			
		||||
 | 
			
		||||
    if (rot_service->queue.head == NULL) {
 | 
			
		||||
        rot_service->queue.tail = NULL;
 | 
			
		||||
 | 
			
		||||
        uint32_t flags = osThreadFlagsClear(rot_service->mask);
 | 
			
		||||
 | 
			
		||||
        // osThreadFlagsClear() sets the msb on failure
 | 
			
		||||
        SPM_ASSERT((flags & SPM_CMSIS_RTOS_ERROR_BIT_MSK) == 0);
 | 
			
		||||
        SPM_ASSERT(flags & rot_service->mask);
 | 
			
		||||
        PSA_UNUSED(flags);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    os_status = osMutexRelease(rot_service->partition->mutex);
 | 
			
		||||
    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static uint32_t psa_wait(bool wait_any, uint32_t bitmask, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
    spm_partition_t *curr_partition = get_active_partition();
 | 
			
		||||
    SPM_ASSERT(NULL != curr_partition); // active thread in SPM must be in partition DB
 | 
			
		||||
 | 
			
		||||
    uint32_t flags_interrupts = curr_partition->flags_interrupts | PSA_DOORBELL;
 | 
			
		||||
    uint32_t flags_all = curr_partition->flags_rot_srv | flags_interrupts;
 | 
			
		||||
 | 
			
		||||
    // In case we're waiting for any signal the bitmask must contain all the flags, otherwise
 | 
			
		||||
    // we should be waiting for a subset of interrupt signals.
 | 
			
		||||
    if (wait_any) {
 | 
			
		||||
        bitmask = flags_all;
 | 
			
		||||
    } else {
 | 
			
		||||
        // Make sure the interrupt mask contains only a subset of interrupt signal mask.
 | 
			
		||||
        if (bitmask != (flags_interrupts & bitmask)) {
 | 
			
		||||
            SPM_PANIC("interrupt mask 0x%x must have only bits from 0x%x!\n",
 | 
			
		||||
                bitmask, flags_interrupts);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t asserted_signals = osThreadFlagsWait(
 | 
			
		||||
        bitmask,
 | 
			
		||||
        osFlagsWaitAny | osFlagsNoClear,
 | 
			
		||||
        (PSA_BLOCK == timeout) ? osWaitForever : timeout
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Asserted_signals must be a subset of the supported ROT_SRV and interrupt signals.
 | 
			
		||||
    SPM_ASSERT((asserted_signals == (asserted_signals & flags_all)) ||
 | 
			
		||||
               ((PSA_BLOCK != timeout) && (osFlagsErrorTimeout == asserted_signals)));
 | 
			
		||||
 | 
			
		||||
    return (osFlagsErrorTimeout == asserted_signals) ? 0 : asserted_signals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t psa_wait_any(uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
    return psa_wait(true, 0, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t psa_wait_interrupt(uint32_t interrupt_mask, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
    return psa_wait(false, interrupt_mask, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_get(psa_signal_t signum, psa_msg_t *msg)
 | 
			
		||||
{
 | 
			
		||||
    spm_partition_t *curr_partition = get_active_partition();
 | 
			
		||||
    SPM_ASSERT(NULL != curr_partition); // active thread in SPM must be in partition DB
 | 
			
		||||
 | 
			
		||||
    if (!is_buffer_accessible(msg, sizeof(*msg), curr_partition)) {
 | 
			
		||||
        SPM_PANIC("msg is inaccessible\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(msg, 0, sizeof(*msg));
 | 
			
		||||
 | 
			
		||||
    // signum must be ONLY ONE of the bits of curr_partition->flags_rot_srv
 | 
			
		||||
    bool is_one_bit = ((signum != 0) && !(signum & (signum - 1)));
 | 
			
		||||
    if (!is_one_bit || !(signum & curr_partition->flags_rot_srv)) {
 | 
			
		||||
        SPM_PANIC(
 | 
			
		||||
            "signum 0x%x must have only 1 bit ON and must be a subset of 0x%x!\n",
 | 
			
		||||
            signum,
 | 
			
		||||
            curr_partition->flags_rot_srv
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t active_flags = osThreadFlagsGet();
 | 
			
		||||
    if (0 == (signum & active_flags)) {
 | 
			
		||||
        SPM_PANIC("flag is not active!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    spm_rot_service_t *curr_rot_service = get_rot_service(curr_partition, signum);
 | 
			
		||||
    if (curr_rot_service == NULL) {
 | 
			
		||||
        SPM_PANIC("Received signal (0x%08x) that does not match any root of trust service", signum);
 | 
			
		||||
    }
 | 
			
		||||
    spm_ipc_channel_t *curr_channel = spm_rot_service_queue_dequeue(curr_rot_service);
 | 
			
		||||
 | 
			
		||||
    switch (curr_channel->msg_type) {
 | 
			
		||||
        case PSA_IPC_CONNECT:
 | 
			
		||||
            channel_state_assert(
 | 
			
		||||
                &curr_channel->state,
 | 
			
		||||
                SPM_CHANNEL_STATE_CONNECTING
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case PSA_IPC_CALL:
 | 
			
		||||
            channel_state_switch(
 | 
			
		||||
                &curr_channel->state,
 | 
			
		||||
                SPM_CHANNEL_STATE_PENDING,
 | 
			
		||||
                SPM_CHANNEL_STATE_ACTIVE
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case PSA_IPC_DISCONNECT:
 | 
			
		||||
        {
 | 
			
		||||
            channel_state_assert(
 | 
			
		||||
                &curr_channel->state,
 | 
			
		||||
                SPM_CHANNEL_STATE_IDLE
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default:
 | 
			
		||||
            SPM_PANIC("psa_get - unexpected message type=0x%08X", curr_channel->msg_type);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    copy_message_to_spm(curr_channel, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t read_or_skip(psa_handle_t msg_handle, uint32_t invec_idx, void *buf, size_t num_bytes)
 | 
			
		||||
{
 | 
			
		||||
    spm_active_msg_t *active_msg = get_msg_from_handle(msg_handle);
 | 
			
		||||
 | 
			
		||||
    channel_state_assert(&active_msg->channel->state, SPM_CHANNEL_STATE_ACTIVE);
 | 
			
		||||
 | 
			
		||||
    if (invec_idx >= PSA_MAX_IOVEC) {
 | 
			
		||||
        SPM_PANIC("Invalid invec_idx\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (invec_idx >= active_msg->out_index) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_invec_t *active_iovec = &active_msg->iovecs[invec_idx].in;
 | 
			
		||||
 | 
			
		||||
    if (num_bytes > active_iovec->len) {
 | 
			
		||||
        num_bytes = active_iovec->len;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (num_bytes > 0) {
 | 
			
		||||
        if (buf) {
 | 
			
		||||
            memcpy(buf, active_iovec->base, num_bytes);
 | 
			
		||||
        }
 | 
			
		||||
        active_iovec->base = (void *)((uint8_t*)active_iovec->base + num_bytes);
 | 
			
		||||
        active_iovec->len -= num_bytes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return num_bytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, void *buf, size_t num_bytes)
 | 
			
		||||
{
 | 
			
		||||
    spm_partition_t *curr_partition = get_active_partition();
 | 
			
		||||
    SPM_ASSERT(NULL != curr_partition); // active thread in SPM must be in partition DB
 | 
			
		||||
 | 
			
		||||
    if (!is_buffer_accessible(buf, num_bytes, curr_partition)) {
 | 
			
		||||
        SPM_PANIC("buffer is inaccessible\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return read_or_skip(msg_handle, invec_idx, buf, num_bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
 | 
			
		||||
{
 | 
			
		||||
    return read_or_skip(msg_handle, invec_idx, NULL, num_bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, const void *buffer, size_t num_bytes)
 | 
			
		||||
{
 | 
			
		||||
    if (0 == num_bytes) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    spm_partition_t *curr_partition = get_active_partition();
 | 
			
		||||
    SPM_ASSERT(NULL != curr_partition); // active thread in S
 | 
			
		||||
 | 
			
		||||
    if (!is_buffer_accessible(buffer, num_bytes, curr_partition)) {
 | 
			
		||||
        SPM_PANIC("buffer is inaccessible\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    spm_active_msg_t *active_msg = get_msg_from_handle(msg_handle);
 | 
			
		||||
 | 
			
		||||
    channel_state_assert(&active_msg->channel->state, SPM_CHANNEL_STATE_ACTIVE);
 | 
			
		||||
 | 
			
		||||
    outvec_idx += active_msg->out_index;
 | 
			
		||||
    if (outvec_idx >= PSA_MAX_IOVEC) {
 | 
			
		||||
        SPM_PANIC("Invalid outvec_idx\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    psa_outvec_t *active_iovec = &active_msg->iovecs[outvec_idx].out;
 | 
			
		||||
    if (num_bytes > active_iovec->len) {
 | 
			
		||||
        SPM_PANIC("Invalid write operation (Requested %d, Avialable %d)\n", num_bytes, active_iovec->len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy((uint8_t *)(active_iovec->base), buffer, num_bytes);
 | 
			
		||||
    active_iovec->base = (void *)((uint8_t *)active_iovec->base + num_bytes);
 | 
			
		||||
    active_iovec->len -= num_bytes;
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_reply(psa_handle_t msg_handle, psa_error_t status)
 | 
			
		||||
{
 | 
			
		||||
    spm_active_msg_t *active_msg = get_msg_from_handle(msg_handle);
 | 
			
		||||
    spm_ipc_channel_t *active_channel = active_msg->channel;
 | 
			
		||||
    SPM_ASSERT(active_channel != NULL);
 | 
			
		||||
    SPM_ASSERT(active_channel->msg_ptr != NULL);
 | 
			
		||||
 | 
			
		||||
    // !!!!!NOTE!!!!! handles must be destroyed before osMemoryPoolFree().
 | 
			
		||||
    // Message creation blocked on resource exhaustion and handle will be created
 | 
			
		||||
    // only after a successful memory allocation and is not expected to fail.
 | 
			
		||||
    {
 | 
			
		||||
        destroy_msg_handle(msg_handle);
 | 
			
		||||
 | 
			
		||||
        memset(active_msg, 0, sizeof(*active_msg));
 | 
			
		||||
        osStatus_t os_status = osMemoryPoolFree(g_spm.active_messages_mem_pool, active_msg);
 | 
			
		||||
        SPM_ASSERT(osOK == os_status);
 | 
			
		||||
        PSA_UNUSED(os_status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    osSemaphoreId_t completion_sem_id = NULL;
 | 
			
		||||
    bool nspe_call = (active_channel->src_partition == NULL);
 | 
			
		||||
    switch (active_channel->msg_type) {
 | 
			
		||||
        case PSA_IPC_CONNECT:
 | 
			
		||||
        {
 | 
			
		||||
            if ((status != PSA_CONNECTION_ACCEPTED) && (status != PSA_CONNECTION_REFUSED)) {
 | 
			
		||||
                SPM_PANIC("status (0X%08x) is not allowed for PSA_IPC_CONNECT", status);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            spm_pending_connect_msg_t *connect_msg_data  = (spm_pending_connect_msg_t *)(active_channel->msg_ptr);
 | 
			
		||||
            completion_sem_id = connect_msg_data->completion_sem_id;
 | 
			
		||||
            if (status == PSA_CONNECTION_REFUSED) {
 | 
			
		||||
                channel_state_assert(&active_channel->state, SPM_CHANNEL_STATE_CONNECTING);
 | 
			
		||||
                // !!!!!NOTE!!!!! handles must be destroyed before osMemoryPoolFree().
 | 
			
		||||
                // Channel creation fails on resource exhaustion and handle will be created
 | 
			
		||||
                // only after a successful memory allocation and is not expected to fail.
 | 
			
		||||
                {
 | 
			
		||||
                    // In psa_connect the handle was written to user's memory before
 | 
			
		||||
                    // the connection was established.
 | 
			
		||||
                    // Channel state machine and ACL will prevent attacker from
 | 
			
		||||
                    // doing bad stuff before we overwrite it with a negative return code.
 | 
			
		||||
                    destroy_channel_handle((psa_handle_t)connect_msg_data->rc);
 | 
			
		||||
 | 
			
		||||
                    memset(active_channel, 0, sizeof(*active_channel));
 | 
			
		||||
                    osStatus_t os_status = osMemoryPoolFree(g_spm.channel_mem_pool, active_channel);
 | 
			
		||||
                    SPM_ASSERT(osOK == os_status);
 | 
			
		||||
                    PSA_UNUSED(os_status);
 | 
			
		||||
                }
 | 
			
		||||
                // Replace the handle we created in the user's memory with the error code
 | 
			
		||||
                connect_msg_data->rc = status;
 | 
			
		||||
                active_channel = NULL;
 | 
			
		||||
            } else {
 | 
			
		||||
                channel_state_switch(&active_channel->state,
 | 
			
		||||
                    SPM_CHANNEL_STATE_CONNECTING, SPM_CHANNEL_STATE_IDLE);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_CALL:
 | 
			
		||||
        {
 | 
			
		||||
            if ((status >= PSA_RESERVED_ERROR_MIN) && (status <= PSA_RESERVED_ERROR_MAX)) {
 | 
			
		||||
                SPM_PANIC("status (0X%08x) is not allowed for PSA_IPC_CALL", status);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            channel_state_switch(&active_channel->state,
 | 
			
		||||
                    SPM_CHANNEL_STATE_ACTIVE, SPM_CHANNEL_STATE_IDLE);
 | 
			
		||||
 | 
			
		||||
            if (status == PSA_DROP_CONNECTION) {
 | 
			
		||||
                active_channel->is_dropped = TRUE;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            spm_pending_call_msg_t *call_msg_data = (spm_pending_call_msg_t *)(active_channel->msg_ptr);
 | 
			
		||||
            call_msg_data->rc = status;
 | 
			
		||||
            completion_sem_id = call_msg_data->completion_sem_id;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case PSA_IPC_DISCONNECT:
 | 
			
		||||
        {
 | 
			
		||||
            spm_pending_close_msg_t *close_msg_data = (spm_pending_close_msg_t *)(active_channel->msg_ptr);
 | 
			
		||||
            completion_sem_id = close_msg_data->completion_sem_id;
 | 
			
		||||
 | 
			
		||||
            channel_state_switch( &(active_channel->state),
 | 
			
		||||
                                  SPM_CHANNEL_STATE_IDLE,
 | 
			
		||||
                                  SPM_CHANNEL_STATE_INVALID
 | 
			
		||||
                                );
 | 
			
		||||
 | 
			
		||||
            // !!!!!NOTE!!!!! handles must be destroyed before osMemoryPoolFree().
 | 
			
		||||
            // Channel creation fails on resource exhaustion and handle will be created
 | 
			
		||||
            // only after a successful memory allocation and is not expected to fail.
 | 
			
		||||
            {
 | 
			
		||||
                destroy_channel_handle(close_msg_data->handle);
 | 
			
		||||
 | 
			
		||||
                memset(active_channel, 0, sizeof(*active_channel));
 | 
			
		||||
                osStatus_t os_status = osMemoryPoolFree(g_spm.channel_mem_pool, active_channel);
 | 
			
		||||
                active_channel = NULL;
 | 
			
		||||
                SPM_ASSERT(osOK == os_status);
 | 
			
		||||
                PSA_UNUSED(os_status);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
            // Note: The status code is ignored for PSA_IPC_DISCONNECT message type
 | 
			
		||||
        }
 | 
			
		||||
        default:
 | 
			
		||||
            SPM_PANIC("psa_reply() - Unexpected message type=0x%08X", active_channel->msg_type);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (active_channel != NULL) {
 | 
			
		||||
        active_channel->msg_ptr = NULL;
 | 
			
		||||
        active_channel->msg_type = 0;  // uninitialized
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (nspe_call) {
 | 
			
		||||
        nspe_done(completion_sem_id);
 | 
			
		||||
    } else {
 | 
			
		||||
        osStatus_t os_status = osSemaphoreRelease(completion_sem_id);
 | 
			
		||||
        SPM_ASSERT(osOK == os_status);
 | 
			
		||||
        PSA_UNUSED(os_status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_notify(int32_t partition_id)
 | 
			
		||||
{
 | 
			
		||||
    spm_partition_t *target_partition = get_partition_by_pid(partition_id);
 | 
			
		||||
    if (NULL == target_partition) {
 | 
			
		||||
        SPM_PANIC("Could not find partition (partition_id = %d)\n",
 | 
			
		||||
        partition_id
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t flags = osThreadFlagsSet(target_partition->thread_id, PSA_DOORBELL);
 | 
			
		||||
    // osThreadFlagsSet() sets the msb on failure
 | 
			
		||||
    // flags is allowed to be 0 since by the time osThreadFlagsSet() returns
 | 
			
		||||
    // the flag could have been cleared by another thread
 | 
			
		||||
    SPM_ASSERT((flags & SPM_CMSIS_RTOS_ERROR_BIT_MSK) == 0);
 | 
			
		||||
    PSA_UNUSED(flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t flags = osThreadFlagsClear(PSA_DOORBELL);
 | 
			
		||||
 | 
			
		||||
    // osThreadFlagsClear() sets the msb on failure
 | 
			
		||||
    SPM_ASSERT((flags & SPM_CMSIS_RTOS_ERROR_BIT_MSK) == 0);
 | 
			
		||||
 | 
			
		||||
    // psa_clear() must not be called when doorbell signal is not currently asserted
 | 
			
		||||
    if ((flags & PSA_DOORBELL) != PSA_DOORBELL) {
 | 
			
		||||
        SPM_PANIC("psa_call() called without signaled doorbell\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t psa_identity(psa_handle_t msg_handle)
 | 
			
		||||
{
 | 
			
		||||
    spm_active_msg_t *active_msg = get_msg_from_handle(msg_handle);
 | 
			
		||||
    SPM_ASSERT(active_msg->channel != NULL);
 | 
			
		||||
    if (active_msg->channel->src_partition == NULL) {
 | 
			
		||||
        return PSA_NSPE_IDENTIFIER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return active_msg->channel->src_partition->partition_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
 | 
			
		||||
{
 | 
			
		||||
    spm_active_msg_t *active_msg = get_msg_from_handle(msg_handle);
 | 
			
		||||
    active_msg->channel->rhandle = rhandle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void psa_eoi(uint32_t irq_signal)
 | 
			
		||||
{
 | 
			
		||||
    spm_partition_t *curr_partition = get_active_partition();
 | 
			
		||||
    SPM_ASSERT(NULL != curr_partition);
 | 
			
		||||
    if (curr_partition->irq_mapper == NULL) {
 | 
			
		||||
        SPM_PANIC("Try to clear an interrupt flag without declaring IRQ");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (0 == (curr_partition->flags_interrupts & irq_signal)) {
 | 
			
		||||
        SPM_PANIC("Signal %d not in irq range\n", irq_signal);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_one_bit = ((irq_signal != 0) && !(irq_signal & (irq_signal - 1)));
 | 
			
		||||
    if (!is_one_bit) {
 | 
			
		||||
        SPM_PANIC("signal 0x%x must have only 1 bit ON!\n",irq_signal);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IRQn_Type irq_line = curr_partition->irq_mapper(irq_signal);
 | 
			
		||||
    uint32_t flags = osThreadFlagsClear(irq_signal);
 | 
			
		||||
    // osThreadFlagsClear() sets the msb on failure
 | 
			
		||||
    SPM_ASSERT((flags & SPM_CMSIS_RTOS_ERROR_BIT_MSK) == 0);
 | 
			
		||||
 | 
			
		||||
    // psa_eoi() must not be called with an unasserted flag.
 | 
			
		||||
    if ((flags & irq_signal) != irq_signal) {
 | 
			
		||||
        SPM_PANIC("psa_eoi() called without signaled IRQ\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    NVIC_EnableIRQ(irq_line);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,170 @@
 | 
			
		|||
/* Copyright (c) 2017 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 __MBED_SPM_SERVER_H__
 | 
			
		||||
#define __MBED_SPM_SERVER_H__
 | 
			
		||||
 | 
			
		||||
/** @addtogroup SPM
 | 
			
		||||
 * The SPM (Secure Partition Manager) is responsible for isolating software in partitions,@n
 | 
			
		||||
 * managing the execution of software within partitions, and providing IPC between partitions.
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------- Includes ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
#include "psa_defs.h"
 | 
			
		||||
 | 
			
		||||
/* --------------------------------- extern "C" wrapper ------------------------------ */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @addtogroup RoT-Service-API
 | 
			
		||||
 *  The C interface for a Root of Trust Service in a Partition.
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return the signals that have been asserted.@n
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] timeout timeout value:@n
 | 
			
		||||
 *            @a PSA_BLOCK block the caller until any signal is asserted.@n
 | 
			
		||||
 *            @a PSA_POLL Returns immediately.
 | 
			
		||||
 * @return 32-bit value of asserted signals.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t psa_wait_any(uint32_t timeout);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return interrupt/doorbell signals that have been asserted based on the bitmask provided.@n
 | 
			
		||||
 * The mask contains a set of signals the caller is interested in handling and must be a subset
 | 
			
		||||
 * of combined interrupt and doorbell mask for the calling partition.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] interrupt_mask mask of signals.
 | 
			
		||||
 * @param[in] timeout timeout value:@n
 | 
			
		||||
 *            @a PSA_BLOCK block the caller until one of the requested signals is asserted.@n
 | 
			
		||||
 *            @a PSA_POLL Returns immediately.
 | 
			
		||||
 * @return 32-bit value of asserted signals.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t psa_wait_interrupt(uint32_t interrupt_mask, uint32_t timeout);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return the Partition ID of the caller.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Bit[31] is set if the caller is from the NSPE.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] msg_handle Handle for the caller's message.
 | 
			
		||||
 * @return Caller's partition ID
 | 
			
		||||
 */
 | 
			
		||||
int32_t psa_identity(psa_handle_t msg_handle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the message which corresponds to a given signal.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  signum an asserted signal returned from psa_wait().
 | 
			
		||||
 * @param[out] msg    pointer to a psa_msg structure.
 | 
			
		||||
 */
 | 
			
		||||
void psa_get(psa_signal_t signum, psa_msg_t *msg);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Associate the caller-provided private data with a specified handle.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] msg_handle Handle for the caller's message.
 | 
			
		||||
 * @param[in] rhandle    Reverse handle allocated by the Root of Trust Service.
 | 
			
		||||
 */
 | 
			
		||||
void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Copy up to @a len bytes from position @a offset within the client message
 | 
			
		||||
 * payload into the Secure Partition buffer @a buffer.@n
 | 
			
		||||
 *
 | 
			
		||||
 * @note Callers should know how much data is available to read based on the@n
 | 
			
		||||
 *       @a size attribute of the psa_msg structure returned from psa_get().@n
 | 
			
		||||
 *       The copy is truncated if the requested range extends beyond the end of the payload.@n
 | 
			
		||||
 *       In such a case, the remaining space in @a buffer is not modified.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  msg_handle Handle for the client's message.
 | 
			
		||||
 * @param[in]  invec_idx  ::psa_invec index to be read.
 | 
			
		||||
 * @param[out] buf        Buffer to copy the requested data to.
 | 
			
		||||
 * @param[in]  num_bytes  Number of bytes to read from the client's message payload.
 | 
			
		||||
 * @return Number of bytes copied or 0 if offset is greater than the size attribute of psa_msg.
 | 
			
		||||
 */
 | 
			
		||||
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, void *buf, size_t num_bytes);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Advance the current read offset by skipping @a num_bytes bytes for input vector
 | 
			
		||||
 * indexed by @а invec_idx.@n
 | 
			
		||||
 * If @a num_bytes is greater than the remaining number of bytes in the vector then
 | 
			
		||||
 * all the remaining bytes are skipped.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  msg_handle Handle for the client's message.
 | 
			
		||||
 * @param[in]  invec_idx  ::psa_invec index to be skipped.
 | 
			
		||||
 * @param[in]  num_bytes  Number of bytes to skip.
 | 
			
		||||
 * @return Number of bytes skipped or 0 if offset is greater than the size attribute of psa_msg.
 | 
			
		||||
 */
 | 
			
		||||
size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Write a response payload of @a bytes bytes starting at position @a offset in the client's response buffer.
 | 
			
		||||
 *
 | 
			
		||||
 * @note If the caller writes data beyond the client's response buffer size
 | 
			
		||||
 *       (@a response_size attribute of the psa_msg structure returned from psa_get()) a fatal error occurs.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] msg_handle  Handle for the client's message.
 | 
			
		||||
 * @param[in] outvec_idx  ::psa_outvec index to be written to.
 | 
			
		||||
 * @param[in] buffer      Buffer with the data to write.
 | 
			
		||||
 * @param[in] num_bytes   Number of bytes to write.
 | 
			
		||||
 */
 | 
			
		||||
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, const void *buffer, size_t num_bytes);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Complete handling of specific message and unblocks the client.
 | 
			
		||||
 *
 | 
			
		||||
 * A return code must be specified, which will be sent to the client.@n
 | 
			
		||||
 * Negative return code represent errors, Positive integers are application-specific.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] msg_handle Handle for the client's message.
 | 
			
		||||
 * @param[in] status Message result value to be reported to the client.
 | 
			
		||||
 */
 | 
			
		||||
void psa_reply(psa_handle_t msg_handle, psa_error_t status);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Send a doorbell signal to a specific partition that is listening for that signal type.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] partition_id partition ID of the target partition.
 | 
			
		||||
 */
 | 
			
		||||
void psa_notify(int32_t partition_id);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clear the doorbell signal.
 | 
			
		||||
 */
 | 
			
		||||
void psa_clear(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Inform the SPM that an interrupt has been handled (end of interrupt).
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] irq_signal The interrupt signal that has been processed.
 | 
			
		||||
 */
 | 
			
		||||
void psa_eoi(uint32_t irq_signal);
 | 
			
		||||
 | 
			
		||||
/** @}*/ // end of RoT-Service-API group
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/ // end of SPM group
 | 
			
		||||
 | 
			
		||||
#endif  /* __MBED_SPM_SERVER_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,229 @@
 | 
			
		|||
/* Copyright (c) 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Includes
 | 
			
		||||
// --------
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "ipc_defs.h"
 | 
			
		||||
#include "ipc_queue.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "spm_messages.h"
 | 
			
		||||
#include "mbed_critical.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "rtx_lib.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Globals
 | 
			
		||||
// -------
 | 
			
		||||
 | 
			
		||||
extern ipc_producer_queue_t *prod_queue;
 | 
			
		||||
 | 
			
		||||
// API Functions Implementation
 | 
			
		||||
// ----------------------------
 | 
			
		||||
uint32_t psa_framework_version(void)
 | 
			
		||||
{
 | 
			
		||||
    return (uint32_t)PSA_FRAMEWORK_VERSION;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t psa_version(uint32_t sid)
 | 
			
		||||
{
 | 
			
		||||
    osRtxSemaphore_t res_sem_storage = {0, 0, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
 | 
			
		||||
    const osSemaphoreAttr_t res_sem_attr = {
 | 
			
		||||
        .name      = "VER_RES_SEM",
 | 
			
		||||
        .attr_bits = 0,
 | 
			
		||||
        .cb_mem    = &res_sem_storage,
 | 
			
		||||
        .cb_size   = sizeof(res_sem_storage),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const spm_pending_version_msg_t msg = {
 | 
			
		||||
        .rc                = PSA_VERSION_NONE,
 | 
			
		||||
        .completion_sem_id = osSemaphoreNew( IPC_RES_SEM_MAX_COUNT,
 | 
			
		||||
                                             IPC_RES_SEM_INITIAL_COUNT,
 | 
			
		||||
                                             &res_sem_attr
 | 
			
		||||
                                           )
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MBED_ASSERT(msg.completion_sem_id != NULL);
 | 
			
		||||
 | 
			
		||||
    ipc_queue_item_t queue_item = {
 | 
			
		||||
        .a = PSA_IPC_VERSION,
 | 
			
		||||
        .b = (uint32_t)(&msg),
 | 
			
		||||
        .c = sid
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ipc_queue_enqueue(prod_queue, queue_item);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(msg.completion_sem_id, osWaitForever);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreDelete(msg.completion_sem_id);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    return msg.rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
 | 
			
		||||
{
 | 
			
		||||
    osRtxSemaphore_t res_sem_storage = {0, 0, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
 | 
			
		||||
    const osSemaphoreAttr_t res_sem_attr = {
 | 
			
		||||
        .name      = "CONN_RES_SEM",
 | 
			
		||||
        .attr_bits = 0,
 | 
			
		||||
        .cb_mem    = &res_sem_storage,
 | 
			
		||||
        .cb_size   = sizeof(res_sem_storage),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const spm_pending_connect_msg_t msg = {
 | 
			
		||||
        .min_version       = minor_version,
 | 
			
		||||
        .rc                = PSA_SUCCESS,
 | 
			
		||||
        .completion_sem_id = osSemaphoreNew( IPC_RES_SEM_MAX_COUNT,
 | 
			
		||||
                                             IPC_RES_SEM_INITIAL_COUNT,
 | 
			
		||||
                                             &res_sem_attr
 | 
			
		||||
                                           )
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MBED_ASSERT(msg.completion_sem_id != NULL);
 | 
			
		||||
 | 
			
		||||
    ipc_queue_item_t queue_item = {
 | 
			
		||||
        .a = PSA_IPC_CONNECT,
 | 
			
		||||
        .b = (uint32_t)(&msg),
 | 
			
		||||
        .c = sid
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ipc_queue_enqueue(prod_queue, queue_item);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(msg.completion_sem_id, osWaitForever);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreDelete(msg.completion_sem_id);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    return (psa_handle_t)(msg.rc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
psa_error_t psa_call( psa_handle_t        handle,
 | 
			
		||||
                      const psa_invec_t  *in_vec,
 | 
			
		||||
                      size_t              in_len,
 | 
			
		||||
                      const psa_outvec_t *out_vec,
 | 
			
		||||
                      size_t              out_len
 | 
			
		||||
                    )
 | 
			
		||||
{
 | 
			
		||||
    // - Immediate errors are checked here.
 | 
			
		||||
    // - Other errors are checked on the SPM core code
 | 
			
		||||
 | 
			
		||||
    // TODO: Panic instead
 | 
			
		||||
    MBED_ASSERT(handle > 0);
 | 
			
		||||
    // TODO: Panic instead
 | 
			
		||||
    MBED_ASSERT((in_vec != NULL) || (in_len == 0));
 | 
			
		||||
    // TODO: Panic instead
 | 
			
		||||
    MBED_ASSERT((out_vec != NULL) || (out_len == 0));
 | 
			
		||||
    // TODO: Panic instead
 | 
			
		||||
    MBED_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
 | 
			
		||||
 | 
			
		||||
    osRtxSemaphore_t res_sem_storage = {0, 0, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
 | 
			
		||||
    const osSemaphoreAttr_t res_sem_attr = {
 | 
			
		||||
        .name      = "CALL_RES_SEM",
 | 
			
		||||
        .attr_bits = 0,
 | 
			
		||||
        .cb_mem    = &res_sem_storage,
 | 
			
		||||
        .cb_size   = sizeof(res_sem_storage),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const spm_pending_call_msg_t msg = {
 | 
			
		||||
        .in_vec            = in_vec,
 | 
			
		||||
        .in_vec_size       = in_len,
 | 
			
		||||
        .out_vec           = out_vec,
 | 
			
		||||
        .out_vec_size      = out_len,
 | 
			
		||||
        .rc                = PSA_SUCCESS,
 | 
			
		||||
        .completion_sem_id = osSemaphoreNew( IPC_RES_SEM_MAX_COUNT,
 | 
			
		||||
                                             IPC_RES_SEM_INITIAL_COUNT,
 | 
			
		||||
                                             &res_sem_attr
 | 
			
		||||
                                           )
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MBED_ASSERT(msg.completion_sem_id != NULL);
 | 
			
		||||
 | 
			
		||||
    ipc_queue_item_t queue_item = {
 | 
			
		||||
        .a = PSA_IPC_CALL,
 | 
			
		||||
        .b = (uint32_t)(&msg),
 | 
			
		||||
        .c = (uint32_t)handle
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ipc_queue_enqueue(prod_queue, queue_item);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(msg.completion_sem_id, osWaitForever);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreDelete(msg.completion_sem_id);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    return msg.rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void psa_close(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    if (handle == PSA_NULL_HANDLE) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // - Immediate errors are checked here.
 | 
			
		||||
    // - Other errors are checked on the SPM core code
 | 
			
		||||
    // TODO: Panic instead
 | 
			
		||||
    MBED_ASSERT(handle >= 0);
 | 
			
		||||
 | 
			
		||||
    osRtxSemaphore_t res_sem_storage = {0, 0, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
    const osSemaphoreAttr_t res_sem_attr = {
 | 
			
		||||
        .name      = "CLOSE_RES_SEM",
 | 
			
		||||
        .attr_bits = 0,
 | 
			
		||||
        .cb_mem    = &res_sem_storage,
 | 
			
		||||
        .cb_size   = sizeof(res_sem_storage),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    spm_pending_close_msg_t msg = {
 | 
			
		||||
        .handle = handle,
 | 
			
		||||
        .completion_sem_id = osSemaphoreNew( IPC_RES_SEM_MAX_COUNT,
 | 
			
		||||
                                             IPC_RES_SEM_INITIAL_COUNT,
 | 
			
		||||
                                             &res_sem_attr
 | 
			
		||||
                                           )
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MBED_ASSERT(msg.completion_sem_id != NULL);
 | 
			
		||||
    ipc_queue_item_t queue_item = {
 | 
			
		||||
        .a = PSA_IPC_DISCONNECT,
 | 
			
		||||
        .b = (uint32_t)(&msg),
 | 
			
		||||
        .c = (uint32_t)handle
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ipc_queue_enqueue(prod_queue, queue_item);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(msg.completion_sem_id, osWaitForever);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreDelete(msg.completion_sem_id);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,106 @@
 | 
			
		|||
#include "cmsis_os2.h"
 | 
			
		||||
#include "psa_defs.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "ipc_queue.h"
 | 
			
		||||
#include "ipc_defs.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
 | 
			
		||||
static os_mutex_t queue_mutex_storage;
 | 
			
		||||
static os_semaphore_t full_sema;
 | 
			
		||||
static os_semaphore_t read_sema;
 | 
			
		||||
 | 
			
		||||
static const osMutexAttr_t queue_mutex_attr = {
 | 
			
		||||
    .name      = "Q_MUT",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem    = &queue_mutex_storage,
 | 
			
		||||
    .cb_size   = sizeof(queue_mutex_storage)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Full queue semaphore attributes for the consumer queue
 | 
			
		||||
static const osSemaphoreAttr_t full_sem_attr = {
 | 
			
		||||
    .name      = "Q_W_SEM",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem    = &full_sema,
 | 
			
		||||
    .cb_size   = sizeof(full_sema)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Read semaphore attributes for the consumer queue
 | 
			
		||||
static const osSemaphoreAttr_t read_sem_attr = {
 | 
			
		||||
    .name      = "Q_R_SEM",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem    = &read_sema,
 | 
			
		||||
    .cb_size   = sizeof(read_sema)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static ipc_producer_queue_t _prod_queue;
 | 
			
		||||
ipc_producer_queue_t *prod_queue = &_prod_queue;
 | 
			
		||||
static ipc_consumer_queue_t _cons_queue;
 | 
			
		||||
ipc_consumer_queue_t *cons_queue = &_cons_queue;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void on_new_item(void)
 | 
			
		||||
{
 | 
			
		||||
    spm_hal_mailbox_notify();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void on_vacancy(void)
 | 
			
		||||
{
 | 
			
		||||
    spm_hal_mailbox_notify();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void on_popped_item(ipc_queue_item_t item)
 | 
			
		||||
{
 | 
			
		||||
    osStatus_t os_status = osSemaphoreRelease((osSemaphoreId_t)(item.b));
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void spm_ipc_mailbox_init(void)
 | 
			
		||||
{
 | 
			
		||||
    // Initialization by data from shared memory
 | 
			
		||||
    // -----------------------------------------
 | 
			
		||||
 | 
			
		||||
    // This table is holding addresses of the platform's shared memory.
 | 
			
		||||
    addr_table_t *shared_addr_table_ptr = (addr_table_t *)PSA_SHARED_RAM_START;
 | 
			
		||||
    MBED_ASSERT(shared_addr_table_ptr->magic = ADDR_TABLE_MAGIC);
 | 
			
		||||
 | 
			
		||||
    ipc_base_queue_t *tx_queue_mem_ptr = (ipc_base_queue_t *)(shared_addr_table_ptr->tx_queue_ptr);
 | 
			
		||||
    MBED_ASSERT(tx_queue_mem_ptr->magic == IPC_QUEUE_BASE_MAGIC);
 | 
			
		||||
 | 
			
		||||
    ipc_base_queue_t *rx_queue_mem_ptr = (ipc_base_queue_t *)(shared_addr_table_ptr->rx_queue_ptr);
 | 
			
		||||
    MBED_ASSERT(rx_queue_mem_ptr->magic == IPC_QUEUE_BASE_MAGIC);
 | 
			
		||||
 | 
			
		||||
    osMutexId_t queue_mutex = osMutexNew(&queue_mutex_attr);
 | 
			
		||||
    MBED_ASSERT(queue_mutex != NULL);    // TODO: Panic instead
 | 
			
		||||
 | 
			
		||||
    osSemaphoreId_t full_queue_sem = osSemaphoreNew(IPC_QUEUE_SEM_MAX_COUNT, IPC_QUEUE_SEM_INITIAL_COUNT, &full_sem_attr);
 | 
			
		||||
    MBED_ASSERT(full_queue_sem != NULL);    // TODO: Panic instead
 | 
			
		||||
 | 
			
		||||
    osSemaphoreId_t queue_read_sem = osSemaphoreNew(IPC_QUEUE_SEM_MAX_COUNT, IPC_QUEUE_SEM_INITIAL_COUNT, &read_sem_attr);
 | 
			
		||||
    MBED_ASSERT(queue_read_sem != NULL);    // TODO: Panic instead
 | 
			
		||||
 | 
			
		||||
    ipc_producer_queue_init(prod_queue, tx_queue_mem_ptr, queue_mutex, full_queue_sem);
 | 
			
		||||
    ipc_consumer_queue_init(cons_queue, rx_queue_mem_ptr, queue_read_sem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void spm_mailbox_irq_callback(void)
 | 
			
		||||
{
 | 
			
		||||
    osStatus_t os_status = osSemaphoreRelease(prod_queue->full_queue_sem);
 | 
			
		||||
    MBED_ASSERT((osOK == os_status) || (osErrorResource == os_status));
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreRelease(cons_queue->read_sem);
 | 
			
		||||
    MBED_ASSERT((osOK == os_status) || (osErrorResource == os_status));
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
* Function Name: psa_spm_mailbox_dispatcher
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
void psa_spm_mailbox_dispatcher(void *arg)
 | 
			
		||||
{
 | 
			
		||||
    while (true) {
 | 
			
		||||
        ipc_queue_drain(cons_queue);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,167 @@
 | 
			
		|||
#include "psa_defs.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "spm_messages.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "ipc_queue.h"
 | 
			
		||||
#include "ipc_defs.h"
 | 
			
		||||
#include "spm_api.h"
 | 
			
		||||
 | 
			
		||||
static os_mutex_t queue_mutex_storage;
 | 
			
		||||
static os_semaphore_t full_sema;
 | 
			
		||||
static os_semaphore_t read_sema;
 | 
			
		||||
 | 
			
		||||
static const osMutexAttr_t queue_mutex_attr = {
 | 
			
		||||
    .name      = "Q_MUT",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem    = &queue_mutex_storage,
 | 
			
		||||
    .cb_size   = sizeof(queue_mutex_storage)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Full queue semaphore attributes for the consumer queue
 | 
			
		||||
static const osSemaphoreAttr_t full_sem_attr = {
 | 
			
		||||
    .name      = "Q_W_SEM",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem    = &full_sema,
 | 
			
		||||
    .cb_size   = sizeof(full_sema)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Read semaphore attributes for the consumer queue
 | 
			
		||||
static const osSemaphoreAttr_t read_sem_attr = {
 | 
			
		||||
    .name      = "Q_R_SEM",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem    = &read_sema,
 | 
			
		||||
    .cb_size   = sizeof(read_sema)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static ipc_producer_queue_t _prod_queue;
 | 
			
		||||
ipc_producer_queue_t *prod_queue = &_prod_queue;
 | 
			
		||||
static ipc_consumer_queue_t _cons_queue;
 | 
			
		||||
ipc_consumer_queue_t *cons_queue = &_cons_queue;
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    (sizeof(addr_table_t) + sizeof(ipc_base_queue_t) + sizeof(ipc_base_queue_t)) <= PSA_SHARED_RAM_SIZE,
 | 
			
		||||
    "shared memory size is too small!"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void spm_mailbox_irq_callback(void)
 | 
			
		||||
{
 | 
			
		||||
    osStatus_t os_status = osSemaphoreRelease(prod_queue->full_queue_sem);
 | 
			
		||||
    MBED_ASSERT((osOK == os_status) || (osErrorResource == os_status));
 | 
			
		||||
 | 
			
		||||
    os_status = osSemaphoreRelease(cons_queue->read_sem);
 | 
			
		||||
    MBED_ASSERT((osOK == os_status) || (osErrorResource == os_status));
 | 
			
		||||
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void on_new_item(void)
 | 
			
		||||
{
 | 
			
		||||
    spm_hal_mailbox_notify();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void on_vacancy(void)
 | 
			
		||||
{
 | 
			
		||||
    spm_hal_mailbox_notify();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void on_popped_item(ipc_queue_item_t item)
 | 
			
		||||
{
 | 
			
		||||
    // item.a hold the message type (connect / call /close)
 | 
			
		||||
    switch (item.a)
 | 
			
		||||
    {
 | 
			
		||||
        case PSA_IPC_CONNECT:
 | 
			
		||||
        {
 | 
			
		||||
            psa_connect_async(item.c, (spm_pending_connect_msg_t *)(item.b));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case PSA_IPC_CALL:
 | 
			
		||||
        {
 | 
			
		||||
            psa_call_async((psa_handle_t)(item.c), (spm_pending_call_msg_t *)(item.b));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case PSA_IPC_DISCONNECT:
 | 
			
		||||
        {
 | 
			
		||||
            psa_close_async((psa_handle_t)(item.c), (spm_pending_close_msg_t *)(item.b));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case PSA_IPC_VERSION:
 | 
			
		||||
        {
 | 
			
		||||
            spm_pending_version_msg_t *msg = (spm_pending_version_msg_t *)(item.b);
 | 
			
		||||
            if (!is_buffer_accessible(msg, sizeof(*msg), NULL)) {
 | 
			
		||||
                SPM_PANIC("message data is inaccessible\n");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            msg->rc = psa_version(item.c);
 | 
			
		||||
            nspe_done(msg->completion_sem_id);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
        {
 | 
			
		||||
            MBED_ASSERT(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void spm_ipc_mailbox_init(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t *shared_memory_start = (uint32_t *)PSA_SHARED_RAM_START;
 | 
			
		||||
 | 
			
		||||
    // This struct is set with initial values for the address table (addresses of CM0+ / CM4 shared memory)
 | 
			
		||||
    const addr_table_t shared_addr_table = {
 | 
			
		||||
        .magic        = ADDR_TABLE_MAGIC,
 | 
			
		||||
        .tx_queue_ptr = (uintptr_t)( shared_memory_start +
 | 
			
		||||
                                     (sizeof(addr_table_t) / sizeof(uint32_t))
 | 
			
		||||
                                   ),
 | 
			
		||||
        .rx_queue_ptr = (uintptr_t)( shared_memory_start +
 | 
			
		||||
                                     ((sizeof(addr_table_t) + sizeof(ipc_base_queue_t)) / sizeof(uint32_t))
 | 
			
		||||
                                   )
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This struct is set with initial values to be used for IPC queues initialization.
 | 
			
		||||
    // Same values are used to initial both tx and rx queues.
 | 
			
		||||
    const ipc_base_queue_t queue_mem = {
 | 
			
		||||
        .magic        = IPC_QUEUE_BASE_MAGIC,
 | 
			
		||||
        .read_idx     = 0,
 | 
			
		||||
        .write_idx    = 0,
 | 
			
		||||
        .data         = {{0, 0}}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ipc_base_queue_t *tx_queue_mem_ptr = (ipc_base_queue_t *)(shared_addr_table.tx_queue_ptr);
 | 
			
		||||
    ipc_base_queue_t *rx_queue_mem_ptr = (ipc_base_queue_t *)(shared_addr_table.rx_queue_ptr);
 | 
			
		||||
 | 
			
		||||
    // Copy initial queue values for tx & tx queues to the right location in the CM0+ / CM4 shared memory
 | 
			
		||||
    memcpy(tx_queue_mem_ptr, &queue_mem, sizeof(ipc_base_queue_t));
 | 
			
		||||
    memcpy(rx_queue_mem_ptr, &queue_mem, sizeof(ipc_base_queue_t));
 | 
			
		||||
 | 
			
		||||
    // Copy the content of shared_addr_table to the start address of CM0+ / CM4 shared memory.
 | 
			
		||||
    memcpy(shared_memory_start, &shared_addr_table, sizeof(shared_addr_table));
 | 
			
		||||
 | 
			
		||||
    // Init producer queue and consumer queue
 | 
			
		||||
 | 
			
		||||
    osMutexId_t queue_mutex = osMutexNew(&queue_mutex_attr);
 | 
			
		||||
    MBED_ASSERT(queue_mutex != NULL);    // TODO: Panic instead
 | 
			
		||||
 | 
			
		||||
    osSemaphoreId_t full_queue_sem = osSemaphoreNew(IPC_QUEUE_SEM_MAX_COUNT, IPC_QUEUE_SEM_INITIAL_COUNT, &full_sem_attr);
 | 
			
		||||
    MBED_ASSERT(full_queue_sem != NULL);    // TODO: Panic instead
 | 
			
		||||
 | 
			
		||||
    osSemaphoreId_t queue_read_sem = osSemaphoreNew(IPC_QUEUE_SEM_MAX_COUNT, IPC_QUEUE_SEM_INITIAL_COUNT, &read_sem_attr);
 | 
			
		||||
    MBED_ASSERT(queue_read_sem != NULL);    // TODO: Panic instead
 | 
			
		||||
 | 
			
		||||
    ipc_producer_queue_init(prod_queue, rx_queue_mem_ptr, queue_mutex, full_queue_sem);
 | 
			
		||||
    ipc_consumer_queue_init(cons_queue, tx_queue_mem_ptr, queue_read_sem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nspe_done(osSemaphoreId_t completion_sem_id)
 | 
			
		||||
{
 | 
			
		||||
    ipc_queue_item_t item_to_enqueue = {
 | 
			
		||||
        .b = (uint32_t)(completion_sem_id)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ipc_queue_enqueue(prod_queue, item_to_enqueue);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
/* Copyright (c) 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 __PSA_MBED_IPC_DEFS_H__
 | 
			
		||||
#define __PSA_MBED_IPC_DEFS_H__
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
// Includes
 | 
			
		||||
// --------
 | 
			
		||||
    
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
// Definitions
 | 
			
		||||
// -----------
 | 
			
		||||
 | 
			
		||||
#define IPC_RES_SEM_MAX_COUNT       (1UL) // Maximum number of available tokens for an IPC result semaphore
 | 
			
		||||
#define IPC_RES_SEM_INITIAL_COUNT   (0UL) // Initial number of available tokens for an IPC result semaphore
 | 
			
		||||
 | 
			
		||||
#define ADDR_TABLE_MAGIC            0xDEADBEEF
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
// NOTE: STRUCT SIZE MUST BE 4 BYTES ALIGNED !!
 | 
			
		||||
typedef struct addr_table_t {
 | 
			
		||||
    uint32_t  magic;
 | 
			
		||||
    uintptr_t tx_queue_ptr;
 | 
			
		||||
    uintptr_t rx_queue_ptr;
 | 
			
		||||
 | 
			
		||||
} addr_table_t;
 | 
			
		||||
MBED_STATIC_ASSERT((sizeof(addr_table_t) % sizeof(uint32_t) == 0), "addr_table_t: Struct size must be 4 bytes aligned!");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // __PSA_MBED_IPC_DEFS_H__
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
/* Copyright (c) 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Includes
 | 
			
		||||
// --------
 | 
			
		||||
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "ipc_queue.h"
 | 
			
		||||
#include "psa_defs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// API Implmentation
 | 
			
		||||
// -----------------
 | 
			
		||||
 | 
			
		||||
void ipc_producer_queue_init( ipc_producer_queue_t *queue,
 | 
			
		||||
                              ipc_base_queue_t     *base_queue_mem,
 | 
			
		||||
                              osMutexId_t           mutex,
 | 
			
		||||
                              osSemaphoreId_t       full_queue_sem
 | 
			
		||||
                            )
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(queue != NULL);
 | 
			
		||||
    MBED_ASSERT(base_queue_mem != NULL);
 | 
			
		||||
    MBED_ASSERT(base_queue_mem->magic == IPC_QUEUE_BASE_MAGIC);
 | 
			
		||||
    MBED_ASSERT(mutex != NULL);
 | 
			
		||||
    MBED_ASSERT(full_queue_sem != NULL);
 | 
			
		||||
 | 
			
		||||
    queue->magic          = IPC_QUEUE_PRODUCER_MAGIC;
 | 
			
		||||
    queue->read_idx       = &(base_queue_mem->read_idx);
 | 
			
		||||
    queue->write_idx      = &(base_queue_mem->write_idx);
 | 
			
		||||
    queue->data           = base_queue_mem->data;
 | 
			
		||||
    queue->mutex          = mutex;
 | 
			
		||||
    queue->full_queue_sem = full_queue_sem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ipc_consumer_queue_init( ipc_consumer_queue_t *queue,
 | 
			
		||||
                              ipc_base_queue_t     *base_queue_mem,
 | 
			
		||||
                              osSemaphoreId_t       read_sem
 | 
			
		||||
                            )
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(queue != NULL);
 | 
			
		||||
    MBED_ASSERT(base_queue_mem != NULL);
 | 
			
		||||
    MBED_ASSERT(base_queue_mem->magic == IPC_QUEUE_BASE_MAGIC);
 | 
			
		||||
    MBED_ASSERT(read_sem != NULL);
 | 
			
		||||
 | 
			
		||||
    queue->magic          = IPC_QUEUE_CONSUMER_MAGIC;
 | 
			
		||||
    queue->read_idx       = &(base_queue_mem->read_idx);
 | 
			
		||||
    queue->write_idx      = &(base_queue_mem->write_idx);
 | 
			
		||||
    queue->data           = base_queue_mem->data;
 | 
			
		||||
    queue->read_sem       = read_sem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ipc_queue_enqueue( ipc_producer_queue_t *queue,
 | 
			
		||||
                        ipc_queue_item_t      queue_item
 | 
			
		||||
                      )
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(queue != NULL);
 | 
			
		||||
    MBED_ASSERT(queue->magic == IPC_QUEUE_PRODUCER_MAGIC);
 | 
			
		||||
 | 
			
		||||
    osStatus_t os_status = osMutexAcquire(queue->mutex, osWaitForever);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
 | 
			
		||||
    // While queue is full, wait on full_queue_sem
 | 
			
		||||
    while (((*(queue->write_idx) + 1) % IPC_QUEUE_SLOTS) == *(queue->read_idx)) {
 | 
			
		||||
        os_status = osSemaphoreAcquire(queue->full_queue_sem, IPC_QUEUE_WAIT_ON_FULL_MS);
 | 
			
		||||
        MBED_ASSERT((osOK == os_status) || (osErrorTimeout == os_status));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Write data to queue (shallow copy)
 | 
			
		||||
    (queue->data)[*(queue->write_idx)] = queue_item;
 | 
			
		||||
    *(queue->write_idx) = ((*(queue->write_idx) + 1) % IPC_QUEUE_SLOTS);
 | 
			
		||||
 | 
			
		||||
    // If the queue was empty before the push, call the supplied CB function
 | 
			
		||||
    if (((*(queue->read_idx) + 1) % IPC_QUEUE_SLOTS) == *(queue->write_idx)) {
 | 
			
		||||
        on_new_item();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    os_status = osMutexRelease(queue->mutex);
 | 
			
		||||
    MBED_ASSERT(osOK == os_status);
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ipc_queue_drain( ipc_consumer_queue_t *queue)
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(queue != NULL);
 | 
			
		||||
    MBED_ASSERT(queue->magic == IPC_QUEUE_CONSUMER_MAGIC);
 | 
			
		||||
 | 
			
		||||
    // queue->read_sem is released when the queue becomes non empty
 | 
			
		||||
    osStatus_t os_status = osSemaphoreAcquire(queue->read_sem, IPC_QUEUE_WAIT_ON_EMPTY_MS);
 | 
			
		||||
    MBED_ASSERT((osOK == os_status) || (osErrorTimeout == os_status));
 | 
			
		||||
    PSA_UNUSED(os_status);
 | 
			
		||||
 | 
			
		||||
    // While queue is not empty, keep on popping queue items
 | 
			
		||||
    while (*(queue->read_idx) != *(queue->write_idx)) {
 | 
			
		||||
 | 
			
		||||
        // Pop an item from the queue (shallow copy)
 | 
			
		||||
        ipc_queue_item_t popped_item = (queue->data)[*(queue->read_idx)];
 | 
			
		||||
        *(queue->read_idx) = ((*(queue->read_idx) + 1) % IPC_QUEUE_SLOTS);
 | 
			
		||||
 | 
			
		||||
        // If queue was full before this pop, call the corresponding CB function
 | 
			
		||||
        if (((*(queue->write_idx) + 2) % IPC_QUEUE_SLOTS) == *(queue->read_idx)) {
 | 
			
		||||
            on_vacancy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        on_popped_item(popped_item);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
/* Copyright (c) 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 __PSA_MBED_IPC_QUEUE_H__
 | 
			
		||||
#define __PSA_MBED_IPC_QUEUE_H__
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Includes
 | 
			
		||||
// --------
 | 
			
		||||
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "cmsis_compiler.h"
 | 
			
		||||
#include "rtx_lib.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// IPC Queue Definitions
 | 
			
		||||
// ---------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef IPC_QUEUE_SLOTS
 | 
			
		||||
#define IPC_QUEUE_SLOTS             4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Maximum number of queue items equals (IPC_QUEUE_SLOTS - 1).
 | 
			
		||||
// Therefore we enforce a minimum of 2 IPC_QUEUE_SLOTS
 | 
			
		||||
#if IPC_QUEUE_SLOTS <= 1
 | 
			
		||||
#undef IPC_QUEUE_SLOTS
 | 
			
		||||
#define IPC_QUEUE_SLOTS             2
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define IPC_QUEUE_BASE_MAGIC        0xCAFEBABE
 | 
			
		||||
#define IPC_QUEUE_PRODUCER_MAGIC    0xDAC0FFEE
 | 
			
		||||
#define IPC_QUEUE_CONSUMER_MAGIC    0xFACEB00C
 | 
			
		||||
 | 
			
		||||
#define IPC_QUEUE_WAIT_ON_FULL_MS   500
 | 
			
		||||
#define IPC_QUEUE_WAIT_ON_EMPTY_MS  500
 | 
			
		||||
 | 
			
		||||
#define IPC_QUEUE_SEM_MAX_COUNT     (1UL)   // Maximum number of available tokens for an IPC Queue semaphore
 | 
			
		||||
#define IPC_QUEUE_SEM_INITIAL_COUNT (0UL)   // Initial number of available tokens for an IPC Queue semaphore
 | 
			
		||||
 | 
			
		||||
// NOTE: STRUCT SIZE MUST BE 4 BYTES ALIGNED !!
 | 
			
		||||
typedef __PACKED_STRUCT ipc_queue_item_t {
 | 
			
		||||
    uint32_t  a;
 | 
			
		||||
    uint32_t  b;
 | 
			
		||||
    uint32_t  c;
 | 
			
		||||
 | 
			
		||||
} __ALIGNED(4) ipc_queue_item_t;
 | 
			
		||||
MBED_STATIC_ASSERT((sizeof(ipc_queue_item_t) % sizeof(uint32_t) == 0), "ipc_queue_item_t: Struct size must be 4 bytes aligned!");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// NOTE: STRUCT SIZE MUST BE 4 BYTES ALIGNED !!
 | 
			
		||||
typedef __PACKED_STRUCT ipc_base_queue_t {
 | 
			
		||||
    uint32_t           magic;
 | 
			
		||||
    volatile uint32_t  read_idx;
 | 
			
		||||
    volatile uint32_t  write_idx;
 | 
			
		||||
    ipc_queue_item_t   data[IPC_QUEUE_SLOTS];
 | 
			
		||||
 | 
			
		||||
} __ALIGNED(4) ipc_base_queue_t;
 | 
			
		||||
MBED_STATIC_ASSERT((sizeof(ipc_base_queue_t) % sizeof(uint32_t) == 0), "ipc_base_queue_t: Struct size must be 4 bytes aligned!");
 | 
			
		||||
 | 
			
		||||
typedef struct ipc_producer_queue_t {
 | 
			
		||||
    uint32_t                    magic;
 | 
			
		||||
    volatile __PACKED uint32_t  *read_idx;
 | 
			
		||||
    volatile __PACKED uint32_t  *write_idx;
 | 
			
		||||
    __PACKED ipc_queue_item_t   *data;
 | 
			
		||||
    osMutexId_t                 mutex;
 | 
			
		||||
    osSemaphoreId_t             full_queue_sem;
 | 
			
		||||
 | 
			
		||||
} ipc_producer_queue_t;
 | 
			
		||||
 | 
			
		||||
typedef struct ipc_consumer_queue_t {
 | 
			
		||||
    uint32_t                    magic;
 | 
			
		||||
    volatile __PACKED uint32_t  *read_idx;
 | 
			
		||||
    volatile __PACKED uint32_t  *write_idx;
 | 
			
		||||
    __PACKED ipc_queue_item_t   *data;
 | 
			
		||||
    osSemaphoreId_t             read_sem;
 | 
			
		||||
 | 
			
		||||
} ipc_consumer_queue_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Event handling functions
 | 
			
		||||
// ------------------------
 | 
			
		||||
 | 
			
		||||
void on_new_item(void);
 | 
			
		||||
void on_vacancy(void);
 | 
			
		||||
void on_popped_item(ipc_queue_item_t item);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// IPC Queue API
 | 
			
		||||
// -------------
 | 
			
		||||
 | 
			
		||||
void ipc_producer_queue_init( ipc_producer_queue_t *queue,
 | 
			
		||||
                              ipc_base_queue_t     *base_queue_mem,
 | 
			
		||||
                              osMutexId_t           mutex,
 | 
			
		||||
                              osSemaphoreId_t       full_queue_sem
 | 
			
		||||
                            );
 | 
			
		||||
 | 
			
		||||
void ipc_consumer_queue_init( ipc_consumer_queue_t *queue,
 | 
			
		||||
                              ipc_base_queue_t     *base_queue_mem,
 | 
			
		||||
                              osSemaphoreId_t       read_sem
 | 
			
		||||
                            );
 | 
			
		||||
 | 
			
		||||
void ipc_queue_enqueue( ipc_producer_queue_t *queue,
 | 
			
		||||
                        ipc_queue_item_t      item_ptr
 | 
			
		||||
                      );
 | 
			
		||||
 | 
			
		||||
void ipc_queue_drain( ipc_consumer_queue_t *queue);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // __PSA_MBED_IPC_QUEUE_H__
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_CLIENT_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_NEG_CLIENT_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define NEG_CLIENT_PART1_ROT_SRV1 0x00001A06
 | 
			
		||||
#define NEG_CLIENT_PART1_ROT_SRV2 0x00001A07
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_CLIENT_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_neg_client_part1_partition.h"
 | 
			
		||||
#include "psa_neg_client_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t neg_client_part1_thread_stack[512] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t neg_client_part1_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t neg_client_part1_thread_attr = {
 | 
			
		||||
    .name = "neg_client_part1",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &neg_client_part1_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(neg_client_part1_thread_cb),
 | 
			
		||||
    .stack_mem = neg_client_part1_thread_stack,
 | 
			
		||||
    .stack_size = 512,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t neg_client_part1_rot_services[NEG_CLIENT_PART1_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = NEG_CLIENT_PART1_ROT_SRV1,
 | 
			
		||||
        .mask = NEG_CLIENT_PART1_ROT_SRV1_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = NEG_CLIENT_PART1_ROT_SRV2,
 | 
			
		||||
        .mask = NEG_CLIENT_PART1_ROT_SRV2_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_STRICT,
 | 
			
		||||
        .allow_nspe = false,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t neg_client_part1_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t neg_client_part1_mutex_attr = {
 | 
			
		||||
    .name = "neg_client_part1_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &neg_client_part1_mutex,
 | 
			
		||||
    .cb_size = sizeof(neg_client_part1_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void server_main1(void *ptr);
 | 
			
		||||
 | 
			
		||||
void neg_client_part1_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&neg_client_part1_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition neg_client_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < NEG_CLIENT_PART1_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        neg_client_part1_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = neg_client_part1_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(server_main1, NULL, &neg_client_part1_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition neg_client_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_CLIENT_PART1_PARTITION_H
 | 
			
		||||
#define PSA_NEG_CLIENT_PART1_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define NEG_CLIENT_PART1_ID 5
 | 
			
		||||
 | 
			
		||||
#define NEG_CLIENT_PART1_ROT_SRV_COUNT (2UL)
 | 
			
		||||
#define NEG_CLIENT_PART1_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* NEG_CLIENT_PART1 event flags */
 | 
			
		||||
#define NEG_CLIENT_PART1_RESERVED1_POS (1UL)
 | 
			
		||||
#define NEG_CLIENT_PART1_RESERVED1_MSK (1UL << NEG_CLIENT_PART1_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_CLIENT_PART1_RESERVED2_POS (2UL)
 | 
			
		||||
#define NEG_CLIENT_PART1_RESERVED2_MSK (1UL << NEG_CLIENT_PART1_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define NEG_CLIENT_PART1_ROT_SRV1_MSK_POS (4UL)
 | 
			
		||||
#define NEG_CLIENT_PART1_ROT_SRV1_MSK (1UL << NEG_CLIENT_PART1_ROT_SRV1_MSK_POS)
 | 
			
		||||
#define NEG_CLIENT_PART1_ROT_SRV2_MSK_POS (5UL)
 | 
			
		||||
#define NEG_CLIENT_PART1_ROT_SRV2_MSK (1UL << NEG_CLIENT_PART1_ROT_SRV2_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_CLIENT_PART1_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    NEG_CLIENT_PART1_ROT_SRV1_MSK | \
 | 
			
		||||
    NEG_CLIENT_PART1_ROT_SRV2_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define NEG_CLIENT_PART1_WAIT_ANY_MSK (\
 | 
			
		||||
    NEG_CLIENT_PART1_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_CLIENT_PART1_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,357 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !ENABLE_SPM
 | 
			
		||||
    #error [NOT_SUPPORTED] SPM is not supported on this platform
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "rtos.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "psa_neg_client_part1_ifs.h"
 | 
			
		||||
#include "neg_tests.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MINOR_VER               5
 | 
			
		||||
#define CLIENT_RSP_BUF_SIZE     128
 | 
			
		||||
#define OFFSET_POS              1
 | 
			
		||||
#define INVALID_SID             (NEG_CLIENT_PART1_ROT_SRV1 + 30)
 | 
			
		||||
#define INVALID_MINOR           (MINOR_VER + 10)
 | 
			
		||||
#define INVALID_TX_LEN          (PSA_MAX_IOVEC + 1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
Semaphore test_sem(0);
 | 
			
		||||
bool error_thrown = false;
 | 
			
		||||
uint8_t response_buf[CLIENT_RSP_BUF_SIZE];
 | 
			
		||||
extern "C" void spm_reboot(void);
 | 
			
		||||
 | 
			
		||||
void error(const char* format, ...)
 | 
			
		||||
{
 | 
			
		||||
    error_thrown = true;
 | 
			
		||||
    osStatus status = test_sem.release();
 | 
			
		||||
    MBED_ASSERT(status == osOK);
 | 
			
		||||
    PSA_UNUSED(status);
 | 
			
		||||
    while(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------- Functions ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
static psa_handle_t negative_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 negative_client_ipc_tests_call( psa_handle_t handle,
 | 
			
		||||
                                   psa_invec_t *iovec_temp,
 | 
			
		||||
                                   size_t tx_len,
 | 
			
		||||
                                   size_t rx_len
 | 
			
		||||
                                 )
 | 
			
		||||
{
 | 
			
		||||
    error_t status = PSA_SUCCESS;
 | 
			
		||||
    memset(response_buf, 0, sizeof(response_buf));
 | 
			
		||||
    psa_outvec_t resp = { response_buf, rx_len };
 | 
			
		||||
 | 
			
		||||
    status = psa_call(handle, iovec_temp, tx_len, &resp, 1);
 | 
			
		||||
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void negative_client_ipc_tests_close(psa_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    psa_close(handle);
 | 
			
		||||
 | 
			
		||||
    // Wait for psa_close to finish on server side
 | 
			
		||||
    osDelay(50);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client call with an invalid SID
 | 
			
		||||
void client_connect_invalid_sid()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( INVALID_SID,
 | 
			
		||||
                 MINOR_VER
 | 
			
		||||
               );
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_connect_invalid_sid negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client connect version policy is RELAXED and minor version is bigger than the minimum version
 | 
			
		||||
void client_connect_invalid_pol_ver_RELAXED()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( NEG_CLIENT_PART1_ROT_SRV1,           //NEG_CLIENT_PART1_ROT_SRV1 should have RELAXED policy
 | 
			
		||||
                 INVALID_MINOR
 | 
			
		||||
               );
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_connect_invalid_pol_ver_RELAXED negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client connect version policy is STRICT and requeted version is higher than the minimum version
 | 
			
		||||
void client_connect_invalid_high_pol_ver_STRICT()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( NEG_CLIENT_PART1_ROT_SRV2,           //NEG_CLIENT_PART1_ROT_SRV2 should have STRICT policy
 | 
			
		||||
                 INVALID_MINOR
 | 
			
		||||
               );
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_connect_invalid_high_pol_ver_STRICT negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client connect version policy is STRICT and requeted version equales the minimum version
 | 
			
		||||
void client_connect_invalid_equal_pol_ver_STRICT()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( NEG_CLIENT_PART1_ROT_SRV2,           //NEG_CLIENT_PART1_ROT_SRV2 should have STRICT policy
 | 
			
		||||
                 MINOR_VER
 | 
			
		||||
               );
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_connect_invalid_equal_pol_ver_STRICT negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client call num of iovecs (tx_len + rx_len) is bigger than max value allowed
 | 
			
		||||
void client_call_invalid_iovecs_len()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = 0;
 | 
			
		||||
 | 
			
		||||
    handle = negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
 | 
			
		||||
    psa_invec_t invec_temp[PSA_MAX_IOVEC] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    psa_outvec_t outvec_temp[1] = {
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // PSA_MAX_IOVEC invecs + 1 outvec
 | 
			
		||||
    psa_call(handle, invec_temp, PSA_MAX_IOVEC, outvec_temp, 1);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_invalid_iovecs_len negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client call return buffer (rx_buff) is NULL and return buffer len is not 0
 | 
			
		||||
void client_call_rx_buff_null_rx_len_not_zero()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = 0;
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
    psa_invec_t iovec_temp[3] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    handle = negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    psa_call(handle, iovec_temp, 3, NULL, 1);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_rx_buff_null_rx_len_not_zero negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client call iovecs pointer is NULL and num of iovecs is not 0
 | 
			
		||||
void client_call_iovecs_null_tx_len_not_zero()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = 0;
 | 
			
		||||
 | 
			
		||||
    handle = negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
    memset(response_buf, 0, CLIENT_RSP_BUF_SIZE);
 | 
			
		||||
    psa_outvec_t resp = { response_buf, CLIENT_RSP_BUF_SIZE };
 | 
			
		||||
 | 
			
		||||
    psa_call(handle, NULL, 2, &resp, 1);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_iovecs_null_tx_len_not_zero negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client call iovec base pointer is NULL and iovec size is not 0
 | 
			
		||||
void client_call_iovec_base_null_len_not_zero()
 | 
			
		||||
{
 | 
			
		||||
    negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {NULL, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    negative_client_ipc_tests_call(PSA_NULL_HANDLE, iovec_temp, PSA_MAX_IOVEC - 1, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_iovec_base_null_len_not_zero negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client call handle does not exist on the platform
 | 
			
		||||
void client_call_invalid_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = 0, invalid_handle = 0;
 | 
			
		||||
 | 
			
		||||
    handle = negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
    invalid_handle = handle + 10;
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    negative_client_ipc_tests_call(invalid_handle, iovec_temp, PSA_MAX_IOVEC - 1, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_invalid_handle negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client call handle is null (PSA_NULL_HANDLE)
 | 
			
		||||
void client_call_handle_is_null()
 | 
			
		||||
{
 | 
			
		||||
    negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    negative_client_ipc_tests_call(PSA_NULL_HANDLE, iovec_temp, PSA_MAX_IOVEC - 1, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_handle_is_null negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing client close handle does not exist on the platform
 | 
			
		||||
void client_close_invalid_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = 0, invalid_handle = 0;
 | 
			
		||||
 | 
			
		||||
    handle = negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
    invalid_handle = handle + 10;
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    negative_client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, 0);
 | 
			
		||||
 | 
			
		||||
    negative_client_ipc_tests_close(invalid_handle);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_close_invalid_handle negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void client_call_buffer_wrap_around()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = 0;
 | 
			
		||||
    psa_invec_t iovec_temp = { (void *)0x80000000, UINT32_MAX };
 | 
			
		||||
 | 
			
		||||
    handle = negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
    psa_call(handle, &iovec_temp, 1, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_buffer_wrap_around negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void client_connect_not_allowed_from_nspe()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(NEG_CLIENT_PART1_ROT_SRV2, 5);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_connect_not_allowed_from_nspe negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void client_call_excess_outvec()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = 0;
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
    psa_outvec_t iovec_temp[PSA_MAX_IOVEC + 1] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    handle = negative_client_ipc_tests_connect(NEG_CLIENT_PART1_ROT_SRV1, MINOR_VER);
 | 
			
		||||
    psa_call(handle, NULL, 0, iovec_temp, PSA_MAX_IOVEC + 1);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("client_call_excess_outvec negative test failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_NEG_TEST(client_connect_invalid_sid)
 | 
			
		||||
PSA_NEG_TEST(client_connect_invalid_pol_ver_RELAXED)
 | 
			
		||||
PSA_NEG_TEST(client_connect_invalid_high_pol_ver_STRICT)
 | 
			
		||||
PSA_NEG_TEST(client_connect_invalid_equal_pol_ver_STRICT)
 | 
			
		||||
PSA_NEG_TEST(client_call_invalid_iovecs_len)
 | 
			
		||||
PSA_NEG_TEST(client_call_rx_buff_null_rx_len_not_zero)
 | 
			
		||||
PSA_NEG_TEST(client_call_iovecs_null_tx_len_not_zero)
 | 
			
		||||
PSA_NEG_TEST(client_call_iovec_base_null_len_not_zero)
 | 
			
		||||
PSA_NEG_TEST(client_call_invalid_handle)
 | 
			
		||||
PSA_NEG_TEST(client_call_handle_is_null)
 | 
			
		||||
PSA_NEG_TEST(client_close_invalid_handle)
 | 
			
		||||
PSA_NEG_TEST(client_call_buffer_wrap_around)
 | 
			
		||||
PSA_NEG_TEST(client_connect_not_allowed_from_nspe)
 | 
			
		||||
PSA_NEG_TEST(client_call_excess_outvec)
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
 | 
			
		||||
{
 | 
			
		||||
    spm_reboot();
 | 
			
		||||
    error_thrown = false;
 | 
			
		||||
    return greentea_case_teardown_handler(source, passed, failed, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SPM_UTEST_CASE(desc, test) Case(desc, PSA_NEG_TEST_NAME(test), spm_case_teardown)
 | 
			
		||||
 | 
			
		||||
// Test cases
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    SPM_UTEST_CASE("Testing client connect invalid sid", client_connect_invalid_sid),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client connect version policy RELAXED invalid minor", client_connect_invalid_pol_ver_RELAXED),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client connect version policy STRICT high minor", client_connect_invalid_high_pol_ver_STRICT),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client connect version policy STRICT equal minor", client_connect_invalid_equal_pol_ver_STRICT),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call invalid num of iovecs (tx_len + rx_len)", client_call_invalid_iovecs_len),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call rx_buff is NULL rx_len is not 0", client_call_rx_buff_null_rx_len_not_zero),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call iovecs is NULL tx_len is not 0", client_call_iovecs_null_tx_len_not_zero),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call iovec base NULL while iovec len not 0", client_call_iovec_base_null_len_not_zero),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call handle does not exist", client_call_invalid_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call handle is PSA_NULL_HANDLE", client_call_handle_is_null),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client close handle does not exist", client_close_invalid_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call with buffer wrap-around", client_call_buffer_wrap_around),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client connect to non-NSPE ROT_SRV", client_connect_not_allowed_from_nspe),
 | 
			
		||||
    SPM_UTEST_CASE("Testing client call with too much outvec's", client_call_excess_outvec)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
#ifndef NO_GREENTEA
 | 
			
		||||
    GREENTEA_SETUP(60, "default_auto");
 | 
			
		||||
#endif
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(spm_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define PSA_NEG_TEST_NAME(test_name) psa_neg_test_ ## test_name
 | 
			
		||||
 | 
			
		||||
#define PSA_NEG_TEST(test_name)       \
 | 
			
		||||
void PSA_NEG_TEST_NAME(test_name)()   \
 | 
			
		||||
{                                     \
 | 
			
		||||
    osStatus status = osOK;           \
 | 
			
		||||
    Thread T1;                        \
 | 
			
		||||
                                      \
 | 
			
		||||
    status = T1.start(test_name);     \
 | 
			
		||||
    TEST_ASSERT_TRUE(status == osOK); \
 | 
			
		||||
    test_sem.wait(osWaitForever);     \
 | 
			
		||||
    TEST_ASSERT_TRUE(error_thrown);   \
 | 
			
		||||
                                      \
 | 
			
		||||
    status = T1.terminate();          \
 | 
			
		||||
    TEST_ASSERT_TRUE(status == osOK); \
 | 
			
		||||
}                                     \
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "NEG_CLIENT_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000005",
 | 
			
		||||
  "entry_point": "server_main1",
 | 
			
		||||
  "stack_size": "0x200",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "NEG_CLIENT_PART1_ROT_SRV1",
 | 
			
		||||
      "identifier": "0x00001A06",
 | 
			
		||||
      "signal": "NEG_CLIENT_PART1_ROT_SRV1_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "NEG_CLIENT_PART1_ROT_SRV2",
 | 
			
		||||
      "identifier": "0x00001A07",
 | 
			
		||||
      "signal": "NEG_CLIENT_PART1_ROT_SRV2_MSK",
 | 
			
		||||
      "non_secure_clients": false,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "STRICT"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "server1.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_neg_client_part1_partition.h"
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
spm_partition_t g_partitions[1] = {
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = NEG_CLIENT_PART1_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = NEG_CLIENT_PART1_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = NEG_CLIENT_PART1_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = NEG_CLIENT_PART1_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Check all the defined memory regions for overlapping. */
 | 
			
		||||
 | 
			
		||||
/* A list of all the memory regions. */
 | 
			
		||||
const mem_region_t *mem_regions = NULL;
 | 
			
		||||
 | 
			
		||||
const uint32_t mem_region_count = 0;
 | 
			
		||||
 | 
			
		||||
// forward declaration of partition initializers
 | 
			
		||||
void neg_client_part1_init(spm_partition_t *partition);
 | 
			
		||||
 
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partitions) {
 | 
			
		||||
        SPM_PANIC("partitions is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    neg_client_part1_init(&(g_partitions[0]));
 | 
			
		||||
 
 | 
			
		||||
    *partitions = g_partitions;
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_neg_client_part1_partition.h"
 | 
			
		||||
 | 
			
		||||
#define msg_buff_SIZE 128
 | 
			
		||||
char msg_buff[msg_buff_SIZE];
 | 
			
		||||
 | 
			
		||||
void server_main1(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
    memset(msg_buff, 0, sizeof(msg_buff));
 | 
			
		||||
    while (true) {
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
        if (signals & NEG_CLIENT_PART1_ROT_SRV1_MSK) {
 | 
			
		||||
            psa_msg_t msg = {0};
 | 
			
		||||
            psa_get(NEG_CLIENT_PART1_ROT_SRV1_MSK, &msg);
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CONNECT:
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                    break;
 | 
			
		||||
                case PSA_IPC_CALL: {
 | 
			
		||||
                    memset(msg_buff, 0, msg_buff_SIZE);
 | 
			
		||||
                    uint32_t bytes_read = 0;
 | 
			
		||||
                    for (size_t i = 0; i < PSA_MAX_IOVEC; i++) {
 | 
			
		||||
                        bytes_read = psa_read(msg.handle, i, msg_buff + bytes_read, msg.in_size[i]);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (msg.out_size[0] > 0) {
 | 
			
		||||
                        psa_write(msg.handle, 0, msg_buff, bytes_read);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                default:
 | 
			
		||||
                    SPM_PANIC("Unknown message type");
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,67 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
 | 
			
		||||
extern spm_db_t g_spm;
 | 
			
		||||
extern psa_handle_item_t g_channels_handle_storage[];
 | 
			
		||||
extern psa_handle_item_t g_messages_handle_storage[];
 | 
			
		||||
extern spm_ipc_channel_t g_channel_data[];
 | 
			
		||||
extern spm_active_msg_t g_active_messages_data[];
 | 
			
		||||
 | 
			
		||||
void psa_spm_init(void);
 | 
			
		||||
 | 
			
		||||
void spm_reboot(void)
 | 
			
		||||
{
 | 
			
		||||
    osStatus_t status;
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < g_spm.partition_count; ++i) {
 | 
			
		||||
        status = osThreadTerminate(g_spm.partitions[i].thread_id);
 | 
			
		||||
        MBED_ASSERT(status == osOK);
 | 
			
		||||
        status = osMutexDelete(g_spm.partitions[i].mutex);
 | 
			
		||||
        MBED_ASSERT(status == osOK);
 | 
			
		||||
 | 
			
		||||
        for (uint32_t j = 0; j < g_spm.partitions[i].rot_services_count; ++j) {
 | 
			
		||||
            g_spm.partitions[i].rot_services[j].partition = NULL;
 | 
			
		||||
            g_spm.partitions[i].rot_services[j].queue.head = NULL;
 | 
			
		||||
            g_spm.partitions[i].rot_services[j].queue.tail = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        g_spm.partitions[i].rot_services = NULL;
 | 
			
		||||
        g_spm.partitions[i].mutex = NULL;
 | 
			
		||||
        g_spm.partitions[i].thread_id = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = osMemoryPoolDelete(g_spm.channel_mem_pool);
 | 
			
		||||
    MBED_ASSERT(status == osOK);
 | 
			
		||||
    status = osMemoryPoolDelete(g_spm.active_messages_mem_pool);
 | 
			
		||||
    MBED_ASSERT(status == osOK);
 | 
			
		||||
    memset(g_channels_handle_storage, 0, (sizeof(psa_handle_item_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS));
 | 
			
		||||
    memset(g_messages_handle_storage, 0, (sizeof(psa_handle_item_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES));
 | 
			
		||||
    memset(g_channel_data, 0, (sizeof(spm_ipc_channel_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS));
 | 
			
		||||
    memset(g_active_messages_data, 0, (sizeof(spm_active_msg_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES));
 | 
			
		||||
    memset(&g_spm, 0, sizeof(g_spm));
 | 
			
		||||
 | 
			
		||||
    g_spm.channels_handle_mgr.handle_generator = PSA_HANDLE_MGR_INVALID_HANDLE;
 | 
			
		||||
    g_spm.channels_handle_mgr.pool_size        = MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS;
 | 
			
		||||
    g_spm.channels_handle_mgr.handles_pool     = g_channels_handle_storage;
 | 
			
		||||
    g_spm.messages_handle_mgr.handle_generator = PSA_HANDLE_MGR_INVALID_HANDLE;
 | 
			
		||||
    g_spm.messages_handle_mgr.pool_size        = MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES;
 | 
			
		||||
    g_spm.messages_handle_mgr.handles_pool     = g_messages_handle_storage;
 | 
			
		||||
 | 
			
		||||
    psa_spm_init();
 | 
			
		||||
    PSA_UNUSED(status);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_DUAL_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_NEG_DUAL_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define PART1_CALL_NON_EXISTS_EXTERN_SID 0x00001A08
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_DUAL_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,97 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_neg_dual_part1_partition.h"
 | 
			
		||||
#include "psa_neg_dual_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t neg_dual_part1_thread_stack[512] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t neg_dual_part1_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t neg_dual_part1_thread_attr = {
 | 
			
		||||
    .name = "neg_dual_part1",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &neg_dual_part1_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(neg_dual_part1_thread_cb),
 | 
			
		||||
    .stack_mem = neg_dual_part1_thread_stack,
 | 
			
		||||
    .stack_size = 512,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t neg_dual_part1_rot_services[NEG_DUAL_PART1_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART1_CALL_NON_EXISTS_EXTERN_SID,
 | 
			
		||||
        .mask = PART1_CALL_NON_EXISTS_EXTERN_SID_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t neg_dual_part1_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t neg_dual_part1_mutex_attr = {
 | 
			
		||||
    .name = "neg_dual_part1_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &neg_dual_part1_mutex,
 | 
			
		||||
    .cb_size = sizeof(neg_dual_part1_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void server_main1(void *ptr);
 | 
			
		||||
 | 
			
		||||
void neg_dual_part1_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&neg_dual_part1_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition neg_dual_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < NEG_DUAL_PART1_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        neg_dual_part1_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = neg_dual_part1_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(server_main1, NULL, &neg_dual_part1_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition neg_dual_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_DUAL_PART1_PARTITION_H
 | 
			
		||||
#define PSA_NEG_DUAL_PART1_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART1_ID 6
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART1_ROT_SRV_COUNT (1UL)
 | 
			
		||||
#define NEG_DUAL_PART1_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* NEG_DUAL_PART1 event flags */
 | 
			
		||||
#define NEG_DUAL_PART1_RESERVED1_POS (1UL)
 | 
			
		||||
#define NEG_DUAL_PART1_RESERVED1_MSK (1UL << NEG_DUAL_PART1_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART1_RESERVED2_POS (2UL)
 | 
			
		||||
#define NEG_DUAL_PART1_RESERVED2_MSK (1UL << NEG_DUAL_PART1_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define PART1_CALL_NON_EXISTS_EXTERN_SID_MSK_POS (4UL)
 | 
			
		||||
#define PART1_CALL_NON_EXISTS_EXTERN_SID_MSK (1UL << PART1_CALL_NON_EXISTS_EXTERN_SID_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART1_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    PART1_CALL_NON_EXISTS_EXTERN_SID_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define NEG_DUAL_PART1_WAIT_ANY_MSK (\
 | 
			
		||||
    NEG_DUAL_PART1_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_DUAL_PART1_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_DUAL_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_NEG_DUAL_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define DUMMY 0x00001A09
 | 
			
		||||
#define PART2_CALL_INSIDE_PARTITION 0x00001A0A
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_DUAL_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,115 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_neg_dual_part2_partition.h"
 | 
			
		||||
#include "psa_neg_dual_part2_ifs.h"
 | 
			
		||||
#include "psa_neg_dual_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t neg_dual_part2_thread_stack[512] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t neg_dual_part2_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t neg_dual_part2_thread_attr = {
 | 
			
		||||
    .name = "neg_dual_part2",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &neg_dual_part2_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(neg_dual_part2_thread_cb),
 | 
			
		||||
    .stack_mem = neg_dual_part2_thread_stack,
 | 
			
		||||
    .stack_size = 512,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t neg_dual_part2_rot_services[NEG_DUAL_PART2_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = DUMMY,
 | 
			
		||||
        .mask = DUMMY_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = false,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_CALL_INSIDE_PARTITION,
 | 
			
		||||
        .mask = PART2_CALL_INSIDE_PARTITION_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* External SIDs used by NEG_DUAL_PART2 */
 | 
			
		||||
const uint32_t neg_dual_part2_external_sids[1] =
 | 
			
		||||
{
 | 
			
		||||
    PART1_CALL_NON_EXISTS_EXTERN_SID,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t neg_dual_part2_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t neg_dual_part2_mutex_attr = {
 | 
			
		||||
    .name = "neg_dual_part2_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &neg_dual_part2_mutex,
 | 
			
		||||
    .cb_size = sizeof(neg_dual_part2_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void server_main2(void *ptr);
 | 
			
		||||
 | 
			
		||||
void neg_dual_part2_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&neg_dual_part2_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition neg_dual_part2!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < NEG_DUAL_PART2_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        neg_dual_part2_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = neg_dual_part2_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(server_main2, NULL, &neg_dual_part2_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition neg_dual_part2!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_DUAL_PART2_PARTITION_H
 | 
			
		||||
#define PSA_NEG_DUAL_PART2_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART2_ID 7
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART2_ROT_SRV_COUNT (2UL)
 | 
			
		||||
#define NEG_DUAL_PART2_EXT_ROT_SRV_COUNT (1UL)
 | 
			
		||||
 | 
			
		||||
/* NEG_DUAL_PART2 event flags */
 | 
			
		||||
#define NEG_DUAL_PART2_RESERVED1_POS (1UL)
 | 
			
		||||
#define NEG_DUAL_PART2_RESERVED1_MSK (1UL << NEG_DUAL_PART2_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART2_RESERVED2_POS (2UL)
 | 
			
		||||
#define NEG_DUAL_PART2_RESERVED2_MSK (1UL << NEG_DUAL_PART2_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define DUMMY_MSK_POS (4UL)
 | 
			
		||||
#define DUMMY_MSK (1UL << DUMMY_MSK_POS)
 | 
			
		||||
#define PART2_CALL_INSIDE_PARTITION_MSK_POS (5UL)
 | 
			
		||||
#define PART2_CALL_INSIDE_PARTITION_MSK (1UL << PART2_CALL_INSIDE_PARTITION_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_DUAL_PART2_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    DUMMY_MSK | \
 | 
			
		||||
    PART2_CALL_INSIDE_PARTITION_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define NEG_DUAL_PART2_WAIT_ANY_MSK (\
 | 
			
		||||
    NEG_DUAL_PART2_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_DUAL_PART2_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,101 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !ENABLE_SPM
 | 
			
		||||
    #error [NOT_SUPPORTED] SPM is not supported on this platform
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "rtos.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "psa_neg_dual_part1_ifs.h"
 | 
			
		||||
#include "psa_neg_dual_part2_ifs.h"
 | 
			
		||||
#include "neg_tests.h"
 | 
			
		||||
 | 
			
		||||
#define MINOR_VER 5
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
Semaphore test_sem(0);
 | 
			
		||||
bool error_thrown = false;
 | 
			
		||||
extern "C" void spm_reboot(void);
 | 
			
		||||
 | 
			
		||||
void error(const char* format, ...)
 | 
			
		||||
{
 | 
			
		||||
    error_thrown = true;
 | 
			
		||||
    osStatus status = test_sem.release();
 | 
			
		||||
    MBED_ASSERT(status == osOK);
 | 
			
		||||
    PSA_UNUSED(status);
 | 
			
		||||
    while(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------- Functions ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
void server_call_sid_without_extern_sid()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = psa_connect(PART1_CALL_NON_EXISTS_EXTERN_SID, MINOR_VER);
 | 
			
		||||
    TEST_ASSERT_TRUE(handle > 0);
 | 
			
		||||
 | 
			
		||||
    psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
    TEST_FAIL_MESSAGE("psa_call from SP to SID not listed as extern_sids didn't fail");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_call_sid_in_same_partition()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = psa_connect(PART2_CALL_INSIDE_PARTITION, MINOR_VER);
 | 
			
		||||
    TEST_ASSERT_TRUE(handle > 0);
 | 
			
		||||
 | 
			
		||||
    psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
    TEST_FAIL_MESSAGE("psa_call from SP to SID within same SP didn't fail");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PSA_NEG_TEST(server_call_sid_without_extern_sid)
 | 
			
		||||
PSA_NEG_TEST(server_call_sid_in_same_partition)
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
 | 
			
		||||
{
 | 
			
		||||
    spm_reboot();
 | 
			
		||||
    error_thrown = false;
 | 
			
		||||
    return greentea_case_teardown_handler(source, passed, failed, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SPM_UTEST_CASE(desc, test) Case(desc, PSA_NEG_TEST_NAME(test), spm_case_teardown)
 | 
			
		||||
 | 
			
		||||
// Test cases
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    SPM_UTEST_CASE("Testing server calling sid without extern sid", server_call_sid_without_extern_sid),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server calling sid within the same partition", server_call_sid_in_same_partition)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
#ifndef NO_GREENTEA
 | 
			
		||||
    GREENTEA_SETUP(60, "default_auto");
 | 
			
		||||
#endif
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(spm_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define PSA_NEG_TEST_NAME(test_name) psa_neg_test_ ## test_name
 | 
			
		||||
 | 
			
		||||
#define PSA_NEG_TEST(test_name)       \
 | 
			
		||||
void PSA_NEG_TEST_NAME(test_name)()   \
 | 
			
		||||
{                                     \
 | 
			
		||||
    osStatus status = osOK;           \
 | 
			
		||||
    Thread T1;                        \
 | 
			
		||||
                                      \
 | 
			
		||||
    status = T1.start(test_name);     \
 | 
			
		||||
    TEST_ASSERT_TRUE(status == osOK); \
 | 
			
		||||
    test_sem.wait(osWaitForever);     \
 | 
			
		||||
    TEST_ASSERT_TRUE(error_thrown);   \
 | 
			
		||||
                                      \
 | 
			
		||||
    status = T1.terminate();          \
 | 
			
		||||
    TEST_ASSERT_TRUE(status == osOK); \
 | 
			
		||||
}                                     \
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "NEG_DUAL_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000006",
 | 
			
		||||
  "entry_point": "server_main1",
 | 
			
		||||
  "stack_size": "0x200",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "PART1_CALL_NON_EXISTS_EXTERN_SID",
 | 
			
		||||
      "identifier": "0x00001A08",
 | 
			
		||||
      "signal": "PART1_CALL_NON_EXISTS_EXTERN_SID_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "server1.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "NEG_DUAL_PART2",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000007",
 | 
			
		||||
  "entry_point": "server_main2",
 | 
			
		||||
  "stack_size": "0x200",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "DUMMY",
 | 
			
		||||
      "identifier": "0x00001A09",
 | 
			
		||||
      "signal": "DUMMY_MSK",
 | 
			
		||||
      "non_secure_clients": false,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_CALL_INSIDE_PARTITION",
 | 
			
		||||
      "identifier": "0x00001A0A",
 | 
			
		||||
      "signal": "PART2_CALL_INSIDE_PARTITION_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "extern_sids": [
 | 
			
		||||
    "PART1_CALL_NON_EXISTS_EXTERN_SID"
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "server2.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "handles_manager.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "psa_neg_dual_part1_partition.h"
 | 
			
		||||
#include "psa_neg_dual_part2_partition.h"
 | 
			
		||||
 
 | 
			
		||||
extern const uint32_t neg_dual_part2_external_sids[1];
 | 
			
		||||
 
 | 
			
		||||
spm_partition_t g_partitions[2] = {
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = NEG_DUAL_PART1_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = NEG_DUAL_PART1_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = NEG_DUAL_PART1_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = NULL,
 | 
			
		||||
        .extern_sids_count = NEG_DUAL_PART1_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .partition_id = NEG_DUAL_PART2_ID,
 | 
			
		||||
        .thread_id = 0,
 | 
			
		||||
        .flags_rot_srv = NEG_DUAL_PART2_WAIT_ANY_SID_MSK,
 | 
			
		||||
        .flags_interrupts = 0,
 | 
			
		||||
        .rot_services = NULL,
 | 
			
		||||
        .rot_services_count = NEG_DUAL_PART2_ROT_SRV_COUNT,
 | 
			
		||||
        .extern_sids = neg_dual_part2_external_sids,
 | 
			
		||||
        .extern_sids_count = NEG_DUAL_PART2_EXT_ROT_SRV_COUNT,
 | 
			
		||||
        .irq_mapper = NULL,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Check all the defined memory regions for overlapping. */
 | 
			
		||||
 | 
			
		||||
/* A list of all the memory regions. */
 | 
			
		||||
const mem_region_t *mem_regions = NULL;
 | 
			
		||||
 | 
			
		||||
const uint32_t mem_region_count = 0;
 | 
			
		||||
 | 
			
		||||
// forward declaration of partition initializers
 | 
			
		||||
void neg_dual_part1_init(spm_partition_t *partition);
 | 
			
		||||
void neg_dual_part2_init(spm_partition_t *partition);
 | 
			
		||||
 
 | 
			
		||||
uint32_t init_partitions(spm_partition_t **partitions)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partitions) {
 | 
			
		||||
        SPM_PANIC("partitions is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    neg_dual_part1_init(&(g_partitions[0]));
 | 
			
		||||
    neg_dual_part2_init(&(g_partitions[1]));
 | 
			
		||||
 
 | 
			
		||||
    *partitions = g_partitions;
 | 
			
		||||
    return 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_neg_dual_part1_partition.h"
 | 
			
		||||
#include "psa_neg_dual_part2_ifs.h"
 | 
			
		||||
 | 
			
		||||
#define MINOR_VER 5
 | 
			
		||||
 | 
			
		||||
void server_main1(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    psa_msg_t msg = {0};
 | 
			
		||||
    uint32_t signals = 0;
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
        if (signals & PART1_CALL_NON_EXISTS_EXTERN_SID_MSK) {
 | 
			
		||||
            psa_get(PART1_CALL_NON_EXISTS_EXTERN_SID_MSK, &msg);
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CONNECT: {
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case PSA_IPC_CALL: {
 | 
			
		||||
                    psa_connect(PART2_CALL_INSIDE_PARTITION, MINOR_VER);
 | 
			
		||||
                    TEST_FAIL_MESSAGE("server_call_sid_without_extern_sid negative test failed");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                default: {
 | 
			
		||||
                    TEST_FAIL_MESSAGE("server_call_sid_without_extern_sid msg type failure");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            SPM_PANIC("Unknown signal (0x%08x)", signals);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,67 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_server.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "psa_neg_dual_part2_partition.h"
 | 
			
		||||
#include "psa_neg_dual_part2_ifs.h"
 | 
			
		||||
 | 
			
		||||
#define MINOR_VER 5
 | 
			
		||||
 | 
			
		||||
void server_main2(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t  signals   = 0;
 | 
			
		||||
    psa_msg_t msg       = {0};
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
        signals = psa_wait_any(PSA_BLOCK);
 | 
			
		||||
        if (signals & DUMMY_MSK) {
 | 
			
		||||
            psa_get(DUMMY_MSK, &msg);
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CALL:
 | 
			
		||||
                case PSA_IPC_CONNECT:
 | 
			
		||||
                case PSA_IPC_DISCONNECT:
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    SPM_PANIC("Invalid msg type");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (signals & PART2_CALL_INSIDE_PARTITION_MSK) {
 | 
			
		||||
            psa_get(PART2_CALL_INSIDE_PARTITION_MSK, &msg);
 | 
			
		||||
            switch (msg.type) {
 | 
			
		||||
                case PSA_IPC_CONNECT: {
 | 
			
		||||
                    psa_reply(msg.handle, PSA_SUCCESS);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case PSA_IPC_CALL: {
 | 
			
		||||
                    psa_connect(DUMMY, MINOR_VER);
 | 
			
		||||
                    TEST_FAIL_MESSAGE("server_call_sid_in_same_partition negative test failed");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                default: {
 | 
			
		||||
                    TEST_FAIL_MESSAGE("server_call_sid_in_same_partition msg type failure");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            SPM_PANIC("Unknown signal (0x%08x)", signals);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,67 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
 | 
			
		||||
extern spm_db_t g_spm;
 | 
			
		||||
extern psa_handle_item_t g_channels_handle_storage[];
 | 
			
		||||
extern psa_handle_item_t g_messages_handle_storage[];
 | 
			
		||||
extern spm_ipc_channel_t g_channel_data[];
 | 
			
		||||
extern spm_active_msg_t g_active_messages_data[];
 | 
			
		||||
 | 
			
		||||
void psa_spm_init(void);
 | 
			
		||||
 | 
			
		||||
void spm_reboot(void)
 | 
			
		||||
{
 | 
			
		||||
    osStatus_t status;
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < g_spm.partition_count; ++i) {
 | 
			
		||||
        status = osThreadTerminate(g_spm.partitions[i].thread_id);
 | 
			
		||||
        MBED_ASSERT(status == osOK);
 | 
			
		||||
        status = osMutexDelete(g_spm.partitions[i].mutex);
 | 
			
		||||
        MBED_ASSERT(status == osOK);
 | 
			
		||||
 | 
			
		||||
        for (uint32_t j = 0; j < g_spm.partitions[i].rot_services_count; ++j) {
 | 
			
		||||
            g_spm.partitions[i].rot_services[j].partition = NULL;
 | 
			
		||||
            g_spm.partitions[i].rot_services[j].queue.head = NULL;
 | 
			
		||||
            g_spm.partitions[i].rot_services[j].queue.tail = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        g_spm.partitions[i].rot_services = NULL;
 | 
			
		||||
        g_spm.partitions[i].mutex = NULL;
 | 
			
		||||
        g_spm.partitions[i].thread_id = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = osMemoryPoolDelete(g_spm.channel_mem_pool);
 | 
			
		||||
    MBED_ASSERT(status == osOK);
 | 
			
		||||
    status = osMemoryPoolDelete(g_spm.active_messages_mem_pool);
 | 
			
		||||
    MBED_ASSERT(status == osOK);
 | 
			
		||||
    memset(g_channels_handle_storage, 0, (sizeof(psa_handle_item_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS));
 | 
			
		||||
    memset(g_messages_handle_storage, 0, (sizeof(psa_handle_item_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES));
 | 
			
		||||
    memset(g_channel_data, 0, (sizeof(spm_ipc_channel_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS));
 | 
			
		||||
    memset(g_active_messages_data, 0, (sizeof(spm_active_msg_t) * MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES));
 | 
			
		||||
    memset(&g_spm, 0, sizeof(g_spm));
 | 
			
		||||
 | 
			
		||||
    g_spm.channels_handle_mgr.handle_generator = PSA_HANDLE_MGR_INVALID_HANDLE;
 | 
			
		||||
    g_spm.channels_handle_mgr.pool_size        = MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS;
 | 
			
		||||
    g_spm.channels_handle_mgr.handles_pool     = g_channels_handle_storage;
 | 
			
		||||
    g_spm.messages_handle_mgr.handle_generator = PSA_HANDLE_MGR_INVALID_HANDLE;
 | 
			
		||||
    g_spm.messages_handle_mgr.pool_size        = MBED_CONF_SPM_IPC_MAX_NUM_OF_MESSAGES;
 | 
			
		||||
    g_spm.messages_handle_mgr.handles_pool     = g_messages_handle_storage;
 | 
			
		||||
 | 
			
		||||
    psa_spm_init();
 | 
			
		||||
    PSA_UNUSED(status);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_SERVER_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_NEG_SERVER_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define PART1_REPLY_INVALID_RETVAL_CONNECT 0x00001A25
 | 
			
		||||
#define PART1_REPLY_INVALID_RETVAL_CALL 0x00001A26
 | 
			
		||||
#define PART1_CLEAR_NO_DOORBELL 0x00001A27
 | 
			
		||||
#define PART1_WRITE_OUTVEC_IX_SIZE_0 0x00001A28
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_SERVER_PART1_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,133 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_neg_server_part1_partition.h"
 | 
			
		||||
#include "psa_neg_server_part1_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t neg_server_part1_thread_stack[512] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t neg_server_part1_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t neg_server_part1_thread_attr = {
 | 
			
		||||
    .name = "neg_server_part1",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &neg_server_part1_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(neg_server_part1_thread_cb),
 | 
			
		||||
    .stack_mem = neg_server_part1_thread_stack,
 | 
			
		||||
    .stack_size = 512,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t neg_server_part1_rot_services[NEG_SERVER_PART1_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART1_REPLY_INVALID_RETVAL_CONNECT,
 | 
			
		||||
        .mask = PART1_REPLY_INVALID_RETVAL_CONNECT_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART1_REPLY_INVALID_RETVAL_CALL,
 | 
			
		||||
        .mask = PART1_REPLY_INVALID_RETVAL_CALL_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART1_CLEAR_NO_DOORBELL,
 | 
			
		||||
        .mask = PART1_CLEAR_NO_DOORBELL_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART1_WRITE_OUTVEC_IX_SIZE_0,
 | 
			
		||||
        .mask = PART1_WRITE_OUTVEC_IX_SIZE_0_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t neg_server_part1_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t neg_server_part1_mutex_attr = {
 | 
			
		||||
    .name = "neg_server_part1_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &neg_server_part1_mutex,
 | 
			
		||||
    .cb_size = sizeof(neg_server_part1_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void server_main1(void *ptr);
 | 
			
		||||
 | 
			
		||||
void neg_server_part1_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&neg_server_part1_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition neg_server_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < NEG_SERVER_PART1_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        neg_server_part1_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = neg_server_part1_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(server_main1, NULL, &neg_server_part1_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition neg_server_part1!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_SERVER_PART1_PARTITION_H
 | 
			
		||||
#define PSA_NEG_SERVER_PART1_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART1_ID 7
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART1_ROT_SRV_COUNT (4UL)
 | 
			
		||||
#define NEG_SERVER_PART1_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* NEG_SERVER_PART1 event flags */
 | 
			
		||||
#define NEG_SERVER_PART1_RESERVED1_POS (1UL)
 | 
			
		||||
#define NEG_SERVER_PART1_RESERVED1_MSK (1UL << NEG_SERVER_PART1_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART1_RESERVED2_POS (2UL)
 | 
			
		||||
#define NEG_SERVER_PART1_RESERVED2_MSK (1UL << NEG_SERVER_PART1_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define PART1_REPLY_INVALID_RETVAL_CONNECT_MSK_POS (4UL)
 | 
			
		||||
#define PART1_REPLY_INVALID_RETVAL_CONNECT_MSK (1UL << PART1_REPLY_INVALID_RETVAL_CONNECT_MSK_POS)
 | 
			
		||||
#define PART1_REPLY_INVALID_RETVAL_CALL_MSK_POS (5UL)
 | 
			
		||||
#define PART1_REPLY_INVALID_RETVAL_CALL_MSK (1UL << PART1_REPLY_INVALID_RETVAL_CALL_MSK_POS)
 | 
			
		||||
#define PART1_CLEAR_NO_DOORBELL_MSK_POS (6UL)
 | 
			
		||||
#define PART1_CLEAR_NO_DOORBELL_MSK (1UL << PART1_CLEAR_NO_DOORBELL_MSK_POS)
 | 
			
		||||
#define PART1_WRITE_OUTVEC_IX_SIZE_0_MSK_POS (7UL)
 | 
			
		||||
#define PART1_WRITE_OUTVEC_IX_SIZE_0_MSK (1UL << PART1_WRITE_OUTVEC_IX_SIZE_0_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART1_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    PART1_REPLY_INVALID_RETVAL_CONNECT_MSK | \
 | 
			
		||||
    PART1_REPLY_INVALID_RETVAL_CALL_MSK | \
 | 
			
		||||
    PART1_CLEAR_NO_DOORBELL_MSK | \
 | 
			
		||||
    PART1_WRITE_OUTVEC_IX_SIZE_0_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define NEG_SERVER_PART1_WAIT_ANY_MSK (\
 | 
			
		||||
    NEG_SERVER_PART1_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_SERVER_PART1_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_SERVER_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
#define PSA_NEG_SERVER_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
 | 
			
		||||
#define PART2_INT_MASK 0x00001A0B
 | 
			
		||||
#define PART2_GET_MSG_NULL 0x00001A0C
 | 
			
		||||
#define PART2_GET_SIGNUM_MULTIPLE_BIT 0x00001A0D
 | 
			
		||||
#define PART2_GET_SIGNUM_NOT_SUBSET 0x00001A0E
 | 
			
		||||
#define PART2_GET_SIGNUM_NOT_ACTIVE 0x00001A0F
 | 
			
		||||
#define PART2_GET_SIGNUM_TWICE 0x00001A10
 | 
			
		||||
#define PART2_READ_INVALID_HANDLE 0x00001A11
 | 
			
		||||
#define PART2_READ_NULL_HANDLE 0x00001A12
 | 
			
		||||
#define PART2_READ_TX_SIZE_ZERO 0x00001A13
 | 
			
		||||
#define PART2_WRITE_BUFFER_NULL 0x00001A14
 | 
			
		||||
#define PART2_WRITE_RX_BUFF_NULL 0x00001A15
 | 
			
		||||
#define PART2_WRITE_INVALID_HANDLE 0x00001A16
 | 
			
		||||
#define PART2_WRITE_NULL_HANDLE 0x00001A17
 | 
			
		||||
#define PART2_REPLY_INVALID_HANDLE 0x00001A18
 | 
			
		||||
#define PART2_REPLY_NULL_HANDLE 0x00001A19
 | 
			
		||||
#define PART2_NOTIFY_PART_ID_INVALID 0x00001A1A
 | 
			
		||||
#define PART2_IDENTITY_INVALID_HANDLE 0x00001A1B
 | 
			
		||||
#define PART2_IDENTITY_NULL_HANDLE 0x00001A1C
 | 
			
		||||
#define PART2_SET_RHANDLE_INVALID_HANDLE 0x00001A1D
 | 
			
		||||
#define PART2_SET_RHANDLE_NULL_HANDLE 0x00001A1E
 | 
			
		||||
#define PART2_READ_WRAPAROUND 0x00001A1F
 | 
			
		||||
#define PART2_READ_EXCESS_INVEC 0x00001A20
 | 
			
		||||
#define PART2_WRITE_WRAPAROUND 0x00001A21
 | 
			
		||||
#define PART2_WRITE_EXCESS_OUTVEC 0x00001A22
 | 
			
		||||
#define PART2_WRITE_SIZE_OVERFLOW 0x00001A23
 | 
			
		||||
#define PART2_READ_NULL_BUFFER 0x00001A24
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_SERVER_PART2_PARTITION_ROT_SERVICES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,397 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
 | 
			
		||||
#include "rtx_os.h"
 | 
			
		||||
#include "spm_panic.h"
 | 
			
		||||
#include "spm_internal.h"
 | 
			
		||||
#include "psa_neg_server_part2_partition.h"
 | 
			
		||||
#include "psa_neg_server_part2_ifs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Threads stacks */
 | 
			
		||||
MBED_ALIGN(8) uint8_t neg_server_part2_thread_stack[640] = {0};
 | 
			
		||||
 | 
			
		||||
/* Threads control blocks */
 | 
			
		||||
osRtxThread_t neg_server_part2_thread_cb = {0};
 | 
			
		||||
 | 
			
		||||
/* Thread attributes - for thread initialization */
 | 
			
		||||
osThreadAttr_t neg_server_part2_thread_attr = {
 | 
			
		||||
    .name = "neg_server_part2",
 | 
			
		||||
    .attr_bits = 0,
 | 
			
		||||
    .cb_mem = &neg_server_part2_thread_cb,
 | 
			
		||||
    .cb_size = sizeof(neg_server_part2_thread_cb),
 | 
			
		||||
    .stack_mem = neg_server_part2_thread_stack,
 | 
			
		||||
    .stack_size = 640,
 | 
			
		||||
    .priority = osPriorityNormal,
 | 
			
		||||
    .tz_module = 0,
 | 
			
		||||
    .reserved = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
spm_rot_service_t neg_server_part2_rot_services[NEG_SERVER_PART2_ROT_SRV_COUNT] = {
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_INT_MASK,
 | 
			
		||||
        .mask = PART2_INT_MASK_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_GET_MSG_NULL,
 | 
			
		||||
        .mask = PART2_GET_MSG_NULL_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_GET_SIGNUM_MULTIPLE_BIT,
 | 
			
		||||
        .mask = PART2_GET_SIGNUM_MULTIPLE_BIT_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_GET_SIGNUM_NOT_SUBSET,
 | 
			
		||||
        .mask = PART2_GET_SIGNUM_NOT_SUBSET_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_GET_SIGNUM_NOT_ACTIVE,
 | 
			
		||||
        .mask = PART2_GET_SIGNUM_NOT_ACTIVE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_GET_SIGNUM_TWICE,
 | 
			
		||||
        .mask = PART2_GET_SIGNUM_TWICE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_READ_INVALID_HANDLE,
 | 
			
		||||
        .mask = PART2_READ_INVALID_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_READ_NULL_HANDLE,
 | 
			
		||||
        .mask = PART2_READ_NULL_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_READ_TX_SIZE_ZERO,
 | 
			
		||||
        .mask = PART2_READ_TX_SIZE_ZERO_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_WRITE_BUFFER_NULL,
 | 
			
		||||
        .mask = PART2_WRITE_BUFFER_NULL_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_WRITE_RX_BUFF_NULL,
 | 
			
		||||
        .mask = PART2_WRITE_RX_BUFF_NULL_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_WRITE_INVALID_HANDLE,
 | 
			
		||||
        .mask = PART2_WRITE_INVALID_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_WRITE_NULL_HANDLE,
 | 
			
		||||
        .mask = PART2_WRITE_NULL_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_REPLY_INVALID_HANDLE,
 | 
			
		||||
        .mask = PART2_REPLY_INVALID_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_REPLY_NULL_HANDLE,
 | 
			
		||||
        .mask = PART2_REPLY_NULL_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_NOTIFY_PART_ID_INVALID,
 | 
			
		||||
        .mask = PART2_NOTIFY_PART_ID_INVALID_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_IDENTITY_INVALID_HANDLE,
 | 
			
		||||
        .mask = PART2_IDENTITY_INVALID_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_IDENTITY_NULL_HANDLE,
 | 
			
		||||
        .mask = PART2_IDENTITY_NULL_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_SET_RHANDLE_INVALID_HANDLE,
 | 
			
		||||
        .mask = PART2_SET_RHANDLE_INVALID_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_SET_RHANDLE_NULL_HANDLE,
 | 
			
		||||
        .mask = PART2_SET_RHANDLE_NULL_HANDLE_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_READ_WRAPAROUND,
 | 
			
		||||
        .mask = PART2_READ_WRAPAROUND_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_READ_EXCESS_INVEC,
 | 
			
		||||
        .mask = PART2_READ_EXCESS_INVEC_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_WRITE_WRAPAROUND,
 | 
			
		||||
        .mask = PART2_WRITE_WRAPAROUND_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_WRITE_EXCESS_OUTVEC,
 | 
			
		||||
        .mask = PART2_WRITE_EXCESS_OUTVEC_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_WRITE_SIZE_OVERFLOW,
 | 
			
		||||
        .mask = PART2_WRITE_SIZE_OVERFLOW_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .sid = PART2_READ_NULL_BUFFER,
 | 
			
		||||
        .mask = PART2_READ_NULL_BUFFER_MSK,
 | 
			
		||||
        .partition = NULL,
 | 
			
		||||
        .min_version = 5,
 | 
			
		||||
        .min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
 | 
			
		||||
        .allow_nspe = true,
 | 
			
		||||
        .queue = {
 | 
			
		||||
            .head = NULL,
 | 
			
		||||
            .tail = NULL
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static osRtxMutex_t neg_server_part2_mutex = {0};
 | 
			
		||||
static const osMutexAttr_t neg_server_part2_mutex_attr = {
 | 
			
		||||
    .name = "neg_server_part2_mutex",
 | 
			
		||||
    .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
 | 
			
		||||
    .cb_mem = &neg_server_part2_mutex,
 | 
			
		||||
    .cb_size = sizeof(neg_server_part2_mutex),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void server_main2(void *ptr);
 | 
			
		||||
 | 
			
		||||
void neg_server_part2_init(spm_partition_t *partition)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == partition) {
 | 
			
		||||
        SPM_PANIC("partition is NULL!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition->mutex = osMutexNew(&neg_server_part2_mutex_attr);
 | 
			
		||||
    if (NULL == partition->mutex) {
 | 
			
		||||
        SPM_PANIC("Failed to create mutex for secure partition neg_server_part2!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < NEG_SERVER_PART2_ROT_SRV_COUNT; ++i) {
 | 
			
		||||
        neg_server_part2_rot_services[i].partition = partition;
 | 
			
		||||
    }
 | 
			
		||||
    partition->rot_services = neg_server_part2_rot_services;
 | 
			
		||||
 | 
			
		||||
    partition->thread_id = osThreadNew(server_main2, NULL, &neg_server_part2_thread_attr);
 | 
			
		||||
    if (NULL == partition->thread_id) {
 | 
			
		||||
        SPM_PANIC("Failed to create start main thread of partition neg_server_part2!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,127 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***********************************************************************************************************************
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 * THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
 | 
			
		||||
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
			
		||||
 **********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef PSA_NEG_SERVER_PART2_PARTITION_H
 | 
			
		||||
#define PSA_NEG_SERVER_PART2_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART2_ID 8
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART2_ROT_SRV_COUNT (26UL)
 | 
			
		||||
#define NEG_SERVER_PART2_EXT_ROT_SRV_COUNT (0UL)
 | 
			
		||||
 | 
			
		||||
/* NEG_SERVER_PART2 event flags */
 | 
			
		||||
#define NEG_SERVER_PART2_RESERVED1_POS (1UL)
 | 
			
		||||
#define NEG_SERVER_PART2_RESERVED1_MSK (1UL << NEG_SERVER_PART2_RESERVED1_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART2_RESERVED2_POS (2UL)
 | 
			
		||||
#define NEG_SERVER_PART2_RESERVED2_MSK (1UL << NEG_SERVER_PART2_RESERVED2_POS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define PART2_INT_MASK_MSK_POS (4UL)
 | 
			
		||||
#define PART2_INT_MASK_MSK (1UL << PART2_INT_MASK_MSK_POS)
 | 
			
		||||
#define PART2_GET_MSG_NULL_MSK_POS (5UL)
 | 
			
		||||
#define PART2_GET_MSG_NULL_MSK (1UL << PART2_GET_MSG_NULL_MSK_POS)
 | 
			
		||||
#define PART2_GET_SIGNUM_MULTIPLE_BIT_MSK_POS (6UL)
 | 
			
		||||
#define PART2_GET_SIGNUM_MULTIPLE_BIT_MSK (1UL << PART2_GET_SIGNUM_MULTIPLE_BIT_MSK_POS)
 | 
			
		||||
#define PART2_GET_SIGNUM_NOT_SUBSET_MSK_POS (7UL)
 | 
			
		||||
#define PART2_GET_SIGNUM_NOT_SUBSET_MSK (1UL << PART2_GET_SIGNUM_NOT_SUBSET_MSK_POS)
 | 
			
		||||
#define PART2_GET_SIGNUM_NOT_ACTIVE_MSK_POS (8UL)
 | 
			
		||||
#define PART2_GET_SIGNUM_NOT_ACTIVE_MSK (1UL << PART2_GET_SIGNUM_NOT_ACTIVE_MSK_POS)
 | 
			
		||||
#define PART2_GET_SIGNUM_TWICE_MSK_POS (9UL)
 | 
			
		||||
#define PART2_GET_SIGNUM_TWICE_MSK (1UL << PART2_GET_SIGNUM_TWICE_MSK_POS)
 | 
			
		||||
#define PART2_READ_INVALID_HANDLE_MSK_POS (10UL)
 | 
			
		||||
#define PART2_READ_INVALID_HANDLE_MSK (1UL << PART2_READ_INVALID_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_READ_NULL_HANDLE_MSK_POS (11UL)
 | 
			
		||||
#define PART2_READ_NULL_HANDLE_MSK (1UL << PART2_READ_NULL_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_READ_TX_SIZE_ZERO_MSK_POS (12UL)
 | 
			
		||||
#define PART2_READ_TX_SIZE_ZERO_MSK (1UL << PART2_READ_TX_SIZE_ZERO_MSK_POS)
 | 
			
		||||
#define PART2_WRITE_BUFFER_NULL_MSK_POS (13UL)
 | 
			
		||||
#define PART2_WRITE_BUFFER_NULL_MSK (1UL << PART2_WRITE_BUFFER_NULL_MSK_POS)
 | 
			
		||||
#define PART2_WRITE_RX_BUFF_NULL_MSK_POS (14UL)
 | 
			
		||||
#define PART2_WRITE_RX_BUFF_NULL_MSK (1UL << PART2_WRITE_RX_BUFF_NULL_MSK_POS)
 | 
			
		||||
#define PART2_WRITE_INVALID_HANDLE_MSK_POS (15UL)
 | 
			
		||||
#define PART2_WRITE_INVALID_HANDLE_MSK (1UL << PART2_WRITE_INVALID_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_WRITE_NULL_HANDLE_MSK_POS (16UL)
 | 
			
		||||
#define PART2_WRITE_NULL_HANDLE_MSK (1UL << PART2_WRITE_NULL_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_REPLY_INVALID_HANDLE_MSK_POS (17UL)
 | 
			
		||||
#define PART2_REPLY_INVALID_HANDLE_MSK (1UL << PART2_REPLY_INVALID_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_REPLY_NULL_HANDLE_MSK_POS (18UL)
 | 
			
		||||
#define PART2_REPLY_NULL_HANDLE_MSK (1UL << PART2_REPLY_NULL_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_NOTIFY_PART_ID_INVALID_MSK_POS (19UL)
 | 
			
		||||
#define PART2_NOTIFY_PART_ID_INVALID_MSK (1UL << PART2_NOTIFY_PART_ID_INVALID_MSK_POS)
 | 
			
		||||
#define PART2_IDENTITY_INVALID_HANDLE_MSK_POS (20UL)
 | 
			
		||||
#define PART2_IDENTITY_INVALID_HANDLE_MSK (1UL << PART2_IDENTITY_INVALID_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_IDENTITY_NULL_HANDLE_MSK_POS (21UL)
 | 
			
		||||
#define PART2_IDENTITY_NULL_HANDLE_MSK (1UL << PART2_IDENTITY_NULL_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_SET_RHANDLE_INVALID_HANDLE_MSK_POS (22UL)
 | 
			
		||||
#define PART2_SET_RHANDLE_INVALID_HANDLE_MSK (1UL << PART2_SET_RHANDLE_INVALID_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_SET_RHANDLE_NULL_HANDLE_MSK_POS (23UL)
 | 
			
		||||
#define PART2_SET_RHANDLE_NULL_HANDLE_MSK (1UL << PART2_SET_RHANDLE_NULL_HANDLE_MSK_POS)
 | 
			
		||||
#define PART2_READ_WRAPAROUND_MSK_POS (24UL)
 | 
			
		||||
#define PART2_READ_WRAPAROUND_MSK (1UL << PART2_READ_WRAPAROUND_MSK_POS)
 | 
			
		||||
#define PART2_READ_EXCESS_INVEC_MSK_POS (25UL)
 | 
			
		||||
#define PART2_READ_EXCESS_INVEC_MSK (1UL << PART2_READ_EXCESS_INVEC_MSK_POS)
 | 
			
		||||
#define PART2_WRITE_WRAPAROUND_MSK_POS (26UL)
 | 
			
		||||
#define PART2_WRITE_WRAPAROUND_MSK (1UL << PART2_WRITE_WRAPAROUND_MSK_POS)
 | 
			
		||||
#define PART2_WRITE_EXCESS_OUTVEC_MSK_POS (27UL)
 | 
			
		||||
#define PART2_WRITE_EXCESS_OUTVEC_MSK (1UL << PART2_WRITE_EXCESS_OUTVEC_MSK_POS)
 | 
			
		||||
#define PART2_WRITE_SIZE_OVERFLOW_MSK_POS (28UL)
 | 
			
		||||
#define PART2_WRITE_SIZE_OVERFLOW_MSK (1UL << PART2_WRITE_SIZE_OVERFLOW_MSK_POS)
 | 
			
		||||
#define PART2_READ_NULL_BUFFER_MSK_POS (29UL)
 | 
			
		||||
#define PART2_READ_NULL_BUFFER_MSK (1UL << PART2_READ_NULL_BUFFER_MSK_POS)
 | 
			
		||||
 | 
			
		||||
#define NEG_SERVER_PART2_WAIT_ANY_SID_MSK (\
 | 
			
		||||
    PART2_INT_MASK_MSK | \
 | 
			
		||||
    PART2_GET_MSG_NULL_MSK | \
 | 
			
		||||
    PART2_GET_SIGNUM_MULTIPLE_BIT_MSK | \
 | 
			
		||||
    PART2_GET_SIGNUM_NOT_SUBSET_MSK | \
 | 
			
		||||
    PART2_GET_SIGNUM_NOT_ACTIVE_MSK | \
 | 
			
		||||
    PART2_GET_SIGNUM_TWICE_MSK | \
 | 
			
		||||
    PART2_READ_INVALID_HANDLE_MSK | \
 | 
			
		||||
    PART2_READ_NULL_HANDLE_MSK | \
 | 
			
		||||
    PART2_READ_TX_SIZE_ZERO_MSK | \
 | 
			
		||||
    PART2_WRITE_BUFFER_NULL_MSK | \
 | 
			
		||||
    PART2_WRITE_RX_BUFF_NULL_MSK | \
 | 
			
		||||
    PART2_WRITE_INVALID_HANDLE_MSK | \
 | 
			
		||||
    PART2_WRITE_NULL_HANDLE_MSK | \
 | 
			
		||||
    PART2_REPLY_INVALID_HANDLE_MSK | \
 | 
			
		||||
    PART2_REPLY_NULL_HANDLE_MSK | \
 | 
			
		||||
    PART2_NOTIFY_PART_ID_INVALID_MSK | \
 | 
			
		||||
    PART2_IDENTITY_INVALID_HANDLE_MSK | \
 | 
			
		||||
    PART2_IDENTITY_NULL_HANDLE_MSK | \
 | 
			
		||||
    PART2_SET_RHANDLE_INVALID_HANDLE_MSK | \
 | 
			
		||||
    PART2_SET_RHANDLE_NULL_HANDLE_MSK | \
 | 
			
		||||
    PART2_READ_WRAPAROUND_MSK | \
 | 
			
		||||
    PART2_READ_EXCESS_INVEC_MSK | \
 | 
			
		||||
    PART2_WRITE_WRAPAROUND_MSK | \
 | 
			
		||||
    PART2_WRITE_EXCESS_OUTVEC_MSK | \
 | 
			
		||||
    PART2_WRITE_SIZE_OVERFLOW_MSK | \
 | 
			
		||||
    PART2_READ_NULL_BUFFER_MSK)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#define NEG_SERVER_PART2_WAIT_ANY_MSK (\
 | 
			
		||||
    NEG_SERVER_PART2_WAIT_ANY_SID_MSK) | \
 | 
			
		||||
    PSA_DOORBELL)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PSA_NEG_SERVER_PART2_PARTITION_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,460 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !ENABLE_SPM
 | 
			
		||||
    #error [NOT_SUPPORTED] SPM is not supported on this platform
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "rtos.h"
 | 
			
		||||
#include "spm_client.h"
 | 
			
		||||
#include "psa_neg_server_part1_ifs.h"
 | 
			
		||||
#include "psa_neg_server_part2_ifs.h"
 | 
			
		||||
#include "neg_tests.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MINOR_VER               5
 | 
			
		||||
#define CLIENT_RSP_BUF_SIZE     128
 | 
			
		||||
#define OFFSET_POS              1
 | 
			
		||||
#define INVALID_SID             (PART1_ROT_SRV1 + 30)
 | 
			
		||||
#define INVALID_MINOR           (MINOR_VER + 10)
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
Semaphore test_sem(0);
 | 
			
		||||
bool error_thrown = false;
 | 
			
		||||
uint8_t response_buf[CLIENT_RSP_BUF_SIZE];
 | 
			
		||||
extern "C" void spm_reboot(void);
 | 
			
		||||
 | 
			
		||||
void error(const char* format, ...)
 | 
			
		||||
{
 | 
			
		||||
    error_thrown = true;
 | 
			
		||||
    osStatus status = test_sem.release();
 | 
			
		||||
    MBED_ASSERT(status == osOK);
 | 
			
		||||
    PSA_UNUSED(status);
 | 
			
		||||
    while(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------- Functions ----------------------------------- */
 | 
			
		||||
 | 
			
		||||
static psa_handle_t negative_server_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 negative_server_ipc_tests_call( psa_handle_t handle,
 | 
			
		||||
                                   psa_invec_t *invec,
 | 
			
		||||
                                   size_t tx_len,
 | 
			
		||||
                                   psa_outvec_t *outvec,
 | 
			
		||||
                                   size_t rx_len
 | 
			
		||||
                                 )
 | 
			
		||||
{
 | 
			
		||||
    error_t status = PSA_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    status = psa_call(handle, invec, tx_len, outvec, rx_len);
 | 
			
		||||
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server interrupt mask contains only a subset of interrupt signal mask
 | 
			
		||||
void server_interrupt_mask_invalid()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( PART2_INT_MASK, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_interrupt_mask_invalid negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server get with msg NULL
 | 
			
		||||
void server_get_msg_null()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( PART2_GET_MSG_NULL, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_get_msg_null negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server get signum have more than one bit ON
 | 
			
		||||
void server_get_multiple_bit_signum()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( PART2_GET_SIGNUM_MULTIPLE_BIT, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_get_multiple_bit_signum negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server get signum is not a subset of current partition flags
 | 
			
		||||
void server_get_signum_not_subset()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( PART2_GET_SIGNUM_NOT_SUBSET, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_get_signum_not_subset negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server get signum flag is not active
 | 
			
		||||
void server_get_signum_not_active()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( PART2_GET_SIGNUM_NOT_ACTIVE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_get_signum_not_active negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server get signum flag twice
 | 
			
		||||
void server_get_signum_twice()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect( PART2_GET_SIGNUM_TWICE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_get_signum_twice negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server read handle does not exist on the platform
 | 
			
		||||
void server_read_invalid_handle()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t data = 52;
 | 
			
		||||
    psa_invec_t data_vec = {&data, sizeof(data)};
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_READ_INVALID_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    negative_server_ipc_tests_call(handle, &data_vec, 1, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_read_invalid_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server read handle is null (PSA_NULL_HANDLE)
 | 
			
		||||
void server_read_null_handle()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t data = 52;
 | 
			
		||||
    psa_invec_t data_vec = {&data, sizeof(data)};
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_READ_NULL_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    negative_server_ipc_tests_call(handle, &data_vec, 1, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_read_null_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server read buffer is null
 | 
			
		||||
void server_read_null_buffer()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t data = 52;
 | 
			
		||||
    psa_invec_t data_vec = {&data, sizeof(data)};
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_READ_NULL_BUFFER, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    negative_server_ipc_tests_call(handle, &data_vec, 1, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_read_null_buffer negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server write buffer is null
 | 
			
		||||
void server_write_null_buffer()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_WRITE_BUFFER_NULL, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
    psa_outvec_t resp = { NULL, CLIENT_RSP_BUF_SIZE };
 | 
			
		||||
 | 
			
		||||
    negative_server_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, &resp, 1);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_null_buffer negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server write rx_buff is null
 | 
			
		||||
void server_write_rx_buff_null()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_WRITE_RX_BUFF_NULL, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    negative_server_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_rx_buff_null negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server write handle does not exist on the platform
 | 
			
		||||
void server_write_invalid_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_WRITE_INVALID_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
    psa_outvec_t resp = { response_buf, CLIENT_RSP_BUF_SIZE };
 | 
			
		||||
 | 
			
		||||
    negative_server_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, &resp, 1);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_invalid_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server write handle is null (PSA_NULL_HANDLE)
 | 
			
		||||
void server_write_null_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_WRITE_NULL_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    uint8_t data[2] = {1, 0};
 | 
			
		||||
    psa_invec_t iovec_temp[PSA_MAX_IOVEC - 1] = {
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)},
 | 
			
		||||
        {data, sizeof(data)}
 | 
			
		||||
    };
 | 
			
		||||
    psa_outvec_t resp = { response_buf, CLIENT_RSP_BUF_SIZE };
 | 
			
		||||
 | 
			
		||||
    negative_server_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, &resp, 1);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_null_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server reply with a null handle
 | 
			
		||||
void server_reply_null_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART2_REPLY_NULL_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_reply_null_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server reply handle does not exist on the platform
 | 
			
		||||
void server_reply_invalid_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART2_REPLY_INVALID_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_reply_invalid_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server reply invalid retval for connect
 | 
			
		||||
void server_reply_invalid_retval_connect()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART1_REPLY_INVALID_RETVAL_CONNECT, MINOR_VER);
 | 
			
		||||
   
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_reply_invalid_retval_connect negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server reply invalid retval for call
 | 
			
		||||
void server_reply_invalid_retval_call()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART1_REPLY_INVALID_RETVAL_CALL, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_reply_invalid_retval_call negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server notify partition id doesnt exist
 | 
			
		||||
void server_notify_part_id_invalid()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART2_NOTIFY_PART_ID_INVALID, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_notify_part_id_invalid negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server psa_identity handle does not exist on the platform
 | 
			
		||||
void server_psa_identity_invalid_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART2_IDENTITY_INVALID_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_psa_identity_invalid_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server psa_identity handle is null (PSA_NULL_HANDLE)
 | 
			
		||||
void server_psa_identity_null_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART2_IDENTITY_NULL_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_psa_identity_null_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server psa_set_rhandle handle does not exist on the platform
 | 
			
		||||
void server_set_rhandle_invalid_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART2_SET_RHANDLE_INVALID_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_set_rhandle_invalid_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Testing server psa_set_rhandle handle is null (PSA_NULL_HANDLE)
 | 
			
		||||
void server_set_rhandle_null_handle()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART2_SET_RHANDLE_NULL_HANDLE, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_set_rhandle_null_handle negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_read_on_wraparound_msg_ptr()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_READ_WRAPAROUND, MINOR_VER);
 | 
			
		||||
    psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_read_on_wraparound_msg_ptr negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_read_from_excess_invec()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_READ_EXCESS_INVEC, MINOR_VER);
 | 
			
		||||
    psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_read_from_excess_invec negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_write_on_wraparound_msg_ptr()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_WRITE_WRAPAROUND, MINOR_VER);
 | 
			
		||||
    psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_on_wraparound_msg_ptr negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_write_from_excess_outvec()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_WRITE_EXCESS_OUTVEC, MINOR_VER);
 | 
			
		||||
    psa_call(handle, NULL, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_from_excess_outvec negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_write_from_outvec_index_size_0()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART1_WRITE_OUTVEC_IX_SIZE_0, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    psa_outvec_t resp[2] = { {response_buf, CLIENT_RSP_BUF_SIZE},
 | 
			
		||||
                             {response_buf, 0}
 | 
			
		||||
                           };
 | 
			
		||||
 | 
			
		||||
    psa_call(handle, NULL, 0, resp, 2);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_from_outvec_index_size_0 negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_write_with_size_overflow()
 | 
			
		||||
{
 | 
			
		||||
    psa_handle_t handle = negative_server_ipc_tests_connect(PART2_WRITE_SIZE_OVERFLOW, MINOR_VER);
 | 
			
		||||
    psa_outvec_t resp = { response_buf, CLIENT_RSP_BUF_SIZE };
 | 
			
		||||
    psa_call(handle, NULL, 0, &resp, 1);
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_write_with_size_overflow negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Testing server psa_clear() when doorbell signal is not currently asserted
 | 
			
		||||
void server_clear_no_doorbell()
 | 
			
		||||
{
 | 
			
		||||
    psa_connect(PART1_CLEAR_NO_DOORBELL, MINOR_VER);
 | 
			
		||||
 | 
			
		||||
    TEST_FAIL_MESSAGE("server_clear_no_doorbell negative test failed at client side");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PSA_NEG_TEST(server_interrupt_mask_invalid)
 | 
			
		||||
PSA_NEG_TEST(server_get_msg_null)
 | 
			
		||||
PSA_NEG_TEST(server_get_multiple_bit_signum)
 | 
			
		||||
PSA_NEG_TEST(server_get_signum_not_subset)
 | 
			
		||||
PSA_NEG_TEST(server_get_signum_not_active)
 | 
			
		||||
PSA_NEG_TEST(server_get_signum_twice)
 | 
			
		||||
PSA_NEG_TEST(server_read_invalid_handle)
 | 
			
		||||
PSA_NEG_TEST(server_read_null_handle)
 | 
			
		||||
PSA_NEG_TEST(server_read_null_buffer)
 | 
			
		||||
PSA_NEG_TEST(server_write_null_buffer)
 | 
			
		||||
PSA_NEG_TEST(server_write_rx_buff_null)
 | 
			
		||||
PSA_NEG_TEST(server_write_invalid_handle)
 | 
			
		||||
PSA_NEG_TEST(server_write_null_handle)
 | 
			
		||||
PSA_NEG_TEST(server_reply_null_handle)
 | 
			
		||||
PSA_NEG_TEST(server_reply_invalid_handle)
 | 
			
		||||
PSA_NEG_TEST(server_reply_invalid_retval_connect)
 | 
			
		||||
PSA_NEG_TEST(server_reply_invalid_retval_call)
 | 
			
		||||
PSA_NEG_TEST(server_notify_part_id_invalid)
 | 
			
		||||
PSA_NEG_TEST(server_psa_identity_invalid_handle)
 | 
			
		||||
PSA_NEG_TEST(server_psa_identity_null_handle)
 | 
			
		||||
PSA_NEG_TEST(server_set_rhandle_invalid_handle)
 | 
			
		||||
PSA_NEG_TEST(server_set_rhandle_null_handle)
 | 
			
		||||
PSA_NEG_TEST(server_read_on_wraparound_msg_ptr)
 | 
			
		||||
PSA_NEG_TEST(server_read_from_excess_invec)
 | 
			
		||||
PSA_NEG_TEST(server_write_on_wraparound_msg_ptr)
 | 
			
		||||
PSA_NEG_TEST(server_write_with_size_overflow)
 | 
			
		||||
PSA_NEG_TEST(server_write_from_excess_outvec)
 | 
			
		||||
PSA_NEG_TEST(server_write_from_outvec_index_size_0)
 | 
			
		||||
PSA_NEG_TEST(server_clear_no_doorbell)
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_case_setup(const Case *const source, const size_t index_of_case)
 | 
			
		||||
{
 | 
			
		||||
    memset(response_buf, 0, sizeof(response_buf));
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    spm_reboot();
 | 
			
		||||
    error_thrown = false;
 | 
			
		||||
    return greentea_case_teardown_handler(source, passed, failed, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SPM_UTEST_CASE(desc, test) Case(desc, spm_case_setup, PSA_NEG_TEST_NAME(test), spm_case_teardown)
 | 
			
		||||
 | 
			
		||||
// Test cases
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    SPM_UTEST_CASE("Testing server interrupt mask invalid", server_interrupt_mask_invalid),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server get with msg NULL", server_get_msg_null),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server get signum have more than one bit ON", server_get_multiple_bit_signum),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server get signum flag is not a subset of current partition flags", server_get_signum_not_subset),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server get signum flag is not active", server_get_signum_not_active),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server get signum twice", server_get_signum_twice),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server read handle does not exist on the platform", server_read_invalid_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server read handle is PSA_NULL_HANDLE", server_read_null_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server read buffer is NULL", server_read_null_buffer),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write buffer is NULL", server_write_null_buffer),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write rx_buff is null", server_write_rx_buff_null),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write handle does not exist on the platform", server_write_invalid_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write handle is PSA_NULL_HANDLE", server_write_null_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server reply with PSA_NULL_HANDLE", server_reply_null_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server reply handle does not exist on the platform", server_reply_invalid_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server reply invalid retval for connect", server_reply_invalid_retval_connect),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server reply invalid retval for call", server_reply_invalid_retval_call),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server notify partition id does not exist", server_notify_part_id_invalid),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server identify handle does not exist on the platform", server_psa_identity_invalid_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server identify handle is PSA_NULL_HANDLE", server_psa_identity_null_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server set_rhandle handle does not exist on the platform", server_set_rhandle_invalid_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server set_rhandle handle is PSA_NULL_HANDLE", server_set_rhandle_null_handle),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server read on wrap around pointer", server_read_on_wraparound_msg_ptr),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server read on excess invec index", server_read_from_excess_invec),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write on wrap around pointer", server_write_on_wraparound_msg_ptr),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write on excess out_vec index", server_write_from_excess_outvec),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write on out_vec index with size 0", server_write_from_outvec_index_size_0),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server write with size overflow", server_write_with_size_overflow),
 | 
			
		||||
    SPM_UTEST_CASE("Testing server clear when doorbell signal is not asserted", server_clear_no_doorbell)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t spm_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
#ifndef NO_GREENTEA
 | 
			
		||||
    GREENTEA_SETUP(60, "default_auto");
 | 
			
		||||
#endif
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(spm_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
/* Copyright (c) 2017 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define PSA_NEG_TEST_NAME(test_name) psa_neg_test_ ## test_name
 | 
			
		||||
 | 
			
		||||
#define PSA_NEG_TEST(test_name)       \
 | 
			
		||||
void PSA_NEG_TEST_NAME(test_name)()   \
 | 
			
		||||
{                                     \
 | 
			
		||||
    osStatus status = osOK;           \
 | 
			
		||||
    Thread T1;                        \
 | 
			
		||||
                                      \
 | 
			
		||||
    status = T1.start(test_name);     \
 | 
			
		||||
    TEST_ASSERT_TRUE(status == osOK); \
 | 
			
		||||
    test_sem.wait(osWaitForever);     \
 | 
			
		||||
    TEST_ASSERT_TRUE(error_thrown);   \
 | 
			
		||||
                                      \
 | 
			
		||||
    status = T1.terminate();          \
 | 
			
		||||
    TEST_ASSERT_TRUE(status == osOK); \
 | 
			
		||||
}                                     \
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "NEG_SERVER_PART1",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000007",
 | 
			
		||||
  "entry_point": "server_main1",
 | 
			
		||||
  "stack_size": "0x200",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "PART1_REPLY_INVALID_RETVAL_CONNECT",
 | 
			
		||||
      "identifier": "0x00001A25",
 | 
			
		||||
      "signal": "PART1_REPLY_INVALID_RETVAL_CONNECT_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART1_REPLY_INVALID_RETVAL_CALL",
 | 
			
		||||
      "identifier": "0x00001A26",
 | 
			
		||||
      "signal": "PART1_REPLY_INVALID_RETVAL_CALL_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART1_CLEAR_NO_DOORBELL",
 | 
			
		||||
      "identifier": "0x00001A27",
 | 
			
		||||
      "signal": "PART1_CLEAR_NO_DOORBELL_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART1_WRITE_OUTVEC_IX_SIZE_0",
 | 
			
		||||
      "identifier": "0x00001A28",
 | 
			
		||||
      "signal": "PART1_WRITE_OUTVEC_IX_SIZE_0_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "server1.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,221 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "NEG_SERVER_PART2",
 | 
			
		||||
  "type": "APPLICATION-ROT",
 | 
			
		||||
  "priority": "NORMAL",
 | 
			
		||||
  "id": "0x00000008",
 | 
			
		||||
  "entry_point": "server_main2",
 | 
			
		||||
  "stack_size": "0x280",
 | 
			
		||||
  "heap_size": "0x400",
 | 
			
		||||
  "services": [{
 | 
			
		||||
      "name": "PART2_INT_MASK",
 | 
			
		||||
      "identifier": "0x00001A0B",
 | 
			
		||||
      "signal": "PART2_INT_MASK_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_GET_MSG_NULL",
 | 
			
		||||
      "identifier": "0x00001A0C",
 | 
			
		||||
      "signal": "PART2_GET_MSG_NULL_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_GET_SIGNUM_MULTIPLE_BIT",
 | 
			
		||||
      "identifier": "0x00001A0D",
 | 
			
		||||
      "signal": "PART2_GET_SIGNUM_MULTIPLE_BIT_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_GET_SIGNUM_NOT_SUBSET",
 | 
			
		||||
      "identifier": "0x00001A0E",
 | 
			
		||||
      "signal": "PART2_GET_SIGNUM_NOT_SUBSET_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_GET_SIGNUM_NOT_ACTIVE",
 | 
			
		||||
      "identifier": "0x00001A0F",
 | 
			
		||||
      "signal": "PART2_GET_SIGNUM_NOT_ACTIVE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_GET_SIGNUM_TWICE",
 | 
			
		||||
      "identifier": "0x00001A10",
 | 
			
		||||
      "signal": "PART2_GET_SIGNUM_TWICE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_READ_INVALID_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A11",
 | 
			
		||||
      "signal": "PART2_READ_INVALID_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_READ_NULL_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A12",
 | 
			
		||||
      "signal": "PART2_READ_NULL_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_READ_TX_SIZE_ZERO",
 | 
			
		||||
      "identifier": "0x00001A13",
 | 
			
		||||
      "signal": "PART2_READ_TX_SIZE_ZERO_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_WRITE_BUFFER_NULL",
 | 
			
		||||
      "identifier": "0x00001A14",
 | 
			
		||||
      "signal": "PART2_WRITE_BUFFER_NULL_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_WRITE_RX_BUFF_NULL",
 | 
			
		||||
      "identifier": "0x00001A15",
 | 
			
		||||
      "signal": "PART2_WRITE_RX_BUFF_NULL_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_WRITE_INVALID_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A16",
 | 
			
		||||
      "signal": "PART2_WRITE_INVALID_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_WRITE_NULL_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A17",
 | 
			
		||||
      "signal": "PART2_WRITE_NULL_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_REPLY_INVALID_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A18",
 | 
			
		||||
      "signal": "PART2_REPLY_INVALID_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_REPLY_NULL_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A19",
 | 
			
		||||
      "signal": "PART2_REPLY_NULL_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_NOTIFY_PART_ID_INVALID",
 | 
			
		||||
      "identifier": "0x00001A1A",
 | 
			
		||||
      "signal": "PART2_NOTIFY_PART_ID_INVALID_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_IDENTITY_INVALID_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A1B",
 | 
			
		||||
      "signal": "PART2_IDENTITY_INVALID_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_IDENTITY_NULL_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A1C",
 | 
			
		||||
      "signal": "PART2_IDENTITY_NULL_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_SET_RHANDLE_INVALID_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A1D",
 | 
			
		||||
      "signal": "PART2_SET_RHANDLE_INVALID_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_SET_RHANDLE_NULL_HANDLE",
 | 
			
		||||
      "identifier": "0x00001A1E",
 | 
			
		||||
      "signal": "PART2_SET_RHANDLE_NULL_HANDLE_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_READ_WRAPAROUND",
 | 
			
		||||
      "identifier": "0x00001A1F",
 | 
			
		||||
      "signal": "PART2_READ_WRAPAROUND_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_READ_EXCESS_INVEC",
 | 
			
		||||
      "identifier": "0x00001A20",
 | 
			
		||||
      "signal": "PART2_READ_EXCESS_INVEC_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_WRITE_WRAPAROUND",
 | 
			
		||||
      "identifier": "0x00001A21",
 | 
			
		||||
      "signal": "PART2_WRITE_WRAPAROUND_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_WRITE_EXCESS_OUTVEC",
 | 
			
		||||
      "identifier": "0x00001A22",
 | 
			
		||||
      "signal": "PART2_WRITE_EXCESS_OUTVEC_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_WRITE_SIZE_OVERFLOW",
 | 
			
		||||
      "identifier": "0x00001A23",
 | 
			
		||||
      "signal": "PART2_WRITE_SIZE_OVERFLOW_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "PART2_READ_NULL_BUFFER",
 | 
			
		||||
      "identifier": "0x00001A24",
 | 
			
		||||
      "signal": "PART2_READ_NULL_BUFFER_MSK",
 | 
			
		||||
      "non_secure_clients": true,
 | 
			
		||||
      "minor_version": 5,
 | 
			
		||||
      "minor_policy": "RELAXED"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "source_files": [
 | 
			
		||||
    "server2.c"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue