• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <transfer.h>
17 #include <cmd_loop.h>
18 #include <crc.h>
19 
20 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
21 #include <load_crypto.h>
22 #endif
23 
24 #define FLASHBOOT_MAX_SIZE       0x8000
25 #define DEFAULT_KERNEL_BURN_ADDR 0xD000
26 
27 upload_context *g_upload_ctx = HI_NULL;
28 
loader_serial_ymodem(hi_u32 offset,hi_u32 erased_size,hi_u32 min,hi_u32 max)29 hi_u32 loader_serial_ymodem(hi_u32 offset, hi_u32 erased_size, hi_u32 min, hi_u32 max)
30 {
31     hi_u32 size = 0;
32     uintptr_t store_addr = offset;
33     hi_u32 file_length, remain, read_len, ret, cs;
34 
35     ret = loader_ymodem_open();
36     if (ret != HI_ERR_SUCCESS) {
37         return ret;
38     }
39 
40     file_length = ymodem_get_length();
41     if (file_length <= min || file_length > max) {
42         boot_msg1("file length err : ", file_length);
43         return HI_ERR_FAILURE;
44     }
45 
46     if (erased_size && (erased_size < file_length)) {
47         boot_msg0("file_size > erase_size");
48         return HI_ERR_FAILURE;
49     }
50 
51     remain = file_length;
52 
53     while (remain > 0) {
54         hi_u32 read_size = (hi_u32)hi_min(remain, SZ_1KB);
55         read_len = ymodem_read(g_ymodem_buf, read_size, ((uintptr_t)g_ymodem_buf) ^ read_size);
56         if (read_len == 0 || remain < read_len) {
57             return HI_ERR_FAILURE;
58         }
59 
60         if (erased_size == 0) {
61             cs = (uintptr_t)(hi_void *)store_addr ^ (hi_u32)remain ^ (uintptr_t)g_ymodem_buf ^ (hi_u32)read_len;
62             if (memcpy_s((hi_void *)store_addr, (hi_u32)remain, g_ymodem_buf, read_len, cs) != EOK) {
63                 return HI_ERR_FAILURE;
64             }
65         } else {
66             ret = g_flash_cmd_funcs.write(store_addr, read_len, (hi_u8 *)g_ymodem_buf, HI_FALSE);
67             if (ret != HI_ERR_SUCCESS) {
68                 boot_msg1("flash write fail", ret);
69                 return HI_ERR_FAILURE;
70             }
71         }
72         remain -= read_len;
73         size += read_len;
74         store_addr += (hi_u32)read_len;
75     }
76     cs = ((uintptr_t)g_ymodem_buf) ^ SZ_1KB;
77     (hi_void) ymodem_read(g_ymodem_buf, SZ_1KB, cs);
78 
79     ymodem_close();
80     if ((hi_u32)size == file_length) {
81         boot_msg1("total size:", (hi_u32)size);
82         return HI_ERR_SUCCESS;
83     }
84 
85     return HI_ERR_FAILURE;
86 }
87 
loady_file(uintptr_t ram_addr)88 hi_u32 loady_file(uintptr_t ram_addr)
89 {
90     hi_u32 ret;
91 
92     if (load_malloc_init() != HI_ERR_SUCCESS) {
93         return HI_ERR_FAILURE; /* failure */
94     }
95 
96     loader_ack(ACK_SUCCESS);
97     ret = loader_serial_ymodem(ram_addr, 0, sizeof(efuse_config_header), EFUSE_CFG_MAX_LEN);
98 
99     load_malloc_deinit();
100 
101     return ret;
102 }
103 
loady_version_file(uintptr_t ram_addr)104 hi_u32 loady_version_file(uintptr_t ram_addr)
105 {
106     hi_u32 ret;
107 
108     if (load_malloc_init() != HI_ERR_SUCCESS) {
109         return HI_ERR_FAILURE;
110     }
111 
112     loader_ack(ACK_SUCCESS);
113 
114     ret = loader_serial_ymodem(ram_addr, 0, 0x7, 0x8);
115 
116     load_malloc_deinit();
117 
118     return ret;
119 }
120 
download_to_flash(hi_u32 flash_offset,hi_u32 erase_size,hi_u32 flash_size)121 hi_u32 download_to_flash(hi_u32 flash_offset, hi_u32 erase_size, hi_u32 flash_size)
122 {
123     hi_u32 ret;
124 
125     ret = g_flash_cmd_funcs.init();
126     if (ret != HI_ERR_FLASH_RE_INIT && ret != HI_ERR_SUCCESS &&
127         ret != HI_ERR_FLASH_QUAD_MODE_COMPARE_REG) {
128         boot_msg1("probe ", ret);
129         return HI_ERR_FAILURE;
130     }
131 
132     if (load_malloc_init() != HI_ERR_SUCCESS) {
133         return HI_ERR_FAILURE;  /* failure */
134     }
135 
136     if (erase_size == 0) {
137         boot_msg0("len error");
138         load_malloc_deinit();
139         return HI_ERR_FAILURE;
140     }
141 
142     boot_msg2("erase flash ", flash_offset, erase_size);
143 
144     ret = g_flash_cmd_funcs.erase(flash_offset, erase_size);
145     if (ret != HI_ERR_SUCCESS) {
146         boot_msg1("erase failed ret=", (hi_u32)ret);
147         load_malloc_deinit();
148         return HI_ERR_FAILURE;
149     }
150 
151     boot_msg0("Ready for download");
152 
153     loader_ack(ACK_SUCCESS);
154     ret = loader_serial_ymodem(flash_offset, erase_size, 0, flash_size);
155     load_malloc_deinit();
156     return ret;
157 }
158 
download_image(hi_u32 addr,hi_u32 erase_size,hi_u32 flash_size,hi_u8 burn_efuse)159 hi_u32 download_image(hi_u32 addr, hi_u32 erase_size, hi_u32 flash_size, hi_u8 burn_efuse)
160 {
161     hi_u32 ret;
162     hi_unref_param(burn_efuse);
163 
164     ret = download_to_flash(addr, erase_size, flash_size);
165     if (ret != HI_ERR_SUCCESS) {
166         return HI_ERR_FAILURE;
167     }
168 
169 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
170     if (((addr == DEFAULT_KERNEL_BURN_ADDR) && (erase_size > FLASHBOOT_MAX_SIZE)) ||
171         ((addr == 0) && (erase_size > FLASHBOOT_MAX_SIZE))) {
172         ret = crypto_check_encrypt();
173         if (ret != HI_ERR_SUCCESS) {
174             boot_put_errno(HI_PRINT_ERRNO_CRYPTO_FW_ENCRYPT_ERR);
175             return ret;
176         }
177     }
178 #endif
179 
180     return HI_ERR_SUCCESS;
181 }
182 
download_factory_image(hi_u32 addr,hi_u32 erase_size,hi_u32 flash_size,hi_u8 burn_efuse)183 hi_u32 download_factory_image(hi_u32 addr, hi_u32 erase_size, hi_u32 flash_size, hi_u8 burn_efuse)
184 {
185     hi_u32 ret;
186     hi_unref_param(burn_efuse);
187 
188     ret = download_to_flash(addr, erase_size, flash_size);
189     if (ret != HI_ERR_SUCCESS) {
190         return HI_ERR_FAILURE;
191     }
192 
193 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
194         ret = crypto_encrypt_factory_image(addr);
195         if (ret != HI_ERR_SUCCESS) {
196             return ret;
197         }
198 #endif
199 
200     return HI_ERR_SUCCESS;
201 }
202 
upload_malloc_init(hi_void)203 hi_u32 upload_malloc_init(hi_void)
204 {
205     if (g_upload_ctx == HI_NULL) {
206         g_upload_ctx = (upload_context *)boot_malloc(sizeof(upload_context));
207     }
208 
209     if (g_upload_ctx == HI_NULL) {
210         return HI_ERR_FAILURE;
211     }
212 
213     hi_u32 check_sum = (uintptr_t)g_upload_ctx ^ (hi_u32)sizeof(upload_context) ^ 0 ^ (hi_u32)sizeof(upload_context);
214     (hi_void) memset_s(g_upload_ctx, sizeof(upload_context), 0, sizeof(upload_context), check_sum);
215 
216     return HI_ERR_SUCCESS;
217 }
upload_malloc_deinit(hi_void)218 hi_u32 upload_malloc_deinit(hi_void)
219 {
220     hi_u32 ret;
221     ret = boot_free(g_upload_ctx);
222     if (ret == HI_ERR_SUCCESS) {
223         g_upload_ctx = HI_NULL;
224     }
225 
226     return ret;
227 }
228 
upload_send_file_info(hi_void)229 hi_void upload_send_file_info(hi_void)
230 {
231     upload_context *ctx = g_upload_ctx;
232     hi_u8 name_length = UPLOAD_FILE_NAME_LEN;
233     hi_u8 *data = HI_NULL;
234     hi_s32 temp_length = (hi_s32)ctx->file_length;
235     hi_s32 count = 0;
236     hi_u8 temp_char;
237     hi_u16 crc;
238     hi_s32 i;
239     hi_u32 check_sum;
240 
241     if (ctx->retry > 0) {
242         serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
243         return;
244     }
245 
246     hi_u32 check_sum_val = (uintptr_t)(ctx->buffer) ^ (hi_u32)sizeof(ctx->buffer) ^ 0 ^ (hi_u32)sizeof(ctx->buffer);
247     (hi_void) memset_s(ctx->buffer, sizeof(ctx->buffer), 0, sizeof(ctx->buffer), check_sum_val);
248     ctx->buffer[0] = MODEM_SOH;
249     ctx->buffer[1] = ctx->seq;
250     ctx->buffer[2] = (hi_u8)~ctx->buffer[1]; /* buffer[2] is buffer[1] invert val */
251 
252     check_sum = (uintptr_t)(ctx->buffer + MSG_START_LEN) ^ SOH_MSG_LEN ^ (uintptr_t)(ctx->file_name) ^
253         (hi_u32)name_length;
254     if (memcpy_s(ctx->buffer + MSG_START_LEN, SOH_MSG_LEN, ctx->file_name, name_length, check_sum) != EOK) {
255         return;
256     }
257 
258     data = ctx->buffer + MSG_START_LEN + name_length;
259 
260     while (temp_length > 0) {
261         data[count++] = (hi_u8)((hi_u8)'0' + (temp_length % DECIMAL));
262         temp_length /= DECIMAL;
263     }
264 
265     /* 64 bytes, enough for storing 32-bit decimal digits
266        CNcomment:64字节足够存放32位10进制数 */
267     for (i = 0; i < count / 2; i++) { /* count should be divided by 2 */
268         temp_char = data[i];
269         data[i] = data[count - i - 1];
270         data[count - i - 1] = temp_char;
271     }
272 
273     check_sum = 0 ^ (uintptr_t)(ctx->buffer + MSG_START_LEN) ^ SOH_MSG_LEN;
274     crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, SOH_MSG_LEN, check_sum);
275     ctx->buffer[131] = (hi_u8)(crc >> 8); /* buffer[131] is crc high 8 bit */
276     ctx->buffer[132] = (hi_u8)crc; /* buffer[132] is crc low 8 bit */
277 
278     serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
279 
280     ctx->status = UPLOAD_WAIT_INIT_ACK;
281 }
282 
upload_send_null_info(hi_void)283 hi_void upload_send_null_info(hi_void)
284 {
285     upload_context *ctx = g_upload_ctx;
286     hi_u16 crc;
287 
288     hi_u32 check_sum_val = (uintptr_t)(ctx->buffer) ^ (hi_u32)sizeof(ctx->buffer) ^ 0 ^ SOH_MSG_LEN;
289     (hi_void) memset_s(ctx->buffer, sizeof(ctx->buffer), 0, SOH_MSG_LEN, check_sum_val);
290     ctx->buffer[0] = MODEM_SOH;
291     ctx->buffer[1] = 0;
292     ctx->buffer[2] = 0xFF;  /* buffer[2] is buffer[1] invert val */
293     hi_u32 check_sum = 0 ^ (uintptr_t)(ctx->buffer + MSG_START_LEN) ^ SOH_MSG_LEN;
294     crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, SOH_MSG_LEN, check_sum);
295     ctx->buffer[131] = (hi_u8)(crc >> 8); /* buffer[131] is crc high 8 bit */
296     ctx->buffer[132] = (hi_u8)crc; /* buffer[132] is crc low 8 bit */
297     serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
298 
299     ctx->status = UPLOAD_WAIT_ZERO_ACK;
300 }
301 
upload_send_data(hi_void)302 hi_void upload_send_data(hi_void)
303 {
304     upload_context *ctx = g_upload_ctx;
305     hi_u32 remain = ctx->file_length - ctx->offset;
306     hi_u16 crc;
307 
308     if (ctx->retry > 0) {
309         if (ctx->buffer[0] == MODEM_SOH) {
310             serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
311         } else {
312             serial_put_buf((const char *)ctx->buffer, UPLOAD_BUFF_LEN);
313         }
314 
315         return;
316     }
317 
318     ctx->status = UPLOAD_WAIT_FINAL_ACK;
319     hi_u32 check_sum = (uintptr_t)(ctx->buffer) ^ (hi_u32)sizeof(ctx->buffer) ^ MODEM_EOF ^ (hi_u32)sizeof(ctx->buffer);
320     (hi_void) memset_s(ctx->buffer, sizeof(ctx->buffer), MODEM_EOF, sizeof(ctx->buffer), check_sum);
321 
322     ctx->buffer[0] = MODEM_STX;
323     ctx->buffer[1] = ++ctx->seq;
324     ctx->buffer[2] = (hi_u8)~ctx->buffer[1];  /* buffer[2] is buffer[1] invert val */
325 
326     if (remain <= SOH_MSG_LEN) {
327         ctx->buffer[0] = MODEM_SOH;
328         if (memcpy_s (ctx->buffer + MSG_START_LEN, SOH_MSG_LEN,
329             (const hi_void *)(uintptr_t)(ctx->file_addr + ctx->offset), remain, (uintptr_t)(ctx->buffer + MSG_START_LEN)
330             ^ SOH_MSG_LEN ^ (uintptr_t)(const hi_void *)(uintptr_t)(ctx->file_addr + ctx->offset) ^ remain) != EOK) {
331             return;
332         }
333         check_sum = 0 ^ (uintptr_t)(ctx->buffer + MSG_START_LEN) ^ SOH_MSG_LEN;
334         crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, SOH_MSG_LEN, check_sum);
335         ctx->buffer[131] = (hi_u8)(crc >> 8); /* buffer[131] is crc high 8 bit */
336         ctx->buffer[132] = (hi_u8)crc; /* buffer[132] is crc low 8 bit */
337         serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
338     } else {
339         if (remain > UPLOAD_DATA_SIZE) {
340             remain = UPLOAD_DATA_SIZE;
341             ctx->status = UPLOAD_WAIT_INTER_ACK;
342         }
343         check_sum = (uintptr_t)(ctx->buffer + MSG_START_LEN) ^ UPLOAD_DATA_SIZE ^
344             (uintptr_t)(const hi_void *)(uintptr_t)(ctx->file_addr + ctx->offset) ^ remain;
345         if (memcpy_s(ctx->buffer + MSG_START_LEN, UPLOAD_DATA_SIZE,
346             (const hi_void *)(uintptr_t)(ctx->file_addr + ctx->offset), remain, check_sum) != EOK) {
347             return;
348         }
349         check_sum = 0 ^ (uintptr_t)(ctx->buffer + MSG_START_LEN) ^ UPLOAD_DATA_SIZE;
350         crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, UPLOAD_DATA_SIZE, check_sum);
351         ctx->buffer[1027] = (hi_u8)(crc >> 8); /* buffer[1027] is crc high 8 bit */
352         ctx->buffer[1028] = (hi_u8)crc; /* buffer[1028] is crc low 8 bit */
353         serial_put_buf((const char *)ctx->buffer, UPLOAD_BUFF_LEN);
354     }
355 
356     ctx->offset += remain;
357 }
358 
upload_modem_c_step(hi_u8 status)359 hi_s32 upload_modem_c_step(hi_u8 status)
360 {
361     switch (status) {
362         case UPLOAD_WAIT_START_C:
363             upload_send_file_info();
364             return 1;
365         case UPLOAD_WAIT_TRANS_C:
366             upload_send_data();
367             return 1;
368         case UPLOAD_WAIT_EOT_C:
369             upload_send_null_info();
370             return 1;
371         default:
372             return 0;
373     }
374 }
375 
upload_modem_ack_step(hi_u8 * status,hi_u32 * timeout)376 hi_s32 upload_modem_ack_step(hi_u8 *status, hi_u32 *timeout)
377 {
378     switch (*status) {
379         case UPLOAD_WAIT_INIT_ACK:
380             *timeout = UPLOAD_WAIT_DEFAULT_TIME;
381             *status = UPLOAD_WAIT_TRANS_C;
382             return 1;
383         case UPLOAD_WAIT_INTER_ACK:
384             upload_send_data();
385             return 1;
386         case UPLOAD_WAIT_FINAL_ACK:
387             serial_putc(MODEM_EOT);
388             *status = UPLOAD_WAIT_EOT_C;
389             return 1;
390         default:
391             return 0;
392     }
393 }
394 
upload_modem_nak_step(hi_u8 * status,hi_u32 * timeout)395 hi_s32 upload_modem_nak_step(hi_u8 *status, hi_u32 *timeout)
396 {
397     switch (*status) {
398         case UPLOAD_WAIT_INIT_ACK:
399             *timeout = UPLOAD_WAIT_START_C_TIME;
400             upload_send_file_info();
401             return 1;
402         case UPLOAD_WAIT_INTER_ACK:
403         case UPLOAD_WAIT_FINAL_ACK:
404             upload_send_data();
405             return 1;
406         case UPLOAD_WAIT_EOT_C:
407             serial_putc(MODEM_EOT);
408             *status = UPLOAD_WAIT_EOT_C;
409             return 1;
410         case UPLOAD_WAIT_ZERO_ACK:
411             upload_send_null_info();
412             return 1;
413         default:
414             return 0;
415     }
416 }
417 
upload_serial_ymodem(hi_void)418 hi_u32 upload_serial_ymodem(hi_void)
419 {
420     upload_context *ctx = g_upload_ctx;
421     hi_u8 ch;
422     hi_u32 timeout = UPLOAD_WAIT_START_C_TIME;
423 
424     for (;;) {
425         hi_u32 ret = serial_getc_timeout(timeout, &ch);
426         if (ret != HI_ERR_SUCCESS) {
427             continue;
428         }
429 
430         switch (ch) {
431             case MODEM_C:
432                 ctx->can_cnt = 0;
433                 ctx->retry = 0;
434                 if (upload_modem_c_step(ctx->status) == 1) {
435                     continue;
436                 }
437                 break;
438 
439             case MODEM_ACK:
440                 ctx->can_cnt = 0;
441                 ctx->retry = 0;
442                 if (ctx->status == UPLOAD_WAIT_ZERO_ACK) {
443                     mdelay(WAIT_ZERO_ACK_DELAY);
444                     return HI_ERR_SUCCESS;
445                 }
446                 if (upload_modem_ack_step(&ctx->status, &timeout) == 1) {
447                     continue;
448                 }
449                 break;
450 
451             case MODEM_NAK:
452                 ctx->can_cnt = 0;
453 
454                 if (++ctx->retry == RETRY_COUNT) {
455                     return HI_ERR_FAILURE;
456                 }
457                 if (upload_modem_nak_step(&ctx->status, &timeout) == 1) {
458                     continue;
459                 }
460                 break;
461 
462             case MODEM_CAN:
463                 ctx->retry = 0;
464 
465                 if (++ctx->can_cnt == CAN_COUNT) {
466                     return HI_ERR_FAILURE;
467                 }
468 
469                 continue;
470                 /* fall-through */
471             default:
472                 continue;
473         }
474     }
475 }
476 
upload_data(hi_u32 addr,hi_u32 length)477 hi_u32 upload_data(hi_u32 addr, hi_u32 length)
478 {
479     if (upload_malloc_init() != HI_ERR_SUCCESS) {
480         boot_msg0("upload init fail.");
481         return HI_ERR_FAILURE;
482     }
483 
484     g_upload_ctx->file_addr = addr + FLASH_ADDR_OFFSET;
485     g_upload_ctx->file_length = length;
486     g_upload_ctx->file_name = UPLOAD_FILE_NAME;
487     g_upload_ctx->status = UPLOAD_WAIT_START_C;
488 
489     loader_ack(ACK_SUCCESS);
490 
491     if (upload_serial_ymodem() == HI_ERR_SUCCESS) {
492         upload_malloc_deinit();
493         return HI_ERR_SUCCESS;
494     }
495     upload_malloc_deinit();
496     return HI_ERR_FAILURE;
497 }
498