1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2019 Broadcom. 4 */ 5 6 #include <crc32.h> 7 #include <drivers/bcm/bnxt.h> 8 #include <stdint.h> 9 #include <stdlib.h> 10 #include <string.h> 11 12 /* 13 * These macros are the offsets where images reside on sec mem 14 */ 15 #define BNXT_BUFFER_SEC_MEM 0x8ae00000 16 #define BNXT_FW_SEC_MEM_SRC BNXT_BUFFER_SEC_MEM 17 #define BNXT_FW_SEC_MEM_CFG (BNXT_BUFFER_SEC_MEM + 0x100000) 18 #define TEMP_MEM (BNXT_BUFFER_SEC_MEM + 0x180000) 19 20 #define BNXT_CRASH_SEC_MEM 0x8b000000 21 #define BNXT_CRASH_LEN 0x2000000 22 23 #define BNXT_CONFIG_NS3_DEST 0x03a00000 24 #define BNXT_BSPD_CFG_OFFSET 0x51b0 25 #define BNXT_CONFIG_NS3_BSPD_DEST (BNXT_CONFIG_NS3_DEST + \ 26 BNXT_BSPD_CFG_OFFSET) 27 #define BNXT_BSPD_CFG_SIZE 0x200 28 29 #define BNXT_CRASH_DUMP_INFO_NS3_BASE 0x3a5ff00 30 31 #define IS_ALIGNED(addr, algn) (!((addr) & ((algn) - 1))) 32 33 #define SZ_1K 0x400 34 35 #define BUFFER_PADDING SZ_1K 36 37 #define INC_SRC_ADDR 1 38 39 #define EOF -1 40 41 #define BCM_BNXT_FASTBOOT_MASK 0x3u 42 #define BCM_BNXT_FASTBOOT_TYPE_1 1 43 44 #define ADDR_IS_4BYTE_ALIGNED(addr) IS_ALIGNED(addr, 4) 45 46 #define SECTION_IS_LOADABLE(section_ptr) \ 47 ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_LOADABLE) 48 #define SECTION_IS_ZIPPED(section_ptr) \ 49 ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_ZIPPED) 50 #define SECTION_IS_TOBE_COPIED(section_ptr) \ 51 ((section_ptr)->flags_src_offset & \ 52 (SECTION_FLAGS_IS_EXEC_INSTR | SECTION_FLAGS_IS_DATA)) 53 #define SECTION_IS_TOBE_ZEROED(section_ptr) \ 54 ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_BSS) 55 #define SECTION_IS_4BYTE_ALIGNED(section_ptr) \ 56 ADDR_IS_4BYTE_ALIGNED((section_ptr)->dest_addr) 57 58 #define SECTION_SRC_OFFSET(section_ptr) \ 59 ((section_ptr)->flags_src_offset & SECTION_SRC_OFFFSET_MASK) 60 61 /* -------------------------------------------------------------------------- */ 62 63 /* Section header for each image block */ 64 struct ape_section_hdr_s { 65 /* Destination address that this section is to be copied to */ 66 uint32_t dest_addr; 67 68 /* 69 * bit[0:23] source offset address that this image copy from 70 * bit[24:31] flags 71 */ 72 uint32_t flags_src_offset; 73 #define SECTION_FLAGS_MASK 0xff000000 74 /* Session is compressed (zipped) */ 75 #define SECTION_FLAGS_IS_ZIPPED 0x01000000 76 /* Session contains CRC */ 77 #define SECTION_FLAGS_IS_CRC 0x02000000 78 /* Session contains executable code (e.g. .text) */ 79 #define SECTION_FLAGS_IS_EXEC_INSTR 0x04000000 80 /* Session contains initialized data (e.g. .data) */ 81 #define SECTION_FLAGS_IS_DATA 0x08000000 82 /* Session contains zero initialized data (e.g. .bss) */ 83 #define SECTION_FLAGS_IS_BSS 0x10000000 84 /* Loadable section mask */ 85 #define SECTION_FLAGS_IS_LOADABLE (SECTION_FLAGS_IS_EXEC_INSTR | \ 86 SECTION_FLAGS_IS_DATA | \ 87 SECTION_FLAGS_IS_BSS) 88 #define SECTION_SRC_OFFFSET_MASK 0x00ffffff 89 90 /* Original image length, dword (4byte) length */ 91 uint32_t org_data_len; 92 93 /* Compressed image length (if FlAGS_IS_ZIPPED is set) */ 94 uint32_t zip_data_len; 95 96 /* 97 * checksum value for this image block, if FLAGS_IS_CRC then 98 * this is CRC checksum; otherwise it is a simple summation 99 */ 100 uint32_t checksum; 101 }; 102 103 struct version_s { 104 uint8_t version[16]; /* Null-terminated file version string */ 105 }; 106 107 struct ver_ext_offset_s { 108 uint8_t version[12]; /* Null-terminated file version string */ 109 uint32_t ext_hdr_offset; 110 }; 111 112 union version_and_offset_u { 113 struct version_s version1; 114 struct ver_ext_offset_s version2; 115 }; 116 117 struct ape_bin_hdr_s { 118 /* APE binary header signature; expects APE_BIN_HDR_SIGNATURE */ 119 uint32_t signature; 120 #define APE_BIN_HDR_SIGNATURE 0x1a4d4342 /* "BCM"+0x1a */ 121 /* Reserved for ChiMP's use */ 122 uint8_t flags; 123 uint8_t code_type; 124 uint8_t device; 125 uint8_t media; 126 union version_and_offset_u ver; 127 uint8_t build; 128 uint8_t revision; 129 uint8_t minor_ver; 130 uint8_t major_ver; 131 uint32_t entry_address; 132 uint8_t reserved; 133 uint8_t header_dword_size; 134 uint8_t num_total_sections; 135 uint8_t num_loadable_sections; 136 uint32_t checksum; 137 } __packed __aligned(1); 138 139 #define APE_BIN_HDR_SIZE sizeof(struct ape_bin_hdr_s) 140 #define APE_SECTION_HDR_SIZE sizeof(struct ape_section_hdr_s) 141 142 /* MAX number of image sections that will be accepted */ 143 #define APE_IMG_MAX_SECTIONS 16 144 145 #define APE_IMG_LOAD_DEBUG 0 146 147 /* -------------------------------------------------------------------------- */ 148 149 struct ape_mem_region_s { 150 uint32_t c_base; /* ChiMP's view of address */ 151 uint32_t h_base; /* Host's view of address */ 152 uint32_t size; /* Size in bytes */ 153 }; 154 155 /* Memory map into various scratchpad memories */ 156 static struct ape_mem_region_s ape_mem_regions[] = { 157 /* CHIMP scratchpad */ 158 {0x00100000, 0x03100000, 1024 * SZ_1K}, 159 160 /* APE scratchpad */ 161 {0x61000000, 0x03300000, 1152 * SZ_1K}, 162 163 /* BONO scratchpad */ 164 {0x61600000, 0x03a00000, 512 * SZ_1K}, 165 166 /* KONG scratchpad */ 167 {0x61400000, 0x03800000, 512 * SZ_1K}, 168 169 /* Keep this last!! */ 170 {0, 0, 0} 171 }; 172 173 /* Nitro crash address configuration related macros */ 174 #define BNXT_CRASH_INFO_SIGNATURE 0x20524444 175 #define BNXT_CRASH_INFO_VALID 0x1 176 #define MAX_CRASH_ADDR_ITEM 8 177 178 struct nitro_crash_addr_item { 179 uint32_t info; 180 uint32_t size; 181 uint32_t addr_hi; 182 uint32_t addr_lo; 183 }; 184 185 struct nitro_crash_addr_info { 186 /* CRC of the struct content, starting at next field. */ 187 uint32_t crc; 188 uint32_t signature; 189 uint32_t version; 190 struct nitro_crash_addr_item table[MAX_CRASH_ADDR_ITEM]; 191 }; 192 193 static inline void memcpy32_helper(uintptr_t src, 194 uintptr_t dst, 195 uint32_t entries, 196 int inc_src_addr) 197 { 198 uint32_t copied_entries = 0; 199 200 while (entries) { 201 copied_entries = bnxt_write32_multiple(dst, src, entries, 202 inc_src_addr); 203 204 if (copied_entries < entries) { 205 dst += copied_entries * sizeof(uint32_t); 206 src += (inc_src_addr) ? 207 (copied_entries * sizeof(uint32_t)) : 0; 208 entries -= copied_entries; 209 } else { 210 entries = 0; 211 } 212 } 213 } 214 215 static uint32_t ape_host_view_addr_get(uint32_t bnxt_view_addr, uint32_t size) 216 { 217 struct ape_mem_region_s *region = ape_mem_regions; 218 uint32_t addr = 0; 219 220 for (; region->size != 0; region++) { 221 if (bnxt_view_addr < region->c_base) 222 continue; 223 224 if (bnxt_view_addr >= (region->c_base + region->size)) 225 continue; 226 227 if (size > (region->c_base + region->size - bnxt_view_addr)) { 228 EMSG("ERROR: 0x%x + 0x%x spans memory boundary", 229 bnxt_view_addr, size); 230 break; 231 } 232 233 addr = bnxt_view_addr - region->c_base; 234 addr += region->h_base; 235 break; 236 } 237 238 return addr; 239 } 240 241 static uint32_t ape_hdr_crc_calc(const struct ape_bin_hdr_s *hdr) 242 { 243 uint32_t crc = 0; 244 uint32_t dummy = 0; 245 246 /* Compute the CRC up to, but not including, the checksum field */ 247 crc = CRC32(CRC32_INIT_VAL, 248 (const char *)hdr, 249 (uintptr_t)(&hdr->checksum) - (uintptr_t)hdr); 250 251 /* Compute the CRC with the checksum field zeroed out */ 252 crc = CRC32(~crc, (const char *)&dummy, sizeof(uint32_t)); 253 254 /* 255 * Compute the remainder part of the image header, i.e., the 256 * section headers 257 */ 258 crc = CRC32(~crc, 259 (const char *)((uintptr_t)hdr + APE_BIN_HDR_SIZE), 260 hdr->num_total_sections * APE_SECTION_HDR_SIZE); 261 262 return crc; 263 } 264 265 static int ape_bin_hdr_valid(const struct ape_bin_hdr_s *hdr) 266 { 267 uint32_t checksum = 0; 268 269 if (!hdr) { 270 EMSG("ERROR: no APE image header"); 271 return BNXT_FAILURE; 272 } 273 274 if (hdr->signature != APE_BIN_HDR_SIGNATURE) { 275 EMSG("ERROR: bad APE image signature"); 276 return BNXT_FAILURE; 277 } 278 279 if (hdr->num_total_sections > APE_IMG_MAX_SECTIONS) { 280 EMSG("ERROR: too many sections in APE image"); 281 return BNXT_FAILURE; 282 } 283 284 checksum = ape_hdr_crc_calc(hdr); 285 if (hdr->checksum != checksum) { 286 EMSG("ERROR: bad APE header checksum (exp: %x, act: %x)", 287 hdr->checksum, checksum); 288 return BNXT_FAILURE; 289 } 290 291 return BNXT_SUCCESS; 292 } 293 294 static int get_char(uint8_t *inbuf, size_t *inbuf_idx, size_t inbuf_size) 295 { 296 int c = 0; 297 298 if (*inbuf_idx >= inbuf_size) 299 return EOF; 300 301 c = inbuf[*inbuf_idx]; 302 *inbuf_idx += 1; 303 304 return c; 305 } 306 307 static void put_char(uint8_t *outbuf, 308 size_t *outbuf_idx, 309 size_t outbuf_size, 310 uint8_t ch) 311 { 312 if (*outbuf_idx >= outbuf_size) 313 return; 314 315 outbuf[*outbuf_idx] = ch; 316 *outbuf_idx += 1; 317 } 318 319 static size_t ape_section_uncompress(uint8_t *inbuf, 320 size_t inbuf_size, 321 uint8_t *outbuf, 322 size_t outbuf_size) 323 { 324 int i = 0, j = 0, k = 0, r = 0, c = 0; 325 uint32_t flags = 0; 326 size_t exp_size = 0, codesize = 0; 327 size_t inbuf_idx = 0, outbuf_idx = 0; 328 #define CODE_8U_MASK 0xff00u /* 8 code units count mask (8 bits) */ 329 #define CODE_END_MASK 0x100u /* End of code units mask */ 330 #define CODE_IS_UNENCODED_MASK 1 /* Unencoded code unit mask */ 331 #define CODE_POS_MASK 0xe0u /* Encoded unit position mask and */ 332 #define CODE_POS_SHIFT 3 /* Bit shift */ 333 #define CODE_LEN_MASK 0x1fu /* Encoded unit length mask */ 334 #define NS 2048 /* Size of ring buffer */ 335 #define F 34 /* Upper limit for match_length */ 336 #define THRESHOLD 2 /* Encode string into position and 337 * length, if match_length is 338 * greater than this. 339 */ 340 /* 341 * Ring buffer of size NS, with an extra F-1 bytes to facilitate 342 * string comparisons. 343 */ 344 uint8_t text_buf[NS + F - 1]; 345 346 inbuf_idx = 0; 347 outbuf_idx = 0; 348 349 for (i = 0; i < NS - F; i++) 350 text_buf[i] = ' '; 351 352 r = NS - F; 353 354 for (;;) { 355 if (((flags >>= 1) & CODE_END_MASK) == 0) { 356 c = get_char(inbuf, &inbuf_idx, inbuf_size); 357 if (c == EOF) 358 break; 359 ++exp_size; 360 361 if (exp_size > inbuf_size) 362 break; 363 364 /* Use higher byte cleverly to count to eight */ 365 flags = c | CODE_8U_MASK; 366 } 367 368 if (flags & CODE_IS_UNENCODED_MASK) { 369 /* Not encoded; simply copy the unit */ 370 c = get_char(inbuf, &inbuf_idx, inbuf_size); 371 if (c == EOF) 372 break; 373 374 ++exp_size; 375 if (exp_size > inbuf_size) 376 break; 377 378 put_char(outbuf, &outbuf_idx, outbuf_size, c); 379 text_buf[r++] = c; 380 r &= (NS - 1); 381 ++codesize; 382 } else { 383 /* Encoded; get the position and length & duplicate */ 384 i = get_char(inbuf, &inbuf_idx, inbuf_size); 385 if (i == EOF) 386 break; 387 388 ++exp_size; 389 if (exp_size > inbuf_size) 390 break; 391 392 j = get_char(inbuf, &inbuf_idx, inbuf_size); 393 if (j == EOF) 394 break; 395 396 ++exp_size; 397 if (exp_size > inbuf_size) 398 break; 399 400 i |= ((j & CODE_POS_MASK) << CODE_POS_SHIFT); 401 j = ((j & CODE_LEN_MASK) + THRESHOLD); 402 403 for (k = 0; k <= j; k++) { 404 c = text_buf[((i + k) & (NS - 1))]; 405 put_char(outbuf, &outbuf_idx, outbuf_size, c); 406 text_buf[r++] = c; 407 r &= (NS - 1); 408 ++codesize; 409 } 410 } 411 } 412 413 return codesize; 414 } 415 416 static int ape_section_copy(struct ape_bin_hdr_s *bin_hdr, 417 struct ape_section_hdr_s *section) 418 { 419 uintptr_t src = 0; 420 uintptr_t dst = 0; 421 uint32_t checksum = 0; 422 uint32_t i = 0; 423 size_t size = 0; 424 uint8_t *section_data = NULL; 425 size_t work_buff_size = 0; 426 void *work_buff = NULL; 427 int rc = BNXT_FAILURE; 428 429 if (SECTION_IS_ZIPPED(section)) { 430 work_buff_size = section->org_data_len + BUFFER_PADDING; 431 work_buff = (void *)phys_to_virt(TEMP_MEM, MEM_AREA_RAM_SEC); 432 if (!work_buff) { 433 EMSG("ERROR: buffer allocation"); 434 return BNXT_FAILURE; 435 } 436 437 section_data = (uint8_t *)((uintptr_t)bin_hdr + 438 SECTION_SRC_OFFSET(section)); 439 size = ape_section_uncompress(section_data, 440 section->zip_data_len, 441 work_buff, 442 work_buff_size); 443 if (size >= work_buff_size) { 444 EMSG("ERROR: section uncompress"); 445 goto ape_section_copy_exit; 446 } 447 if (size < section->org_data_len) { 448 EMSG("ERROR: decompressed data size mismatch "); 449 EMSG("(exp: %d, act: %ld)", 450 section->org_data_len, size); 451 goto ape_section_copy_exit; 452 } 453 src = (uintptr_t)work_buff; 454 } else { 455 src = (uintptr_t)bin_hdr + SECTION_SRC_OFFSET(section); 456 } 457 458 size = section->org_data_len; 459 460 if (section->flags_src_offset & SECTION_FLAGS_IS_CRC) { 461 checksum = CRC32(CRC32_INIT_VAL, (const char *)src, size); 462 } else { 463 checksum = 0; 464 for (i = 0; i < size / sizeof(uint32_t); i++) 465 checksum += ((uint32_t *)src)[i]; 466 } 467 if (checksum != section->checksum) { 468 EMSG("ERROR: checksum mismatch (exp: %x, act: %x)", 469 section->checksum, checksum); 470 goto ape_section_copy_exit; 471 } 472 473 dst = ape_host_view_addr_get(section->dest_addr, size); 474 if (dst == 0) { 475 EMSG("ERROR: ChiMP-to-host address conversion of %x", 476 section->dest_addr); 477 goto ape_section_copy_exit; 478 } 479 480 /* Copy the section */ 481 size = size / sizeof(uint32_t); 482 memcpy32_helper(src, dst, size, INC_SRC_ADDR); 483 484 rc = BNXT_SUCCESS; 485 486 ape_section_copy_exit: 487 return rc; 488 } 489 490 static int ape_section_zero(struct ape_section_hdr_s *section) 491 { 492 uint32_t dst = 0; 493 uint32_t size = section->org_data_len; 494 uint32_t zero = 0; 495 496 if (section->org_data_len == 0) 497 return BNXT_SUCCESS; 498 499 /* Convert ChiMP's view of the address in the image to the host view */ 500 dst = ape_host_view_addr_get(section->dest_addr, size); 501 if (dst == 0) { 502 EMSG("ERROR: ChiMP-to-host address conversion of %x", 503 section->dest_addr); 504 return BNXT_FAILURE; 505 } 506 507 /* 508 * Zero the section; we simply copy zeros and do not increment the 509 * source buffer address. 510 */ 511 size = size / sizeof(uint32_t); 512 memcpy32_helper((uintptr_t)&zero, dst, size, !INC_SRC_ADDR); 513 514 return BNXT_SUCCESS; 515 } 516 517 static int bnxt_load(vaddr_t img_buffer) 518 { 519 struct ape_bin_hdr_s *bin_hdr = NULL; 520 struct ape_section_hdr_s *section = NULL; 521 int sidx = 0; 522 int rc = BNXT_SUCCESS; 523 524 bin_hdr = (struct ape_bin_hdr_s *)img_buffer; 525 section = (struct ape_section_hdr_s *)(img_buffer + 526 APE_BIN_HDR_SIZE); 527 528 if (ape_bin_hdr_valid(bin_hdr) != BNXT_SUCCESS) 529 return BNXT_FAILURE; 530 531 for (sidx = 0; sidx < bin_hdr->num_total_sections; sidx++, section++) { 532 if (!SECTION_IS_LOADABLE(section)) 533 continue; 534 535 if (!ADDR_IS_4BYTE_ALIGNED(section->dest_addr)) { 536 EMSG("ERROR: unaligned section dest address 0x%x", 537 section->dest_addr); 538 rc = BNXT_FAILURE; 539 break; 540 } 541 542 if (!ADDR_IS_4BYTE_ALIGNED(SECTION_SRC_OFFSET(section))) { 543 EMSG("ERROR: unaligned section src offset (0x%x)", 544 SECTION_SRC_OFFSET(section)); 545 rc = BNXT_FAILURE; 546 break; 547 } 548 549 if (section->org_data_len % sizeof(uint32_t)) { 550 EMSG("ERROR: section size (%d) not divisible by 4", 551 section->org_data_len); 552 rc = BNXT_FAILURE; 553 break; 554 } 555 556 if (SECTION_IS_TOBE_COPIED(section)) { 557 rc = ape_section_copy(bin_hdr, section); 558 if (rc != BNXT_SUCCESS) 559 break; 560 } else if (SECTION_IS_TOBE_ZEROED(section)) { 561 rc = ape_section_zero(section); 562 if (rc != BNXT_SUCCESS) 563 break; 564 } 565 } 566 567 /* Set up boot mode and take BNXT out of reset */ 568 if (rc == BNXT_SUCCESS) { 569 bnxt_fastboot((bin_hdr->entry_address & 570 ~BCM_BNXT_FASTBOOT_MASK) | 571 BCM_BNXT_FASTBOOT_TYPE_1); 572 } 573 574 return rc; 575 } 576 577 static TEE_Result bnxt_crash_config(uintptr_t info_dst, 578 uint32_t crash_area_start, 579 uint32_t crash_len) 580 { 581 struct nitro_crash_addr_item *item = NULL; 582 uintptr_t dst = 0; 583 struct nitro_crash_addr_info *info = NULL; 584 uintptr_t src = 0; 585 uint32_t crc = 0; 586 size_t size = 0; 587 588 /* 589 * First we write into local memory to calculate CRC before 590 * updating into Nitro memory 591 */ 592 info = malloc(sizeof(struct nitro_crash_addr_info)); 593 if (!info) { 594 EMSG("ERROR: buffer allocation"); 595 return TEE_ERROR_OUT_OF_MEMORY; 596 } 597 598 memset(info, 0, sizeof(struct nitro_crash_addr_info)); 599 600 info->signature = BNXT_CRASH_INFO_SIGNATURE; 601 info->version = 0x01000000 | MAX_CRASH_ADDR_ITEM; 602 603 /* As of now only one item is filled */ 604 item = &info->table[0]; 605 item->info = 0; 606 item->size = crash_len | BNXT_CRASH_INFO_VALID; 607 item->addr_hi = 0; 608 item->addr_lo = crash_area_start; 609 610 /* Checksum calculation */ 611 crc = CRC32(CRC32_INIT_VAL, 612 (const char *)info + sizeof(uint32_t), 613 sizeof(struct nitro_crash_addr_info) - sizeof(uint32_t)); 614 info->crc = crc; 615 616 /* First we write the contents and then set valid bit */ 617 item->size &= ~BNXT_CRASH_INFO_VALID; 618 619 size = sizeof(struct nitro_crash_addr_info) / sizeof(uint32_t); 620 dst = info_dst; 621 src = (uintptr_t)info; 622 memcpy32_helper(src, dst, size, INC_SRC_ADDR); 623 624 /* Set the valid bit */ 625 item->size |= BNXT_CRASH_INFO_VALID; 626 dst = info_dst + offsetof(struct nitro_crash_addr_info, table) + 627 offsetof(struct nitro_crash_addr_item, size); 628 bnxt_write32_multiple(dst, (uintptr_t)&item->size, 1, 1); 629 630 free(info); 631 632 return TEE_SUCCESS; 633 } 634 635 TEE_Result bnxt_load_fw(int chip_type) 636 { 637 uint32_t size = 0; 638 uintptr_t dst = 0; 639 uintptr_t src = 0; 640 struct bnxt_images_info bnxt_src_image_info; 641 vaddr_t sec_mem_dest = (vaddr_t)phys_to_virt(BNXT_BUFFER_SEC_MEM, 642 MEM_AREA_RAM_SEC); 643 644 memset(&bnxt_src_image_info, 0, sizeof(struct bnxt_images_info)); 645 646 if (get_bnxt_images_info(&bnxt_src_image_info, 647 chip_type, sec_mem_dest) != BNXT_SUCCESS) 648 return TEE_ERROR_ITEM_NOT_FOUND; 649 650 bnxt_kong_halt(); 651 bnxt_chimp_halt(); 652 653 /* Copy the configs */ 654 src = (uintptr_t)bnxt_src_image_info.bnxt_cfg_vaddr; 655 dst = (uintptr_t)BNXT_CONFIG_NS3_DEST; 656 size = bnxt_src_image_info.bnxt_cfg_len; 657 size = size / sizeof(uint32_t); 658 memcpy32_helper(src, dst, size, INC_SRC_ADDR); 659 660 /* Copy bspd config */ 661 src = (uintptr_t)bnxt_src_image_info.bnxt_bspd_cfg_vaddr; 662 size = bnxt_src_image_info.bnxt_bspd_cfg_len; 663 dst = (uintptr_t)BNXT_CONFIG_NS3_BSPD_DEST; 664 665 size = size / sizeof(uint32_t); 666 memcpy32_helper(src, dst, size, INC_SRC_ADDR); 667 668 /* Fill the bnxt crash dump info */ 669 bnxt_crash_config((uintptr_t)BNXT_CRASH_DUMP_INFO_NS3_BASE, 670 BNXT_CRASH_SEC_MEM, 671 BNXT_CRASH_LEN); 672 673 /* Load bnxt firmware and fastboot */ 674 bnxt_load(bnxt_src_image_info.bnxt_fw_vaddr); 675 676 /* Wait for handshke */ 677 bnxt_wait_handshake(); 678 679 return TEE_SUCCESS; 680 } 681