Skip to content

Commit e6753aa

Browse files
tomchynordicjm
authored andcommitted
suit: Add module to define SUIT processing events
Add a module that allows to synchronize SUIT processing among several threads. The primary use case is to control the main processor logic, based on SSF requests. Ref: NCSDK-29996 Signed-off-by: Tomasz Chyrowicz <[email protected]>
1 parent 4a5c939 commit e6753aa

File tree

15 files changed

+1082
-90
lines changed

15 files changed

+1082
-90
lines changed

subsys/suit/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ add_subdirectory_ifdef(CONFIG_SUIT_DFU orchestrator_app)
2020
add_subdirectory_ifdef(CONFIG_SUIT_ENVELOPE_INFO envelope_info)
2121
add_subdirectory_ifdef(CONFIG_SUIT_EXECUTION_MODE execution_mode)
2222
add_subdirectory_ifdef(CONFIG_SUIT_VALIDATOR validator)
23+
add_subdirectory_ifdef(CONFIG_SUIT_EVENTS events)

subsys/suit/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ config SUIT_ENABLE_DEFAULTS_SDFW
174174
imply SUIT_UPDATE_REBOOT_ENABLED
175175
imply SUIT_BOOT_RECOVERY_REBOOT_ENABLED
176176
imply SUIT_VALIDATOR
177+
imply SUIT_EVENTS
177178

178179
config SUIT_ENABLE_DEFAULTS_SDFW_EXTMEM
179180
bool "SDFW SUIT defaults with external flash support"
@@ -196,6 +197,7 @@ rsource "envelope_info/Kconfig"
196197
rsource "execution_mode/Kconfig"
197198
rsource "memory_layout/Kconfig"
198199
rsource "validator/Kconfig"
200+
rsource "events/Kconfig"
199201

200202
# Configure SUIT_LOG_LEVEL
201203
module = SUIT

subsys/suit/events/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# Copyright (c) 2024 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
# SUIT Events API
8+
zephyr_interface_library_named(suit_events)
9+
target_include_directories(suit_events INTERFACE include)
10+
11+
zephyr_library()
12+
zephyr_library_sources(src/suit_events.c)
13+
zephyr_library_link_libraries(suit_events)

