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