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