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