subsys/suit/events/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# Copyright (c) 2024 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
config SUIT_EVENTS
8+
bool "Enable SUIT events module"
9+
select EVENTS
10+
11+
if SUIT_EVENTS
12+
13+
config APP_LINK_WITH_SUIT_EVENTS
14+
bool
15+
default y
16+
17+
endif # SUIT_EVENTS
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef SUIT_EVENTS_H__
8+
#define SUIT_EVENTS_H__
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
#include <stdint.h>
15+
#include <stdbool.h>
16+
17+
/* Pendable events that threads can wait for. */
18+
19+
/** Event indicating a successful execution of the suit-invoke command. */
20+
#define SUIT_EVENT_INVOKE_SUCCESS BIT(0)
21+
22+
/** Event indicating an unsuccessful execution of the suit-invoke command. */
23+
#define SUIT_EVENT_INVOKE_FAIL BIT(1)
24+
25+
/** Mask for events, related to the execution of the suit-invoke command. */
26+
#define SUIT_EVENT_INVOKE_MASK (SUIT_EVENT_INVOKE_SUCCESS | SUIT_EVENT_INVOKE_FAIL)
27+
28+
/** CPU ID indicating all supported CPU IDs */
29+
#define SUIT_EVENT_CPU_ID_ANY 0xFF
30+
31+
/** Special value of the timeout that represents infinite time. */
32+
#define SUIT_WAIT_FOREVER 0xFFFFFFFF
33+
34+
/**
35+
* @brief Post one or more events for a given CPU.
36+
*
37+
* This routine posts one or more events to an internal event object for a given CPU.
38+
* All tasks waiting using @ref suit_event_wait whose waiting conditions become met by this
39+
* posting immediately unpend.
40+
*
41+
* @note This API is a proxy for @ref k_event_post API that splits the event mask
42+
* into 8 distinct 4-bit pools for 8 different CPU IDs.
43+
*
44+
* @param cpu_id The CPU ID for which the events will be posted.
45+
* Use @ref SUIT_EVENT_CPU_ID_ANY to post an event for all of the CPUs.
46+
* @param events Set of events to post for a given CPU.
47+
*
48+
* @retval Previous value of the events for a given CPU.
49+
*/
50+
uint32_t suit_event_post(uint8_t cpu_id, uint8_t events);
51+
52+
/**
53+
* @brief Clear the events for given CPU.
54+
*
55+
* This routine clears (resets) the specified events for given CPU stored in
56+
* an event object. Use @ref SUIT_EVENT_CPU_ID_ANY to clear events for all CPUs.
57+
*
58+
* @note This API is a proxy for @ref k_event_clear API that splits the event mask
59+
* into 8 distinct 4-bit pools for 8 different CPU IDs.
60+
*
61+
* @param cpu_id The CPU ID for which the events will be cleared.
62+
* Use @ref SUIT_EVENT_CPU_ID_ANY to clear events for all of the CPUs.
63+
* @param events Set of events to clear for a given CPU.
64+
*
65+
* @retval Previous value of the events for a given CPU.
66+
*/
67+
uint32_t suit_event_clear(uint8_t cpu_id, uint8_t events);
68+
69+
/**
70+
* @brief Wait for any of the specified events assigned to a given CPU.
71+
*
72+
* This routine waits on internal @a event object untli any of the specifies
73+
* events for a given CPU ID have been posted, or the maximum wait time
74+
* @a timeout has expired.
75+
* A thread may wait on up to 4 distinctly numbered events that are expressed
76+
* as bits in a single 8-bit word.
77+
*
78+
* @note This API is a proxy for @ref k_event_wait API that splits the event mask
79+
* into 8 distinct 4-bit pools for 8 different CPU IDs.
80+
*
81+
* @param cpu_id The CPU ID whose events to wait for.
82+
* Use @ref SUIT_EVENT_CPU_ID_ANY to wait for an event for any of the CPUs.
83+
* @param events Set of desired events on which to wait
84+
* @param reset If true, clear the set of events for given CPU ID tracked by the
85+
* event object before waiting. If false, do not clear the events.
86+
* @param timeout Waiting period for the desired set of events.
87+
* Use @ref SUIT_WAIT_FOREVER to wait forever.
88+
*
89+
* @retval set of matching events for a given CPU upon success.
90+
* @retval 0 if matching events were not received for a given CPU within the specified time.
91+
*/
92+
uint32_t suit_event_wait(uint8_t cpu_id, uint8_t events, bool reset, uint32_t timeout_ms);
93+
94+
#ifdef __cplusplus
95+
}
96+
#endif
97+
98+
#endif /* SUIT_EVENTS_H__ */
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <suit_events.h>
8+
#include <zephyr/kernel.h>
9+
10+
/* Helper mask, with 0th bits for all processors set. */
11+
#define ALL_CPUS_MASK 0x11111111
12+
13+
/* Helper mask, with all event bits for a given processor set. */
14+
#define ALL_EVENT_MASK 0x0F
15+
16+
/* The maximum CPU ID handled by this module. */
17+
#define CPU_N 8
18+
19+
/* The number of bits per CPU inside the event mask. */
20+
#define BITS_N 4
21+
22+
/* Internal event structure, common for all API calls. */
23+
static K_EVENT_DEFINE(suit_events);
24+
25+
/* Convert (cpu_id, event mask) pair into global (common for all CPUs) event mask. */
26+
static uint32_t cpu_events_to_suit_events_mask(uint8_t cpu_id, uint8_t events)
27+
{
28+
/* Check for valid CPU ID values. */
29+
if ((cpu_id >= CPU_N) && (cpu_id != SUIT_EVENT_CPU_ID_ANY)) {
30+
return 0;
31+
}
32+
33+
/* Mask all unsupported events. */
34+
events &= ALL_EVENT_MASK;
35+
36+
if (cpu_id == SUIT_EVENT_CPU_ID_ANY) {
37+
return events * ALL_CPUS_MASK;
38+
}
39+
40+
return (uint32_t)events << (cpu_id * BITS_N);
41+
}
42+
43+
/* Convert global (common for all CPUs) event mask into an event mask for a given CPU. */
44+
static uint8_t suit_events_mask_to_cpu_events(uint8_t cpu_id, uint32_t events)
45+
{
46+
uint32_t cpu_shift = 0;
47+
uint32_t cpu_events = 0;
48+
49+
/* Check for valid CPU ID values. */
50+
if ((cpu_id >= CPU_N) && (cpu_id != SUIT_EVENT_CPU_ID_ANY)) {
51+
return 0;
52+
}
53+
54+
if (cpu_id == SUIT_EVENT_CPU_ID_ANY) {
55+
uint8_t common_mask = 0;
56+
57+
for (size_t id = 0; id < CPU_N; id++) {
58+
cpu_shift = (id * BITS_N);
59+
cpu_events =
60+
(events & ((uint32_t)ALL_EVENT_MASK << cpu_shift)) >> cpu_shift;
61+
common_mask |= (cpu_events & ALL_EVENT_MASK);
62+
}
63+
64+
return common_mask;
65+
}
66+
67+
cpu_shift = (cpu_id * BITS_N);
68+
cpu_events = (events & ((uint32_t)ALL_EVENT_MASK << cpu_shift)) >> cpu_shift;
69+
70+
return (cpu_events & ALL_EVENT_MASK);
71+
}
72+
73+
uint32_t suit_event_post(uint8_t cpu_id, uint8_t events)
74+
{
75+
uint32_t main_mask = cpu_events_to_suit_events_mask(cpu_id, events);
76+
77+
if (main_mask == 0) {
78+
/* Unsupported CPU ID. */
79+
return 0;
80+
}
81+
82+
return suit_events_mask_to_cpu_events(cpu_id, k_event_post(&suit_events, main_mask));
83+
}
84+
85+
uint32_t suit_event_clear(uint8_t cpu_id, uint8_t events)
86+
{
87+
uint32_t main_mask = cpu_events_to_suit_events_mask(cpu_id, events);
88+
89+
if (main_mask == 0) {
90+
/* Unsupported CPU ID. */
91+
return 0;
92+
}
93+
94+
return suit_events_mask_to_cpu_events(cpu_id, k_event_clear(&suit_events, main_mask));
95+
}
96+
97+
uint32_t suit_event_wait(uint8_t cpu_id, uint8_t events, bool reset, uint32_t timeout_ms)
98+
{
99+
k_timeout_t timeout = K_NO_WAIT;
100+
uint32_t main_mask = cpu_events_to_suit_events_mask(cpu_id, events);
101+
102+
if (main_mask == 0) {
103+
/* Unsupported CPU ID. */
104+
return 0;
105+
}
106+
107+
if (reset) {
108+
(void)suit_event_clear(cpu_id, main_mask);
109+
}
110+
111+
if (timeout_ms == SUIT_WAIT_FOREVER) {
112+
timeout = K_FOREVER;
113+
} else if (timeout_ms != 0) {
114+
timeout = K_MSEC(timeout_ms);
115+
}
116+
117+
return suit_events_mask_to_cpu_events(
118+
cpu_id, k_event_wait(&suit_events, main_mask, false, timeout));
119+
}

