1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4
5 #include <stdarg.h>
6 #include "libc.h"
7 #include "updater.h"
8
9 #if !defined __LINUX_HOST__
10 #include "2ndboot.h"
11
12 typedef struct blklist {
13 struct blklist *next;
14 unsigned int magic_size;
15 } blk_head_t;
16
17 static blk_head_t freelist_head;
18 static blk_head_t *freelist_tail = NULL;
19 static unsigned int heap_free_size;
20 static unsigned int heap_free_size_min;
21 #endif
22
23 #ifdef AOS_2ND_BOOT_NO_LDS
24 void *_rec_heap_start;
25 unsigned int _rec_heap_len;
26 #endif
27
28 /* memory & string operation */
ota_memcpy(void * dest,const void * src,unsigned int n)29 void *ota_memcpy(void *dest, const void *src, unsigned int n)
30 {
31 if (NULL == dest || NULL == src)
32 return NULL;
33 char *tempDest = (char *)dest;
34 char *tempSrc = (char *)src;
35
36 while (n-- > 0)
37 *tempDest++ = *tempSrc++;
38 return dest;
39 }
40
ota_memset(void * s,int c,unsigned int n)41 void *ota_memset(void *s, int c, unsigned int n)
42 {
43 if (NULL == s)
44 return NULL;
45 char * tmpS = (char *)s;
46 while(n-- > 0)
47 *tmpS++ = c;
48 return s;
49 }
50
ota_strlen(char * str)51 unsigned int ota_strlen(char * str)
52 {
53 const char *eos = str;
54 while(*eos++) ;
55 return (eos - str - 1);
56 }
57
ota_strcat(char * dst,const char * src)58 char *ota_strcat (char * dst, const char * src)
59 {
60 char * cp = dst;
61 while( *cp )
62 cp++;
63
64 while( cp && src) {
65 *cp++ = *src++;
66 }
67 return dst;
68 }
69
ota_memcmp(const void * buf1,const void * buf2,unsigned int count)70 int ota_memcmp(const void * buf1, const void * buf2, unsigned int count)
71 {
72 if (!count)
73 return(0);
74
75 while ( --count && *(char *)buf1 == *(char *)buf2 ) {
76 buf1 = (char *)buf1 + 1;
77 buf2 = (char *)buf2 + 1;
78 }
79 return (*((unsigned char *)buf1) - *((unsigned char *)buf2));
80 }
81
ota_memmove(void * dest,const void * src,unsigned int count)82 void *ota_memmove(void *dest, const void *src, unsigned int count)
83 {
84 char *tmp;
85 const char *s;
86
87 if (dest <= src) {
88 tmp = dest;
89 s = src;
90 while (count--)
91 *tmp++ = *s++;
92 } else {
93 tmp = dest;
94 tmp += count;
95 s = src;
96 s += count;
97 while (count--)
98 *--tmp = *--s;
99 }
100 return dest;
101 }
102
103 #if !defined __LINUX_HOST__
uitoa_16(unsigned int value,char * str)104 char* uitoa_16(unsigned int value, char *str){
105 char reverse[36] = {0};
106 char *p = reverse;
107
108 *p++ = '\0';
109 do{
110 *p++ = "0123456789abcdef"[value%16];
111 value /= 16;
112 }while(value != 0);
113 p--;
114
115 while (p >= reverse) {
116 *str++ = *p--;
117 }
118 return str;
119 }
120
itoa_10(int value,char * str)121 char* itoa_10(int value, char *str){
122 char reverse[40] = {0};
123 char *p = reverse;
124 int tmp = value;
125
126 *p++ = '\0';
127 if(value < 0) {
128 tmp = -value;
129 }
130 do{
131 *p++ = "0123456789"[tmp%10];
132 tmp /= 10;
133 }while(tmp != 0);
134 if(value < 0) {
135 *p++ = '-';
136 }
137 p--;
138 while (p >= reverse){
139 *str++ = *p--;
140 }
141 return str;
142 }
143
uitoa_10(unsigned int value,char * str)144 char* uitoa_10(unsigned int value, char *str){
145 char reverse[36] = {0};
146 char *p = reverse;
147
148 *p++ = '\0';
149 do{
150 *p++ = "0123456789"[value%10];
151 value /= 10;
152 }while(value != 0);
153 p--;
154 while (p >= reverse) {
155 *str++ = *p--;
156 }
157 return str;
158 }
159
ota_puts(const char * str)160 int ota_puts(const char *str)
161 {
162 uart_send_string(str);
163 }
164
ota_printf(const char * fmt,...)165 int ota_printf(const char *fmt, ...)
166 {
167 char buf[256];
168 char *p = NULL;
169 char *s = NULL;
170 int i = 0;
171 int len = 0;
172 int waiting_fmt = 0;
173 va_list args;
174
175 memset(buf, 0, sizeof(buf));
176 va_start(args, fmt);
177
178 for (p = buf; *fmt;) {
179 if (waiting_fmt == 0 && *fmt != '%') {
180 *p++ = *fmt++;
181 continue;
182 }
183 if (waiting_fmt > 8) {
184 puts("Non supported format!\r\n");
185 *p = '\0';
186 va_end(args);
187 return puts(buf);
188 }
189 fmt++;
190 switch (*fmt){
191 case 'd':
192 itoa_10(va_arg(args, unsigned int),p);
193 p += strlen(p);
194 waiting_fmt = 0;
195 fmt++;
196 break;
197 case 'u':
198 uitoa_10(va_arg(args, unsigned int),p);
199 p += strlen(p);
200 waiting_fmt = 0;
201 fmt++;
202 break;
203 case 'x':
204 case 'p':
205 uitoa_16(va_arg(args, unsigned int),p);
206 p += strlen(p);
207 waiting_fmt = 0;
208 fmt++;
209 waiting_fmt = 0;
210 fmt++;
211 break;
212 case 'c':
213 *p++ = va_arg(args, int);
214 waiting_fmt = 0;
215 fmt++;
216 break;
217 case 's':
218 *p = '\0';
219 s = va_arg(args, char *);
220 if (!s) {
221 s = "<NULL>";
222 len = 7;
223 } else {
224 len = (strlen(s) > 128 ? 128 : strlen(s));
225 }
226 for (i = 0; i < len; ++i) *p++ = *s++;
227 waiting_fmt = 0;
228 fmt++;
229 break;
230 default:
231 waiting_fmt++;
232 break;
233 }
234 }
235 *p = '\0';
236 va_end(args);
237 return puts(buf);
238 }
239
240 /* HEAP implement */
heap_init(void)241 static void heap_init(void)
242 {
243 blk_head_t *free_blk = NULL;
244 if ( XZ_HEAP_BASE%XZ_HEAP_ALIGNMENT != 0
245 || XZ_HEAP_SIZE > (~XZ_HEAP_MAGIC)
246 || XZ_HEAP_SIZE < XZ_HEAP_BLK_MIN*2 ) {
247 OTA_LOG_I("err:param invalid!\n");
248 return;
249 }
250
251 heap_free_size = XZ_HEAP_SIZE;
252 heap_free_size_min = XZ_HEAP_SIZE;
253
254 freelist_head.next = (void *) XZ_HEAP_BASE;
255 freelist_head.magic_size = 0;
256 freelist_tail = (void *)(XZ_HEAP_BASE + ALIGN(XZ_HEAP_SIZE, XZ_HEAP_ALIGNMENT) -
257 XZ_HEAP_BLK_HEAD_SIZE);
258 freelist_tail->next = NULL;
259 freelist_tail->magic_size = 0;
260 /* Only one block when init. */
261 free_blk = (void *) XZ_HEAP_BASE;
262 free_blk->next = freelist_tail;
263 free_blk->magic_size = (unsigned int)freelist_tail - (unsigned int) free_blk;
264
265 heap_free_size = free_blk->magic_size;
266 heap_free_size_min = free_blk->magic_size;
267 }
268
heap_freeblk_insert(blk_head_t * blk_insert)269 static void heap_freeblk_insert(blk_head_t *blk_insert)
270 {
271 blk_head_t *blk_before = NULL;
272 blk_head_t *blk_after = NULL;
273
274 /* freelist is ordered by address, find blk_before */
275 for (blk_before = &freelist_head; blk_before->next < blk_insert; blk_before = blk_before->next) {
276 if (blk_before == freelist_tail) {
277 return;
278 }
279 }
280 blk_after = blk_before->next;
281 if ((char *)blk_before + blk_before->magic_size == (char *)blk_insert) {
282 blk_before->magic_size += blk_insert->magic_size;
283 blk_insert = blk_before;
284 } else {
285 /* do not merge, just insert new node to freelist */
286 blk_before->next = blk_insert;
287 }
288
289 /* try to merge blk_insert and blk_after */
290 if (blk_after != freelist_tail &&
291 (char *)blk_insert + blk_insert->magic_size == (char *)blk_after) {
292 blk_insert->magic_size += blk_after->magic_size;
293 blk_insert->next = blk_after->next;
294 } else {
295 /* do not merge, just insert new node to freelist */
296 blk_insert->next = blk_after;
297 }
298 }
299
ota_heap_malloc(unsigned int alloc_size)300 void * ota_heap_malloc(unsigned int alloc_size)
301 {
302 blk_head_t *blk_alloc = NULL;
303 blk_head_t *blk_prev = NULL;
304 blk_head_t *blk_left = NULL;
305
306 if (freelist_tail == NULL) {
307 heap_init();
308 }
309 if ((alloc_size == 0) || (alloc_size > heap_free_size)) {
310 return NULL;
311 }
312 alloc_size += XZ_HEAP_BLK_HEAD_SIZE;
313 alloc_size = ALIGN(alloc_size, XZ_HEAP_ALIGNMENT);
314 /* find a free block bigger than alloc_size */
315 blk_prev = &freelist_head;
316 blk_alloc = freelist_head.next;
317 while ((blk_alloc->magic_size < alloc_size) && (blk_alloc->next != NULL)) {
318 blk_prev = blk_alloc;
319 blk_alloc = blk_alloc->next;
320 }
321 if (blk_alloc->next == NULL) {
322 return NULL;
323 }
324 /* delete blk_alloc from freelist */
325 blk_prev->next = blk_alloc->next;
326 /* check whether blk_alloc can split */
327 if (blk_alloc->magic_size - alloc_size > XZ_HEAP_BLK_MIN) {
328 /* split */
329 blk_left = (void *)((char *)blk_alloc + alloc_size);
330 blk_left->magic_size = blk_alloc->magic_size - alloc_size;
331 blk_alloc->magic_size = alloc_size;
332 /* Insert the new block into the list of free blocks. */
333 heap_freeblk_insert(blk_left);
334 }
335 /* update statistic */
336 heap_free_size -= blk_alloc->magic_size;
337 if (heap_free_size < heap_free_size_min) {
338 heap_free_size_min = heap_free_size;
339 }
340 /* blk belong to APP, magic set */
341 blk_alloc->magic_size |= XZ_HEAP_MAGIC;
342 blk_alloc->next = NULL;
343 /* app used addr is after blk_head_t */
344 return (void *)((char *)blk_alloc + XZ_HEAP_BLK_HEAD_SIZE);
345 }
346
ota_heap_free(void * pfree)347 void ota_heap_free(void *pfree)
348 {
349 blk_head_t *free_blk;
350 if (pfree == NULL) {
351 return;
352 }
353 free_blk = (blk_head_t *)((char *)pfree - XZ_HEAP_BLK_HEAD_SIZE);
354 if (free_blk->next != NULL
355 ||(free_blk->magic_size & XZ_HEAP_MAGIC) != XZ_HEAP_MAGIC) {
356 OTA_LOG_I("err:block destroyed!\n");
357 return;
358 }
359 /* blk belong to free list, magic clear */
360 free_blk->magic_size &= ~XZ_HEAP_MAGIC;
361 /* update statistic */
362 heap_free_size += free_blk->magic_size;
363 heap_freeblk_insert(free_blk);
364 }
365 #endif
update(unsigned short crcIn,unsigned char byte)366 unsigned short update(unsigned short crcIn, unsigned char byte)
367 {
368 unsigned int crc = crcIn;
369 unsigned int in = byte | 0x100;
370 do {
371 crc <<= 1;
372 in <<= 1;
373 if (in & 0x100) {
374 ++crc;
375 }
376 if (crc & 0x10000) {
377 crc ^= 0x1021;
378 }
379 } while (!(in & 0x10000));
380 return crc & 0xffffu;
381 }
382
crc16_init(CRC16_CTX * inContext)383 void crc16_init(CRC16_CTX *inContext)
384 {
385 inContext->crc = 0;
386 }
387
crc16_update(CRC16_CTX * inContext,const void * inSrc,long inLen)388 void crc16_update(CRC16_CTX *inContext, const void *inSrc, long inLen)
389 {
390 const unsigned char *src = (const unsigned char *) inSrc;
391 const unsigned char *srcEnd = src + inLen;
392 while ( src < srcEnd ) {
393 inContext->crc = update(inContext->crc, *src++);
394 }
395 }
396
crc16_final(CRC16_CTX * inContext,unsigned short * outResult)397 void crc16_final(CRC16_CTX *inContext, unsigned short *outResult)
398 {
399 inContext->crc = update(inContext->crc, 0);
400 inContext->crc = update(inContext->crc, 0);
401 *outResult = inContext->crc & 0xffffu;
402 }
403
crc16_computer(void * buf,long len)404 unsigned short crc16_computer(void *buf, long len)
405 {
406 unsigned short patch_crc = 0;
407 CRC16_CTX crc_ctx;
408 crc16_init(&crc_ctx);
409 crc16_update(&crc_ctx, buf, len);
410 crc16_final(&crc_ctx, &patch_crc);
411 return patch_crc;
412 }
413