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 #include <util.h>
13 
14 /*
15  * These macros are the offsets where images reside on sec mem
16  */
17 #define BNXT_BUFFER_SEC_MEM	0x8ae00000
18 #define BNXT_FW_SEC_MEM_SRC	BNXT_BUFFER_SEC_MEM
19 #define BNXT_FW_SEC_MEM_CFG	(BNXT_BUFFER_SEC_MEM + 0x100000)
20 #define TEMP_MEM		(BNXT_BUFFER_SEC_MEM + 0x180000)
21 
22 #define BNXT_CRASH_SEC_MEM	0x8b000000
23 #define BNXT_CRASH_LEN		0x2000000
24 
25 #define BNXT_CONFIG_NS3_DEST	0x03a00000
26 #define BNXT_BSPD_CFG_OFFSET	0x51b0
27 #define BNXT_CONFIG_NS3_BSPD_DEST	(BNXT_CONFIG_NS3_DEST + \
28 					 BNXT_BSPD_CFG_OFFSET)
29 #define BNXT_BSPD_CFG_SIZE	0x200
30 
31 #define BNXT_CRASH_DUMP_INFO_NS3_BASE	0x3a5ff00
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 
memcpy32_helper(uintptr_t src,uintptr_t dst,uint32_t entries,int inc_src_addr)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 
ape_host_view_addr_get(uint32_t bnxt_view_addr,uint32_t size)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 
ape_hdr_crc_calc(const struct ape_bin_hdr_s * hdr)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 
ape_bin_hdr_valid(const struct ape_bin_hdr_s * hdr)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 
get_char(uint8_t * inbuf,size_t * inbuf_idx,size_t inbuf_size)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 
put_char(uint8_t * outbuf,size_t * outbuf_idx,size_t outbuf_size,uint8_t ch)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 
ape_section_uncompress(uint8_t * inbuf,size_t inbuf_size,uint8_t * outbuf,size_t outbuf_size)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 
ape_section_copy(struct ape_bin_hdr_s * bin_hdr,struct ape_section_hdr_s * section)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 						 work_buff_size);
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 
ape_section_zero(struct ape_section_hdr_s * section)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 
bnxt_load(vaddr_t img_buffer)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 
bnxt_crash_config(uintptr_t info_dst,uint32_t crash_area_start,uint32_t crash_len)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 
bnxt_load_fw(int chip_type)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, 1);
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 
bnxt_copy_crash_dump(uint8_t * d,uint32_t offset,uint32_t len)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, len);
691 
692 	cache_op_inner(DCACHE_AREA_INVALIDATE, s, len);
693 
694 	memcpy(d, s, len);
695 
696 	return TEE_SUCCESS;
697 }
698