subsys/suit/platform/sdfw/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ zephyr_library_link_libraries_ifdef(CONFIG_SUIT_DEVCONFIG suit_mci)
4444
zephyr_library_link_libraries_ifdef(CONFIG_SUIT_AUTHENTICATE suit_mci)
4545
zephyr_library_link_libraries_ifdef(CONFIG_SUIT_PLAT_CHECK_COMPONENT_COMPATIBILITY suit_mci)
4646
zephyr_library_link_libraries_ifdef(CONFIG_SUIT_STREAM_FILTER_DECRYPT suit_stream_filters_interface)
47+
zephyr_library_link_libraries_ifdef(CONFIG_SUIT_EVENTS suit_events)
4748

4849

4950
zephyr_library_link_libraries(suit_sdfw_platform)

subsys/suit/platform/sdfw/include/suit_cpu_run.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef SUIT_PLAT_RUN_CPU_H__
88
#define SUIT_PLAT_RUN_CPU_H__
99

10+
#include <stdint.h>
1011
#include <suit_plat_err.h>
1112

1213
#ifdef __cplusplus

subsys/suit/platform/sdfw/src/suit_plat_invoke.c

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <suit_platform.h>
1111
#include <suit_plat_decode_util.h>
1212
#include <suit_cpu_run.h>
13+
#ifdef CONFIG_SUIT_EVENTS
14+
#include <suit_events.h>
15+
#endif /* CONFIG_SUIT_EVENTS */
1316

1417
LOG_MODULE_REGISTER(suit_plat_invoke, CONFIG_SUIT_LOG_LEVEL);
1518

