Skip to content

Commit

Permalink
drivers: stm32_etzpc: new driver to use firewall API
Browse files Browse the repository at this point in the history
Implement stm32_etzpc.c driver in the firewall driver directory.
Use the new firewall API to populate the firewall bus and register
the ETZPC as a firewall provider.

The ETZPC driver register the following ops:
-set_conf
-check_access
-acquire_access
-release_access
-check_memory_access
-acquire_memory_access
-release_memory_access

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
  • Loading branch information
GseoC committed May 3, 2024
1 parent 18ad475 commit 8501466
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 31 deletions.
28 changes: 25 additions & 3 deletions core/arch/arm/plat-stm32mp1/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <drivers/gic.h>
#include <drivers/pinctrl.h>
#include <drivers/stm32_etzpc.h>
#include <drivers/firewall/firewall_device.h>
#include <drivers/stm32_gpio.h>
#include <drivers/stm32_iwdg.h>
#include <drivers/stm32_tamp.h>
Expand All @@ -22,6 +23,8 @@
#include <kernel/panic.h>
#include <kernel/spinlock.h>
#include <kernel/tee_misc.h>
#include <libfdt.h>
#include <malloc.h>
#include <mm/core_memprot.h>
#include <platform_config.h>
#include <sm/psci.h>
Expand Down Expand Up @@ -302,10 +305,29 @@ service_init_late(init_stm32mp15_secure_srams);

