Samsung Internal API reference  2.0
Loadable driver API

Data Structures

struct  intrinfo
 

Typedefs

typedef struct __TEES_InterruptHandle * TEES_InterruptHandle
 
typedef void(* intruhandler) (struct intrinfo *)
 
typedef void(* TEES_DriverDestructor_t) (int)
 

Functions

int TEES_DcacheFlush (const void *addr, size_t nbytes)
 Perform data cache flush. More...
 
int TEES_DcacheClean (const void *addr, size_t nbytes)
 Perform data cache clean. More...
 
int TEES_InitDriver (char *name, struct fops *fops, unsigned int drvid, struct usr_drv_info **info)
 Register user driver in /dev/ directory under name, using mask of file operations fops and drvid of served asset. More...
 
int TEES_RegisterIoctlDesc (struct usr_drv_info *info, unsigned int cmd, struct ioctl_desc *desc)
 Register an ioctl() cmd for driver. More...
 
int TEES_FiniDriver (struct usr_drv_info *info)
 Allow to release driver that was registered by using struct usr_drv_info. More...
 
int TEES_RegisterDriver (char *name, struct fops *fops, unsigned int drvid, struct usr_drv_info **info) _deprecated_
 Register user driver in /dev/ directory under name, using mask of file operations fops and drvid of served asset. More...
 
int TEES_ReleaseDriver (struct usr_drv_info **info) _deprecated_
 Allow to release driver that was registered by using struct usr_drv_info. More...
 
int TEES_CompleteRequest (struct drv_info *filp, long ret)
 Complete deferred request(read, write, etc.) to driver. More...
 
void * TEES_AcquireUserBuffer (struct drv_info *filp, uint64_t addr, const size_t size, int prot)
 Get shared mapped area to use as buffer. this API can not be used in read()/write() cmd for driver. More...
 
int TEES_ReleaseUserBuffer (const void *addr, const size_t size)
 Deletes the shared mapped area for the specified address range. More...
 
TEE_Result TEES_AllocateInterrupt (int nr, intruhandler handler, TEES_InterruptHandle *handle)
 This function is used to allocate interrupt and register user handler. More...
 
TEE_Result TEES_ReleaseInterrupt (TEES_InterruptHandle handle)
 This function is used to release interrupt. More...
 
TEE_Result TEES_GenerateInterrupt (TEES_InterruptHandle handle)
 This function is used to generate interrupt. More...
 
TEE_Result TEES_WaitForInterrupt (TEES_InterruptHandle handle, uint32_t timeout)
 This function is used to wait for interrupt. More...
 
TEE_Result TEES_CompleteInterrupt (TEES_InterruptHandle handle)
 This function is used to notify about interrupt arrival. More...
 
TEE_Result TEES_RegisterDriverDestructor (TEES_DriverDestructor_t destr)
 Initializes driver destructor function pointer. The destructor will be called when secure kernel generates any interrupting signal. More...
 

Detailed Description

Provides set of function to interact with device drivers from userspace comonents.


Data Structure Documentation

struct intrinfo

interrupt information structure

Data Fields
unsigned int cpu
unsigned int nr

Typedef Documentation

intruhandler

#include <tee_interrupt.h>

interrupt handler abstraction

TEES_DriverDestructor_t

#include <tee_ta_destructor.h>

Pointer to driver destructor function. int parameter - is an interrupting signal value

#include <tee_interrupt.h>

interrupt handle abstraction

Function Documentation

void* TEES_AcquireUserBuffer ( struct drv_info *  filp,
uint64_t  addr,
const size_t  size,
int  prot 
)

#include <driver.h>

Get shared mapped area to use as buffer. this API can not be used in read()/write() cmd for driver.

Parameters
[in]filpPointer to struct drv_info related to driver:
           struct drv_info {
              int pid;
              int fd;
              int share_fd;
              struct uuid uuid;
              char profile_name[PROFILE_STR_LEN];
           };
           
[in]addrOffset in the file (or other object) referred to by the file descriptor filp->share_fd
[in]sizeThe length of the buffer
[in]protDesired memory protection of the mapping
Returns
Pointer to userspace buffer

Example:

static int driver_ioctl(struct drv_info *info, int ioctl_cmd, unsigned long ioctl_data)
{
(void) ioctl_cmd;
char *vaddr = NULL;
// Always return "Ioctl".
vaddr = TEES_AcquireUserBuffer(info, (uint64_t)ioctl_data, (ROUND_PGUP(ioctl_data) - ioctl_data), PROT_READ | PROT_WRITE);
strcpy(vaddr, "Ioctl");
TEES_ReleaseUserBuffer(vaddr, (ROUND_PGUP(ioctl_data) - ioctl_data));
return 0;
}
TEE_Result TEES_AllocateInterrupt ( int  nr,
intruhandler  handler,
TEES_InterruptHandle handle 
)

