• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 /*****************************************************************************
17 *
18 * File Name : wm_fwup.c
19 *
20 * Description: firmware update Module
21 *
22 * Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd.
23 * All rights reserved.
24 *
25 * Author : dave
26 *
27 * Date : 2014-6-16
28 *****************************************************************************/
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 
33 #include "wm_mem.h"
34 #include "list.h"
35 #include "wm_debug.h"
36 #include "wm_internal_flash.h"
37 #include "wm_crypto_hard.h"
38 
39 #include "utils.h"
40 #include "wm_watchdog.h"
41 #include "wm_wifi.h"
42 #include "wm_flash_map.h"
43 #include "wm_wl_task.h"
44 #include "wm_params.h"
45 #include "wm_param.h"
46 #include "wm_fwup.h"
47 
48 #define FWUP_MSG_QUEUE_SIZE      (4)
49 
50 #define FWUP_TASK_STK_SIZE      (256)
51 
52 #define FWUP_MSG_START_ENGINEER      (1)
53 
54 static struct tls_fwup *fwup = NULL;
55 static tls_os_queue_t *fwup_msg_queue = NULL;
56 
57 #if TLS_OS_FREERTOS
58 static u32 *fwup_task_stk = NULL;
59 #endif
60 static u8 oneshotback = 0;
61 
62 extern int tls_fls_fast_write_init(void);
63 extern int tls_fls_fast_write(u32 addr, u8 *buf, u32 length);
64 extern void tls_fls_fast_write_destroy(void);
65 
fwup_update_autoflag(void)66 static void fwup_update_autoflag(void)
67 {
68     u8 auto_reconnect = 0xff;
69 
70     tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_reconnect);
71     if (auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) {
72         auto_reconnect = WIFI_AUTO_CNT_ON;
73         tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_reconnect);
74     }
75     return;
76 }
77 
tls_fwup_img_header_check(IMAGE_HEADER_PARAM_ST * img_param)78 int tls_fwup_img_header_check(IMAGE_HEADER_PARAM_ST *img_param)
79 {
80     psCrcContext_t    crcContext;
81     unsigned int crcvalue = 0;
82     unsigned int crccallen = 0;
83     int i = 0;
84 
85     if (img_param->magic_no != SIGNATURE_WORD) {
86         return FALSE;
87     }
88 
89     if (img_param->img_addr % IMAGE_START_ADDR_MSK) { // vbr register must be 1024 align.
90         return FALSE;
91     }
92 
93     if ((img_param->img_addr|FLASH_BASE_ADDR) >= USER_ADDR_START) {
94         return FALSE;
95     }
96 
97     if ((img_param->img_addr|FLASH_BASE_ADDR) + img_param->img_len >= USER_ADDR_START) {
98         return FALSE;
99     }
100 
101     if (((img_param->upgrade_img_addr|FLASH_BASE_ADDR) < CODE_UPD_START_ADDR)
102         || ((img_param->upgrade_img_addr|FLASH_BASE_ADDR) + img_param->img_len >= CODE_RUN_START_ADDR)) {
103         return FALSE;
104     }
105 
106     crccallen = (sizeof(IMAGE_HEADER_PARAM_ST)-4);
107 
108     tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3);
109     for (i = 0; i <  crccallen/4; i++) {
110         MEMCPY((unsigned char *)&crcvalue, (unsigned char *)img_param +i*4, 4);
111         tls_crypto_crc_update(&crcContext, (unsigned char *)&crcvalue, 4);
112     }
113     crcvalue = 0;
114     tls_crypto_crc_final(&crcContext, &crcvalue);
115     if (img_param->hd_checksum == crcvalue) {
116         return TRUE;
117     } else {
118         return FALSE;
119     }
120 }
121 
fwup_scheduler(void * data)122 static void fwup_scheduler(void *data)
123 {
124     u8 *buffer = NULL;
125     int err;
126     u32 msg;
127     u32 len;
128     u32 image_checksum = 0;
129     struct tls_fwup_request *request;
130     struct tls_fwup_request *temp;
131     IMAGE_HEADER_PARAM_ST booter;
132 
133     while (1) {
134         err = tls_os_queue_receive(fwup_msg_queue, (void **)&msg, 0, 0);
135             tls_watchdog_clr();
136         if (err != TLS_OS_SUCCESS) {
137             continue;
138         }
139         switch (msg) {
140             case FWUP_MSG_START_ENGINEER:
141                 if (dl_list_empty(&fwup->wait_list) == 0) {
142                     fwup->current_state |= TLS_FWUP_STATE_BUSY;
143                 }
144                 dl_list_for_each_safe(request, temp, &fwup->wait_list, struct tls_fwup_request, list)
145                 {
146                     request->status = TLS_FWUP_REQ_STATUS_BUSY;
147                     if (fwup->current_state & TLS_FWUP_STATE_ERROR) {
148                         TLS_DBGPRT_WARNING("some error happened during firmware update, \
149                                            so discard all the request in the waiting queue!\n");
150                         if (fwup->current_state & TLS_FWUP_STATE_ERROR_IO) {
151                             request->status = TLS_FWUP_REQ_STATUS_FIO;
152                         }
153                         else if (fwup->current_state & TLS_FWUP_STATE_ERROR_SIGNATURE) {
154                             request->status = TLS_FWUP_REQ_STATUS_FSIGNATURE;
155                         } else if (fwup->current_state & TLS_FWUP_STATE_ERROR_MEM) {
156                             request->status = TLS_FWUP_REQ_STATUS_FMEM;
157                         } else if (fwup->current_state & TLS_FWUP_STATE_ERROR_CRC) {
158                             request->status = TLS_FWUP_REQ_STATUS_FCRC;
159                         }
160                         goto request_finish;
161                     } else if (fwup->current_state & TLS_FWUP_STATE_COMPLETE) {
162                         TLS_DBGPRT_WARNING("the firmware updating conpletes, \
163                                            so discard the request in the waiting queue!\n");
164                         request->status = TLS_FWUP_REQ_STATUS_FCOMPLETE;
165                         goto request_finish;
166                     }
167 
168                     if (fwup->current_image_src <= TLS_FWUP_IMAGE_SRC_WEB) {
169                         buffer = request->data;
170                         if (fwup->received_len < sizeof(IMAGE_HEADER_PARAM_ST)) {
171                             len = sizeof(IMAGE_HEADER_PARAM_ST) - fwup->received_len;
172                             if (request->data_len < len) {
173                                 len = request->data_len;
174                             }
175 
176                             MEMCPY((u8 *)&booter + fwup->received_len, buffer, len);
177                             request->data_len  -= len;
178                             buffer += len;
179                             fwup->received_len += len;
180                             if (fwup->received_len == sizeof(IMAGE_HEADER_PARAM_ST)) {
181                                 if (!tls_fwup_img_header_check(&booter)) {
182                                     request->status = TLS_FWUP_REQ_STATUS_FIO;
183                                     fwup->current_state |= TLS_FWUP_STATE_ERROR_IO;
184                                     goto request_finish;
185                                 }
186 
187                                 fwup->program_base = booter.upgrade_img_addr | FLASH_BASE_ADDR;
188                                 fwup->program_offset = 0;
189                                 fwup->total_len = booter.img_len + sizeof(IMAGE_HEADER_PARAM_ST);
190                                 if (booter.img_attr.b.signature) {
191                                     fwup->total_len += 128;
192                                 }
193                                 /* write booter header to flash */
194                                 err = tls_fls_fast_write(fwup->program_base + fwup->program_offset,
195                                     (u8 *)&booter, sizeof(IMAGE_HEADER_PARAM_ST));
196                                 if (err != TLS_FLS_STATUS_OK) {
197                                     TLS_DBGPRT_ERR("failed to program flash!\n");
198                                     request->status = TLS_FWUP_REQ_STATUS_FIO;
199                                     fwup->current_state |= TLS_FWUP_STATE_ERROR_IO;
200                                     goto request_finish;
201                                 }
202                                 /* initialize updated_len */
203                                 fwup->updated_len = sizeof(IMAGE_HEADER_PARAM_ST);
204                                 fwup->program_offset = sizeof(IMAGE_HEADER_PARAM_ST);
205                             }
206                         }
207                         fwup->received_len += request->data_len;
208                     }
209                     if (request->data_len > 0) {
210                         err = tls_fls_fast_write(fwup->program_base + fwup->program_offset, buffer, request->data_len);
211                         if (err != TLS_FLS_STATUS_OK) {
212                             TLS_DBGPRT_ERR("failed to program flash!\n");
213                             request->status = TLS_FWUP_REQ_STATUS_FIO;
214                             fwup->current_state |= TLS_FWUP_STATE_ERROR_IO;
215                             goto request_finish;
216                         }
217 
218                         fwup->program_offset += request->data_len;
219                         fwup->updated_len += request->data_len;
220                         if (fwup->updated_len >= (fwup->total_len)) {
221                             u8 *buffer_t;
222                             u32 len, left, offset;
223 
224                             psCrcContext_t    crcContext;
225 
226                             tls_fls_fast_write_destroy();
227                             buffer_t = tls_mem_alloc(1024);
228                             if (buffer_t == NULL) {
229                                 TLS_DBGPRT_ERR("unable to verify because of no memory\n");
230                                 request->status = TLS_FWUP_REQ_STATUS_FMEM;
231                                 fwup->current_state |= TLS_FWUP_STATE_ERROR_MEM;
232                                 goto request_finish;
233                             } else {
234                                 offset = sizeof(IMAGE_HEADER_PARAM_ST);
235                                 if (booter.img_attr.b.signature) {
236                                     left = fwup->total_len - 128 - sizeof(IMAGE_HEADER_PARAM_ST);
237                                 } else {
238                                     left = fwup->total_len - sizeof(IMAGE_HEADER_PARAM_ST);
239                                 }
240 
241                                 tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3);
242                                 while (left > 0) {
243                                     len = left > 1024 ? 1024 : left;
244                                     err = tls_fls_read(fwup->program_base + offset, buffer_t, len);
245                                     if (err != TLS_FLS_STATUS_OK) {
246                                         request->status = TLS_FWUP_REQ_STATUS_FIO;
247                                         fwup->current_state |= TLS_FWUP_STATE_ERROR_IO;
248                                         goto request_finish;
249                                     }
250                                     tls_crypto_crc_update(&crcContext, buffer_t, len);
251                                     offset += len;
252                                     left -= len;
253                                 }
254                                 tls_crypto_crc_final(&crcContext, &image_checksum);
255                                 tls_mem_free(buffer_t);
256                             }
257 
258                             if (booter.org_checksum != image_checksum) {
259                                 TLS_DBGPRT_ERR("varify incorrect[0x%02x, but 0x%02x]\n",
260                                                booter.org_checksum, image_checksum);
261                                 request->status = TLS_FWUP_REQ_STATUS_FCRC;
262                                 fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC;
263                                 goto request_finish;
264                             } else {
265                                 /* Write OTA flag to flash used by boot loader */
266                                 tls_fls_write(TLS_FLASH_OTA_FLAG_ADDR, (u8 *)&booter.org_checksum,
267                                               sizeof(booter.org_checksum));
268                             }
269 
270                             TLS_DBGPRT_INFO("update the firmware successfully!\n");
271                             fwup->current_state |= TLS_FWUP_STATE_COMPLETE;
272                             if (oneshotback != 0) {
273                                 tls_wifi_set_oneshot_flag(oneshotback);    // �ָ�һ������
274                             }
275                         }
276                     }
277                     request->status = TLS_FWUP_REQ_STATUS_SUCCESS;
278 request_finish:
279                     tls_os_sem_acquire(fwup->list_lock, 0);
280                     dl_list_del(&request->list);
281                     tls_os_sem_release(fwup->list_lock);
282                     if (dl_list_empty(&fwup->wait_list) == 1) {
283                         fwup->current_state &= ~TLS_FWUP_STATE_BUSY;
284                     }
285                     if (request->complete) {
286                         request->complete(request, request->arg);
287                     }
288                     if (fwup->updated_len >= (fwup->total_len)) {
289                         fwup_update_autoflag();
290                         tls_sys_reset();
291                     }
292                 }
293                 break;
294 
295             default:
296                 break;
297         }
298     }
299 }
300 
fwup_request_complete(struct tls_fwup_request * request,void * arg)301 void fwup_request_complete(struct tls_fwup_request *request, void *arg)
302 {
303     tls_os_sem_t *sem;
304 
305     if ((request == NULL) || (arg == NULL)) {
306         return;
307     }
308     sem = (tls_os_sem_t *)arg;
309     tls_os_sem_release(sem);
310 }
311 
tls_fwup_enter(enum tls_fwup_image_src image_src)312 u32 tls_fwup_enter(enum tls_fwup_image_src image_src)
313 {
314     u32 session_id = 0;
315     u32 cpu_sr;
316     bool enable = FALSE;
317 
318     tls_fwup_init();
319 
320     if (fwup == NULL) {
321         TLS_DBGPRT_INFO("fwup is null!\n");
322         return 0;
323     }
324     if (fwup->busy == TRUE) {
325         TLS_DBGPRT_INFO("fwup is busy!\n");
326         return 0;
327     }
328 
329     cpu_sr = tls_os_set_critical();
330 
331     do {
332         session_id = rand();
333     } while (session_id == 0);
334 
335     fwup->current_state = 0;
336     fwup->current_image_src = image_src;
337 
338     fwup->received_len = 0;
339     fwup->total_len = 0;
340     fwup->updated_len = 0;
341     fwup->program_base = 0;
342     fwup->program_offset = 0;
343     fwup->received_number = -1;
344 
345     fwup->current_session_id = session_id;
346     fwup->busy = TRUE;
347     oneshotback = tls_wifi_get_oneshot_flag();
348     if (oneshotback != 0) {
349         tls_wifi_set_oneshot_flag(0);    // �˳�һ������
350     }
351     tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE);
352     if (TRUE == enable) {
353         tls_wifi_set_psflag(FALSE, 0);
354     }
355     tls_fls_fast_write_init();
356     tls_os_release_critical(cpu_sr);
357     return session_id;
358 }
359 
tls_fwup_exit(u32 session_id)360 int tls_fwup_exit(u32 session_id)
361 {
362     u32 cpu_sr;
363     bool enable = FALSE;
364 
365     if ((fwup == NULL) || (fwup->busy == FALSE)) {
366         return TLS_FWUP_STATUS_EPERM;
367     }
368     if (session_id != fwup->current_session_id) {
369         return TLS_FWUP_STATUS_ESESSIONID;
370     }
371     if (fwup->current_state & TLS_FWUP_STATE_BUSY) {
372         return TLS_FWUP_STATUS_EBUSY;
373     }
374 
375     cpu_sr = tls_os_set_critical();
376 
377     fwup->current_state = 0;
378 
379     fwup->received_len = 0;
380     fwup->total_len = 0;
381     fwup->updated_len = 0;
382     fwup->program_base = 0;
383     fwup->program_offset = 0;
384     fwup->received_number = -1;
385 
386     fwup->current_session_id = 0;
387     fwup->busy = FALSE;
388     if (oneshotback != 0) {
389         tls_wifi_set_oneshot_flag(oneshotback); // �ָ�һ������
390     }
391     tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE);
392     tls_wifi_set_psflag(enable, 0);
393     tls_os_release_critical(cpu_sr);
394     return TLS_FWUP_STATUS_OK;
395 }
396 
tls_fwup_get_current_session_id(void)397 int tls_fwup_get_current_session_id(void)
398 {
399     if (fwup) {
400         return fwup->current_session_id;
401     }
402     return 0;
403 }
404 
tls_fwup_set_update_numer(int number)405 int tls_fwup_set_update_numer(int number)
406 {
407     if (number - fwup->received_number == 1) {
408         fwup->received_number = number;
409         return TLS_FWUP_STATUS_OK;
410     }
411     return TLS_FWUP_STATE_UNDEF;
412 }
413 
tls_fwup_get_current_update_numer(void)414 int tls_fwup_get_current_update_numer(void)
415 {
416     return fwup->received_number;
417 }
418 
tls_fwup_get_status(void)419 int tls_fwup_get_status(void)
420 {
421     return fwup->busy;
422 }
423 
tls_fwup_set_crc_error(u32 session_id)424 int tls_fwup_set_crc_error(u32 session_id)
425 {
426     if (fwup == NULL) {
427         return TLS_FWUP_STATUS_EPERM;
428     }
429     if (session_id != fwup->current_session_id) {
430         return TLS_FWUP_STATUS_ESESSIONID;
431     }
432     fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC;
433 
434     return TLS_FWUP_STATUS_OK;
435 }
436 
tls_fwup_request_async(u32 session_id,struct tls_fwup_request * request)437 static int tls_fwup_request_async(u32 session_id, struct tls_fwup_request *request)
438 {
439     u8 need_sched;
440 
441     if (fwup == NULL) {
442         return TLS_FWUP_STATUS_EPERM;
443     }
444     if (session_id != fwup->current_session_id) {
445         return TLS_FWUP_STATUS_ESESSIONID;
446     }
447     if ((request == NULL) || (request->data == NULL) || (request->data_len == 0)) {
448         return TLS_FWUP_STATUS_EINVALID;
449     }
450     tls_os_sem_acquire(fwup->list_lock, 0);
451     if (dl_list_empty(&fwup->wait_list)) {
452         need_sched = 1;
453     } else {
454         need_sched = 0;
455     }
456     request->status = TLS_FWUP_REQ_STATUS_IDLE;
457     dl_list_add_tail(&fwup->wait_list, &request->list);
458     tls_os_sem_release(fwup->list_lock);
459     if (need_sched == 1) {
460         tls_os_queue_send(fwup_msg_queue, (void *)FWUP_MSG_START_ENGINEER, 0);
461     }
462     return TLS_FWUP_STATUS_OK;
463 }
464 
tls_fwup_request_sync(u32 session_id,u8 * data,u32 data_len)465 int tls_fwup_request_sync(u32 session_id, u8 *data, u32 data_len)
466 {
467     int err;
468     tls_os_sem_t *sem;
469     struct tls_fwup_request request;
470 
471     if (fwup == NULL) {
472         return TLS_FWUP_STATUS_EPERM;
473     }
474     if (session_id != fwup->current_session_id) {
475         return TLS_FWUP_STATUS_ESESSIONID;
476     }
477     if ((data == NULL) || (data_len == 0)) {
478         return TLS_FWUP_STATUS_EINVALID;
479     }
480 
481     err = tls_os_sem_create(&sem, 0);
482     if (err != TLS_OS_SUCCESS) {
483         return TLS_FWUP_STATUS_EMEM;
484     }
485     request.data = data;
486     request.data_len = data_len;
487     request.complete = fwup_request_complete;
488     request.arg = (void *)sem;
489 
490     err = tls_fwup_request_async(session_id, &request);
491     if (err == TLS_FWUP_STATUS_OK) {
492         tls_os_sem_acquire(sem, 0);
493     }
494     tls_os_sem_delete(sem);
495 
496     switch (request.status) {
497         case TLS_FWUP_REQ_STATUS_SUCCESS:
498             err = TLS_FWUP_STATUS_OK;
499             break;
500 
501         case TLS_FWUP_REQ_STATUS_FIO:
502             err = TLS_FWUP_STATUS_EIO;
503             break;
504 
505         case TLS_FWUP_REQ_STATUS_FSIGNATURE:
506             err = TLS_FWUP_STATUS_ESIGNATURE;
507             break;
508 
509         case TLS_FWUP_REQ_STATUS_FMEM:
510             err = TLS_FWUP_STATUS_EMEM;
511             break;
512 
513         case TLS_FWUP_REQ_STATUS_FCRC:
514             err = TLS_FWUP_STATUS_ECRC;
515             break;
516 
517         case TLS_FWUP_REQ_STATUS_FCOMPLETE:
518             err = TLS_FWUP_STATUS_EIO;
519             break;
520 
521         default:
522             err = TLS_FWUP_STATUS_EUNDEF;
523             break;
524     }
525     return err;
526 }
527 
tls_fwup_current_state(u32 session_id)528 u16 tls_fwup_current_state(u32 session_id)
529 {
530     if (fwup == NULL) {
531         return TLS_FWUP_STATE_UNDEF;
532     }
533     if (session_id != fwup->current_session_id) {
534         return TLS_FWUP_STATE_UNDEF;
535     }
536     return fwup->current_state;
537 }
538 
tls_fwup_reset(u32 session_id)539 int tls_fwup_reset(u32 session_id)
540 {
541     u32 cpu_sr;
542 
543     if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;}
544     if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;}
545     if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;}
546 
547     cpu_sr = tls_os_set_critical();
548 
549     fwup->current_state = 0;
550 
551     fwup->received_len = 0;
552     fwup->total_len = 0;
553     fwup->updated_len = 0;
554     fwup->program_base = 0;
555     fwup->program_offset = 0;
556 
557     tls_os_release_critical(cpu_sr);
558 
559     return TLS_FWUP_STATUS_OK;
560 }
561 
tls_fwup_clear_error(u32 session_id)562 int tls_fwup_clear_error(u32 session_id)
563 {
564     u32 cpu_sr;
565 
566     if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;}
567     if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;}
568     if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;}
569 
570     cpu_sr = tls_os_set_critical();
571 
572     fwup->current_state &= ~TLS_FWUP_STATE_ERROR;
573 
574     tls_os_release_critical(cpu_sr);
575 
576     return TLS_FWUP_STATUS_OK;
577 }
578 
tls_fwup_init(void)579 int tls_fwup_init(void)
580 {
581     int err;
582 
583     if (fwup != NULL) {
584         TLS_DBGPRT_ERR("firmware update module has been installed!\n");
585         return TLS_FWUP_STATUS_EBUSY;
586     }
587 
588     fwup = tls_mem_alloc(sizeof(*fwup));
589     if (fwup == NULL) {
590         TLS_DBGPRT_ERR("allocate @fwup fail!\n");
591         return TLS_FWUP_STATUS_EMEM;
592     }
593     memset_s(fwup, sizeof(fwup), 0, sizeof(*fwup));
594 
595     err = tls_os_sem_create(&fwup->list_lock, 1);
596     if (err != TLS_OS_SUCCESS) {
597         TLS_DBGPRT_ERR("create semaphore @fwup->list_lock fail!\n");
598         tls_mem_free(fwup);
599         return TLS_FWUP_STATUS_EMEM;
600     }
601 
602     dl_list_init(&fwup->wait_list);
603     fwup->busy = FALSE;
604 
605     err = tls_os_queue_create(&fwup_msg_queue, FWUP_MSG_QUEUE_SIZE);
606     if (err != TLS_OS_SUCCESS) {
607         TLS_DBGPRT_ERR("create message queue @fwup_msg_queue fail!\n");
608         tls_os_sem_delete(fwup->list_lock);
609         tls_mem_free(fwup);
610         return TLS_FWUP_STATUS_EMEM;
611     }
612 #if TLS_OS_FREERTOS
613     fwup_task_stk = (u32 *)tls_mem_alloc(FWUP_TASK_STK_SIZE * sizeof(u32));
614     if (fwup_task_stk) {
615 #endif
616         err = tls_os_task_create(NULL, "fwup",
617                                  fwup_scheduler,
618                                  (void *)fwup,
619 #if TLS_OS_FREERTOS
620                                  (void *)fwup_task_stk,
621 #else
622                                  NULL,
623 #endif
624                                  FWUP_TASK_STK_SIZE * sizeof(u32),
625                                  TLS_FWUP_TASK_PRIO,
626                                  0);
627         if (err != TLS_OS_SUCCESS) {
628             TLS_DBGPRT_ERR("create firmware update process task fail!\n");
629 
630             tls_os_queue_delete(fwup_msg_queue);
631             fwup_msg_queue = NULL;
632             tls_os_sem_delete(fwup->list_lock);
633             fwup->list_lock = NULL;
634             tls_mem_free(fwup);
635             fwup = NULL;
636 #if TLS_OS_FREERTOS
637             tls_mem_free(fwup_task_stk);
638             fwup_task_stk = NULL;
639 #endif
640             return TLS_FWUP_STATUS_EMEM;
641         }
642 #if TLS_OS_FREERTOS
643     } else {
644         tls_os_queue_delete(fwup_msg_queue);
645         fwup_msg_queue = NULL;
646         tls_os_sem_delete(fwup->list_lock);
647         fwup->list_lock = NULL;
648         tls_mem_free(fwup);
649         return TLS_FWUP_STATUS_EMEM;
650     }
651 #endif
652 
653     return TLS_FWUP_STATUS_OK;
654 }