| Samsung Internal API reference 2.0

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

Data Structures | Typedefs | Functions
Loadable driver API
Samsung Internal 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

TEES_InterruptHandle

`#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] | filp | Pointer 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] | addr | Offset in the file (or other object) referred to by the file descriptor filp->share_fd
  [in] | size | The length of the buffer
  [in] | prot | Desired 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] | nr | An interrupt id.
  [in] | handler | An interrupt handler.
  [out] | handle | An interrupt handle.

Return values

  TEE_SUCCESS | on success.
  TEE_ERROR | on 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);
TEES_CompleteInterrupt(handle);
} 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] | handle | An interrupt handle.

Return values

  TEE_SUCCESS | on success.
  TEE_ERROR | on 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);
TEES_CompleteInterrupt(handle);
} 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) {
TEES_GenerateInterrupt(handle);
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] | filp | Pointer 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] | ret | Ret value that should be delivered to the driver's client.

Return values

  0 | no error.
  -1 | on 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] | addr | Start address pointer.
  [in] | nbytes | Size of the region.

Return values

  0 | no error.
  -1 | on failure. errno variable is set appropriately.

int TEES_DcacheFlush | ( | const void * | addr,
|  | size_t | nbytes
| ) |  |

`#include <cache.h>`

Perform data cache flush.

Parameters

  [in] | addr | Start address pointer.
  [in] | nbytes | Size of the region.

Return values

  0 | no error.
  -1 | on 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] | info | A pointer to struct usr_drv_info that contains information describing the driver.

Return values

  non-negative | driver handle.
  -1 | on 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] | handle | An interrupt handle.

Return values

  TEE_SUCCESS | on success.
  TEE_ERROR | on 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);
TEES_CompleteInterrupt(handle);
} 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) {
TEES_GenerateInterrupt(handle);
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] | name | A pointer to an array storing driver name
  [in] | fops | A pointer to struct fops containing file operations supported by driver
  [in] | drvid | Identificator of driver asset, used by access control
  [out] | info | Double pointer to struct usr_drv_info that contains information describing the driver

Return values

  0 | no error.
  -1 | on 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] | name | A pointer to an array storing driver name
  [in] | fops | A pointer to struct fops containing file operations supported by driver
  [in] | drvid | Identificator of driver asset, used by access control
  [out] | info | Double pointer to struct usr_drv_info that contains information describing the driver

Return values

  0 | no error.
  -1 | on 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_PARAMETERS | when destr is NULL
  TEE_SUCCESS | all 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] | info | A pointer to struct usr_drv_info that contains information describing the driver.
  [in] | cmd | An ioctl() command being added.
  [in] | desc | An ioctl() arguments descriptor, see below for details.

Return values

  0 | on 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] | info | Double pointer to struct usr_drv_info that contains information describing the driver.

Return values

  non-negative | driver handle.
  -1 | on 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] | handle | An interrupt handle.

Return values

  TEE_SUCCESS | on success.
  TEE_ERROR | on 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] | addr | Starting address of releasing buffer
  [in] | size | The length of the mapping

Return values

  0 | no error.
  -1 | on 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] | handle | An interrupt handle.
  [in] | timeout | waiting timeout.

Return values

  TEE_SUCCESS | on success.
  TEE_ERROR | on 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);
TEES_CompleteInterrupt(handle);
} 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) {
TEES_GenerateInterrupt(handle);
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;
}