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