xref: /optee_os/core/drivers/bnxt/bnxt_fw.c (revision 4af447d4084e293800d4e463d65003c016b91f29)
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 						 work_buff_size);
434 		if (!work_buff) {
435 			EMSG("ERROR: buffer allocation");
436 			return BNXT_FAILURE;
437 		}
438 
439 		section_data = (uint8_t *)((uintptr_t)bin_hdr +
440 					   SECTION_SRC_OFFSET(section));
441 		size = ape_section_uncompress(section_data,
442 					      section->zip_data_len,
443 					      work_buff,
444 					      work_buff_size);
445 		if (size >= work_buff_size) {
446 			EMSG("ERROR: section uncompress");
447 			goto ape_section_copy_exit;
448 		}
449 		if (size < section->org_data_len) {
450 			EMSG("ERROR: decompressed data size mismatch ");
451 			EMSG("(exp: %d, act: %ld)",
452 			     section->org_data_len, size);
453 			goto ape_section_copy_exit;
454 		}
455 		src = (uintptr_t)work_buff;
456 	} else {
457 		src = (uintptr_t)bin_hdr + SECTION_SRC_OFFSET(section);
458 	}
459 
460 	size = section->org_data_len;
461 
462 	if (section->flags_src_offset & SECTION_FLAGS_IS_CRC) {
463 		checksum = CRC32(CRC32_INIT_VAL, (const char *)src, size);
464 	} else {
465 		checksum = 0;
466 		for (i = 0; i < size / sizeof(uint32_t); i++)
467 			checksum += ((uint32_t *)src)[i];
468 	}
469 	if (checksum != section->checksum) {
470 		EMSG("ERROR: checksum mismatch (exp: %x, act: %x)",
471 		     section->checksum, checksum);
472 		goto ape_section_copy_exit;
473 	}
474 
475 	dst = ape_host_view_addr_get(section->dest_addr, size);
476 	if (dst == 0) {
477 		EMSG("ERROR: ChiMP-to-host address conversion of %x",
478 		     section->dest_addr);
479 		goto ape_section_copy_exit;
480 	}
481 
482 	/* Copy the section */
483 	size = size / sizeof(uint32_t);
484 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
485 
486 	rc = BNXT_SUCCESS;
487 
488 ape_section_copy_exit:
489 	return rc;
490 }
491 
492 static int ape_section_zero(struct ape_section_hdr_s *section)
493 {
494 	uint32_t dst = 0;
495 	uint32_t size = section->org_data_len;
496 	uint32_t zero = 0;
497 
498 	if (section->org_data_len == 0)
499 		return BNXT_SUCCESS;
500 
501 	/* Convert ChiMP's view of the address in the image to the host view */
502 	dst = ape_host_view_addr_get(section->dest_addr, size);
503 	if (dst == 0) {
504 		EMSG("ERROR: ChiMP-to-host address conversion of %x",
505 		     section->dest_addr);
506 		return BNXT_FAILURE;
507 	}
508 
509 	/*
510 	 * Zero the section; we simply copy zeros and do not increment the
511 	 * source buffer address.
512 	 */
513 	size = size / sizeof(uint32_t);
514 	memcpy32_helper((uintptr_t)&zero, dst, size, !INC_SRC_ADDR);
515 
516 	return BNXT_SUCCESS;
517 }
518 
519 static int bnxt_load(vaddr_t img_buffer)
520 {
521 	struct ape_bin_hdr_s *bin_hdr = NULL;
522 	struct ape_section_hdr_s *section = NULL;
523 	int sidx = 0;
524 	int rc = BNXT_SUCCESS;
525 
526 	bin_hdr = (struct ape_bin_hdr_s *)img_buffer;
527 	section = (struct ape_section_hdr_s *)(img_buffer +
528 					       APE_BIN_HDR_SIZE);
529 
530 	if (ape_bin_hdr_valid(bin_hdr) != BNXT_SUCCESS)
531 		return BNXT_FAILURE;
532 
533 	for (sidx = 0; sidx < bin_hdr->num_total_sections; sidx++, section++) {
534 		if (!SECTION_IS_LOADABLE(section))
535 			continue;
536 
537 		if (!ADDR_IS_4BYTE_ALIGNED(section->dest_addr)) {
538 			EMSG("ERROR: unaligned section dest address 0x%x",
539 			     section->dest_addr);
540 			rc = BNXT_FAILURE;
541 			break;
542 		}
543 
544 		if (!ADDR_IS_4BYTE_ALIGNED(SECTION_SRC_OFFSET(section))) {
545 			EMSG("ERROR: unaligned section src offset (0x%x)",
546 			     SECTION_SRC_OFFSET(section));
547 			rc = BNXT_FAILURE;
548 			break;
549 		}
550 
551 		if (section->org_data_len % sizeof(uint32_t)) {
552 			EMSG("ERROR: section size (%d) not divisible by 4",
553 			     section->org_data_len);
554 			rc = BNXT_FAILURE;
555 			break;
556 		}
557 
558 		if (SECTION_IS_TOBE_COPIED(section)) {
559 			rc = ape_section_copy(bin_hdr, section);
560 			if (rc != BNXT_SUCCESS)
561 				break;
562 		} else if (SECTION_IS_TOBE_ZEROED(section)) {
563 			rc = ape_section_zero(section);
564 			if (rc != BNXT_SUCCESS)
565 				break;
566 		}
567 	}
568 
569 	/* Set up boot mode and take BNXT out of reset */
570 	if (rc == BNXT_SUCCESS) {
571 		bnxt_fastboot((bin_hdr->entry_address &
572 			       ~BCM_BNXT_FASTBOOT_MASK) |
573 			       BCM_BNXT_FASTBOOT_TYPE_1);
574 	}
575 
576 	return rc;
577 }
578 
579 static TEE_Result bnxt_crash_config(uintptr_t info_dst,
580 				    uint32_t crash_area_start,
581 				    uint32_t crash_len)
582 {
583 	struct nitro_crash_addr_item *item = NULL;
584 	uintptr_t dst = 0;
585 	struct nitro_crash_addr_info *info = NULL;
586 	uintptr_t src = 0;
587 	uint32_t crc = 0;
588 	size_t size = 0;
589 
590 	/*
591 	 * First we write into local memory to calculate CRC before
592 	 * updating into Nitro memory
593 	 */
594 	info = malloc(sizeof(struct nitro_crash_addr_info));
595 	if (!info) {
596 		EMSG("ERROR: buffer allocation");
597 		return TEE_ERROR_OUT_OF_MEMORY;
598 	}
599 
600 	memset(info, 0, sizeof(struct nitro_crash_addr_info));
601 
602 	info->signature = BNXT_CRASH_INFO_SIGNATURE;
603 	info->version = 0x01000000 | MAX_CRASH_ADDR_ITEM;
604 
605 	/* As of now only one item is filled */
606 	item = &info->table[0];
607 	item->info = 0;
608 	item->size = crash_len | BNXT_CRASH_INFO_VALID;
609 	item->addr_hi = 0;
610 	item->addr_lo = crash_area_start;
611 
612 	/* Checksum calculation  */
613 	crc = CRC32(CRC32_INIT_VAL,
614 		    (const char *)info + sizeof(uint32_t),
615 		     sizeof(struct nitro_crash_addr_info) - sizeof(uint32_t));
616 	info->crc = crc;
617 
618 	/* First we write the contents and then set valid bit */
619 	item->size &= ~BNXT_CRASH_INFO_VALID;
620 
621 	size = sizeof(struct nitro_crash_addr_info) / sizeof(uint32_t);
622 	dst = info_dst;
623 	src = (uintptr_t)info;
624 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
625 
626 	/* Set the valid bit */
627 	item->size |= BNXT_CRASH_INFO_VALID;
628 	dst = info_dst + offsetof(struct nitro_crash_addr_info, table) +
629 	      offsetof(struct nitro_crash_addr_item, size);
630 	bnxt_write32_multiple(dst, (uintptr_t)&item->size, 1, 1);
631 
632 	free(info);
633 
634 	return TEE_SUCCESS;
635 }
636 
637 TEE_Result bnxt_load_fw(int chip_type)
638 {
639 	uint32_t size = 0;
640 	uintptr_t dst = 0;
641 	uintptr_t src = 0;
642 	struct bnxt_images_info bnxt_src_image_info;
643 	vaddr_t sec_mem_dest = (vaddr_t)phys_to_virt(BNXT_BUFFER_SEC_MEM,
644 						     MEM_AREA_RAM_SEC, 1);
645 
646 	memset(&bnxt_src_image_info, 0, sizeof(struct bnxt_images_info));
647 
648 	if (get_bnxt_images_info(&bnxt_src_image_info,
649 				 chip_type, sec_mem_dest) != BNXT_SUCCESS)
650 		return TEE_ERROR_ITEM_NOT_FOUND;
651 
652 	bnxt_handshake_clear();
653 	bnxt_kong_halt();
654 	bnxt_chimp_halt();
655 
656 	/* Copy the configs */
657 	src = (uintptr_t)bnxt_src_image_info.bnxt_cfg_vaddr;
658 	dst = (uintptr_t)BNXT_CONFIG_NS3_DEST;
659 	size = bnxt_src_image_info.bnxt_cfg_len;
660 	size = size / sizeof(uint32_t);
661 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
662 
663 	/* Copy bspd config */
664 	src = (uintptr_t)bnxt_src_image_info.bnxt_bspd_cfg_vaddr;
665 	size = bnxt_src_image_info.bnxt_bspd_cfg_len;
666 	dst = (uintptr_t)BNXT_CONFIG_NS3_BSPD_DEST;
667 
668 	size = size / sizeof(uint32_t);
669 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
670 
671 	/* Fill the bnxt crash dump info */
672 	bnxt_crash_config((uintptr_t)BNXT_CRASH_DUMP_INFO_NS3_BASE,
673 			  BNXT_CRASH_SEC_MEM,
674 			  BNXT_CRASH_LEN);
675 
676 	/* Load bnxt firmware and fastboot */
677 	bnxt_load(bnxt_src_image_info.bnxt_fw_vaddr);
678 
679 	return TEE_SUCCESS;
680 }
681 
682 TEE_Result bnxt_copy_crash_dump(uint8_t *d, uint32_t offset, uint32_t len)
683 {
684 	size_t crash_len = 0;
685 	void *s = NULL;
686 
687 	if (ADD_OVERFLOW(offset, len, &crash_len) ||
688 	    crash_len > BNXT_CRASH_LEN)
689 		return TEE_ERROR_BAD_PARAMETERS;
690 
691 	s = phys_to_virt(BNXT_CRASH_SEC_MEM + offset, MEM_AREA_RAM_SEC, len);
692 
693 	cache_op_inner(DCACHE_AREA_INVALIDATE, s, len);
694 
695 	memcpy(d, s, len);
696 
697 	return TEE_SUCCESS;
698 }
699