• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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  * Description: UPG storage functions source file
15  */
16 
17 #include <stddef.h>
18 #include <stdio.h>
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include "securec.h"
22 #include "upg_config.h"
23 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == YES)
24 #include "fcntl.h"
25 #include "sys/stat.h"
26 #include "sys/vfs.h"
27 #endif /* (UPG_CFG_SUPPORT_FILE_SYSTEM == YES) */
28 #include "errcode.h"
29 #include "common_def.h"
30 #include "partition.h"
31 #include "upg_definitions.h"
32 #include "upg_common.h"
33 #include "upg_common_porting.h"
34 #include "upg_alloc.h"
35 #include "upg_verify.h"
36 #include "upg_porting.h"
37 #include "upg_debug.h"
38 
39 STATIC errcode_t upg_package_storage_write(uint32_t offset, const uint8_t *buff, uint16_t len, uint32_t pkg_len);
40 
upg_prepare_erase(uint32_t package_len)41 STATIC errcode_t upg_prepare_erase(uint32_t package_len)
42 {
43     errcode_t ret;
44     uint32_t status_start_addr;
45     uint32_t status_size;
46     unused(package_len);
47     ret = upg_get_progress_status_start_addr(&status_start_addr, &status_size);
48     if (ret != ERRCODE_SUCC) {
49         return ret;
50     }
51 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == NO)
52     partition_information_t info;
53     ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
54     if (ret != ERRCODE_SUCC) {
55         return ret;
56     }
57     ret = upg_flash_erase(info.part_info.addr_info.addr, package_len);
58     if (ret != ERRCODE_SUCC) {
59         return ret;
60     }
61 #endif
62     ret = upg_flash_erase(status_start_addr, status_size);
63     if (ret != ERRCODE_SUCC) {
64         return ret;
65     }
66     return ret;
67 }
68 /*
69  * 存储升级包前对Flash的准备工作(包括擦除升级区、初始化升级标记中的head_before_offset和Head_magic)
70  * prepare_info 分区准备信息,如升级包总长度
71  */
uapi_upg_prepare(upg_prepare_info_t * prepare_info)72 errcode_t uapi_upg_prepare(upg_prepare_info_t *prepare_info)
73 {
74     if (upg_is_inited() == false) {
75         return ERRCODE_UPG_NOT_INIT;
76     }
77 
78     errcode_t ret;
79     uint32_t flag_start_addr;
80     if (prepare_info == NULL || prepare_info->package_len == 0) {
81         return ERRCODE_UPG_INVALID_PARAMETER;
82     }
83 
84 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == NO)
85     if (prepare_info->package_len > uapi_upg_get_storage_size()) {
86         return ERRCODE_UPG_INVALID_PARAMETER;
87     }
88 #endif
89 
90     upg_storage_ctx_t *ctx = upg_get_ctx();
91     ctx->packge_len = prepare_info->package_len;
92 
93     do {
94         /* 擦除FOTA区 */
95         ret = upg_prepare_erase(prepare_info->package_len);
96         if (ret != ERRCODE_SUCC) {
97             break;
98         }
99 
100         /* 初始化head_before_offset */
101         ret = upg_get_upgrade_flag_flash_start_addr(&flag_start_addr);
102         if (ret != ERRCODE_SUCC) {
103             break;
104         }
105         uint32_t flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_before_offset);
106         /* head_before_offset为FOTA区起始地址相对APP分区的偏移地址 */
107         uint32_t head_before_offset = 0;
108         ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_before_offset, false);
109         if (ret != ERRCODE_SUCC) {
110             break;
111         }
112 
113         /* 初始化 package_length */
114         flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, package_length);
115         ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&prepare_info->package_len, false);
116         if (ret != ERRCODE_SUCC) {
117             break;
118         }
119 
120         /* 初始化 Head_magic */
121         uint32_t head_magic = UPG_HEAD_MAGIC;
122         flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_magic);
123         ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_magic, false);
124         if (ret != ERRCODE_SUCC) {
125             break;
126         }
127     } while (0);
128     return ret;
129 }
130 
131 /* 重置升级标记,准备升级 */
uapi_upg_reset_upgrade_flag(void)132 errcode_t uapi_upg_reset_upgrade_flag(void)
133 {
134     errcode_t ret = 0;
135     uint32_t flag_start_addr;
136     uint32_t upg_flag_address = 0;
137     uint32_t status_size;
138 
139     if (upg_is_inited() == false) {
140         return ERRCODE_UPG_NOT_INIT;
141     }
142 
143     ret = upg_get_progress_status_start_addr(&upg_flag_address, &status_size);
144     if (ret != ERRCODE_SUCC) {
145         return ret;
146     }
147 
148     ret = upg_get_upgrade_flag_flash_start_addr(&flag_start_addr);
149     if (ret != ERRCODE_SUCC) {
150         return ret;
151     }
152 
153     /* 擦除标记区前,读取package_len */
154     uint32_t package_len = 0;
155     uint32_t flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, package_length);
156     ret = upg_flash_read(flash_offset, sizeof(uint32_t), (uint8_t *)&package_len);
157     if (ret != ERRCODE_SUCC) {
158         return ret;
159     }
160 
161     /* 擦除标记区 */
162     ret = upg_flash_erase(upg_flag_address, status_size);
163     if (ret != ERRCODE_SUCC) {
164         return ret;
165     }
166 
167     /* 初始化 head_before_offset */
168     flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_before_offset);
169     uint32_t head_before_offset = 0;
170     ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_before_offset, false);
171     if (ret != ERRCODE_SUCC) {
172         return ret;
173     }
174 
175     /* 初始化 Head_magic */
176     uint32_t head_magic = UPG_HEAD_MAGIC;
177     flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_magic);
178     ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_magic, false);
179     if (ret != ERRCODE_SUCC) {
180         return ret;
181     }
182 
183     /* 回写package_length */
184     flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, package_length);
185     return upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&package_len, false);
186 }
187 
upg_check_buff(const uint8_t * buff,uint16_t len)188 STATIC errcode_t upg_check_buff(const uint8_t *buff, uint16_t len)
189 {
190     if (buff == NULL) {
191         return ERRCODE_UPG_NULL_POINTER;
192     }
193     if (len == 0) {
194         return ERRCODE_UPG_INVALID_BUFF_LEN;
195     }
196 
197     return ERRCODE_SUCC;
198 }
199 
200 /*
201  * 升级包存入本地存储空间
202  * offset     要存入本地存储空间的位置(相对起始位置的偏移)
203  * buff       要存入的数据包数据指针
204  * len        要存入的数据包长度(4字节对齐)
205  */
upg_write_package(uint32_t offset,const uint8_t * buff,uint16_t len)206 STATIC errcode_t upg_write_package(uint32_t offset, const uint8_t *buff, uint16_t len)
207 {
208     if (!upg_is_inited()) {
209         return ERRCODE_UPG_NOT_INIT;
210     }
211 
212     errcode_t ret = upg_check_buff(buff, len);
213     if (ret != ERRCODE_SUCC) {
214         return ret;
215     }
216 
217     upg_storage_ctx_t *ctx = upg_get_ctx();
218     if (ctx->packge_len == 0) {
219         return ERRCODE_UPG_NOT_PREPARED;
220     }
221 
222     return upg_package_storage_write(offset, buff, len, ctx->packge_len);
223 }
224 
225 /*
226  * 升级包存入本地存储空间,异步接口
227  * offset     要存入本地存储空间的位置(相对起始位置的偏移)
228  * buff       要存入的数据包数据指针
229  * len        要存入的数据包长度(4字节对齐)
230  * callback   写入完成的回调函数。
231  */
uapi_upg_write_package_async(uint32_t offset,const uint8_t * buff,uint16_t len,uapi_upg_write_done_cb callback)232 errcode_t uapi_upg_write_package_async(uint32_t offset, const uint8_t *buff, uint16_t len,
233                                        uapi_upg_write_done_cb callback)
234 {
235     errcode_t ret = upg_write_package(offset, buff, len);
236     if (ret != ERRCODE_SUCC) {
237         return ret;
238     }
239 
240     if (callback != NULL) {
241         callback(ret);
242     }
243     return ret;
244 }
245 
246 /*
247  * 升级包存入本地存储空间,同步接口
248  * offset     要存入本地存储空间的位置(相对起始位置的偏移)
249  * buff       要存入的数据包数据指针
250  * len        要存入的数据包长度(4字节对齐)
251  */
uapi_upg_write_package_sync(uint32_t offset,const uint8_t * buff,uint16_t len)252 errcode_t uapi_upg_write_package_sync(uint32_t offset, const uint8_t *buff, uint16_t len)
253 {
254     return upg_write_package(offset, buff, len);
255 }
256 
257 /*
258  * 从本地存储空间读取升级包数据
259  * offset     要读取的本地存储空间的位置(相对与升级包起始位置的偏移)
260  * buff       存放数据包的空间指针
261  * len        要读取的数据包长度(4字节对齐)
262  */
uapi_upg_read_package(uint32_t offset,uint8_t * buff,uint32_t len)263 errcode_t uapi_upg_read_package(uint32_t offset, uint8_t *buff, uint32_t len)
264 {
265     if (upg_is_inited() == false) {
266         return ERRCODE_UPG_NOT_INIT;
267     }
268 
269     errcode_t ret = upg_check_buff(buff, (uint16_t)len);
270     if (ret != ERRCODE_SUCC) {
271         return ret;
272     }
273 
274     return upg_read_fota_pkg_data(offset, buff, (uint32_t *)&len);
275 }
276 
upg_get_firmware_number_in_package(const upg_package_header_t * pkg_header,uint32_t * firmware_num)277 STATIC errcode_t upg_get_firmware_number_in_package(const upg_package_header_t *pkg_header, uint32_t *firmware_num)
278 {
279     errcode_t ret;
280     upg_image_hash_node_t *img_hash_table = NULL;
281 
282     uint32_t image_num = pkg_header->info_area.image_num;
283     uint32_t fw_num = 0;
284 
285     if (image_num > UPG_FIRMWARE_MAX_NUM) {
286         return ERRCODE_UPG_WRONG_IMAGE_NUM;
287     }
288 
289     ret = upg_get_pkg_image_hash_table((const upg_package_header_t *)pkg_header, &img_hash_table);
290     if (ret != ERRCODE_SUCC || img_hash_table == NULL) {
291         upg_log_err("[UPG] upg_get_pkg_image_hash_table fail\r\n");
292         return ret;
293     }
294 
295     for (uint32_t i = 0; i < image_num; i++) {
296         if (img_hash_table[i].image_id != UPG_IMAGE_ID_NV) {
297             fw_num++;
298         }
299     }
300     *firmware_num = fw_num;
301     upg_free(img_hash_table);
302     return ret;
303 }
304 
305 /*
306  * 申请开始本地升级
307  * firmware_num 升级包中firmware数量
308  */
upg_upgrade_request(uint32_t firmware_num)309 STATIC errcode_t upg_upgrade_request(uint32_t firmware_num)
310 {
311     uint32_t flag_start_address = 0;
312     errcode_t ret = upg_get_upgrade_flag_flash_start_addr(&flag_start_address);
313     if (ret != ERRCODE_SUCC) {
314         return ret;
315     }
316 
317     /* 写入firmware_num */
318     uint32_t flash_offset = (uint32_t)flag_start_address + offsetof(fota_upgrade_flag_area_t, firmware_num);
319     ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)(&firmware_num), false);
320     if (ret != ERRCODE_SUCC) {
321         return ret;
322     }
323 
324     /* 写入Head_end_magic */
325     uint32_t head_end_magic = UPG_END_MAGIC;
326     flash_offset = (uint32_t)flag_start_address + offsetof(fota_upgrade_flag_area_t, head_end_magic);
327     ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&(head_end_magic), false);
328     if (ret != ERRCODE_SUCC) {
329         return ret;
330     }
331 
332     return ERRCODE_SUCC;
333 }
334 
uapi_upg_request_upgrade(bool reset)335 errcode_t uapi_upg_request_upgrade(bool reset)
336 {
337     errcode_t ret;
338     upg_package_header_t *pkg_header = NULL;
339     uint32_t firmware_num = 0;
340 
341     if (upg_is_inited() == false) {
342         return ERRCODE_UPG_NOT_INIT;
343     }
344 
345     ret = upg_get_package_header(&pkg_header);
346     if (ret != ERRCODE_SUCC || pkg_header == NULL) {
347         upg_log_err("[UPG] upg_get_package_header fail\r\n");
348         return ret;
349     }
350 
351 #if (UPG_CFG_VERIFICATION_SUPPORT == YES)
352     ret = uapi_upg_verify_file((const upg_package_header_t *)pkg_header);
353     if (ret != ERRCODE_SUCC) {
354         upg_free(pkg_header);
355         upg_log_err("[UPG] uapi_upg_verify_file fail, ret = 0x%x\r\n", ret);
356         return ret;
357     }
358 #endif
359 
360     ret = upg_get_firmware_number_in_package((const upg_package_header_t *)pkg_header, &firmware_num);
361     if (ret != ERRCODE_SUCC) {
362         upg_free(pkg_header);
363         upg_log_err("[UPG] upg_get_firmware_number_in_package fail, ret = 0x%x\r\n", ret);
364         return ret;
365     }
366 
367     upg_free(pkg_header);
368 
369     ret = upg_upgrade_request(firmware_num);
370     if (ret != ERRCODE_SUCC) {
371         upg_log_err("[UPG] upg_upgrade_request fail. ret = 0x%x\r\n", ret);
372         return ret;
373     }
374     /* app中下载后直接开始升级流程,升级流程结束后重启 */
375     if (reset) {
376         /* IOT设备重启 */
377         upg_reboot();
378     }
379     return ERRCODE_SUCC;
380 }
381 
382 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == YES)
upg_package_storage_write(uint32_t offset,const uint8_t * buff,uint16_t len,uint32_t pkg_len)383 STATIC errcode_t upg_package_storage_write(uint32_t offset, const uint8_t *buff, uint16_t len, uint32_t pkg_len)
384 {
385     uint16_t write_len = 0;
386     static FILE *wr_fd = NULL;
387     static uint32_t wr_pos = 0;
388     errcode_t ret = ERRCODE_SUCC;
389 
390     if (wr_fd == NULL && (upg_get_pkg_file_path() != NULL)) {
391         /* 第一次调用,打开文件 */
392         wr_fd = fopen(upg_get_pkg_file_path(), "wb");
393         if (wr_fd == NULL) {
394             return ERRCODE_UPG_FILE_OPEN_FAIL;
395         }
396     }
397 
398     if (offset != wr_pos) {
399         ret = ERRCODE_UPG_INVALID_OFFSET;
400         goto end;
401     }
402 
403     uint16_t left_len = (uint16_t)((wr_pos + len > pkg_len) ? pkg_len - wr_pos : len);
404     while (left_len > 0) {
405         /* 一次未写完,可多次读取 */
406         uint16_t tmp = (uint16_t)fwrite(buff + write_len, 1, left_len, wr_fd);
407         if (tmp == 0) {
408             /* 写入失败,中断写入操作 */
409             upg_log_err("[UPG] set file error : %d\r\n", ferror(wr_fd));
410             ret = ERRCODE_UPG_FILE_WRITE_FAIL;
411             goto end;
412         }
413         left_len -= tmp;
414         write_len += tmp;
415     }
416     wr_pos = (uint32_t)ftell(wr_fd);
417 end:
418     if (ret != ERRCODE_SUCC || wr_pos >= pkg_len) {
419         /* 失败或者全部写完后,关闭文件 */
420         fclose(wr_fd);
421         wr_fd = NULL;
422         wr_pos = 0;
423     }
424     return ret;
425 }
426 #else
upg_package_storage_write(uint32_t offset,const uint8_t * buff,uint16_t len,uint32_t pkg_len)427 STATIC errcode_t upg_package_storage_write(uint32_t offset, const uint8_t *buff, uint16_t len, uint32_t pkg_len)
428 {
429     uint32_t start_addr = 0;
430     uint32_t size = 0;
431     errcode_t ret = upg_get_fota_partiton_area_addr(&start_addr, &size);
432     if (ret != ERRCODE_SUCC) {
433         return ret;
434     }
435 
436     size -= UPG_META_DATA_LENGTH + UPG_UPGRADE_FLAG_LENGTH;
437     if (offset >= size || offset + len > size || offset >= pkg_len || offset + len > pkg_len) {
438         return ERRCODE_UPG_NO_ENOUGH_SPACE;
439     }
440 
441     return upg_flash_write(start_addr + offset, len, buff, false); /* prepare过程已擦除整个fota区,此处不需写前擦 */
442 }
443 #endif
444 
uapi_upg_get_status(void)445 upg_status_t uapi_upg_get_status(void)
446 {
447     return upg_get_ctx()->upg_status;
448 }