Here you can find detailed documentation for:
- Configuration macros, to configure a secure box and protect data and peripherals.
- Secure function calls, to execute code in the context of a secure box.
- Box Identity, to retrieve a box-specific ID or the namespace of the current or calling box.
- Low level APIs, to access uVisor functions that are not available to unprivileged code (interrupts, restricted system registers).
- Type definitions.
- Error codes.
UVISOR_BOX_CONFIG(box_name
const UvBoxAclItem *module_acl_list,
uint32_t module_stack_size,
[struct __your_context])
Description | Secure box configuration | |
Type | C/C++ pre-processor macro (pseudo-function) | |
Parameters | box_name |
Secure box name |
const UvBoxAclItem *module_acl_list |
List of ACLs for the module | |
uint32_t module_stack_size |
Required stack size for the secure box | |
struct __your_context |
[optional] Type definition of the struct hosting the box context data |
Example:
#include "uvisor-lib/uvisor-lib.h"
/* Required stack size */
#define BOX_STACK_SIZE 0x100
/* Define the box context. */
typedef struct {
uint8_t secret[SECRET_SIZE];
bool initialized;
State_t current_state
} BoxContext;
/* Create the ACL list for the module. */
static const UvBoxAclItem g_box_acl[] = {
{PORTB, sizeof(*PORTB), UVISOR_TACLDEF_PERIPH},
{RTC, sizeof(*RTC), UVISOR_TACLDEF_PERIPH},
{LPTMR0, sizeof(*LPTMR0), UVISOR_TACLDEF_PERIPH},
};
/* Configure the secure box compartment. */
UVISOR_BOX_NAMESPACE("com.example.my-box-name");
UVISOR_BOX_CONFIG(my_box_name, g_box_acl, BOX_STACK_SIZE, BoxContext);
UVISOR_SET_MODE(uvisor_mode);
Description | [temporary] Set mode for the uVisor | |
Type | C/C++ pre-processor macro (object declaration) | |
Parameters | uvisor_mode |
UVISOR_DISABLED |
UVISOR_PERMISSIVE |
||
UVISOR_ENABLED |
Example:
#include "uvisor-lib/uvisor-lib.h"
/* Set the uVisor mode. */
UVISOR_SET_MODE(UVISOR_ENABLED);
Note:
-
This macro is only needed temporarily (uVisor disabled by default) and will be removed in the future.
-
This macro must be used only once in the top level yotta executable.
UVISOR_SET_MODE_ACL(uvisor_mode, const UvBoxAcl *main_box_acl_list);
Description | [temporary] Set mode for the uVisor and provide background ACLs for the main box | |
Type | C/C++ pre-processor macro (object declaration) | |
Parameters | uvisor_mode |
UVISOR_DISABLED |
UVISOR_PERMISSIVE |
||
UVISOR_ENABLED |
||
const UvBoxAclItem *main_box_acl_list |
List of ACLs for the main box (background ACLs) |
Example:
#include "uvisor-lib/uvisor-lib.h"
/* Create background ACLs for the main box. */
static const UvBoxAclItem g_background_acl[] = {
{UART0, sizeof(*UART0), UVISOR_TACL_PERIPHERAL},
{UART1, sizeof(*UART1), UVISOR_TACL_PERIPHERAL},
{PIT, sizeof(*PIT), UVISOR_TACL_PERIPHERAL},
};
/* Set the uVisor mode. */
UVISOR_SET_MODE_ACL(UVISOR_ENABLED, g_background_acl);
Note:
-
This macro is only needed temporarily (uVisor disabled by default) and will be removed in the future.
-
This macro must be used only once in the top level yotta executable.
UVISOR_BOX_NAMESPACE(static const char const namespace[])
Description | Specify the namespace for a box.
| |
Type | C/C++ pre-processor macro (pseudo-function) | |
Parameters | namespace |
The namespace of the box |
Example:
#include "uvisor-lib/uvisor-lib.h"
/* Configure the secure box. */
UVISOR_BOX_NAMESPACE("com.example.my-box-name");
UVISOR_BOX_CONFIG(my_box_name, UVISOR_BOX_STACK_SIZE);
uint32_t secure_gateway(box_name, uint32_t target_fn, ...)
Description | Call a function using the context of a secure box | |
Type | C/C++ pre-processor macro (pseudo-function) | |
Return value | [optional] A maximum of one 32bit value | |
Parameters | box_name |
Secure box name |
uint32_t target_fn |
Function to execute in the secure context | |
... |
A maximum of four 32bit arguments |
Example:
/* The box is configured here. */
...
/* The actual function implementation */
extern "C" uint32_t __secure_sum(uint32_t op1, uint32_t op2)
{
return op1 + op2;op3 + op4;
}
/* The entry point to the actual function implementation */
uint32_t secure_sum(uint32_t op1, uint32_t op2)
{
return secure_gateway(my_box_name, __secure_sum, op1, op2)
}
A box identity identifies a security domain uniquely and globally.
The box identity API can be used to determine the source box of an inbound secure gateway call. This can be useful for implementing complex authorization logic between mutually distrustful security domains.
uVisor provides the ability to retrieve the box ID of the current box (uvisor_box_id_self
), or of the box that most recently called the current box through a secure gateway (uvisor_box_id_caller
).
The box ID number is not constant and can change between reboots. But, the box ID number can be used as a token to retrieve a constant string identifier, known as the box namespace.
A box namespace is a static, box-specific string, that can help identify which box has which ID at run-time. In the future, the box namespace will be guaranteed to be globally unique.
A full example using this API is available at example-uvisor-box-id.
int uvisor_box_id_self(void)
Description | Get the ID of the current box | |
Return value | The ID of the current box |
int uvisor_box_id_caller(void)
Description | Get the ID of the box that is calling the current box through the most recent secure gateway | |
Return value | The ID of the caller box, or -1 if there is no secure gateway calling box |
int uvisor_box_namespace(int box_id, char *box_namespace, size_t length)
Description | Copy the namespace of the specified box to the provided buffer. | |
Return value | Return how many bytes were copied into box_namespace . Return UVISOR_ERROR_INVALID_BOX_ID if the provided box ID is invalid. Return UVISOR_ERROR_BUFFER_TOO_SMALL if the provided box_namespace is too small to hold MAX_BOX_NAMESPACE_LENGTH bytes. Return UVISOR_ERROR_BOX_NAMESPACE_ANONYMOUS if the box is anonymous. |
|
Parameters | int box_id |
The ID of the box you want to retrieve the namespace of |
char *box_namespace |
The buffer where the box namespace will be copied to | |
size_t length |
The length in bytes of the provided box_namespace buffer |
Currently the following low level operations are permitted:
- Interrupt management.
void vIRQ_SetVector(uint32_t irqn, uint32_t vector)
Description | Register an ISR to the currently active box | |
Parameters | uint32_t irqn |
IRQn |
uint32_t vector |
Interrupt handler; if 0 the IRQn slot is de-registered for the current box |
uint32_t vIRQ_GetVector(uint32_t irqn)
Description | Get the ISR registered for IRQn | |
Return value | The ISR registered for IRQn, if present; 0 otherwise | |
Parameters | uint32_t irqn |
IRQn |
void vIRQ_EnableIRQ(uint32_t irqn)
Description | Enable IRQn for the currently active box | |
Parameters | uint32_t irqn |
IRQn |
void vIRQ_DisableIRQ(uint32_t irqn)
Description | Disable IRQn for the currently active box | |
Parameters | uint32_t irqn |
IRQn |
void vIRQ_ClearPendingIRQ(uint32_t irqn)
Description | Clear pending status of IRQn | |
Parameters | uint32_t irqn |
IRQn |
void vIRQ_SetPendingIRQ(uint32_t irqn)
Description | Set pending status of IRQn | |
Parameters | uint32_t irqn |
IRQn |
uint32_t vIRQ_GetPendingIRQ(uint32_t irqn)
Description | Get pending status of IRQn | |
Parameters | uint32_t irqn |
IRQn |
void vIRQ_SetPriority(uint32_t irqn, uint32_t priority)
Description | Set priority level of IRQn | |
Parameters | uint32_t irqn |
IRQn |
uint32_t priority |
Priority level (minimum: 1) |
uint32_t vIRQ_GetPriority(uint32_t irqn)
Description | Get priority level of IRQn | |
Return value | The priority level of IRQn, if available; 0 otherwise | |
Parameters | uint32_t irqn |
IRQn |
int vIRQ_GetLevel(void)
Description | Get level of currently active IRQn, if any | |
Return value | The priority level of the currently active IRQn, if any; -1 otherwise |
typedef uint32_t UvisroBoxAcl; /* Permssion mask */
typedef struct
{
const volatile void* start; /* Start address of the protected area */
uint32_t length; /* Size of the protected area */
UvisorBoxAcl acl; /* Permission mask for the protected area */
} UvisorBoxAclItem;
Error reason | Error code |
---|---|
PERMISSION_DENIED |
1 |
SANITY_CHECK_FAILED |
2 |
NOT_IMPLEMENTED |
3 |
NOT_ALLOWED |
4 |
FAULT_MEMMANAGE |
5 |
FAULT_BUS |
6 |
FAULT_USAGE |
7 |
FAULT_HARD |
8 |
FAULT_DEBUG |
9 |