@@ -31,6 +31,16 @@ struct system_update_work {
3131
3232static struct k_work_q system_update_work_queue ;
3333
34+ /* Timeout duration for the semaphore which waits for envelope processing
35+ * to complete. This needs to be quite long because, in cases
36+ * where partitions in external memory are modified, the cleanup process
37+ * involves erasing them, which can be time-consuming.
38+ */
39+ #define ENVELOPE_PROCESSING_STOPPING_TIMEOUT K_SECONDS(20)
40+
41+ K_SEM_DEFINE (envelope_processing_finished_sem , 0 , 1 );
42+ static atomic_t envelope_processing_in_progress ;
43+
3444static void update_failure (void )
3545{
3646 if (suit_dfu_cleanup () < 0 ) {
@@ -42,23 +52,64 @@ static void schedule_envelope_processing(struct k_work *item)
4252{
4353 int ret = suit_dfu_candidate_preprocess ();
4454
55+
56+ if (atomic_get (& envelope_processing_in_progress ) == 0 ) {
57+ LOG_INF ("Envelope processing has been interrupted" );
58+ ret = - ECANCELED ;
59+ }
60+
4561 if (ret < 0 ) {
4662 LOG_ERR ("Envelope processing error" );
4763 update_failure ();
64+ atomic_set (& envelope_processing_in_progress , 0 );
65+ k_sem_give (& envelope_processing_finished_sem );
4866 return ;
4967 }
68+
5069 k_msleep (CONFIG_MGMT_SUITFU_TRIGGER_UPDATE_RESET_DELAY_MS );
5170
71+ LOG_INF ("Rebooting to start firmware upgrade" );
5272 ret = suit_dfu_update_start ();
5373 if (ret < 0 ) {
5474 LOG_ERR ("Failed to start firmware upgrade!" );
5575 update_failure ();
76+ atomic_set (& envelope_processing_in_progress , 0 );
77+ k_sem_give (& envelope_processing_finished_sem );
5678 return ;
5779 }
80+
81+ atomic_set (& envelope_processing_in_progress , 0 );
82+ k_sem_give (& envelope_processing_finished_sem );
83+ }
84+
85+ static void stop_current_envelope_processing (void )
86+ {
87+ if (atomic_get (& envelope_processing_in_progress ) == 0 ) {
88+ return ;
89+ }
90+ LOG_INF ("Stopping old envelope processing" );
91+
92+ #ifdef CONFIG_MGMT_SUITFU_GRP_SUIT_IMAGE_FETCH
93+ suitfu_mgmt_suit_image_fetch_stop ();
94+ #endif
95+ /* Wait for the envelope processing to finish.
96+ * Note: If we have already finished envelope processing with success
97+ * and we are just waiting to send the response to the host,
98+ * this function will not stop the update anymore - the device will
99+ * reboot and start the update.
100+ */
101+ atomic_set (& envelope_processing_in_progress , 0 );
102+ if (k_sem_take (& envelope_processing_finished_sem ,
103+ ENVELOPE_PROCESSING_STOPPING_TIMEOUT ) == 0 ) {
104+ LOG_INF ("Envelope processing stopped successfully" );
105+ } else {
106+ LOG_WRN ("Stopping envelope processing timed out" );
107+ }
58108}
59109
60110int suitfu_mgmt_cleanup (void )
61111{
112+ stop_current_envelope_processing ();
62113 if (suit_dfu_cleanup () < 0 ) {
63114 return MGMT_ERR_EUNKNOWN ;
64115 }
@@ -86,6 +137,12 @@ int suitfu_mgmt_candidate_envelope_process(void)
86137 LOG_INF ("Schedule envelope processing" );
87138 k_work_init_delayable (& suw .work , schedule_envelope_processing );
88139
140+ if (atomic_get (& envelope_processing_in_progress ) == 1 ) {
141+ LOG_WRN ("Current envelope processing is already in progress, new request rejected" );
142+ return MGMT_ERR_EBUSY ;
143+ }
144+ atomic_set (& envelope_processing_in_progress , 1 );
145+ k_sem_reset (& envelope_processing_finished_sem );
89146 int ret = k_work_schedule_for_queue (& system_update_work_queue , & suw .work , K_NO_WAIT );
90147
91148 if (ret < 0 ) {
@@ -103,6 +160,8 @@ int suitfu_mgmt_erase(struct suit_nvm_device_info *device_info, size_t num_bytes
103160 return MGMT_ERR_EINVAL ;
104161 }
105162
163+ stop_current_envelope_processing ();
164+
106165 size_t erase_size = DIV_ROUND_UP (num_bytes , device_info -> erase_block_size ) *
107166 device_info -> erase_block_size ;
108167
@@ -133,6 +192,8 @@ int suitfu_mgmt_write(struct suit_nvm_device_info *device_info, size_t req_img_o
133192
134193 int rc ;
135194
195+ stop_current_envelope_processing ();
196+
136197 if (device_info == NULL || device_info -> fdev == NULL || chunk == NULL ) {
137198 LOG_ERR ("Wrong parameters" );
138199 return MGMT_ERR_EINVAL ;
@@ -252,6 +313,7 @@ int suitfu_mgmt_write(struct suit_nvm_device_info *device_info, size_t req_img_o
252313
253314int suitfu_mgmt_init (void )
254315{
316+ atomic_set (& envelope_processing_in_progress , 0 );
255317 k_work_queue_init (& system_update_work_queue );
256318 k_work_queue_start (& system_update_work_queue , system_update_stack_area ,
257319 K_THREAD_STACK_SIZEOF (system_update_stack_area ), K_HIGHEST_THREAD_PRIO ,
0 commit comments