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