Skip to content

Commit

Permalink
platform: nordic: Add platform memory write service
Browse files Browse the repository at this point in the history
There are some hardware registers in Nordic platforms
which are mapped as secure only. In order to allow the
non-secure application to control these registers I added
here a secure service which allows 32-bit writes to secure
mapped memory. The writes are only allowed on  addresses and
masks defined in a header list. It is also possible to
provide an allowed_values list in order to further limit
the accepted values.

Renamed:  tfm_read_ranges.h -> tfm_platform_user_memory_ranges.h
since now it can be used for both reads and writes.

The list in the current platforms is empty and might be populated
later.

Signed-off-by: Georgios Vasilakis <georgios.vasilakis@nordicsemi.no>
Change-Id: Ifa31ba73ec07b216a7e987653255fcc6e9d3989c
  • Loading branch information
Vge0rge authored and adeaarm committed Jun 17, 2024
1 parent 20e5801 commit 57b3342
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef TFM_READ_RANGES_H__
#define TFM_READ_RANGES_H__
#ifndef TFM_PLATFORM_USER_MEMORY_RANGES_H__
#define TFM_PLATFORM_USER_MEMORY_RANGES_H__

#include <tfm_ioctl_core_api.h>

Expand Down Expand Up @@ -33,4 +33,9 @@ static const struct tfm_read_service_range ranges[] = {
{ .start = FICR_XOSC32MTRIM_ADDR, .size = FICR_XOSC32MTRIM_SIZE },
};

#endif /* TFM_READ_RANGES_H__ */
static const struct tfm_write32_service_address tfm_write32_service_addresses[] = {
/* This is a dummy value because this table cannot be empty */
{.addr = 0xFFFFFFFF, .mask = 0x0, .allowed_values = NULL, .allowed_values_array_size = 0},
};

