mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #2228 from AlessandroA/update_uvisor
Update uVisor to v0.20.0-alphapull/2234/merge
commit
a4fb649789
|
@ -2,13 +2,13 @@
|
|||
|
||||
This guide will help you get started with uVisor on mbed OS by walking you through creating a sample application for the NXP FRDM-K64F board.
|
||||
|
||||
The uVisor provides sandboxed environments and resources protection for applications built for ARM Cortex-M3 and Cortex-M4 devices. Here we will show you how to enable the uVisor and configure a secure box to get hold of some exclusive resources (memory, peripherals, interrupts). For more information on the uVisor design philosophy, please check out our the uVisor [introductory document](../README.md).
|
||||
The uVisor provides sandboxed environments and resources protection for applications built for ARM Cortex-M3 and Cortex-M4 devices. Here we will show you how to enable the uVisor and configure a secure box to get hold of some exclusive resources (memory, peripherals, interrupts). For more information on the uVisor design philosophy, please check out our the uVisor [introductory document](../../README.md).
|
||||
|
||||
## Overview
|
||||
|
||||
To get a basic `blinky` application running on mbed OS with uVisor enabled, you will need the following:
|
||||
|
||||
* A platform and a toolchain supported by uVisor on mbed OS. You can verify this on [the official list](../README.md#supported-platforms). Please note that uVisor might support some platform internally, but not on mbed OS. Generally this means that the porting process has only been partially completed. If you want to port your platform to uVisor and enable it on mbed OS, please follow the [uVisor porting guide](PORTING.md).
|
||||
* A platform and a toolchain supported by uVisor on mbed OS. You can verify this on [the official list](../../README.md#supported-platforms). Please note that uVisor might support some platform internally, but not on mbed OS. Generally this means that the porting process has only been partially completed. If you want to port your platform to uVisor and enable it on mbed OS, please follow the [uVisor Porting Guide for mbed OS](../core/PORTING.md).
|
||||
* git. It will be used to download the mbed codebase.
|
||||
* The mbed command-line tools, mbed-cli. You can run `pip install mbed-cli` to install them.
|
||||
|
||||
|
@ -292,7 +292,7 @@ A few things to note in the code above:
|
|||
|
||||
Compile the application again, re-flash the device, and press the reset button. The device LED should be blinking as in the previous case.
|
||||
|
||||
If you don't see the LED blinking, it means that the application halted somewhere, probably because uVisor captured a fault. You can setup the uVisor debug messages to see if there is any problem. Follow the [Debugging uVisor](DEBUGGING.md) document for a step-by-step guide.
|
||||
If you don't see the LED blinking, it means that the application halted somewhere, probably because uVisor captured a fault. You can setup the uVisor debug messages to see if there is any problem. Follow the [Debugging uVisor on mbed OS](DEBUGGING.md) document for a step-by-step guide.
|
||||
|
||||
If the LED is blinking, it means that the app is running fine. If you now press the `SW2` button on the NXP FRDM-K64F board, the `private_timer_button_on_press` function will be executed, printing the values in the timer buffer. You can observe these values by opening a serial port connection to the device, with a baud rate of 9600. When the print is completed, you should see the LED blinking again.
|
||||
|
||||
|
@ -313,8 +313,8 @@ In this guide we showed you how to:
|
|||
|
||||
You can now modify the example or create a new one to protect your resources into a secure box. You might find the following resources useful:
|
||||
|
||||
* [The uVisor API documentation](API.md)
|
||||
* [Debugging uVisor](DEBUGGING.md)
|
||||
* [uVisor API documentation](API.md)
|
||||
* [Debugging uVisor on mbed OS](DEBUGGING.md)
|
||||
|
||||
If you found any bug or inconsistency in this guide, please [raise an issue](https://github.com/ARMmbed/uvisor/issues/new).
|
||||
|
||||
|
@ -354,7 +354,7 @@ NVIC_EnableIRQ(MY_IRQ);
|
|||
|
||||
> **Note**: In this model a call to `NVIC_SetVector` must always happen before an IRQ state is changed. In platforms that don't relocate the interrupt vector table such a call might be originally absent and must be added to work with uVisor.
|
||||
|
||||
For more information on the uVisor APIs, checkout the [uVisor APIs documentation](API.md).
|
||||
For more information on the uVisor APIs, checkout the [uVisor API documentation](API.md) document.
|
||||
|
||||
### The *main box* ACLs
|
||||
|
||||
|
@ -371,13 +371,13 @@ static const UvisorBoxAclItem g_main_box_acls[] = {
|
|||
}
|
||||
```
|
||||
|
||||
You now need to compile your application using uVisor in debug mode. This operation requires some more advanced steps, which are described in detail in the [Debugging uVisor](DEBUGGING.md) document. The main idea is that you compile the application in debug mode:
|
||||
You now need to compile your application using uVisor in debug mode. This operation requires some more advanced steps, which are described in detail in the [Debugging uVisor on mbed OS](DEBUGGING.md) document. The main idea is that you compile the application in debug mode:
|
||||
|
||||
```bash
|
||||
$ mbed compile -m K64F_SECURE -t GCC_ARM -o "debug-info"
|
||||
```
|
||||
|
||||
and then use a GDB-compatible interface to flash the device, enable semihosting, and access the uVisor debug messages. Please read the [Debugging uVisor](DEBUGGING.md) document for the detailed instructions.
|
||||
and then use a GDB-compatible interface to flash the device, enable semihosting, and access the uVisor debug messages. Please read the [Debugging uVisor on mbed OS](DEBUGGING.md) document for the detailed instructions.
|
||||
|
||||
Once the uVisor debug messages are enabled, you will see you application fail. The failure is due to the first missing ACL being hit by the main box code. The message will look like:
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ TARGET_LIB_INC:=$(TARGET_PREFIX)includes/uvisor-lib
|
|||
|
||||
# uVisor source directory - hidden from mbed via TARGET_IGNORE
|
||||
UVISOR_GIT_URL:=https://github.com/ARMmbed/uvisor
|
||||
UVISOR_GIT_BRANCH:=dev
|
||||
UVISOR_GIT_BRANCH:=master
|
||||
UVISOR_DIR:=TARGET_IGNORE/uvisor
|
||||
UVISOR_API:=$(UVISOR_DIR)/api
|
||||
UVISOR_GIT_CFG=$(UVISOR_DIR)/.git/config
|
||||
|
@ -76,7 +76,7 @@ rsync:
|
|||
rsync -a --delete $(UVISOR_API)/rtx/src/ $(TARGET_LIB_SRC)/rtx
|
||||
#
|
||||
# Copying the documentation...
|
||||
cp $(UVISOR_DIR)/docs/QUICKSTART.md $(TARGET_PREFIX)/README.md
|
||||
cp $(UVISOR_DIR)/docs/api/QUICKSTART.md $(TARGET_PREFIX)/README.md
|
||||
#
|
||||
# Copying licenses
|
||||
cp $(UVISOR_DIR)/LICENSE* $(TARGET_SUPPORTED)
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
#define uvisor_read(box_name, shared, addr, op, msk) \
|
||||
({ \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
__attribute__((aligned(4))) static TRegisterGateway const register_gateway = { \
|
||||
UVISOR_ALIGN(4) static TRegisterGateway const register_gateway = { \
|
||||
.svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \
|
||||
.branch = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \
|
||||
__UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \
|
||||
|
@ -119,7 +119,7 @@
|
|||
#define uvisor_write(box_name, shared, addr, val, op, msk) \
|
||||
{ \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
__attribute__((aligned(4))) static TRegisterGateway const register_gateway = { \
|
||||
UVISOR_ALIGN(4) static TRegisterGateway const register_gateway = { \
|
||||
.svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \
|
||||
.branch = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \
|
||||
__UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \
|
||||
|
|
|
@ -47,7 +47,7 @@ typedef struct {
|
|||
uint32_t mask;
|
||||
uint16_t operation;
|
||||
uint16_t bxlr;
|
||||
} UVISOR_PACKED __attribute__((aligned(4))) TRegisterGateway;
|
||||
} UVISOR_PACKED UVISOR_ALIGN(4) TRegisterGateway;
|
||||
|
||||
/** Register gateway operation - Masks
|
||||
* @internal
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_RPC_H__
|
||||
#define __UVISOR_API_RPC_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/** Specify the maximum number of incoming RPC messages for a box
|
||||
*
|
||||
* @param max_num_incoming_rpc The maximum number of incoming RPC messages for
|
||||
* a box
|
||||
*/
|
||||
/* FIXME This is a dummy implementation. */
|
||||
#define UVISOR_BOX_RPC_MAX_INCOMING(max_num_incoming_rpc)
|
||||
|
||||
/* This is the token to wait on for the result of an asynchronous RPC. */
|
||||
typedef uint32_t uvisor_rpc_result_t;
|
||||
|
||||
typedef uint32_t (*TFN_Ptr)(uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
typedef int (*TFN_RPC_Callback)(int);
|
||||
|
||||
/** Wait for incoming RPC.
|
||||
*
|
||||
* @param fn_ptr_array an array of RPC function targets that this call to
|
||||
* `rpc_fncall_waitfor` should handle RPC to
|
||||
* @param fn_count the number of function targets in this array
|
||||
* @param timeout_ms specifies how long to wait (in ms) for an incoming RPC
|
||||
* message before returning
|
||||
*/
|
||||
int rpc_fncall_waitfor(const TFN_Ptr fn_ptr_array[], size_t fn_count, uint32_t timeout_ms);
|
||||
|
||||
#endif /* __UVISOR_API_RPC_H__ */
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_RPC_GATEWAY_H__
|
||||
#define __UVISOR_API_RPC_GATEWAY_H__
|
||||
|
||||
#include "api/inc/rpc_gateway_exports.h"
|
||||
#include "api/inc/rpc.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* ldr pc, [pc, #<label - instr + 4>]
|
||||
* LDR (immediate) - ARMv7M ARM section A7.7.42
|
||||
* 1111;1 00 0; 0 10 1; <Rn - 1111>; <Rt - 1111>; <imm12> (Encoding T3) */
|
||||
#define LDR_PC_PC_IMM_OPCODE(instr, label) \
|
||||
((uint32_t) (0xF000F8DFUL | ((((uint32_t) (label) - ((uint32_t) (instr) + 4)) & 0xFFFUL) << 16)))
|
||||
|
||||
/** Synchronous RPC Gateway
|
||||
*
|
||||
* This macro declares a new function pointer (with no name mangling) named
|
||||
* `gw_name` to perform a remote procedure call (RPC) to the target function
|
||||
* given by `fn_name`. RPCs are assembled into a read-only flash structure that
|
||||
* is read and validated by uVisor before performing the operation.
|
||||
*
|
||||
* Create function with following signature:
|
||||
* UVISOR_EXTERN fn_ret gw_name(uint32_t a, uint32_t b);
|
||||
*
|
||||
* @param box_name[in] The name of the source box as declared in
|
||||
* `UVISOR_BOX_CONFIG`
|
||||
* @param gw_name[in] The new, callable function pointer for performing RPC
|
||||
* @param fn_name[in] The function being designated as an RPC target
|
||||
* @param fn_ret[in] The return type of the function being designated as an
|
||||
* RPC target
|
||||
* @param __VA_ARGS__ The type of each parameter passed to the target
|
||||
* function. There can be up to 4 parameters in a target
|
||||
* function. Each parameter must be no more than uint32_t
|
||||
* in size. If the RPC target function accepts no
|
||||
* arguments, pass `void` here.
|
||||
*/
|
||||
#define UVISOR_BOX_RPC_GATEWAY_SYNC(box_name, gw_name, fn_name, fn_ret, ...) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, __VA_ARGS__) \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
|
||||
.ldr_pc = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
|
||||
__UVISOR_OFFSETOF(TRPCGateway, function)), \
|
||||
.magic = UVISOR_RPC_GATEWAY_MAGIC_SYNC, \
|
||||
.box_ptr = (uint32_t) &box_name ## _cfg_ptr, \
|
||||
.function = (uint32_t) _sgw_sync_ ## fn_name, \
|
||||
}; \
|
||||
\
|
||||
/* Pointer to the gateway we just created. The pointer is located in a
|
||||
* discoverable linker section. */ \
|
||||
__attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
|
||||
uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
|
||||
\
|
||||
/* Declare the actual gateway. */ \
|
||||
UVISOR_EXTERN_C_BEGIN \
|
||||
fn_ret (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (fn_ret (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
|
||||
UVISOR_EXTERN_C_END
|
||||
|
||||
/** Asynchronous RPC Gateway
|
||||
*
|
||||
* This macro declares a new function pointer (with no name mangling) named
|
||||
* `gw_name` to perform a remote procedure call (RPC) to the target function
|
||||
* given by `fn_name`. RPCs are assembled into a read-only flash structure that
|
||||
* is read and validated by uVisor before performing the operation.
|
||||
*
|
||||
* Create function with following signature:
|
||||
* UVISOR_EXTERN uvisor_rpc_result_t gw_name(uint32_t a, uint32_t b);
|
||||
*
|
||||
* @param box_name[in] The name of the source box as declared in
|
||||
* `UVISOR_BOX_CONFIG`
|
||||
* @param gw_name[in] The new, callable function pointer for performing RPC
|
||||
* @param fn_name[in] The function being designated as an RPC target
|
||||
* @param fn_ret[in] The return type of the function being designated as an
|
||||
* RPC target
|
||||
* @param __VA_ARGS__ The type of each parameter passed to the target
|
||||
* function. There can be up to 4 parameters in a target
|
||||
* function. Each parameter must be no more than uint32_t
|
||||
* in size. If the RPC target function accepts no
|
||||
* arguments, pass `void` here.
|
||||
*/
|
||||
#define UVISOR_BOX_RPC_GATEWAY_ASYNC(box_name, gw_name, fn_name, fn_ret, ...) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, __VA_ARGS__) \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
|
||||
.ldr_pc = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
|
||||
__UVISOR_OFFSETOF(TRPCGateway, function)), \
|
||||
.magic = UVISOR_RPC_GATEWAY_MAGIC_ASYNC, \
|
||||
.box_ptr = (uint32_t) &box_name ## _cfg_ptr, \
|
||||
.function = (uint32_t) _sgw_async_ ## fn_name, \
|
||||
}; \
|
||||
\
|
||||
/* Pointer to the gateway we just created. The pointer is located in a
|
||||
* discoverable linker section. */ \
|
||||
__attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
|
||||
uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
|
||||
\
|
||||
/* Declare the actual gateway. */ \
|
||||
UVISOR_EXTERN_C_BEGIN \
|
||||
uvisor_rpc_result_t (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (uvisor_rpc_result_t (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
|
||||
UVISOR_EXTERN_C_END
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, ...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0)(gw_name, __VA_ARGS__)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0(gw_name)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1(gw_name, p0_type) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2(gw_name, p0_type, p1_type) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3(gw_name, p0_type, p1_type, p2_type) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4(gw_name, p0_type, p1_type, p2_type, p3_type) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big); \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p3_type) <= sizeof(uint32_t), gw_name ## _param_3_too_big);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, ...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0)(fn_name, __VA_ARGS__)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0(fn_name, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(void) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(0, 0, 0, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1(fn_name, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, 0, 0, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2(fn_name, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, p1, 0, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3(fn_name, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, p1, p2, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4(fn_name, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, p1, p2, p3, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, ...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0)(fn_name, __VA_ARGS__)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0(fn_name, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(void) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(0, 0, 0, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1(fn_name, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, 0, 0, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2(fn_name, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, p1, 0, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3(fn_name, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, p1, p2, 0, fp); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4(fn_name, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, p1, p2, p3, fp); \
|
||||
}
|
||||
|
||||
/* This function is private to uvisor-lib, but needs to be publicly visible for
|
||||
* the RPC gateway creation macros to work. */
|
||||
UVISOR_EXTERN uint32_t rpc_fncall_sync(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TFN_Ptr fn);
|
||||
|
||||
/* This function is private to uvisor-lib, but needs to be publicly visible for
|
||||
* the RPC gateway creation macros to work. */
|
||||
UVISOR_EXTERN uvisor_rpc_result_t rpc_fncall_async(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TFN_Ptr fn);
|
||||
|
||||
#endif /* __UVISOR_API_RPC_GATEWAY_H__ */
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_RPC_GATEWAY_EXPORTS_H__
|
||||
#define __UVISOR_API_RPC_GATEWAY_EXPORTS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* udf imm16
|
||||
* UDF - ARMv7M ARM section A7.7.191
|
||||
* 111 1;0 111;1111; <imm4>; 1 01 0; <imm12> (Encoding T2)
|
||||
*/
|
||||
#define UDF_OPCODE(imm16) \
|
||||
((uint32_t) (0xA000F7F0UL | (((uint32_t) (imm16) & 0xFFFU) << 16U) | (((uint32_t) (imm16) & 0xF000UL) >> 12)))
|
||||
|
||||
/** RPC gateway magics
|
||||
*
|
||||
* The following magics are used to verify an RPC gateway structure. The magics are
|
||||
* chosen to be one of the explicitly undefined Thumb-2 instructions.
|
||||
*/
|
||||
/* TODO Unify all sources of magic (for register gateway, rpc gateway, and
|
||||
* everybody else) */
|
||||
#if defined(__thumb__) && defined(__thumb2__)
|
||||
#define UVISOR_RPC_GATEWAY_MAGIC_ASYNC UDF_OPCODE(0x07C2)
|
||||
#define UVISOR_RPC_GATEWAY_MAGIC_SYNC UDF_OPCODE(0x07C3)
|
||||
#else
|
||||
#error "Unsupported instruction set. The ARM Thumb-2 instruction set must be supported."
|
||||
#endif /* __thumb__ && __thumb2__ */
|
||||
|
||||
|
||||
/** RPC gateway structure
|
||||
*
|
||||
* This struct is packed because we must ensure that the `ldr_pc` field has no
|
||||
* padding before itself and will be located at a valid instruction location,
|
||||
* and that the `function` field is at a pre-determined offset from the
|
||||
* `ldr_pc` field.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t ldr_pc;
|
||||
uint32_t magic;
|
||||
uint32_t box_ptr;
|
||||
uint32_t function; /* It's like a pretend literal pool. */
|
||||
} UVISOR_PACKED UVISOR_ALIGN(4) TRPCGateway;
|
||||
|
||||
#endif /* __UVISOR_API_RPC_GATEWAY_EXPORTS_H__ */
|
|
@ -32,6 +32,8 @@
|
|||
#include "api/inc/error.h"
|
||||
#include "api/inc/interrupts.h"
|
||||
#include "api/inc/register_gateway.h"
|
||||
#include "api/inc/rpc.h"
|
||||
#include "api/inc/rpc_gateway.h"
|
||||
#include "api/inc/secure_access.h"
|
||||
|
||||
#else /* defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1 */
|
||||
|
@ -55,6 +57,7 @@ UVISOR_EXTERN int uvisor_lib_init(void);
|
|||
#include "api/inc/export_table_exports.h"
|
||||
#include "api/inc/halt_exports.h"
|
||||
#include "api/inc/register_gateway_exports.h"
|
||||
#include "api/inc/rpc_gateway_exports.h"
|
||||
#include "api/inc/svc_exports.h"
|
||||
#include "api/inc/priv_sys_irq_hook_exports.h"
|
||||
#include "api/inc/unvic_exports.h"
|
||||
|
|
|
@ -29,6 +29,21 @@
|
|||
#define UVISOR_EXTERN extern
|
||||
#endif/*__CPP__*/
|
||||
|
||||
/** Extern C block macros
|
||||
*
|
||||
* Use these macros to disable name mangling in C++. Use these macros instead
|
||||
* of UVISOR_EXTERN when you also need to initialize the object. C++ compilers
|
||||
* warn when initializing an object declared as `extern`. Use of these macros
|
||||
* enables the defining of global non-name-mangled symbols in C++ without
|
||||
* affecting C code (which doesn't ever name mangle). */
|
||||
#ifdef __cplusplus
|
||||
#define UVISOR_EXTERN_C_BEGIN extern "C" {
|
||||
#define UVISOR_EXTERN_C_END }
|
||||
#else
|
||||
#define UVISOR_EXTERN_C_BEGIN
|
||||
#define UVISOR_EXTERN_C_END
|
||||
#endif
|
||||
|
||||
/* asm keyword */
|
||||
#ifndef asm
|
||||
#define asm __asm__
|
||||
|
@ -36,12 +51,14 @@
|
|||
|
||||
/* Shared compiler attributes */
|
||||
#if defined(__ICCARM__)
|
||||
#define UVISOR_ALIGN(x) __align(x)
|
||||
#define UVISOR_FORCEINLINE inline
|
||||
#define UVISOR_PACKED __packed
|
||||
#define UVISOR_WEAK __weak
|
||||
#define UVISOR_NORETURN __noreturn
|
||||
#define UVISOR_RAMFUNC __ramfunc
|
||||
#else
|
||||
#define UVISOR_ALIGN(x) __attribute__((aligned(x)))
|
||||
#define UVISOR_FORCEINLINE inline __attribute__((always_inline))
|
||||
#define UVISOR_PACKED __attribute__((packed))
|
||||
#define UVISOR_WEAK __attribute__((weak))
|
||||
|
@ -52,6 +69,15 @@
|
|||
/* array count macro */
|
||||
#define UVISOR_ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
/** Static Assertion Macro
|
||||
*
|
||||
* This macro works from both inside and outside function scope.
|
||||
*
|
||||
* FIXME This is currently not implemented. This issue is tracked at
|
||||
* https://github.com/ARMmbed/uvisor/issues/288
|
||||
*/
|
||||
#define UVISOR_STATIC_ASSERT(cond, msg)
|
||||
|
||||
/* convert macro argument to string */
|
||||
/* note: this needs one level of indirection, accomplished with the helper macro
|
||||
* __UVISOR_TO_STRING */
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue