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