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 upgrade functions source file
15 */
16
17 #include <stdint.h>
18 #include <stddef.h>
19 #include "securec.h"
20 #include "common_def.h"
21 #include "upg_definitions.h"
22 #include "errcode.h"
23 #include "upg_lzmadec.h"
24 #include "upg_common.h"
25 #include "upg_common_porting.h"
26 #include "upg_alloc.h"
27 #include "upg_porting.h"
28 #include "upg_config.h"
29 #include "upg_debug.h"
30 #if (UPG_CFG_SUPPORT_RESOURCES_FILE == YES)
31 #include "dfx_file_operation.h"
32
upg_resource_file_full(const upg_lzma_decode2_data_t * data,upg_resource_node_t * file_info)33 STATIC errcode_t upg_resource_file_full(const upg_lzma_decode2_data_t *data, upg_resource_node_t *file_info)
34 {
35 errcode_t ret = ERRCODE_SUCC;
36 uint32_t file_len = file_info->file_len;
37 uint32_t read_offset = data->in_offset + file_info->offset;
38 uint32_t file_offset = 0;
39
40 int32_t write_fd = dfx_file_open_for_write((const char *)file_info->file_path);
41 if (write_fd < 0) {
42 return ERRCODE_UPG_FILE_OPEN_FAIL;
43 }
44
45 while (file_len > 0) {
46 uint32_t tmp_len = file_len > UPG_FLASH_PAGE_SIZE ? UPG_FLASH_PAGE_SIZE : file_len;
47 (void)memset_s(data->buf.outbuf, UPG_FLASH_PAGE_SIZE, 0, UPG_FLASH_PAGE_SIZE);
48 ret = upg_read_fota_pkg_data(read_offset + file_offset, data->buf.outbuf, &tmp_len);
49 if (ret != ERRCODE_SUCC) {
50 break;
51 }
52
53 if (dfx_file_write_fd(write_fd, file_offset, data->buf.outbuf, tmp_len) != (int32_t)tmp_len) {
54 ret = ERRCODE_UPG_FILE_WRITE_FAIL;
55 break;
56 }
57 file_len -= tmp_len;
58 file_offset += tmp_len;
59 }
60 upg_calculate_and_notify_process((uint32_t)file_offset);
61
62 dfx_file_fsync(write_fd);
63 dfx_file_close(write_fd);
64 return ret;
65 }
66
upg_resource_file_delete(const char * file_path)67 STATIC errcode_t upg_resource_file_delete(const char *file_path)
68 {
69 (void)dfx_file_delete(file_path);
70 return ERRCODE_SUCC;
71 }
72
upg_resource_file_rmdir(const char * path)73 STATIC errcode_t upg_resource_file_rmdir(const char *path)
74 {
75 (void)dfx_file_rmdir(path);
76 return ERRCODE_SUCC;
77 }
78
upg_resource_data_task(CLzmaDec * p,upg_lzma_decode2_data_t * data,const upg_image_header_t * image,upg_resource_node_t * file_info)79 STATIC errcode_t upg_resource_data_task(CLzmaDec *p, upg_lzma_decode2_data_t *data,
80 const upg_image_header_t *image, upg_resource_node_t *file_info)
81 {
82 if (file_info->operation_type != UPG_RESOURCE_ADD_FILE && file_info->operation_type != UPG_RESOURCE_AMEND_FILE) {
83 return ERRCODE_SUCC;
84 }
85
86 if (file_info->file_len == 0) {
87 return ERRCODE_SUCC;
88 }
89
90 if (image->decompress_flag == DECOMPRESS_FLAG_ZIP) {
91 upg_log_info("[UPG] decompress resource file\r\n");
92 return upg_resource_file_decode(p, data, file_info);
93 }
94
95 upg_log_info("[UPG] full resource file\r\n");
96 return upg_resource_file_full(data, file_info);
97 }
98
upg_resource_index_task(upg_resource_node_t * file_info)99 STATIC errcode_t upg_resource_index_task(upg_resource_node_t *file_info)
100 {
101 if (file_info->operation_type == UPG_RESOURCE_DELETE_FILE) {
102 upg_log_info("[UPG] delete resource file\r\n");
103 return upg_resource_file_delete(file_info->file_path);
104 } else if (file_info->operation_type == UPG_RESOURCE_REMOVE_DIR) {
105 upg_log_info("[UPG] remove resource dir\r\n");
106 return upg_resource_file_rmdir(file_info->file_path);
107 }
108
109 return ERRCODE_SUCC;
110 }
111
upg_resource_process_node(CLzmaDec * p,upg_lzma_decode2_data_t * data,const upg_image_header_t * image,bool is_index)112 STATIC errcode_t upg_resource_process_node(CLzmaDec *p, upg_lzma_decode2_data_t *data,
113 const upg_image_header_t *image, bool is_index)
114 {
115 errcode_t ret = ERRCODE_FAIL;
116 upg_resource_index_t resource_index = {0};
117 uint32_t read_len = sizeof(upg_resource_index_t);
118
119 int32_t index_fd = dfx_file_open_for_read(upg_get_res_file_index_path());
120 if (index_fd < 0) {
121 return ERRCODE_UPG_FILE_OPEN_FAIL;
122 }
123
124 if (dfx_file_read_fd(index_fd, 0, (uint8_t *)&resource_index, read_len, true) != (int32_t)read_len) {
125 dfx_file_close(index_fd);
126 return ERRCODE_UPG_FILE_READ_FAIL;
127 }
128
129 upg_resource_node_t *file_info = (upg_resource_node_t *)upg_malloc(sizeof(upg_resource_node_t));
130 if (file_info == NULL) {
131 dfx_file_close(index_fd);
132 return ERRCODE_MALLOC;
133 }
134
135 read_len = sizeof(upg_resource_node_t);
136 for (uint32_t i = 0; i < resource_index.file_num; i++) {
137 memset_s(file_info, sizeof(upg_resource_node_t), 0, sizeof(upg_resource_node_t));
138 uint32_t offset = sizeof(upg_resource_index_t) + (sizeof(upg_resource_node_t) * i);
139
140 if (dfx_file_read_fd(index_fd, offset, (uint8_t *)file_info, read_len, true) != (int32_t)read_len) {
141 ret = ERRCODE_UPG_FILE_READ_FAIL;
142 break;
143 }
144
145 if (is_index) {
146 ret = upg_resource_index_task(file_info);
147 } else {
148 ret = upg_resource_data_task(p, data, image, file_info);
149 }
150 if (ret != ERRCODE_SUCC) {
151 break;
152 }
153 }
154
155 upg_free(file_info);
156 dfx_file_close(index_fd);
157 return ret;
158 }
159
uapi_upg_resource_index_process(const upg_image_header_t * image)160 errcode_t uapi_upg_resource_index_process(const upg_image_header_t *image)
161 {
162 errcode_t ret;
163 upg_log_info("[UPG] resource index decompress_flag: 0x%x\r\n", image->decompress_flag);
164 if (image->decompress_flag == DECOMPRESS_FLAG_ZIP) {
165 /* 压缩升级 */
166 upg_log_info("[UPG] decompress upg\r\n");
167 ret = uapi_upg_compress_image_update(image);
168 } else {
169 /* 全镜像升级 */
170 upg_log_info("[UPG] full upg\r\n");
171 ret = uapi_upg_full_image_update(image);
172 }
173
174 if (ret != ERRCODE_SUCC) {
175 return ret;
176 }
177
178 return upg_resource_process_node(NULL, NULL, image, true);
179 }
180
uapi_upg_resource_data_process(const upg_image_header_t * image)181 errcode_t uapi_upg_resource_data_process(const upg_image_header_t *image)
182 {
183 errcode_t ret;
184 CLzmaDec p;
185 upg_lzma_decode2_data_t val_tmp = { 0 };
186
187 if (image->decompress_flag == DECOMPRESS_FLAG_ZIP) {
188 uint32_t read_offset = image->image_offset;
189 uint8_t header[LZMA_HEAD_ALIGN_SIZE]; /* lzma解压头长度 */
190 uint32_t read_len = (uint32_t)sizeof(header);
191
192 ret = upg_copy_pkg_image_data(image, 0, &read_len, header);
193 if (ret != ERRCODE_SUCC) {
194 return ret;
195 }
196 read_offset += read_len;
197
198 ret = upg_lzma_init(&p, &val_tmp, header, sizeof(header));
199 if (ret != ERRCODE_SUCC) {
200 return ret;
201 }
202
203 val_tmp.image_id = image->image_id;
204 val_tmp.in_offset = read_offset;
205 val_tmp.out_offset = 0;
206 val_tmp.compress_len = image->image_len - (uint32_t)sizeof(header);
207 } else {
208 val_tmp.in_offset = image->image_offset;
209 val_tmp.buf.outbuf = upg_malloc(UPG_FLASH_PAGE_SIZE);
210 if (val_tmp.buf.outbuf == NULL) {
211 return ERRCODE_MALLOC;
212 }
213 }
214
215 ret = upg_resource_process_node(&p, &val_tmp, image, false);
216 if (ret != ERRCODE_SUCC) {
217 upg_log_err("[UPG] upg_resource_process_node fail ret = 0x%x\r\n", ret);
218 }
219
220 if (image->decompress_flag == DECOMPRESS_FLAG_ZIP) {
221 upg_lzma_deinit(&p, &val_tmp);
222 } else {
223 upg_free(val_tmp.buf.outbuf);
224 }
225
226 return ret;
227 }
228 #endif /* (UPG_CFG_SUPPORT_RESOURCES_FILE == YES) */
229