#include <tee_interrupt.h>

This function is used to allocate interrupt and register user handler.

Parameters
[in]nrAn interrupt id.
[in]handlerAn interrupt handler.
[out]handleAn interrupt handle.
Return values
TEE_SUCCESSon success.
TEE_ERRORon fail.

Example:

#define NUM_IRQS_GENERATED (10)
static TEES_InterruptHandle handle;
void handler(struct intrinfo *info)
{
const int error = errno;
if (info->nr == IRQ) {
interrupt_counter++;
// printf_no_alloc() used here due to printf() can sleep in allocator
// but sleeping functions are prohibited in signal handlers
printf_no_alloc("IRQ: nr = %d, counter = %d\n", info->nr, interrupt_counter);
} else {
printf_no_alloc("ERROR:UNKNOWN IRQ: nr = %d\n", info->nr);
TEE_Panic(0);
}
errno = error;
}
static int test_interrupt_allocate(TEE_Param *param)
{
(void)param;
TEE_Result ret;
ret = TEES_AllocateInterrupt(IRQ, &handle, handler);
if (ret != TEE_SUCCESS) {
return -1;
}
return 0;
}
TEE_Result TEES_CompleteInterrupt ( TEES_InterruptHandle  handle)

#include <tee_interrupt.h>

This function is used to notify about interrupt arrival.

Parameters
[in]handleAn interrupt handle.
Return values
TEE_SUCCESSon success.
TEE_ERRORon failure.

Example:

#define NUM_IRQS_GENERATED (10)
static TEES_InterruptHandle handle;
void handler(struct intrinfo *info)
{
const int error = errno;
if (info->nr == IRQ) {
interrupt_counter++;
// printf_no_alloc() used here due to printf() can sleep in allocator
// but sleeping functions are prohibited in signal handlers
printf_no_alloc("IRQ: nr = %d, counter = %d\n", info->nr, interrupt_counter);
} else {
printf_no_alloc("ERROR:UNKNOWN IRQ: nr = %d\n", info->nr);
TEE_Panic(0);
}
errno = error;
}
static int test_interrupt_generate(TEE_Param *param)
{
(void)param;
int i = 0;
while (i < NUM_IRQS_GENERATED) {
if (TEES_WaitForInterrupt(handle, 0)) {
printf("Failed test TEES_WaitForInterrupt() call at line %d.\n"
"errno = %d\n", __LINE__, errno);
return -1;
}
i++;
}
return 0;
}
int TEES_CompleteRequest ( struct drv_info *  filp,
long  ret 
)

#include <driver.h>

Complete deferred request(read, write, etc.) to driver.

Parameters
[in]filpPointer to structure related to driver:
           struct drv_info {
              int pid;
              int fd;
              int share_fd;
              struct uuid uuid;
              char profile_name[PROFILE_STR_LEN];
           };
           
[in]retRet value that should be delivered to the driver's client.
Return values
0no error.
-1on failure. errno variable is set appropriately.

Example:

static struct drv_info filp_write;
static struct drv_info filp_read;
static bool pending_write = false;
static bool pending_read = false;
static int current_data;
static char *current_vaddr;
static void complete_read_write(void)
{
// Wait to receive both read and write requests
if (pending_read && pending_write) {
pending_read = false;
pending_write = false;
*(int *)current_vaddr = current_data;
TEES_ReleaseUserBuffer(current_vaddr, 4);
TEES_CompleteRequest(&filp_read, 0);
TEES_CompleteRequest(&filp_write, 0);
}
}
int TEES_DcacheClean ( const void *  addr,
size_t  nbytes 
)

#include <cache.h>

Perform data cache clean.

Parameters
[in]addrStart address pointer.
[in]nbytesSize of the region.
Return values
0no error.
-1on failure. errno variable is set appropriately.
int TEES_DcacheFlush ( const void *  addr,
size_t  nbytes 
)

#include <cache.h>

Perform data cache flush.

Parameters
[in]addrStart address pointer.
[in]nbytesSize of the region.
Return values
0no error.
-1on failure. errno variable is set appropriately.
int TEES_FiniDriver ( struct usr_drv_info info)

#include <driver.h>

