xref: /optee_os/core/drivers/bnxt/bnxt_fw.c (revision 5b25c76ac40f830867e3d60800120ffd7874e8dc)
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