@@ -40,13 +40,19 @@ struct ipuc_context {
4040 uintptr_t address ;
4141 size_t size ;
4242 bool read_access ;
43+ bool setup_pending ;
44+ #ifdef CONFIG_FLASH_PAGE_LAYOUT
45+ struct flash_pages_layout pages_layout ;
46+ #endif /* CONFIG_FLASH_PAGE_LAYOUT */
4347};
4448
4549#define DEFINE_NRF_IPUC_DATA (x , _ ) \
4650 static struct ipuc_context ipuc_context_data_##x = { \
4751 .component_id = {NULL, 0}, \
4852 .address = 0, \
4953 .size = 0, \
54+ .setup_pending = false, \
55+ .pages_layout = {0}, \
5056 }
5157
5258#define DEFINE_NRF_IPUC (x , _ ) \
@@ -109,6 +115,18 @@ static int nrf_ipuc_write(const struct device *dev, off_t offset, const void *da
109115 return - ENOMEM ;
110116 }
111117
118+ if (ctx -> setup_pending ) {
119+ LOG_DBG ("setup: %p:%zu" , (void * )ctx -> address , ctx -> size );
120+
121+ plat_ret = suit_ipuc_write_setup (& ctx -> component_id , NULL , NULL );
122+ if (plat_ret != SUIT_PLAT_SUCCESS ) {
123+ LOG_ERR ("Failed to setup IPUC for writing: %d" , plat_ret );
124+ return - EIO ;
125+ }
126+
127+ ctx -> setup_pending = false;
128+ }
129+
112130 LOG_DBG ("write: %p:%zu" , (void * )offset , len );
113131
114132 if (len == 0 ) {
@@ -182,10 +200,11 @@ static int nrf_ipuc_write(const struct device *dev, off_t offset, const void *da
182200
183201static int nrf_ipuc_erase (const struct device * dev , off_t offset , size_t size )
184202{
185- static const uint8_t erase_block [WRITE_BLOCK_SIZE ] __ALIGNED (CACHE_ALIGNMENT ) = {
186- ERASE_VALUE };
203+ const uint8_t erase_block [WRITE_BLOCK_SIZE ] __ALIGNED (CACHE_ALIGNMENT ) = {
204+ [ 0 ... WRITE_BLOCK_SIZE - 1 ] = ERASE_VALUE };
187205 suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS ;
188206 struct ipuc_context * ctx = NULL ;
207+ size_t bytes_erased = 0 ;
189208
190209 if (dev == NULL ) {
191210 return - EINVAL ;
@@ -209,17 +228,48 @@ static int nrf_ipuc_erase(const struct device *dev, off_t offset, size_t size)
209228 return - EIO ;
210229 }
211230
231+ if (ctx -> setup_pending ) {
232+ /* Any write sets up the IPUC, which erases the whole area, so we may return here
233+ * immediately.
234+ */
235+ return 0 ;
236+ }
237+
212238 LOG_DBG ("erase: %p:%zu" , (void * )offset , size );
213239
240+ if (size == ctx -> size ) {
241+ /* Optimize: Use write_setup() to erase the whole area with a single SSF IPC call.
242+ */
243+ LOG_DBG ("setup: %p:%zu" , (void * )ctx -> address , ctx -> size );
244+
245+ plat_ret = suit_ipuc_write_setup (& ctx -> component_id , NULL , NULL );
246+ if (plat_ret != SUIT_PLAT_SUCCESS ) {
247+ LOG_ERR ("Failed to erase IPUC through write setup: %d" , plat_ret );
248+ return - EIO ;
249+ }
250+
251+ return 0 ;
252+ }
253+
214254 while (size > 0 ) {
255+ bytes_erased = MIN (sizeof (erase_block ), size );
215256 plat_ret = suit_ipuc_write (& ctx -> component_id , offset , (uintptr_t )erase_block ,
216- sizeof ( erase_block ) , false);
257+ bytes_erased , false);
217258 if (plat_ret != SUIT_PLAT_SUCCESS ) {
259+ LOG_ERR ("Failed to erase IPUC (%p:%zu): %d" ,
260+ (void * )(ctx -> address + offset ), bytes_erased , plat_ret );
218261 return - EIO ;
219262 }
220263
221- offset += sizeof (erase_block );
222- size -= sizeof (erase_block );
264+ offset += bytes_erased ;
265+ size -= bytes_erased ;
266+
267+ /* The erase operation generates a lot of SSF requests.
268+ * It is necessary to give some time SDFW, so it is able to feed the watchdog.
269+ */
270+ if ((offset % 0x10000 == 0 ) && (size > 0 )) {
271+ k_sleep (K_MSEC (2 ));
272+ }
223273 }
224274
225275 return 0 ;
@@ -241,11 +291,31 @@ static const struct flash_parameters *nrf_ipuc_get_parameters(const struct devic
241291 return & parameters ;
242292}
243293
294+ #if defined(CONFIG_FLASH_PAGE_LAYOUT )
295+ static void nrf_ipuc_page_layout (const struct device * dev , const struct flash_pages_layout * * layout ,
296+ size_t * layout_size )
297+ {
298+ struct ipuc_context * ctx = NULL ;
299+
300+ if (dev == NULL ) {
301+ return ;
302+ }
303+
304+ ctx = (struct ipuc_context * )dev -> data ;
305+
306+ * layout = & ctx -> pages_layout ;
307+ * layout_size = 1 ;
308+ }
309+ #endif
310+
244311static const struct flash_driver_api nrf_ipuc_api = {
245312 .read = nrf_ipuc_read ,
246313 .write = nrf_ipuc_write ,
247314 .erase = nrf_ipuc_erase ,
248315 .get_parameters = nrf_ipuc_get_parameters ,
316+ #if defined(CONFIG_FLASH_PAGE_LAYOUT )
317+ .page_layout = nrf_ipuc_page_layout ,
318+ #endif
249319};
250320
251321static bool read_access_check (suit_manifest_role_t role )
@@ -338,7 +408,7 @@ static struct device *flash_component_ipuc(struct zcbor_string *component_id,
338408
339409 dev = get_free_dev ();
340410 if (dev == NULL ) {
341- LOG_ERR ( "Maximum number of IPUCs reached " );
411+ LOG_WRN ( "Unable to allocate new component IPUC device - no free instances " );
342412 return NULL ;
343413 }
344414
@@ -371,13 +441,6 @@ static struct device *flash_component_ipuc(struct zcbor_string *component_id,
371441 continue ;
372442 }
373443
374- plat_err = suit_ipuc_write_setup (& ctx -> component_id , encryption_info ,
375- compression_info );
376- if (plat_err != SUIT_PLAT_SUCCESS ) {
377- LOG_ERR ("Failed to setup IPUC %d write: %d" , i , plat_err );
378- break ;
379- }
380-
381444 LOG_INF ("IPUC for address range (0x%lx, 0x%x) created" , ctx -> address ,
382445 ctx -> size );
383446 }
@@ -388,6 +451,12 @@ static struct device *flash_component_ipuc(struct zcbor_string *component_id,
388451 ctx -> read_access = false;
389452 }
390453
454+ ctx -> setup_pending = true;
455+ #ifdef CONFIG_FLASH_PAGE_LAYOUT
456+ ctx -> pages_layout .pages_count = 1 ;
457+ ctx -> pages_layout .pages_size = ctx -> size ;
458+ #endif /* CONFIG_FLASH_PAGE_LAYOUT */
459+
391460 return dev ;
392461 }
393462
@@ -431,8 +500,15 @@ static struct device *flash_cache_ipuc(uintptr_t min_address, uintptr_t *ipuc_ad
431500 size_t i_max = 0 ;
432501 uintptr_t range_addr ;
433502
503+ if ((ipuc_address == NULL ) || (ipuc_size == NULL )) {
504+ LOG_WRN ("Invalid input arguments: (0x%lx, 0x%lx)" , (uintptr_t )ipuc_address ,
505+ (uintptr_t )ipuc_size );
506+ return NULL ;
507+ }
508+
434509 dev = get_free_dev ();
435- if ((dev == NULL ) || (ipuc_address == NULL ) || (ipuc_size == NULL )) {
510+ if (dev == NULL ) {
511+ LOG_WRN ("Unable to allocate new cache IPUC device - no free instances" );
436512 return NULL ;
437513 }
438514
@@ -497,16 +573,15 @@ static struct device *flash_cache_ipuc(uintptr_t min_address, uintptr_t *ipuc_ad
497573 }
498574
499575 if (!dry_run ) {
500- plat_err = suit_ipuc_write_setup (& ctx -> component_id , NULL , NULL );
501- if (plat_err != SUIT_PLAT_SUCCESS ) {
502- flash_ipuc_release (dev );
503- return NULL ;
504- }
505-
506576 LOG_INF ("Cache IPUC at idx %d for address range (0x%lx, 0x%x) created" , i_max ,
507577 ctx -> address , ctx -> size );
508578 }
509579
580+ ctx -> setup_pending = true;
581+ #ifdef CONFIG_FLASH_PAGE_LAYOUT
582+ ctx -> pages_layout .pages_count = 1 ;
583+ ctx -> pages_layout .pages_size = ctx -> size ;
584+ #endif /* CONFIG_FLASH_PAGE_LAYOUT */
510585 * ipuc_address = ctx -> address ;
511586 * ipuc_size = ctx -> size ;
512587
@@ -559,3 +634,19 @@ struct device *flash_ipuc_find(uintptr_t address, size_t size, uintptr_t *ipuc_a
559634
560635 return NULL ;
561636}
637+
638+ bool flash_ipuc_setup_pending (const struct device * dev )
639+ {
640+ struct ipuc_context * ctx ;
641+
642+ if (dev == NULL ) {
643+ return false;
644+ }
645+
646+ ctx = (struct ipuc_context * )dev -> data ;
647+ if (ctx -> component_id .value != NULL ) {
648+ return ctx -> setup_pending ;
649+ }
650+
651+ return false;
652+ }
0 commit comments