@@ -26,8 +29,8 @@ int suit_plat_check_invoke(suit_component_t image_handle, struct zcbor_string *i
2629
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
2730
}
2831

29-
if (suit_plat_decode_component_id(component_id, &cpu_id, &run_address, &size)
30-
!= SUIT_PLAT_SUCCESS) {
32+
if (suit_plat_decode_component_id(component_id, &cpu_id, &run_address, &size) !=
33+
SUIT_PLAT_SUCCESS) {
3134
LOG_ERR("suit_plat_decode_component_id failed");
3235
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
3336
}
@@ -37,6 +40,11 @@ int suit_plat_check_invoke(suit_component_t image_handle, struct zcbor_string *i
3740
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
3841
}
3942

43+
if (suit_plat_decode_invoke_args(invoke_args, NULL, NULL)) {
44+
LOG_ERR("suit_plat_decode_invoke_args failed");
45+
return SUIT_ERR_UNSUPPORTED_PARAMETER;
46+
}
47+
4048
/* Check if component type supports invocation */
4149
switch (component_type) {
4250
case SUIT_COMPONENT_TYPE_MEM:
@@ -54,6 +62,9 @@ int suit_plat_invoke(suit_component_t image_handle, struct zcbor_string *invoke_
5462
{
5563
struct zcbor_string *component_id;
5664
suit_component_type_t component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED;
65+
uint32_t timeout_ms = 0;
66+
bool synchronous = false;
67+
int ret = 0;
5768
intptr_t run_address;
5869
uint8_t cpu_id;
5970
size_t size;
@@ -63,8 +74,8 @@ int suit_plat_invoke(suit_component_t image_handle, struct zcbor_string *invoke_
6374
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
6475
}
6576

66-
if (suit_plat_decode_component_id(component_id, &cpu_id, &run_address, &size)
67-
!= SUIT_PLAT_SUCCESS) {
77+
if (suit_plat_decode_component_id(component_id, &cpu_id, &run_address, &size) !=
78+
SUIT_PLAT_SUCCESS) {
6879
LOG_ERR("suit_plat_decode_component_id failed");
6980
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
7081
}
@@ -74,15 +85,45 @@ int suit_plat_invoke(suit_component_t image_handle, struct zcbor_string *invoke_
7485
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
7586
}
7687

88+
if (suit_plat_decode_invoke_args(invoke_args, &synchronous, &timeout_ms)) {
89+
LOG_ERR("suit_plat_decode_invoke_args failed");
90+
return SUIT_ERR_UNSUPPORTED_PARAMETER;
91+
}
92+
93+
#ifdef CONFIG_SUIT_EVENTS
94+
/* Clear all pending invoke events */
95+
(void)suit_event_clear(cpu_id, SUIT_EVENT_INVOKE_MASK);
96+
#endif /* CONFIG_SUIT_EVENTS */
97+
7798
/* Check if component type supports invocation */
7899
switch (component_type) {
79100
case SUIT_COMPONENT_TYPE_MEM:
80101
/* memory-mapped */
81-
return suit_plat_cpu_run(cpu_id, run_address);
102+
ret = suit_plat_cpu_run(cpu_id, run_address);
103+
break;
82104
default:
83105
LOG_ERR("Unsupported component type");
84-
break;
106+
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
85107
}
86108

87-
return SUIT_ERR_UNSUPPORTED_COMPONENT_ID;
109+
if ((ret == SUIT_SUCCESS) && synchronous) {
110+
#ifdef CONFIG_SUIT_EVENTS
111+
/* Wait for one of the invoke events */
112+
uint32_t invoke_events =
113+
suit_event_wait(cpu_id, SUIT_EVENT_INVOKE_MASK, false, timeout_ms);
114+
115+
if (invoke_events & SUIT_EVENT_INVOKE_SUCCESS) {
116+
return SUIT_SUCCESS;
117+
}
118+
119+
/* Event timeout or invoke failed */
120+
/* Allow to handle invoke failure inside the manifest. */
121+
return SUIT_FAIL_CONDITION;
122+
#else
123+
/* Synchronous invoke not supported */
124+
return SUIT_ERR_CRASH;
125+
#endif /* CONFIG_SUIT_EVENTS */
126+
}
127+
128+
return ret;
88129
}

0 commit comments

Comments
 (0)