TF-M input/output control (IOCTL)

The TF-M IOTCL library provides an API for platform-specific TF-M services. These services are added by the platform partition. The APIs are available for applications that implement Non-Secure Processing Environment (NSPE) alongside Secure Processing Environment (SPE).

For more information on implementing TF-M in your application, see Trusted Firmware-M in the nRF Connect SDK. For more information about NSPE and SPE, see Processing environments in the nRF Connect SDK.

Functionality

Platform-specific services are internally accessed through the tfm_platform_hal_ioctl() function. Wrapper functions for these accesses are defined in tfm_ioctl_ns_api.c and tfm_ioctl_s_api.c.

The supported platform services are defined by tfm_platform_ioctl_core_reqest_types_t in tfm_ioctl_core_api.h.

/** @brief Supported request types.
 */
enum tfm_platform_ioctl_core_reqest_types_t {
	TFM_PLATFORM_IOCTL_READ_SERVICE,
	TFM_PLATFORM_IOCTL_WRITE32_SERVICE,
	TFM_PLATFORM_IOCTL_GPIO_SERVICE,
	TFM_PLATFORM_IOCTL_MRAMC_INIT_SERVICE,
	TFM_PLATFORM_IOCTL_MRAMC_SET_WEN_SERVICE,
	/* Last core service, start platform specific from this value. */
	TFM_PLATFORM_IOCTL_CORE_LAST
};

Set the CONFIG_TFM_PARTITION_PLATFORM Kconfig option to enable the services.

Read service

The TF-M IOTCL read service allows the NSPE to access memory areas within the SPE that would otherwise be inaccessible to it. For a memory location to be accessible, it must be within the allowed memory areas defined by the tfm_platform_user_memory_ranges.h file.

Caution

Adding locations to the allowed memory areas for reading might lead to major security consequences if the NSPE has access to sensitive data or code in the SPE.

The service is used by the tfm_platform_mem_read() function. For example, you can use the service to read the OTP value from UICR registers:

#include <tfm_ioctl_api.h>

void read_otp_value(void) {
    uint32_t otp_value;
    int err;
    enum tfm_platform_err_t plt_err;

    plt_err = tfm_platform_mem_read(buf, (intptr_t)&NRF_UICR_S->OTP[0], sizeof(otp_value), &err);
    if (plt_err != TFM_PLATFORM_ERR_SUCCESS || err != 0) {
        /* Handle error */
    }

    printk("OTP[0]: %u\n", otp_value);
}

See the TF-M Hello World sample for example usage.

Write service

The TF-M IOTCL write service allows the NSPE to write words of memory to the SPE.

For a memory location to be writable, it must be within the allowed memory areas defined by the tfm_platform_user_memory_ranges.h file.

The allowed areas for writing are described by the tfm_write32_service_address structure that contains the following fields:

struct tfm_write32_service_address {
    uint32_t addr; /* Mandatory field with the address to write to. */
    uint32_t mask; /* Mandatory field with the bitmask of the bits to write. */
    const uint32_t *allowed_values; /* Optional field with the allowed values to write. If NULL, any value is allowed. */
    const uint32_t allowed_values_array_size; /* Optional field with the size of the allowed values array. Must be 0 if allowed_values is NULL. */
};

Caution

Adding locations to the allowed memory areas for writing might lead to major security consequences if the NSPE has access to sensitive data or code in the SPE.

The service is used by the tfm_platform_mem_write32() function. For example, you can use the service to write a value to a memory location in the SPE:

#include <tfm_ioctl_api.h>

void write_memory_value(void) {
    uint32_t *addr = (uint32_t *)0x20000000; /* Randomly picked address for demonstration purposes only */
    uint32_t value_to_write = 0x80;
    uint32_t mask = 0xFF;
    int err;
    enum tfm_platform_err_t plt_err;

    plt_err = tfm_platform_mem_write32(addr, value_to_write, mask, &err);
    if (plt_err != TFM_PLATFORM_ERR_SUCCESS || err != 0) {
        /* Handle error */
    }

}

Prerequisites

This library requires that TF-M is installed on the device.

API documentation

Header file: include/tfm/tfm_ioctl_api.h
Source files: modules/tfm/tfm/boards/src/
TFM IOCTL API