11
11
#include <suit_ipuc.h>
12
12
#include <suit_plat_decode_util.h>
13
13
#include <zephyr/logging/log.h>
14
+ #include <zephyr/cache.h>
14
15
15
- LOG_MODULE_REGISTER (flash_ipuc , CONFIG_FLASH_IPUC_LOG_LEVEL );
16
+ /* __ALIGNED macro is not defined on NATIVE POSIX. This platform uses __aligned macro. */
17
+ #ifndef __ALIGNED
18
+ #ifdef __aligned
19
+ #define __ALIGNED __aligned
20
+ #endif
21
+ #endif
22
+
23
+ #ifdef CONFIG_DCACHE_LINE_SIZE
24
+ #define CACHE_ALIGNMENT CONFIG_DCACHE_LINE_SIZE
25
+ #else
26
+ #define CACHE_ALIGNMENT 4
27
+ #endif
16
28
17
29
#define FLASH_WRITE_BLOCK_SIZE DT_PROP(DT_CHOSEN(zephyr_flash), write_block_size)
18
30
#define WRITE_BLOCK_SIZE FLASH_WRITE_BLOCK_SIZE
@@ -45,6 +57,8 @@ struct ipuc_context {
45
57
46
58
#define DEFINE_NRF_IPUC_REF (x , _ ) &__device_flash_nrf_ipuc_##x
47
59
60
+ LOG_MODULE_REGISTER (flash_ipuc , CONFIG_FLASH_IPUC_LOG_LEVEL );
61
+
48
62
static int nrf_ipuc_read (const struct device * dev , off_t offset , void * data , size_t len )
49
63
{
50
64
struct ipuc_context * ctx = NULL ;
@@ -75,8 +89,11 @@ static int nrf_ipuc_read(const struct device *dev, off_t offset, void *data, siz
75
89
76
90
static int nrf_ipuc_write (const struct device * dev , off_t offset , const void * data , size_t len )
77
91
{
92
+ uint8_t unaligned_data_buf [CACHE_ALIGNMENT ] __ALIGNED (CACHE_ALIGNMENT ) = {0 };
93
+ size_t unaligned_len = MIN (CACHE_ALIGNMENT - (((uintptr_t )data ) % CACHE_ALIGNMENT ), len );
94
+ suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS ;
78
95
struct ipuc_context * ctx = NULL ;
79
- bool last_chunk = false ;
96
+ int ret = 0 ;
80
97
81
98
if (dev == NULL ) {
82
99
return - EINVAL ;
@@ -88,20 +105,75 @@ static int nrf_ipuc_write(const struct device *dev, off_t offset, const void *da
88
105
return - EBADF ;
89
106
}
90
107
108
+ if (offset + len > ctx -> size ) {
109
+ return - ENOMEM ;
110
+ }
111
+
91
112
LOG_DBG ("write: %p:%zu" , (void * )offset , len );
92
113
93
114
if (len == 0 ) {
94
- last_chunk = true;
115
+ plat_ret = suit_ipuc_write (& ctx -> component_id , offset , 0 , 0 , true);
116
+ if (plat_ret != SUIT_PLAT_SUCCESS ) {
117
+ LOG_ERR ("Last write (flush) error: %d" , plat_ret );
118
+ return - EIO ;
119
+ }
120
+
121
+ return 0 ;
95
122
}
96
123
97
- if (offset + len > ctx -> size ) {
98
- return - ENOMEM ;
124
+ /* Optimize: Use a single write call if all bytes can be transferred using stack-based
125
+ * aligned buffer.
126
+ */
127
+ if (len <= ARRAY_SIZE (unaligned_data_buf )) {
128
+ unaligned_len = len ;
99
129
}
100
130
101
- suit_plat_err_t plat_ret =
102
- suit_ipuc_write (& ctx -> component_id , offset , (uintptr_t )data , len , last_chunk );
131
+ /* If the data buffer is not aligned to the cache lines:
132
+ * - copy the unaligned part into stack-based aligned buffer
133
+ * - write the internal buffer
134
+ * - skip the unaligned bytes of the input buffer
135
+ */
136
+ if (unaligned_len != CACHE_ALIGNMENT ) {
137
+ memcpy (unaligned_data_buf , data , unaligned_len );
103
138
139
+ LOG_DBG ("align: %p:%zu" , (void * )data , unaligned_len );
140
+
141
+ ret = sys_cache_data_flush_range ((void * )unaligned_data_buf ,
142
+ sizeof (unaligned_data_buf ));
143
+ if (ret != 0 && ret != - EAGAIN && ret != - ENOTSUP ) {
144
+ LOG_ERR ("Failed to flush cache buffer range (%p, 0x%x): %d" ,
145
+ (void * )unaligned_data_buf , sizeof (unaligned_data_buf ), ret );
146
+ return - EIO ;
147
+ }
148
+
149
+ plat_ret = suit_ipuc_write (& ctx -> component_id , offset ,
150
+ (uintptr_t )unaligned_data_buf , unaligned_len , false);
151
+ if (plat_ret != SUIT_PLAT_SUCCESS ) {
152
+ LOG_ERR ("Unaligned data write (%p, 0x%x) error: %d" ,
153
+ (void * )unaligned_data_buf , unaligned_len , plat_ret );
154
+ return - EIO ;
155
+ }
156
+
157
+ offset += unaligned_len ;
158
+ len -= unaligned_len ;
159
+ data = (void * )((uintptr_t )data + unaligned_len );
160
+ }
161
+
162
+ /* If no more (aligned) bytes left - return. */
163
+ if (len == 0 ) {
164
+ return 0 ;
165
+ }
166
+
167
+ /* Write (now aligned) data buffer. */
168
+ ret = sys_cache_data_flush_range ((void * )data , len );
169
+ if (ret != 0 && ret != - EAGAIN && ret != - ENOTSUP ) {
170
+ LOG_ERR ("Failed to flush cache memory range (%p, 0x%x): %d" , data , len , ret );
171
+ return - EIO ;
172
+ }
173
+
174
+ plat_ret = suit_ipuc_write (& ctx -> component_id , offset , (uintptr_t )data , len , false);
104
175
if (plat_ret != SUIT_PLAT_SUCCESS ) {
176
+ LOG_ERR ("Aligned data write (%p, 0x%x) error: %d" , data , len , plat_ret );
105
177
return - EIO ;
106
178
}
107
179
@@ -110,7 +182,8 @@ static int nrf_ipuc_write(const struct device *dev, off_t offset, const void *da
110
182
111
183
static int nrf_ipuc_erase (const struct device * dev , off_t offset , size_t size )
112
184
{
113
- static uint8_t erase_block [WRITE_BLOCK_SIZE ] = {ERASE_VALUE };
185
+ static const uint8_t erase_block [WRITE_BLOCK_SIZE ] __ALIGNED (CACHE_ALIGNMENT ) = {
186
+ ERASE_VALUE };
114
187
suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS ;
115
188
struct ipuc_context * ctx = NULL ;
116
189
@@ -128,18 +201,27 @@ static int nrf_ipuc_erase(const struct device *dev, off_t offset, size_t size)
128
201
return - ENOMEM ;
129
202
}
130
203
204
+ int ret = sys_cache_data_flush_range ((void * )erase_block , sizeof (erase_block ));
205
+
206
+ if (ret != 0 && ret != - EAGAIN && ret != - ENOTSUP ) {
207
+ LOG_ERR ("Failed to flush cache range (%p, 0x%x): %d" , erase_block ,
208
+ sizeof (erase_block ), ret );
209
+ return - EIO ;
210
+ }
211
+
131
212
LOG_DBG ("erase: %p:%zu" , (void * )offset , size );
213
+
132
214
while (size > 0 ) {
133
215
plat_ret = suit_ipuc_write (& ctx -> component_id , offset , (uintptr_t )erase_block ,
134
216
sizeof (erase_block ), false);
217
+ if (plat_ret != SUIT_PLAT_SUCCESS ) {
218
+ return - EIO ;
219
+ }
220
+
135
221
offset += sizeof (erase_block );
136
222
size -= sizeof (erase_block );
137
223
}
138
224
139
- if (plat_ret != SUIT_PLAT_SUCCESS ) {
140
- return - EIO ;
141
- }
142
-
143
225
return 0 ;
144
226
}
145
227
0 commit comments