Allow to release driver that was registered by using struct usr_drv_info.

Parameters
[in]infoA pointer to struct usr_drv_info that contains information describing the driver.
Return values
non-negativedriver handle.
-1on failure. errno variable is set appropriately.

Example:

ret = TEES_FiniDriver(my_driver_info);
if (ret) {
printf("release_driver failed, ret = %d\n", ret);
}
TEE_Result TEES_GenerateInterrupt ( TEES_InterruptHandle  handle)

#include <tee_interrupt.h>

This function is used to generate interrupt.

Parameters
[in]handleAn interrupt handle.
Return values
TEE_SUCCESSon success.
TEE_ERRORon failure.

Example:

#define NUM_IRQS_GENERATED (10)
static TEES_InterruptHandle handle;
void handler(struct intrinfo *info)
{
const int error = errno;
if (info->nr == IRQ) {
interrupt_counter++;
// printf_no_alloc() used here due to printf() can sleep in allocator
// but sleeping functions are prohibited in signal handlers
printf_no_alloc("IRQ: nr = %d, counter = %d\n", info->nr, interrupt_counter);
} else {
printf_no_alloc("ERROR:UNKNOWN IRQ: nr = %d\n", info->nr);
TEE_Panic(0);
}
errno = error;
}
static int test_interrupt_generate(TEE_Param *param)
{
(void)param;
int i = 0;
while (i < NUM_IRQS_GENERATED) {
if (TEES_WaitForInterrupt(irq_fd, 0) != TEE_SUCCESS) {
return -1;
}
i++;
}
return 0;
}
int TEES_InitDriver ( char *  name,
struct fops fops,
unsigned int  drvid,
struct usr_drv_info **  info 
)

#include <driver.h>

Register user driver in /dev/ directory under name, using mask of file operations fops and drvid of served asset.

Parameters
[in]nameA pointer to an array storing driver name
[in]fopsA pointer to struct fops containing file operations supported by driver
[in]drvidIdentificator of driver asset, used by access control
[out]infoDouble pointer to struct usr_drv_info that contains information describing the driver
Return values
0no error.
-1on failure. errno variable is set appropriately.

Example:

int ret;
char my_driver_name[] = "my_driver";
struct usr_drv_info *my_driver_info = NULL;
struct fops file_ops = {0};
file_ops.open = drv_open;
file_ops.close = drv_close;
file_ops.read = drv_read;
file_ops.write = drv_write;
ret = TEES_InitDriver(my_driver_name, &file_ops, ACC_PERM_I2C, &my_driver_info);
if (ret) {
printf("register_driver failed, ret = %d\n", ret);
return TEE_ERROR_GENERIC;
}
int TEES_RegisterDriver ( char *  name,
struct fops fops,
unsigned int  drvid,
struct usr_drv_info **  info 
)

#include <driver.h>

Register user driver in /dev/ directory under name, using mask of file operations fops and drvid of served asset.

Deprecated:
Use TEES_InitDriver() instead
Parameters
[in]nameA pointer to an array storing driver name
[in]fopsA pointer to struct fops containing file operations supported by driver
[in]drvidIdentificator of driver asset, used by access control
[out]infoDouble pointer to struct usr_drv_info that contains information describing the driver
Return values
0no error.
-1on failure. errno variable is set appropriately.

Example:

int ret;
char my_driver_name[] = "my_driver";
struct usr_drv_info *my_driver_info = NULL;
struct fops file_ops = {0};
file_ops.open = drv_open;
file_ops.close = drv_close;
file_ops.read = drv_read;
file_ops.write = drv_write;
ret = TEES_RegisterDriver(my_driver_name, &file_ops, ACC_PERM_I2C, &my_driver_info);
if (ret) {
printf("register_driver failed, ret = %d\n", ret);
return TEE_ERROR_GENERIC;
}
TEE_Result TEES_RegisterDriverDestructor ( TEES_DriverDestructor_t  destr)

#include <tee_ta_destructor.h>

Initializes driver destructor function pointer. The destructor will be called when secure kernel generates any interrupting signal.

Parameters
[in]destr- pointer to driver destructor function.
Return values
TEE_ERROR_BAD_PARAMETERSwhen destr is NULL
TEE_SUCCESSall other cases
int TEES_RegisterIoctlDesc ( struct usr_drv_info info,
unsigned int  cmd,
struct ioctl_desc desc 
)

#include <driver.h>

Register an ioctl() cmd for driver.

