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