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