1
2 /*
3 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
4 */
5 #include "2ndboot.h"
6
7 #define YMODEM_OK 0
8 #define YMODEM_ERR (-1)
9 #define YMODEM_FILE_TOOBIG (-2)
10
11 #define YMODEM_SOH 0x01
12 #define YMODEM_STX 0x02
13 #define YMODEM_EOT 0x04
14 #define YMODEM_ACK 0x06
15 #define YMODEM_NAK 0x15
16 #define YMODEM_CAN 0x18
17 #define YMODEM_CCHAR 'C'
18 #define SOH_DATA_LEN 128
19 #define STX_DATA_LEN 1024
20
21 #define UART_RECV_TIMEOUT 400000
22
23 #define YMODEM_STATE_INIT 0
24 #define YMODEM_STATE_WAIT_HEAD 1
25 #define YMODEM_STATE_WAIT_DATA 2
26 #define YMODEM_STATE_WAIT_END 3
27 #define YMODEM_STATE_WAIT_NEXT 4
28
29 #define YMODEM_MAX_CHAR_NUM 64
30 #define YMODEM_ERR_NAK_NUM 5
31
32 static unsigned int ymodem_flash_addr = 0;
33 static unsigned int ymodem_flash_size = 0;
34 static unsigned int ymodem_max_write_size = 0;
35
ymodem_str2int(char * buf,unsigned int buf_len)36 unsigned int ymodem_str2int(char *buf, unsigned int buf_len)
37 {
38 int type = 10;
39 int value = 0;
40 int i = 0;
41
42 if((buf[0] == '0') && (buf[1] == 'x' || buf[1] == 'X')) {
43 type = 16;
44 buf += 2;
45 }
46 for (i = 0; i < buf_len; buf++, i++) {
47 if(*buf == 0) {
48 return value;
49 }
50 if (*buf >= '0' && *buf <= '9') {
51 value = value * type + *buf - '0';
52 } else {
53 if(10 == type) {
54 return value;
55 }
56 if (*buf >= 'A' && *buf <= 'F') {
57 value = value * 16 + *buf - 'A' + 10;
58 }
59 else if (*buf >= 'a' && *buf <= 'f') {
60 value = value * 16 + *buf - 'a' + 10;
61 } else {
62 return value;
63 }
64 }
65 }
66 return value;
67 }
68
ymodem_recv_bytes(unsigned char * buffer,unsigned int nbytes,unsigned int timeout)69 unsigned int ymodem_recv_bytes(unsigned char *buffer, unsigned int nbytes, unsigned int timeout)
70 {
71 int ret = 0;
72 unsigned char c = 0;
73 unsigned int i = 0;
74 unsigned int t = 0;
75
76 while ((i < nbytes) && (t < timeout)) {
77 ret = uart_recv_byte(&c);
78 if (1 == ret) {
79 buffer[i] = c;
80 i++;
81 }
82 t++;
83 }
84 return i;
85 }
86
ymodem_data_head_parse(unsigned char data_type)87 int ymodem_data_head_parse(unsigned char data_type)
88 {
89 int i = 0;
90 int ret = YMODEM_ERR;
91 int lp = 0;
92 unsigned int buf_len = 0;
93 unsigned char *buffer = NULL;
94 unsigned short crc = 0;
95 unsigned int value = 0;
96
97 buf_len = ((YMODEM_SOH == data_type) ? SOH_DATA_LEN : STX_DATA_LEN) + 4;
98 buffer = malloc(buf_len);
99 memset(buffer, 0, buf_len);
100 /* SOH HEAD */
101 value = ymodem_recv_bytes(buffer, buf_len, UART_RECV_TIMEOUT);
102 if( (buf_len != value) || (0 != buffer[0]) || (0xFF != buffer[1]) ) {
103 goto err_exit;
104 }
105
106 /* check CRC */
107 crc = crc16_computer(&buffer[2], buf_len-4);
108 if (((crc >> 8) != buffer[buf_len - 2]) || ((crc & 0xFF) != buffer[buf_len - 1])) {
109 goto err_exit;
110 }
111 /* parse file name && file length */
112 for(i = 2; i < buf_len - 2; i++) {
113 if((0 == buffer[i]) && (0 == lp)) {
114 lp = i + 1;
115 continue;
116 }
117
118 if((0 == buffer[i]) && (0 != lp)) {
119 /* from buffer[lp] to buffer[i] is file length ascii */
120 value = ymodem_str2int((char *)&buffer[lp], i - lp);
121 if (0 == value) {
122 goto err_exit;
123 }
124 ymodem_flash_size = value;
125 if(value > ymodem_max_write_size) {
126 ret = YMODEM_FILE_TOOBIG;
127 goto err_exit;
128 }
129 #ifdef AOS_2ND_BOOT_LATER_ERASE
130 flash_erase(ymodem_flash_addr, ymodem_flash_size);
131 #endif
132 break;
133 }
134 }
135
136 for (i = 2; i < buf_len - 4; i ++) {
137 if (buffer[i] != 0) {
138 ret = YMODEM_OK;
139 }
140 }
141
142 err_exit:
143 free(buffer);
144 return ret;
145 }
146
ymodem_write_data_to_flash(unsigned char * buffer,unsigned int addr,unsigned int len)147 int ymodem_write_data_to_flash(unsigned char *buffer, unsigned int addr, unsigned int len)
148 {
149 unsigned int write_len = len;
150 if(addr + len > ymodem_flash_addr + ymodem_flash_size) {
151 write_len = ymodem_flash_addr + ymodem_flash_size - addr;
152 }
153 return flash_write_data(addr, buffer, write_len);
154 }
155
ymodem_data_parse(unsigned char data_type,unsigned int * addr)156 int ymodem_data_parse(unsigned char data_type, unsigned int *addr)
157 {
158 int ret = YMODEM_ERR;
159 unsigned int buf_len = 0;
160 unsigned short crc = 0;
161 unsigned int value = 0;
162 unsigned char *buffer = NULL;
163
164 buf_len = ((YMODEM_SOH == data_type) ? SOH_DATA_LEN : STX_DATA_LEN) + 4;
165 buffer = malloc(buf_len);
166 memset(buffer, 0, buf_len);
167
168 if(NULL == addr) {
169 goto err_exit;
170 }
171 /* SOH HEAD */
172 value = ymodem_recv_bytes(buffer, buf_len, UART_RECV_TIMEOUT * (buf_len / SOH_DATA_LEN));
173 if ((buf_len != value) || (0xFF != buffer[0] + buffer[1])) {
174 goto err_exit;
175 }
176
177 /* check CRC */
178 crc = crc16_computer(&buffer[2], buf_len - 4);
179 if (((crc >> 8) != buffer[buf_len - 2]) || ((crc & 0xFF) != buffer[buf_len - 1])) {
180 goto err_exit;
181 }
182
183 /* write data fo flash */
184 ymodem_write_data_to_flash(&buffer[2], *addr, buf_len - 4);
185 *addr += buf_len - 4;
186 ret = YMODEM_OK;
187
188 err_exit :
189 free(buffer);
190 return ret;
191 }
192
ymodem_recv_file(unsigned int flash_addr)193 int ymodem_recv_file(unsigned int flash_addr)
194 {
195 int i = 0;
196 int ret = YMODEM_OK;
197 int state = 0;
198 int end_flag = 0;
199 unsigned char c = 0;
200 unsigned int bytes = 0;
201 unsigned int addr = flash_addr;
202
203 /* send C */
204 while (1) {
205 if(state != YMODEM_STATE_INIT) {
206 bytes = ymodem_recv_bytes(&c, 1, 5000);
207 }
208
209 switch (state)
210 {
211 case YMODEM_STATE_INIT: /* send 'C' */
212 if(i % 500 == 0) {
213 uart_send_byte(YMODEM_CCHAR);
214 }
215 state = YMODEM_STATE_WAIT_HEAD;
216 break;
217
218 case YMODEM_STATE_WAIT_HEAD: /* wait SOH */
219 if(1 != bytes) {
220 i ++;
221 state = 0;
222 break;
223 }
224 if(( YMODEM_SOH == c ) || ( YMODEM_STX == c )) {
225 ret = ymodem_data_head_parse(c);
226 if (ret == YMODEM_OK) {
227 uart_send_byte(YMODEM_ACK);
228 sys_delayms(100);
229 uart_send_byte(YMODEM_CCHAR);
230 state = YMODEM_STATE_WAIT_DATA;
231 break;
232 } else {
233 /* end */
234 uart_send_byte(YMODEM_ACK);
235 sys_delayms(200);
236 if(end_flag == 1) {
237 ret = YMODEM_OK;
238 } else {
239 for(i = 0; i < YMODEM_ERR_NAK_NUM; i++) {
240 uart_send_byte(YMODEM_NAK);
241 }
242 }
243 return ret;
244 }
245 } else if (3 == c) { /* ctrl+c abort ymodem */
246 printf("Abort\n");
247 return YMODEM_ERR;
248 }
249 break;
250 case YMODEM_STATE_WAIT_DATA: /* receive data */
251 if(1 == bytes) {
252 if( (YMODEM_SOH == c) || (YMODEM_STX == c) ) {
253 ret = ymodem_data_parse(c, &addr);
254 if (ret == YMODEM_OK) {
255 uart_send_byte(YMODEM_ACK);
256 } else {
257 uart_send_byte(YMODEM_NAK);
258 }
259 } else if( YMODEM_EOT == c ) {
260 uart_send_byte(YMODEM_NAK);
261 state = YMODEM_STATE_WAIT_END;
262 }
263 }
264 break;
265 case YMODEM_STATE_WAIT_END: /* receive end eot */
266 if ((1 == bytes) && (YMODEM_EOT == c)) {
267 uart_send_byte(YMODEM_ACK);
268 i = 0;
269 state = YMODEM_STATE_INIT;
270 end_flag = 1;
271 }
272 break;
273 default:
274 state = YMODEM_STATE_INIT;
275 break;
276 }
277 }
278
279 return YMODEM_OK;
280 }
281
ymodem_upgrade(void)282 int ymodem_upgrade(void)
283 {
284 int i = 0;
285 int ret = 0;
286 int flag = 0;
287 unsigned char c = 0;
288 unsigned int addr = 0;
289 char buf[YMODEM_MAX_CHAR_NUM];
290 hal_logic_partition_t *app_info = flash_get_info(HAL_PARTITION_APPLICATION);
291 hal_logic_partition_t *ota_info = flash_get_info(HAL_PARTITION_OTA_TEMP);
292 if((app_info == NULL) || (ota_info == NULL)) {
293 printf("\r\nGet Flash info err !\n");
294 return -1;
295 }
296 #ifdef AOS_2ND_BOOT_AB
297 printf("\r\nA part addr:0x%08x, len:0x%08x\n", app_info->partition_start_addr,
298 app_info->partition_length);
299 printf("\r\nB part addr:0x%08x, len:0x%08x\n", ota_info->partition_start_addr,
300 ota_info->partition_length);
301
302 printf("\r\nNow running on %s\n", (ota_2ndboot_ab_get() == 0)?"A":"B");
303 printf("\r\nBackup part addr:0x%08x\n", (ota_2ndboot_ab_get() == 0)?ota_info->partition_start_addr:app_info->partition_start_addr);
304 #else
305 printf("\r\nOS part addr:0x%08x, len:0x%08x\n", app_info->partition_start_addr,
306 app_info->partition_length);
307 printf("\r\nOTA part addr:0x%08x, len:0x%08x\n", ota_info->partition_start_addr,
308 ota_info->partition_length);
309 printf("\r\nOnly the addr of OS and OTA part are allowed to be written\n");
310 #endif
311 printf("\r\nPlease input flash addr: ");
312 memset(buf, 0, YMODEM_MAX_CHAR_NUM);
313 while(1) {
314 if(uart_recv_byte(&c)&&(c!='w')) {
315 printf("%c", c);
316 if((c == '\r') || (i >= YMODEM_MAX_CHAR_NUM)) {
317 break;
318 }
319 buf[i] = c;
320 i ++;
321 }
322 }
323 printf("\r\nflash addr: %s \n", buf);
324 addr = ymodem_str2int(buf, YMODEM_MAX_CHAR_NUM);
325 if(addr == 0) {
326 printf("\r\naddr is invalid!\n");
327 return -1;
328 }
329 if((addr >= app_info->partition_start_addr) && (addr <= app_info->partition_start_addr + app_info->partition_length)) {
330 flag = 1;
331 ymodem_max_write_size = app_info->partition_length;
332 #ifndef AOS_2ND_BOOT_LATER_ERASE
333 ret = flash_erase(app_info->partition_start_addr, app_info->partition_length);
334 if(ret < 0) {
335 printf("erase err.\n");
336 return -1;
337 }
338 #endif
339 }
340 if((addr >= ota_info->partition_start_addr) && (addr <= ota_info->partition_start_addr + ota_info->partition_length)){
341 flag = 1;
342 ymodem_max_write_size = ota_info->partition_length;
343 #ifndef AOS_2ND_BOOT_LATER_ERASE
344 ret = flash_erase(ota_info->partition_start_addr, ota_info->partition_length);
345 if(ret < 0) {
346 printf("erase err.\n");
347 return -1;
348 }
349 #endif
350 }
351 if(flag == 0) {
352 printf("\r\naddr 0x%x is err \n", addr);
353 return -1;
354 }
355 printf("\r\nPlease start ymodem ... (press ctrl+c to cancel)\r\n");
356 ymodem_flash_addr = addr;
357 ret = ymodem_recv_file(addr);
358 while((1) && (ret != YMODEM_OK)) {
359 if(uart_recv_byte(&c)) {
360 break;
361 }
362 }
363 if(ret == YMODEM_OK) {
364 printf("\r\nRecv flash addr: 0x%08x, len:0x%08x OK \n", addr, ymodem_flash_size);
365 } else if(ret == YMODEM_FILE_TOOBIG) {
366 printf("\r\nfile too big len:0x%08x !!!\n", ymodem_flash_size);
367 } else {
368 printf("\r\nYmodem recv file Err:%d !!!\n", ret);
369 }
370 return ret;
371 }
372