1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4 #include "ota_hal_os.h"
5 #include "xz.h"
6 #include "ota_log.h"
7 #include "xz_export.h"
8
xz_check_file_crc(hal_partition_t src_partition,unsigned int size,unsigned int crc)9 int xz_check_file_crc(hal_partition_t src_partition, unsigned int size, unsigned int crc)
10 {
11 int ret = 0;
12 unsigned char* data_buf = NULL;
13 unsigned int read_size = 0;
14 unsigned int offset = 0;
15 uint16_t cal_crc = 0;
16 ota_crc16_ctx contex;
17 data_buf = ota_malloc(SECTOR_SIZE);
18 if(data_buf == NULL) {
19 OTA_LOG_E("xz check image crc malloc failed");
20 ret = XZ_MALLOC_FAILED;
21 }
22 else {
23 memset(data_buf, 0x00, SECTOR_SIZE);
24 ota_crc16_init(&contex );
25 for( ; size > 0; size -= read_size, offset += read_size ) {
26 read_size = size >= SECTOR_SIZE ? SECTOR_SIZE : size;
27 memset(data_buf, 0, SECTOR_SIZE);
28 ret = xz_flash_read_data(src_partition, offset, data_buf, read_size);
29 if (ret != 0){
30 OTA_LOG_I("r d ret:%d.",ret);
31 }
32 ota_crc16_update(&contex, data_buf, read_size);
33 }
34 ota_crc16_final(&contex, &cal_crc);
35 OTA_LOG_I("cal crc:0x%04x, crc:0x%x", cal_crc, crc);
36 if(data_buf != NULL) {
37 ota_free(data_buf);
38 data_buf = NULL;
39 }
40 if(cal_crc != crc) {
41 ret = XZ_CRC_ERROR;
42 }
43 }
44 return ret;
45 }
46
xz_identify_xz_header(hal_partition_t src_partition,unsigned int offset)47 static bool xz_identify_xz_header(hal_partition_t src_partition, unsigned int offset)
48 {
49 unsigned char data_buf[16] = {0};
50 const unsigned char xz_header[6] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
51 int ret = xz_flash_read_data(src_partition, offset, data_buf, 16);
52 if (0 != ret) {
53 OTA_LOG_I("r xz ret:%d.",ret);
54 }
55 if (!memcmp(data_buf, xz_header, 6)) {
56 OTA_LOG_I("is xz file.");
57 return true;
58 }
59 return false;
60 }
61
copy_xz(hal_partition_t des_partition,hal_partition_t src_partition,unsigned int src_size,unsigned int * des_size)62 static int32_t copy_xz(hal_partition_t des_partition, hal_partition_t src_partition,
63 unsigned int src_size, unsigned int *des_size)
64 {
65 struct xz_buf b;
66 struct xz_dec *s;
67 enum xz_ret ret = XZ_OK;
68 unsigned char* in_buf = NULL;
69 unsigned char* out_buf = NULL;
70 unsigned int read_size;
71 unsigned int rema_size = src_size;
72 unsigned int erase_offset = 0;
73 unsigned int read_offset = 0;
74 unsigned int write_offset = 0;
75 int err = 0;
76
77 if(des_size == NULL) {
78 OTA_LOG_E("input param err");
79 goto exit;
80 }
81 *des_size = 0;
82 err = xz_flash_erase(des_partition, erase_offset, SECTOR_SIZE);
83 if(0 != err) {
84 OTA_LOG_E("e ret:%d",err);
85 }
86 xz_crc32_init();
87 s = xz_dec_init(XZ_DYNALLOC, 1 << 15);
88 if (s == NULL) {
89 OTA_LOG_E("mem fail");
90 goto exit;
91 }
92 in_buf = ota_malloc(XZ_BUF_SIZE);
93 if(in_buf == NULL) {
94 ret = XZ_MALLOC_FAILED;
95 goto exit;
96 }
97 out_buf = ota_malloc(XZ_BUF_SIZE);
98 if(out_buf == NULL) {
99 ret = XZ_MALLOC_FAILED;
100 goto exit;
101 }
102 b.in = in_buf;
103 b.in_pos = 0;
104 b.in_size = 0;
105 b.out = out_buf;
106 b.out_pos = 0;
107 b.out_size = XZ_BUF_SIZE;
108
109 while (1) {
110 if (b.in_pos == b.in_size) {
111 read_size = rema_size > XZ_BUF_SIZE ? XZ_BUF_SIZE : rema_size;
112 err = xz_flash_read_data(src_partition, read_offset, in_buf, read_size);
113 if (0 != err) {
114 OTA_LOG_I("r err:%d.",err);
115 }
116 if(read_size > 0) {
117 b.in_size = read_size;
118 b.in_pos = 0;
119 }
120 rema_size -= read_size;
121 read_offset += read_size;
122 }
123 ret = xz_dec_run(s, &b);
124 //OTA_LOG_I("xz dec ret:%d p:0x%0x s:0x%x out p:0x%0x s:0x%x \n", ret, read_addr, b.in_size, write_addr, b.out_size);
125 if (b.out_pos == b.out_size) {
126 if(write_offset + b.out_pos >= erase_offset + SECTOR_SIZE) {
127 erase_offset += SECTOR_SIZE;
128 err = xz_flash_erase(des_partition, erase_offset, SECTOR_SIZE);
129 if(0 != err) {
130 OTA_LOG_I("e f err:%d",err);
131 }
132 }
133 err = xz_flash_write_data(des_partition, write_offset, out_buf, b.out_pos);
134 if (err != 0) {
135 OTA_LOG_I("w f err:%d.",err);
136 }
137 write_offset += b.out_pos;
138 b.out_pos = 0;
139 }
140 if (ret == XZ_OK)
141 continue;
142 if(write_offset + b.out_pos >= erase_offset + SECTOR_SIZE) {
143 erase_offset += SECTOR_SIZE;
144 err = xz_flash_erase(des_partition, erase_offset, SECTOR_SIZE);
145 if(0 != err) {
146 OTA_LOG_I("er #err:%d", err);
147 }
148 }
149 err = xz_flash_write_data(des_partition, write_offset, out_buf, b.out_pos);
150 if (err != 0) {
151 OTA_LOG_I("w f #err:%d.", err);
152 }
153 write_offset += b.out_pos;
154 switch (ret) {
155 case XZ_STREAM_END:
156 //xz_dec_end(s);
157 OTA_LOG_E("write_offset = %d", write_offset);
158 *des_size = write_offset;
159 ret = 0;
160 goto exit;
161 case XZ_MEM_ERROR:
162 goto exit;
163 case XZ_MEMLIMIT_ERROR:
164 goto exit;
165 case XZ_FORMAT_ERROR:
166 goto exit;
167 case XZ_OPTIONS_ERROR:
168 goto exit;
169 case XZ_DATA_ERROR:
170 case XZ_BUF_ERROR:
171 goto exit;
172 default:
173 goto exit;
174 }
175 }
176 exit:
177 xz_dec_end(s);
178 if(in_buf != NULL) {
179 ota_free(in_buf);
180 in_buf = NULL;
181 }
182 if(out_buf != NULL) {
183 ota_free(out_buf);
184 out_buf = NULL;
185 }
186 return ret;
187 }
188
xz_uncompress(hal_partition_t des_partition,hal_partition_t src_partition,unsigned int src_size,unsigned int * des_size)189 static int xz_uncompress(hal_partition_t des_partition, hal_partition_t src_partition,
190 unsigned int src_size, unsigned int *des_size)
191 {
192 if(xz_identify_xz_header(src_partition, 0x00) == true) {
193 return copy_xz(des_partition, src_partition, src_size, des_size);
194 }
195 return XZ_UNPROCESS_FAILED;
196 }
197
xz_verify_uncompress_file(hal_partition_t des_partition,hal_partition_t src_partition,unsigned int size)198 static int32_t xz_verify_uncompress_file(hal_partition_t des_partition, hal_partition_t src_partition, unsigned int size)
199 {
200 struct xz_buf b;
201 struct xz_dec *s;
202 enum xz_ret ret = XZ_OK;
203 unsigned char* data_buf = NULL;
204 unsigned char* in_buf = NULL;
205 unsigned char* out_buf = NULL;
206 unsigned int read_size;
207 unsigned int rema_size = size;
208 unsigned int read_src_offset = 0;
209 unsigned int read_des_offset = 0;
210 int err = 0;
211 xz_crc32_init();
212 s = xz_dec_init(XZ_DYNALLOC, 1 << 15);
213 if (s == NULL) {
214 OTA_LOG_I("xz fail");
215 goto exit;
216 }
217 data_buf = ota_malloc(SECTOR_SIZE);
218 if(data_buf == NULL) {
219 ret = XZ_MALLOC_FAILED;
220 goto exit;
221 }
222 memset(data_buf, 0x00, SECTOR_SIZE);
223 in_buf = malloc(XZ_BUF_SIZE);
224 if(in_buf == NULL) {
225 ret = XZ_MALLOC_FAILED;
226 goto exit;
227 }
228 out_buf = malloc(XZ_BUF_SIZE);
229 if(out_buf == NULL) {
230 ret = XZ_MALLOC_FAILED;
231 goto exit;
232 }
233
234 b.in = in_buf;
235 b.in_pos = 0;
236 b.in_size = 0;
237 b.out = out_buf;
238 b.out_pos = 0;
239 b.out_size = XZ_BUF_SIZE;
240
241 while (1) {
242 if (b.in_pos == b.in_size) {
243 read_size = rema_size > XZ_BUF_SIZE ? XZ_BUF_SIZE : rema_size;
244 err = xz_flash_read_data(src_partition, read_src_offset, in_buf, read_size);
245 if (0 != err) {
246 OTA_LOG_I("r v err:%d.", err);
247 }
248 if(read_size > 0) {
249 b.in_size = read_size;
250 b.in_pos = 0;
251 }
252 rema_size -= read_size;
253 read_src_offset += read_size;
254 }
255 ret = xz_dec_run(s, &b);
256 //OTA_LOG_I("v xz dec ret:%d p:0x%0x s:0x%x out p:0x%0x s:0x%x \n", ret, b.in_pos, b.in_size, b.out_pos, b.out_size);
257 if (b.out_pos == b.out_size) {
258 memset(data_buf, 0, SECTOR_SIZE);
259 err = xz_flash_read_data(des_partition, read_des_offset, data_buf, b.out_pos);
260 if (0 != err) {
261 OTA_LOG_I("v r err:%d.", err);
262 }
263 if(memcmp(data_buf, out_buf, b.out_pos) != 0)
264 goto exit;
265 read_des_offset += b.out_pos;
266 b.out_pos = 0;
267 }
268 if (ret == XZ_OK)
269 continue;
270 err = xz_flash_read_data(des_partition, read_des_offset, data_buf, b.out_pos);
271 if (0 != err) {
272 OTA_LOG_I("r w err:%d.", err);
273 }
274 if(memcmp(data_buf, out_buf, b.out_pos) != 0)
275 goto exit;
276 switch (ret) {
277 case XZ_STREAM_END:
278 //xz_dec_end(s);
279 OTA_LOG_I("verify xz OK.\n");
280 ret = 0;
281 goto exit;
282 case XZ_MEM_ERROR:
283 goto exit;
284 case XZ_MEMLIMIT_ERROR:
285 goto exit;
286 case XZ_FORMAT_ERROR:
287 goto exit;
288 case XZ_OPTIONS_ERROR:
289 goto exit;
290 case XZ_DATA_ERROR:
291 case XZ_BUF_ERROR:
292 goto exit;
293 default:
294 goto exit;
295 }
296 }
297 exit:
298 if(in_buf != NULL) {
299 ota_free(in_buf);
300 in_buf = NULL;
301 }
302 if(out_buf != NULL) {
303 ota_free(out_buf);
304 out_buf = NULL;
305 }
306 if(data_buf != NULL) {
307 ota_free(data_buf);
308 data_buf = NULL;
309 }
310 xz_dec_end(s);
311 return ret;
312 }
313
xz_verify_unzx_file(hal_partition_t des_partition,hal_partition_t src_partition,unsigned int size)314 static int xz_verify_unzx_file(hal_partition_t des_partition, hal_partition_t src_partition, unsigned int size)
315 {
316 if(xz_identify_xz_header(src_partition, 0x00) == true) {
317 return xz_verify_uncompress_file(des_partition, src_partition, size);
318 }
319 return XZ_VERIFY_FAILED;
320 }
321
xz_file_uncompress(hal_partition_t des_partition,hal_partition_t src_partition,unsigned int xz_size,unsigned short xz_crc16)322 int xz_file_uncompress(hal_partition_t des_partition, hal_partition_t src_partition, unsigned int xz_size, unsigned short xz_crc16)
323 {
324 int ret = 0;
325 int uncompress_size = 0;
326 #ifdef XZ_CHECK_FILE
327 OTA_LOG_I("size:0x%08x,crc:0x%04x", xz_size, xz_crc16);
328 /* check image crc16 */
329 if(xz_check_file_crc(src_partition, xz_size, xz_crc16) != 0) {
330 return XZ_CRC_ERROR;
331 }
332 ota_msleep(20);
333 #endif
334
335 OTA_LOG_I("xz uncompress ...");
336 /* XZ uncompress */
337 if(xz_uncompress(des_partition, src_partition, xz_size, &uncompress_size) != 0) {
338 return XZ_UNPROCESS_FAILED;
339 }
340
341 #ifdef XZ_CHECK_FILE
342 ota_msleep(20);
343 /* XZ verify */
344 if(xz_verify_unzx_file(des_partition, src_partition, xz_size) != 0) {
345 return XZ_VERIFY_FAILED;
346 }
347 #endif
348
349 return uncompress_size;
350 }
351