static TEE_Result init_stm32mp1_drivers(void)
{
struct etzpc_device *etzpc_dev = stm32_get_etzpc_device();
struct dt_driver_provider *prov = NULL;
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t firewall_query_args[2] = { ETZPC_TZMA1_ID, SYSRAM_SEC_SIZE };
struct firewall_query firewall = {
.args = firewall_query_args,
.arg_count = ARRAY_SIZE(firewall_query_args),
};
int node = 0;

node = fdt_node_offset_by_compatible(get_embedded_dt(), -1,
"st,stm32-etzpc");
if (node < 0)
panic("Could not get ETZPC node");

etzpc_do_configure_tzma(etzpc_dev, 1,
SYSRAM_SEC_SIZE >> SMALL_PAGE_SHIFT);
prov = dt_driver_get_provider_by_node(node, DT_DRIVER_FIREWALL);
assert(prov);

firewall.firewall_ctrl = dt_driver_provider_priv_data(prov);

/* Secure SYSRAM */
res = firewall_set_configuration(&firewall);
if (res)
panic("Unable to secure SYSRAM");

if (SYSRAM_SIZE > SYSRAM_SEC_SIZE) {
size_t nsec_size = SYSRAM_SIZE - SYSRAM_SEC_SIZE;
Expand Down
3 changes: 3 additions & 0 deletions core/arch/arm/plat-stm32mp1/platform_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
#define UART7_BASE 0x40018000
#define UART8_BASE 0x40019000

#define ROM_BASE 0
#define ROM_SIZE 0x20000

/* Console configuration */
#define STM32MP1_DEBUG_USART_BASE UART4_BASE
#define GIC_SPI_UART4 84
Expand Down
268 changes: 248 additions & 20 deletions core/drivers/stm32_etzpc.c → core/drivers/firewall/stm32_etzpc.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2024, STMicroelectronics
*/

Expand All @@ -18,6 +18,7 @@
#include <assert.h>
#include <drivers/clk_dt.h>
#include <drivers/stm32_etzpc.h>
#include <drivers/firewall/firewall.h>
#include <drivers/stm32mp_dt_bindings.h>
#include <initcall.h>
#include <io.h>
Expand All @@ -29,6 +30,7 @@
#include <kernel/spinlock.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
#include <mm/core_mmu.h>
#include <stm32_util.h>
#include <util.h>

Expand Down Expand Up @@ -115,13 +117,6 @@ struct etzpc_device {
unsigned int lock;
};

static struct etzpc_device *etzpc_device;

struct etzpc_device *stm32_get_etzpc_device(void)
{
return etzpc_device;
}

static uint32_t etzpc_lock(struct etzpc_device *dev)
{
return may_spin_lock(&dev->lock);
Expand Down Expand Up @@ -230,8 +225,8 @@ static bool is_decprot_locked(struct etzpc_device *etzpc_dev,
return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask;
}

void etzpc_do_configure_tzma(struct etzpc_device *etzpc_dev,
uint32_t tzma_id, uint16_t tzma_value)
static void etzpc_do_configure_tzma(struct etzpc_device *etzpc_dev,
uint32_t tzma_id, uint16_t tzma_value)
{
size_t offset = sizeof(uint32_t) * tzma_id;
vaddr_t base = etzpc_dev->pdata.base.va;
Expand Down Expand Up @@ -334,6 +329,227 @@ static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused,

DECLARE_KEEP_PAGER(etzpc_pm);

static void stm32_etzpc_release_access(struct firewall_query *firewall __unused)
{
}

static void
stm32_etzpc_release_memory_access(struct firewall_query *firewall __unused,
paddr_t paddr __unused, size_t size __unused,
bool read __unused, bool write __unused)
{
}

static TEE_Result stm32_etzpc_check_access(struct firewall_query *firewall)
{
struct etzpc_device *etzpc_dev = firewall->firewall_ctrl->priv;
enum etzpc_decprot_attributes attr_req = ETZPC_DECPROT_MAX;
enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX;
uint32_t id = 0;

if (!firewall || firewall->arg_count != 2)
return TEE_ERROR_BAD_PARAMETERS;

/*
* Peripheral configuration, we assume the configuration is as
* follows:
* firewall->args[0]: Firewall ID
* firewall->args[1]: tzpc_decprot_attributes to check
*/
if (firewall->args[1] >= ETZPC_DECPROT_MAX)
return TEE_ERROR_BAD_PARAMETERS;
id = firewall->args[0];
attr_req = firewall->args[1];

if (id < etzpc_dev->ddata->num_per_sec) {
attr = etzpc_do_get_decprot(etzpc_dev, id);
DMSG("Check access %u - attr %d - requested %d", id, attr,
attr_req);
if (attr == attr_req)
return TEE_SUCCESS;
else
return TEE_ERROR_ACCESS_DENIED;
} else {
return TEE_ERROR_BAD_PARAMETERS;
}

return TEE_ERROR_ACCESS_DENIED;
}

static TEE_Result stm32_etzpc_acquire_access(struct firewall_query *firewall)
{
struct etzpc_device *etzpc_dev = firewall->firewall_ctrl->priv;
enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MCU_ISOLATION;
uint32_t id = 0;

if (!firewall || firewall->arg_count != 2)
return TEE_ERROR_BAD_PARAMETERS;

id = firewall->args[0];

if (id < etzpc_dev->ddata->num_per_sec) {
attr = etzpc_do_get_decprot(etzpc_dev, id);
if (attr == ETZPC_DECPROT_MCU_ISOLATION)
return TEE_ERROR_ACCESS_DENIED;
} else {
return TEE_ERROR_BAD_PARAMETERS;
}

return TEE_SUCCESS;
}

static TEE_Result
stm32_etzpc_check_memory_access(struct firewall_query *firewall, paddr_t paddr,
size_t size, bool read, bool write)
{
struct etzpc_device *etzpc_dev = firewall->firewall_ctrl->priv;
enum etzpc_decprot_attributes attr_req = ETZPC_DECPROT_MAX;
paddr_t tzma_base = 0;
size_t tzma_size = 0;
size_t prot_size = 0;
uint32_t id = 0;

if (!firewall || firewall->arg_count != 2)
return TEE_ERROR_BAD_PARAMETERS;

id = firewall->args[0];
attr_req = firewall->args[1];
if (!(id == ETZPC_TZMA0_ID || id == ETZPC_TZMA1_ID))
return TEE_ERROR_BAD_PARAMETERS;

tzma_base = id == ETZPC_TZMA0_ID ? ROM_BASE : SYSRAM_BASE;
tzma_size = id == ETZPC_TZMA0_ID ? ROM_SIZE : SYSRAM_SIZE;
prot_size = etzpc_do_get_tzma(etzpc_dev, id == ETZPC_TZMA0_ID ? 0 : 1) *
SMALL_PAGE_SIZE;

DMSG("Checking access for TZMA%u, secured from %"PRIxPA" to %"PRIxPA,
id == ETZPC_TZMA0_ID ? 0 : 1, tzma_base, tzma_base + prot_size);

if (paddr >= tzma_base && paddr < tzma_base + prot_size &&
paddr + size - 1 < tzma_base + tzma_size &&
(attr_req == ETZPC_DECPROT_S_RW ||
(attr_req == ETZPC_DECPROT_NS_R_S_W && write)))
return TEE_SUCCESS;

if (paddr >= tzma_base + prot_size &&
paddr + size - 1 <= tzma_base + tzma_size &&
(attr_req == ETZPC_DECPROT_NS_RW ||
(attr_req == ETZPC_DECPROT_NS_R_S_W && read)))
return TEE_SUCCESS;

return TEE_ERROR_ACCESS_DENIED;
}

static TEE_Result
stm32_etzpc_acquire_memory_access(struct firewall_query *firewall,
paddr_t paddr, size_t size,
bool read __unused, bool write __unused)
{
struct etzpc_device *etzpc_dev = firewall->firewall_ctrl->priv;
paddr_t tzma_base = 0;
size_t tzma_size = 0;
size_t prot_size = 0;
uint32_t id = 0;

if (!firewall || firewall->arg_count != 2)
return TEE_ERROR_BAD_PARAMETERS;

id = firewall->args[0];
if (!(id == ETZPC_TZMA0_ID || id == ETZPC_TZMA1_ID))
return TEE_ERROR_BAD_PARAMETERS;

tzma_base = id == ETZPC_TZMA0_ID ? ROM_BASE : SYSRAM_BASE;
tzma_size = id == ETZPC_TZMA0_ID ? ROM_SIZE : SYSRAM_SIZE;
prot_size = etzpc_do_get_tzma(etzpc_dev, id == ETZPC_TZMA0_ID ? 0 : 1) *
SMALL_PAGE_SIZE;

DMSG("Acquiring access for TZMA%u, secured from %"PRIxPA" to %"PRIxPA,
id == ETZPC_TZMA0_ID ? 0 : 1, tzma_base, tzma_base + prot_size);

if (paddr >= tzma_base && paddr < tzma_base + prot_size &&
paddr + size - 1 < tzma_base + tzma_size)
return TEE_SUCCESS;

return TEE_ERROR_ACCESS_DENIED;
}

static TEE_Result stm32_etzpc_configure(struct firewall_query *firewall)
{
struct etzpc_device *etzpc_dev = firewall->firewall_ctrl->priv;
enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX;
unsigned int total_sz = 0;
uint32_t id = 0;

if (firewall->arg_count != 2)
return TEE_ERROR_BAD_PARAMETERS;

id = firewall->args[0];

FMSG("Setting firewall configuration for peripheral ID: %u", id);

if (id < etzpc_dev->ddata->num_per_sec) {
/*
* Peripheral configuration, we assume the configuration is as
* follows:
* firewall->args[0]: Firewall ID
* firewall->args[1]: One of etzpc_decprot_attributes
*/

attr = firewall->args[1];

if (firewall->args[1] >= ETZPC_DECPROT_MAX)
return TEE_ERROR_BAD_PARAMETERS;

if (is_decprot_locked(etzpc_dev, id)) {
EMSG("Peripheral configuration locked");
return TEE_ERROR_ACCESS_DENIED;
}

etzpc_do_configure_decprot(etzpc_dev, id, attr);

return TEE_SUCCESS;
} else if (id == ETZPC_TZMA0_ID || id == ETZPC_TZMA1_ID) {
unsigned int tzma_id = 0;

/*
* TZMA configuration, we assume the configuration is as
* follows:
* firewall->args[0]: Either ETZPC_TZMA0_ID/ETZPC_TZMA1_ID
* firewall->args[1]: Memory size to secure
*/
switch (firewall->args[0]) {
case ETZPC_TZMA0_ID:
if (firewall->args[1] > ROM_SIZE)
return TEE_ERROR_BAD_PARAMETERS;

tzma_id = 0;
break;
case ETZPC_TZMA1_ID:
if (firewall->args[1] > SYSRAM_SIZE)
return TEE_ERROR_BAD_PARAMETERS;

tzma_id = 1;
break;
default:
return TEE_ERROR_BAD_PARAMETERS;
}

if (is_tzma_locked(etzpc_dev, tzma_id)) {
EMSG("TZMA configuration locked");
return TEE_ERROR_ACCESS_DENIED;
}

total_sz = ROUNDUP_DIV(firewall->args[1], SMALL_PAGE_SIZE);
etzpc_do_configure_tzma(etzpc_dev, tzma_id, total_sz);
} else {
EMSG("Unknown firewall ID: %u", id);

return TEE_ERROR_BAD_PARAMETERS;
}

return TEE_SUCCESS;
}

static struct etzpc_device *stm32_etzpc_alloc(void)
{
struct etzpc_device *etzpc_dev = calloc(1, sizeof(*etzpc_dev));
Expand Down Expand Up @@ -466,7 +682,7 @@ static TEE_Result stm32_etzpc_probe(const void *fdt, int node,
{
TEE_Result res = TEE_ERROR_GENERIC;
struct etzpc_device *etzpc_dev = stm32_etzpc_alloc();
int subnode = 0;
struct firewall_controller *controller = NULL;

if (!etzpc_dev) {
res = TEE_ERROR_OUT_OF_MEMORY;
Expand All @@ -477,16 +693,28 @@ static TEE_Result stm32_etzpc_probe(const void *fdt, int node,
if (res)
goto err;

etzpc_device = etzpc_dev;
controller = calloc(1, sizeof(*controller));
if (!controller)
goto err;

fdt_for_each_subnode(subnode, fdt, node) {
res = dt_driver_maybe_add_probe_node(fdt, subnode);
if (res) {
EMSG("Failed to add node %s to probe list: %#"PRIx32,
fdt_get_name(fdt, subnode, NULL), res);
panic();
}
}
controller->base = &etzpc_dev->pdata.base;
controller->name = etzpc_dev->pdata.name;
controller->priv = etzpc_dev;
controller->set_conf = stm32_etzpc_configure;
controller->check_access = stm32_etzpc_check_access;
controller->acquire_access = stm32_etzpc_acquire_access;
controller->release_access = stm32_etzpc_release_access;
controller->check_memory_access = stm32_etzpc_check_memory_access;
controller->acquire_memory_access =
stm32_etzpc_acquire_memory_access;
controller->release_memory_access =
stm32_etzpc_release_memory_access;

res = firewall_dt_controller_register(fdt, node, controller);
if (res)
goto err;

firewall_dt_probe_bus(fdt, node, controller);

register_pm_core_service_cb(etzpc_pm, etzpc_dev, "stm32-etzpc");

Expand Down
1 change: 1 addition & 0 deletions core/drivers/firewall/sub.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c
srcs-$(CFG_STM32_RIF) += stm32_rif.c
srcs-$(CFG_STM32_RIFSC) += stm32_rifsc.c

Expand Down
1 change: 0 additions & 1 deletion core/drivers/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ srcs-$(CFG_ATMEL_TCB) += atmel_tcb.c
srcs-$(CFG_AMLOGIC_UART) += amlogic_uart.c
srcs-$(CFG_MVEBU_UART) += mvebu_uart.c
srcs-$(CFG_STM32_BSEC) += stm32_bsec.c
srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c
srcs-$(CFG_STM32_FMC) += stm32_fmc.c
srcs-$(CFG_STM32_GPIO) += stm32_gpio.c
srcs-$(CFG_STM32_HPDMA) += stm32_hpdma.c
Expand Down

0 comments on commit 8501466

Please sign in to comment.