Parameters
[in]infoA pointer to struct usr_drv_info that contains information describing the driver.
[in]cmdAn ioctl() command being added.
[in]descAn ioctl() arguments descriptor, see below for details.
Return values
0on success, -1 otherwise. errno variable is set appropriately.

Example:

struct example { uint32_t a; char *b; uint32_t items_cnt; uint32_t items[]; };

struct example data = { .a = 0xa5a5a5a5, .b = "0123456789", .items_cnt = 3, .items = {0, 1, 2}, };

struct ioctl_desc example_desc = { .cnt = 5, .tpl = { {.type = DESC_ATOM_VAL, .len = sizeof(uint32_t) }, {.type = DESC_ATOM_REF, .len = 10 }, {.type = DESC_ATOM_ARR_CNT_0, .len = sizeof(uint32_t) }, {.type = DESC_ATOM_ARR_ITEM_0, .len = 1 }, {.type = DESC_ATOM_VAL, .len = sizeof(uint32_t) }, }, };

ret = TEES_RegisterIoctlDesc(my_driver_info, EXAMPLE_IOCTL_ID, &example_desc);
if (ret) {
printf("register ioctl() desc failed, ret = %d\n", ret);
}
int TEES_ReleaseDriver ( struct usr_drv_info **  info)

#include <driver.h>

Allow to release driver that was registered by using struct usr_drv_info.

Deprecated:
Use TEES_FiniDriver() instead
Parameters
[in]infoDouble pointer to struct usr_drv_info that contains information describing the driver.
Return values
non-negativedriver handle.
-1on failure. errno variable is set appropriately.

Example:

ret = TEES_ReleaseDriver(my_driver_info);
if (ret) {
printf("release_driver failed, ret = %d\n", ret);
}
TEE_Result TEES_ReleaseInterrupt ( TEES_InterruptHandle  handle)

#include <tee_interrupt.h>

This function is used to release interrupt.

Parameters
[in]handleAn interrupt handle.
Return values
TEE_SUCCESSon success.
TEE_ERRORon failure.

Example:

static TEES_InterruptHandle handle;
static int test_interrupt_release(TEE_Param *param)
{
(void)param;
if (TEES_ReleaseInterrupt(handle) != TEE_SUCCESS) {
return -1;
}
return 0;
}
int TEES_ReleaseUserBuffer ( const void *  addr,
const size_t  size 
)

#include <driver.h>

Deletes the shared mapped area for the specified address range.

Parameters
[in]addrStarting address of releasing buffer
[in]sizeThe length of the mapping
Return values
0no error.
-1on failure. errno variable is set appropriately.

Example:

static int driver_ioctl(struct drv_info *info, int ioctl_cmd, unsigned long ioctl_data)
{
(void) ioctl_cmd;
char *vaddr = NULL;
// Always return "Ioctl".
vaddr = TEES_AcquireUserBuffer(info, (uint64_t)ioctl_data, (ROUND_PGUP(ioctl_data) - ioctl_data), PROT_READ | PROT_WRITE);
strcpy(vaddr, "Ioctl");
TEES_ReleaseUserBuffer(vaddr, (ROUND_PGUP(ioctl_data) - ioctl_data));
return 0;
}
TEE_Result TEES_WaitForInterrupt ( TEES_InterruptHandle  handle,
uint32_t  timeout 
)

#include <tee_interrupt.h>

This function is used to wait for interrupt.

Parameters
[in]handleAn interrupt handle.
[in]timeoutwaiting timeout.
Return values
TEE_SUCCESSon success.
TEE_ERRORon failure.

Example:

#define NUM_IRQS_GENERATED (10)
static TEES_InterruptHandle handle;
void handler(struct intrinfo *info)
{
const int error = errno;
if (info->nr == IRQ) {
interrupt_counter++;
// printf_no_alloc() used here due to printf() can sleep in allocator
// but sleeping functions are prohibited in signal handlers
printf_no_alloc("IRQ: nr = %d, counter = %d\n", info->nr, interrupt_counter);
} else {
printf_no_alloc("ERROR:UNKNOWN IRQ: nr = %d\n", info->nr);
TEE_Panic(0);
}
errno = error;
}
static int test_interrupt_generate(TEE_Param *param)
{
(void)param;
int i = 0;
while (i < NUM_IRQS_GENERATED) {
if (TEES_WaitForInterrupt(handle, NULL) != TEE_SUCCESS) {
printf("Failed test TEES_WaitForInterrupt() call at line %d.\n"
"errno = %d\n", __LINE__, errno);
return -1;
}
i++;
}
return 0;
}