#endif /* TFM_PLATFORM_USER_MEMORY_RANGES_H__ */
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ extern "C" {
*/
enum tfm_platform_ioctl_core_reqest_types_t {
TFM_PLATFORM_IOCTL_READ_SERVICE,
TFM_PLATFORM_IOCTL_WRITE32_SERVICE,
TFM_PLATFORM_IOCTL_GPIO_SERVICE,

/* Last core service, start platform specific from this value. */
TFM_PLATFORM_IOCTL_CORE_LAST
};
Expand All @@ -50,6 +50,20 @@ struct tfm_read_service_out_t {
uint32_t result;
};

/** @brief Argument list for each platform write32 service.
*/
struct tfm_write32_service_args_t {
uint32_t addr;
uint32_t value;
uint32_t mask;
};
/** @brief Output list for each write32 platform service
*/

struct tfm_write32_service_out_t {
uint32_t result;
};

enum tfm_gpio_service_type {
/** Select which MCU / Subsystem controls the pin */
TFM_GPIO_SERVICE_TYPE_PIN_MCU_SELECT = 0,
Expand Down Expand Up @@ -88,13 +102,42 @@ struct tfm_gpio_service_out {
enum tfm_platform_err_t tfm_platform_mem_read(void *destination, uint32_t addr,
size_t len, uint32_t *result);

/**
* @brief Perform a write32 operation.
*
* @param[in] addr Address to write to
* @param[in] value 32 bit value to write
* @param[in] mask Mask applied to the write value
* @param[out] result An enum tfm_write32_service_result value
*
* @return Returns values as specified by the tfm_platform_err_t
*/
enum tfm_platform_err_t tfm_platform_mem_write32(uint32_t addr, uint32_t value,
uint32_t mask, uint32_t *result);

/** @brief Represents an accepted read range.
*/
struct tfm_read_service_range {
uint32_t start;
size_t size;
};

/** @brief Represents the accepted addresses and masks for write32 service.
*/
struct tfm_write32_service_address {
uint32_t addr;
uint32_t mask;
const uint32_t *allowed_values;
const uint32_t allowed_values_array_size;
};

enum tfm_write32_service_result {
TFM_WRITE32_SERVICE_SUCCESS,
TFM_WRITE32_SERVICE_ERROR_INVALID_ADDRESS,
TFM_WRITE32_SERVICE_ERROR_INVALID_MASK,
TFM_WRITE32_SERVICE_ERROR_INVALID_VALUE,
};

/**
* @brief Perform a GPIO MCU select operation.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ tfm_platform_hal_read_service(const psa_invec *in_vec,
enum tfm_platform_err_t
tfm_platform_hal_gpio_service(const psa_invec *in_vec, const psa_outvec *out_vec);


enum tfm_platform_err_t
tfm_platform_hal_write32_service(const psa_invec *in_vec,
const psa_outvec *out_vec);

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,31 @@ enum tfm_platform_err_t tfm_platform_gpio_pin_mcu_select(uint32_t pin_number, ui
return TFM_PLATFORM_ERR_NOT_SUPPORTED;
#endif
}

enum tfm_platform_err_t tfm_platform_mem_write32(uint32_t addr, uint32_t value,
uint32_t mask, uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_write32_service_args_t args;
struct tfm_write32_service_out_t out;

in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);

out_vec.base = (void *)&out;
out_vec.len = sizeof(out);

args.addr = addr;
args.value = value;
args.mask = mask;
/* Allowed values cannot be specified by the user */

ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_WRITE32_SERVICE, &in_vec,
&out_vec);

*result = out.result;

return ret;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <tfm_hal_isolation.h>

/* This contains the user provided allowed ranges */
#include <tfm_read_ranges.h>
#include <tfm_platform_user_memory_ranges.h>

#include <hal/nrf_gpio.h>

Expand Down Expand Up @@ -127,3 +127,76 @@ tfm_platform_hal_gpio_service(const psa_invec *in_vec, const psa_outvec *out_ve
}
#endif /* NRF_GPIO_HAS_SEL */

enum tfm_platform_err_t tfm_platform_hal_write32_service(const psa_invec *in_vec,
const psa_outvec *out_vec)
{
uint32_t addr;
uint32_t mask;
uint32_t allowed_values_array_size;

struct tfm_write32_service_args_t *args;
struct tfm_write32_service_out_t *out;

enum tfm_platform_err_t err;

if (in_vec->len != sizeof(struct tfm_write32_service_args_t) ||
out_vec->len != sizeof(struct tfm_write32_service_out_t)) {
return TFM_PLATFORM_ERR_INVALID_PARAM;
}

args = (struct tfm_write32_service_args_t *)in_vec->base;
out = (struct tfm_write32_service_out_t *)out_vec->base;

/* Assume failure, in case we don't find a match */
out->result = TFM_WRITE32_SERVICE_ERROR_INVALID_ADDRESS;
err = TFM_PLATFORM_ERR_INVALID_PARAM;

for (size_t i = 0; i < ARRAY_SIZE(tfm_write32_service_addresses); i++) {
addr = tfm_write32_service_addresses[i].addr;
mask = tfm_write32_service_addresses[i].mask;
allowed_values_array_size =
tfm_write32_service_addresses[i].allowed_values_array_size;

if (args->addr == addr) {
out->result = TFM_WRITE32_SERVICE_ERROR_INVALID_MASK;

if (args->mask == mask) {
/* Check for allowed values if provided */
if (allowed_values_array_size > 0 &&
tfm_write32_service_addresses[i].allowed_values != NULL) {
bool is_value_allowed = false;

for (int j = 0; j < allowed_values_array_size; j++) {

const uint32_t allowed_value =
tfm_write32_service_addresses[i]
.allowed_values[j];

if (allowed_value == (args->value & args->mask)) {
is_value_allowed = true;
break;
}
}

if (!is_value_allowed) {
out->result =
TFM_WRITE32_SERVICE_ERROR_INVALID_VALUE;
break;
}
}

uint32_t new_value = *(uint32_t *)addr;
/* Invert the mask to convert the masked bits to 0 first */
new_value &= ~args->mask;
new_value |= (args->value & args->mask);
*(uint32_t *)addr = new_value;

out->result = TFM_WRITE32_SERVICE_SUCCESS;
err = TFM_PLATFORM_ERR_SUCCESS;
break;
}
}
}

return err;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef TFM_READ_RANGES_H__
#define TFM_READ_RANGES_H__
#ifndef TFM_PLATFORM_USER_MEMORY_RANGES_H__
#define TFM_PLATFORM_USER_MEMORY_RANGES_H__

#include <tfm_ioctl_core_api.h>

Expand Down Expand Up @@ -33,4 +33,9 @@ static const struct tfm_read_service_range ranges[] = {
{ .start = FICR_XOSC32MTRIM_ADDR, .size = FICR_XOSC32MTRIM_SIZE },
};

#endif /* TFM_READ_RANGES_H__ */
static const struct tfm_write32_service_address tfm_write32_service_addresses[] = {
/* This is a dummy value because this table cannot be empty */
{.addr = 0xFFFFFFFF, .mask = 0x0, .allowed_values = NULL, .allowed_values_array_size = 0},
};

#endif /* TFM_PLATFORM_USER_MEMORY_RANGES_H__ */
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef TFM_READ_RANGES_H__
#define TFM_READ_RANGES_H__
#ifndef TFM_PLATFORM_USER_MEMORY_RANGES_H__
#define TFM_PLATFORM_USER_MEMORY_RANGES_H__

#include <tfm_ioctl_core_api.h>

Expand All @@ -25,4 +25,9 @@ static const struct tfm_read_service_range ranges[] = {
{ .start = FICR_RESTRICTED_ADDR, .size = FICR_RESTRICTED_SIZE },
};

#endif /* TFM_READ_RANGES_H__ */
static const struct tfm_write32_service_address tfm_write32_service_addresses[] = {
/* This is a dummy value because this table cannot be empty */
{.addr = 0xFFFFFFFF, .mask = 0x0, .allowed_values = NULL, .allowed_values_array_size = 0},
};

#endif /* TFM_PLATFORM_USER_MEMORY_RANGES_H__ */
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef TFM_READ_RANGES_H__
#define TFM_READ_RANGES_H__
#ifndef TFM_PLATFORM_USER_MEMORY_RANGES_H__
#define TFM_PLATFORM_USER_MEMORY_RANGES_H__

#include <tfm_ioctl_core_api.h>

Expand All @@ -25,4 +25,9 @@ static const struct tfm_read_service_range ranges[] = {
{ .start = FICR_RESTRICTED_ADDR, .size = FICR_RESTRICTED_SIZE },
};

#endif /* TFM_READ_RANGES_H__ */
static const struct tfm_write32_service_address tfm_write32_service_addresses[] = {
/* This is a dummy value because this table cannot be empty */
{.addr = 0xFFFFFFFF, .mask = 0x0, .allowed_values = NULL, .allowed_values_array_size = 0},
};

#endif /* TFM_PLATFORM_USER_MEMORY_RANGES_H__ */

0 comments on commit 57b3342

Please sign in to comment.