xref: /optee_os/core/drivers/bnxt/bnxt_fw.c (revision 6d777f268ade9a73ad56e68bd1c418dc905ecf52)
195bec10aSVikas Gupta // SPDX-License-Identifier: BSD-2-Clause
295bec10aSVikas Gupta /*
395bec10aSVikas Gupta  * Copyright 2019 Broadcom.
495bec10aSVikas Gupta  */
595bec10aSVikas Gupta 
695bec10aSVikas Gupta #include <crc32.h>
795bec10aSVikas Gupta #include <drivers/bcm/bnxt.h>
89b726349SSheetal Tigadoli #include <mm/core_mmu.h>
995bec10aSVikas Gupta #include <stdint.h>
1095bec10aSVikas Gupta #include <stdlib.h>
1195bec10aSVikas Gupta #include <string.h>
12*6d777f26SJorge Ramirez-Ortiz #include <util.h>
1395bec10aSVikas Gupta 
1495bec10aSVikas Gupta /*
1595bec10aSVikas Gupta  * These macros are the offsets where images reside on sec mem
1695bec10aSVikas Gupta  */
1795bec10aSVikas Gupta #define BNXT_BUFFER_SEC_MEM	0x8ae00000
1895bec10aSVikas Gupta #define BNXT_FW_SEC_MEM_SRC	BNXT_BUFFER_SEC_MEM
1995bec10aSVikas Gupta #define BNXT_FW_SEC_MEM_CFG	(BNXT_BUFFER_SEC_MEM + 0x100000)
20ccf6a7e7STony Poon #define TEMP_MEM		(BNXT_BUFFER_SEC_MEM + 0x180000)
2195bec10aSVikas Gupta 
2295bec10aSVikas Gupta #define BNXT_CRASH_SEC_MEM	0x8b000000
2395bec10aSVikas Gupta #define BNXT_CRASH_LEN		0x2000000
2495bec10aSVikas Gupta 
2595bec10aSVikas Gupta #define BNXT_CONFIG_NS3_DEST	0x03a00000
2695bec10aSVikas Gupta #define BNXT_BSPD_CFG_OFFSET	0x51b0
2795bec10aSVikas Gupta #define BNXT_CONFIG_NS3_BSPD_DEST	(BNXT_CONFIG_NS3_DEST + \
2895bec10aSVikas Gupta 					 BNXT_BSPD_CFG_OFFSET)
2995bec10aSVikas Gupta #define BNXT_BSPD_CFG_SIZE	0x200
3095bec10aSVikas Gupta 
3195bec10aSVikas Gupta #define BNXT_CRASH_DUMP_INFO_NS3_BASE	0x3a5ff00
3295bec10aSVikas Gupta 
3395bec10aSVikas Gupta #define SZ_1K				0x400
3495bec10aSVikas Gupta 
3595bec10aSVikas Gupta #define BUFFER_PADDING			SZ_1K
3695bec10aSVikas Gupta 
3795bec10aSVikas Gupta #define INC_SRC_ADDR			1
3895bec10aSVikas Gupta 
3995bec10aSVikas Gupta #define EOF				-1
4095bec10aSVikas Gupta 
4195bec10aSVikas Gupta #define BCM_BNXT_FASTBOOT_MASK		0x3u
4295bec10aSVikas Gupta #define BCM_BNXT_FASTBOOT_TYPE_1	1
4395bec10aSVikas Gupta 
4495bec10aSVikas Gupta #define ADDR_IS_4BYTE_ALIGNED(addr)	IS_ALIGNED(addr, 4)
4595bec10aSVikas Gupta 
4695bec10aSVikas Gupta #define SECTION_IS_LOADABLE(section_ptr) \
4795bec10aSVikas Gupta 	((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_LOADABLE)
4895bec10aSVikas Gupta #define SECTION_IS_ZIPPED(section_ptr) \
4995bec10aSVikas Gupta 	((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_ZIPPED)
5095bec10aSVikas Gupta #define SECTION_IS_TOBE_COPIED(section_ptr) \
5195bec10aSVikas Gupta 	((section_ptr)->flags_src_offset & \
5295bec10aSVikas Gupta 	 (SECTION_FLAGS_IS_EXEC_INSTR | SECTION_FLAGS_IS_DATA))
5395bec10aSVikas Gupta #define SECTION_IS_TOBE_ZEROED(section_ptr) \
5495bec10aSVikas Gupta 	((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_BSS)
5595bec10aSVikas Gupta #define SECTION_IS_4BYTE_ALIGNED(section_ptr) \
5695bec10aSVikas Gupta 	ADDR_IS_4BYTE_ALIGNED((section_ptr)->dest_addr)
5795bec10aSVikas Gupta 
5895bec10aSVikas Gupta #define SECTION_SRC_OFFSET(section_ptr) \
5995bec10aSVikas Gupta 	((section_ptr)->flags_src_offset & SECTION_SRC_OFFFSET_MASK)
6095bec10aSVikas Gupta 
6195bec10aSVikas Gupta /* -------------------------------------------------------------------------- */
6295bec10aSVikas Gupta 
6395bec10aSVikas Gupta /* Section header for each image block */
6495bec10aSVikas Gupta struct ape_section_hdr_s {
6595bec10aSVikas Gupta 	/* Destination address that this section is to be copied to */
6695bec10aSVikas Gupta 	uint32_t dest_addr;
6795bec10aSVikas Gupta 
6895bec10aSVikas Gupta 	/*
6995bec10aSVikas Gupta 	 * bit[0:23]  source offset address that this image copy from
7095bec10aSVikas Gupta 	 * bit[24:31] flags
7195bec10aSVikas Gupta 	 */
7295bec10aSVikas Gupta 	uint32_t flags_src_offset;
7395bec10aSVikas Gupta #define SECTION_FLAGS_MASK		0xff000000
7495bec10aSVikas Gupta 	/* Session is compressed (zipped) */
7595bec10aSVikas Gupta #define SECTION_FLAGS_IS_ZIPPED		0x01000000
7695bec10aSVikas Gupta 	/* Session contains CRC */
7795bec10aSVikas Gupta #define SECTION_FLAGS_IS_CRC		0x02000000
7895bec10aSVikas Gupta 	/* Session contains executable code (e.g. .text) */
7995bec10aSVikas Gupta #define SECTION_FLAGS_IS_EXEC_INSTR	0x04000000
8095bec10aSVikas Gupta 	/* Session contains initialized data (e.g. .data) */
8195bec10aSVikas Gupta #define SECTION_FLAGS_IS_DATA		0x08000000
8295bec10aSVikas Gupta 	/* Session contains zero initialized data (e.g. .bss) */
8395bec10aSVikas Gupta #define SECTION_FLAGS_IS_BSS		0x10000000
8495bec10aSVikas Gupta 	/* Loadable section mask */
8595bec10aSVikas Gupta #define SECTION_FLAGS_IS_LOADABLE	(SECTION_FLAGS_IS_EXEC_INSTR | \
8695bec10aSVikas Gupta 					 SECTION_FLAGS_IS_DATA | \
8795bec10aSVikas Gupta 					 SECTION_FLAGS_IS_BSS)
8895bec10aSVikas Gupta #define SECTION_SRC_OFFFSET_MASK	0x00ffffff
8995bec10aSVikas Gupta 
9095bec10aSVikas Gupta 	/* Original image length, dword (4byte) length */
9195bec10aSVikas Gupta 	uint32_t org_data_len;
9295bec10aSVikas Gupta 
9395bec10aSVikas Gupta 	/* Compressed image length (if FlAGS_IS_ZIPPED is set) */
9495bec10aSVikas Gupta 	uint32_t zip_data_len;
9595bec10aSVikas Gupta 
9695bec10aSVikas Gupta 	/*
9795bec10aSVikas Gupta 	 * checksum value for this image block, if FLAGS_IS_CRC then
9895bec10aSVikas Gupta 	 * this is CRC checksum; otherwise it is a simple summation
9995bec10aSVikas Gupta 	 */
10095bec10aSVikas Gupta 	uint32_t checksum;
10195bec10aSVikas Gupta };
10295bec10aSVikas Gupta 
10395bec10aSVikas Gupta struct version_s {
10495bec10aSVikas Gupta 	uint8_t version[16];	/* Null-terminated file version string */
10595bec10aSVikas Gupta };
10695bec10aSVikas Gupta 
10795bec10aSVikas Gupta struct ver_ext_offset_s {
10895bec10aSVikas Gupta 	uint8_t  version[12];	/* Null-terminated file version string */
10995bec10aSVikas Gupta 	uint32_t ext_hdr_offset;
11095bec10aSVikas Gupta };
11195bec10aSVikas Gupta 
11295bec10aSVikas Gupta union version_and_offset_u {
11395bec10aSVikas Gupta 	struct version_s version1;
11495bec10aSVikas Gupta 	struct ver_ext_offset_s	version2;
11595bec10aSVikas Gupta };
11695bec10aSVikas Gupta 
11795bec10aSVikas Gupta struct ape_bin_hdr_s {
11895bec10aSVikas Gupta 	/* APE binary header signature; expects APE_BIN_HDR_SIGNATURE */
11995bec10aSVikas Gupta 	uint32_t signature;
12095bec10aSVikas Gupta #define APE_BIN_HDR_SIGNATURE 0x1a4d4342 /* "BCM"+0x1a */
12195bec10aSVikas Gupta 	/* Reserved for ChiMP's use */
12295bec10aSVikas Gupta 	uint8_t flags;
12395bec10aSVikas Gupta 	uint8_t code_type;
12495bec10aSVikas Gupta 	uint8_t device;
12595bec10aSVikas Gupta 	uint8_t media;
12695bec10aSVikas Gupta 	union version_and_offset_u ver;
12795bec10aSVikas Gupta 	uint8_t build;
12895bec10aSVikas Gupta 	uint8_t revision;
12995bec10aSVikas Gupta 	uint8_t minor_ver;
13095bec10aSVikas Gupta 	uint8_t major_ver;
13195bec10aSVikas Gupta 	uint32_t entry_address;
13295bec10aSVikas Gupta 	uint8_t reserved;
13395bec10aSVikas Gupta 	uint8_t header_dword_size;
13495bec10aSVikas Gupta 	uint8_t num_total_sections;
13595bec10aSVikas Gupta 	uint8_t num_loadable_sections;
13695bec10aSVikas Gupta 	uint32_t checksum;
13795bec10aSVikas Gupta } __packed __aligned(1);
13895bec10aSVikas Gupta 
13995bec10aSVikas Gupta #define APE_BIN_HDR_SIZE	sizeof(struct ape_bin_hdr_s)
14095bec10aSVikas Gupta #define APE_SECTION_HDR_SIZE	sizeof(struct ape_section_hdr_s)
14195bec10aSVikas Gupta 
14295bec10aSVikas Gupta /* MAX number of image sections that will be accepted */
14395bec10aSVikas Gupta #define APE_IMG_MAX_SECTIONS	16
14495bec10aSVikas Gupta 
14595bec10aSVikas Gupta #define APE_IMG_LOAD_DEBUG	0
14695bec10aSVikas Gupta 
14795bec10aSVikas Gupta /* -------------------------------------------------------------------------- */
14895bec10aSVikas Gupta 
14995bec10aSVikas Gupta struct ape_mem_region_s {
15095bec10aSVikas Gupta 	uint32_t c_base;	/* ChiMP's view of address */
15195bec10aSVikas Gupta 	uint32_t h_base;	/* Host's view of address */
15295bec10aSVikas Gupta 	uint32_t size;		/* Size in bytes */
15395bec10aSVikas Gupta };
15495bec10aSVikas Gupta 
15595bec10aSVikas Gupta /* Memory map into various scratchpad memories */
15695bec10aSVikas Gupta static struct ape_mem_region_s ape_mem_regions[] = {
15795bec10aSVikas Gupta 	/* CHIMP scratchpad */
15895bec10aSVikas Gupta 	{0x00100000, 0x03100000, 1024 * SZ_1K},
15995bec10aSVikas Gupta 
16095bec10aSVikas Gupta 	/* APE scratchpad */
16195bec10aSVikas Gupta 	{0x61000000, 0x03300000, 1152 * SZ_1K},
16295bec10aSVikas Gupta 
16395bec10aSVikas Gupta 	/* BONO scratchpad */
16495bec10aSVikas Gupta 	{0x61600000, 0x03a00000, 512 * SZ_1K},
16595bec10aSVikas Gupta 
16695bec10aSVikas Gupta 	/* KONG scratchpad */
16795bec10aSVikas Gupta 	{0x61400000, 0x03800000, 512 * SZ_1K},
16895bec10aSVikas Gupta 
16995bec10aSVikas Gupta 	/* Keep this last!! */
17095bec10aSVikas Gupta 	{0, 0, 0}
17195bec10aSVikas Gupta };
17295bec10aSVikas Gupta 
17395bec10aSVikas Gupta /* Nitro crash address configuration related macros */
17495bec10aSVikas Gupta #define BNXT_CRASH_INFO_SIGNATURE 0x20524444
17595bec10aSVikas Gupta #define BNXT_CRASH_INFO_VALID 0x1
17695bec10aSVikas Gupta #define MAX_CRASH_ADDR_ITEM 8
17795bec10aSVikas Gupta 
17895bec10aSVikas Gupta struct nitro_crash_addr_item {
17995bec10aSVikas Gupta 	uint32_t info;
18095bec10aSVikas Gupta 	uint32_t size;
18195bec10aSVikas Gupta 	uint32_t addr_hi;
18295bec10aSVikas Gupta 	uint32_t addr_lo;
18395bec10aSVikas Gupta };
18495bec10aSVikas Gupta 
18595bec10aSVikas Gupta struct nitro_crash_addr_info {
18695bec10aSVikas Gupta 	/* CRC of the struct content, starting at next field. */
18795bec10aSVikas Gupta 	uint32_t crc;
18895bec10aSVikas Gupta 	uint32_t signature;
18995bec10aSVikas Gupta 	uint32_t version;
19095bec10aSVikas Gupta 	struct nitro_crash_addr_item table[MAX_CRASH_ADDR_ITEM];
19195bec10aSVikas Gupta };
19295bec10aSVikas Gupta 
memcpy32_helper(uintptr_t src,uintptr_t dst,uint32_t entries,int inc_src_addr)19395bec10aSVikas Gupta static inline void memcpy32_helper(uintptr_t src,
19495bec10aSVikas Gupta 				   uintptr_t dst,
19595bec10aSVikas Gupta 				   uint32_t entries,
19695bec10aSVikas Gupta 				   int inc_src_addr)
19795bec10aSVikas Gupta {
19895bec10aSVikas Gupta 	uint32_t copied_entries = 0;
19995bec10aSVikas Gupta 
20095bec10aSVikas Gupta 	while (entries) {
20195bec10aSVikas Gupta 		copied_entries = bnxt_write32_multiple(dst, src, entries,
20295bec10aSVikas Gupta 						       inc_src_addr);
20395bec10aSVikas Gupta 
20495bec10aSVikas Gupta 		if (copied_entries < entries) {
20595bec10aSVikas Gupta 			dst += copied_entries * sizeof(uint32_t);
20695bec10aSVikas Gupta 			src += (inc_src_addr) ?
20795bec10aSVikas Gupta 				(copied_entries * sizeof(uint32_t)) : 0;
20895bec10aSVikas Gupta 			entries -= copied_entries;
20995bec10aSVikas Gupta 		} else {
21095bec10aSVikas Gupta 			entries = 0;
21195bec10aSVikas Gupta 		}
21295bec10aSVikas Gupta 	}
21395bec10aSVikas Gupta }
21495bec10aSVikas Gupta 
ape_host_view_addr_get(uint32_t bnxt_view_addr,uint32_t size)21595bec10aSVikas Gupta static uint32_t ape_host_view_addr_get(uint32_t bnxt_view_addr, uint32_t size)
21695bec10aSVikas Gupta {
21795bec10aSVikas Gupta 	struct ape_mem_region_s *region = ape_mem_regions;
21895bec10aSVikas Gupta 	uint32_t addr = 0;
21995bec10aSVikas Gupta 
22095bec10aSVikas Gupta 	for (; region->size != 0; region++) {
22195bec10aSVikas Gupta 		if (bnxt_view_addr < region->c_base)
22295bec10aSVikas Gupta 			continue;
22395bec10aSVikas Gupta 
22495bec10aSVikas Gupta 		if (bnxt_view_addr >= (region->c_base + region->size))
22595bec10aSVikas Gupta 			continue;
22695bec10aSVikas Gupta 
22795bec10aSVikas Gupta 		if (size > (region->c_base + region->size - bnxt_view_addr)) {
22895bec10aSVikas Gupta 			EMSG("ERROR: 0x%x + 0x%x spans memory boundary",
22995bec10aSVikas Gupta 			     bnxt_view_addr, size);
23095bec10aSVikas Gupta 			break;
23195bec10aSVikas Gupta 		}
23295bec10aSVikas Gupta 
23395bec10aSVikas Gupta 		addr = bnxt_view_addr - region->c_base;
23495bec10aSVikas Gupta 		addr += region->h_base;
23595bec10aSVikas Gupta 		break;
23695bec10aSVikas Gupta 	}
23795bec10aSVikas Gupta 
23895bec10aSVikas Gupta 	return addr;
23995bec10aSVikas Gupta }
24095bec10aSVikas Gupta 
ape_hdr_crc_calc(const struct ape_bin_hdr_s * hdr)24195bec10aSVikas Gupta static uint32_t ape_hdr_crc_calc(const struct ape_bin_hdr_s *hdr)
24295bec10aSVikas Gupta {
24395bec10aSVikas Gupta 	uint32_t crc = 0;
24495bec10aSVikas Gupta 	uint32_t dummy = 0;
24595bec10aSVikas Gupta 
24695bec10aSVikas Gupta 	/* Compute the CRC up to, but not including, the checksum field */
24795bec10aSVikas Gupta 	crc = CRC32(CRC32_INIT_VAL,
24895bec10aSVikas Gupta 		    (const char *)hdr,
24995bec10aSVikas Gupta 		    (uintptr_t)(&hdr->checksum) - (uintptr_t)hdr);
25095bec10aSVikas Gupta 
25195bec10aSVikas Gupta 	/* Compute the CRC with the checksum field zeroed out */
25295bec10aSVikas Gupta 	crc = CRC32(~crc, (const char *)&dummy, sizeof(uint32_t));
25395bec10aSVikas Gupta 
25495bec10aSVikas Gupta 	/*
25595bec10aSVikas Gupta 	 * Compute the remainder part of the image header, i.e., the
25695bec10aSVikas Gupta 	 * section headers
25795bec10aSVikas Gupta 	 */
25895bec10aSVikas Gupta 	crc = CRC32(~crc,
25995bec10aSVikas Gupta 		    (const char *)((uintptr_t)hdr + APE_BIN_HDR_SIZE),
26095bec10aSVikas Gupta 		    hdr->num_total_sections * APE_SECTION_HDR_SIZE);
26195bec10aSVikas Gupta 
26295bec10aSVikas Gupta 	return crc;
26395bec10aSVikas Gupta }
26495bec10aSVikas Gupta 
ape_bin_hdr_valid(const struct ape_bin_hdr_s * hdr)26595bec10aSVikas Gupta static int ape_bin_hdr_valid(const struct ape_bin_hdr_s *hdr)
26695bec10aSVikas Gupta {
26795bec10aSVikas Gupta 	uint32_t checksum = 0;
26895bec10aSVikas Gupta 
26995bec10aSVikas Gupta 	if (!hdr) {
27095bec10aSVikas Gupta 		EMSG("ERROR: no APE image header");
27195bec10aSVikas Gupta 		return BNXT_FAILURE;
27295bec10aSVikas Gupta 	}
27395bec10aSVikas Gupta 
27495bec10aSVikas Gupta 	if (hdr->signature != APE_BIN_HDR_SIGNATURE) {
27595bec10aSVikas Gupta 		EMSG("ERROR: bad APE image signature");
27695bec10aSVikas Gupta 		return BNXT_FAILURE;
27795bec10aSVikas Gupta 	}
27895bec10aSVikas Gupta 
27995bec10aSVikas Gupta 	if (hdr->num_total_sections > APE_IMG_MAX_SECTIONS) {
28095bec10aSVikas Gupta 		EMSG("ERROR: too many sections in APE image");
28195bec10aSVikas Gupta 		return BNXT_FAILURE;
28295bec10aSVikas Gupta 	}
28395bec10aSVikas Gupta 
28495bec10aSVikas Gupta 	checksum = ape_hdr_crc_calc(hdr);
28595bec10aSVikas Gupta 	if (hdr->checksum != checksum) {
28695bec10aSVikas Gupta 		EMSG("ERROR: bad APE header checksum (exp: %x, act: %x)",
28795bec10aSVikas Gupta 		     hdr->checksum, checksum);
28895bec10aSVikas Gupta 		return BNXT_FAILURE;
28995bec10aSVikas Gupta 	}
29095bec10aSVikas Gupta 
29195bec10aSVikas Gupta 	return BNXT_SUCCESS;
29295bec10aSVikas Gupta }
29395bec10aSVikas Gupta 
get_char(uint8_t * inbuf,size_t * inbuf_idx,size_t inbuf_size)29495bec10aSVikas Gupta static int get_char(uint8_t *inbuf, size_t *inbuf_idx, size_t inbuf_size)
29595bec10aSVikas Gupta {
29695bec10aSVikas Gupta 	int c = 0;
29795bec10aSVikas Gupta 
29895bec10aSVikas Gupta 	if (*inbuf_idx >= inbuf_size)
29995bec10aSVikas Gupta 		return EOF;
30095bec10aSVikas Gupta 
30195bec10aSVikas Gupta 	c = inbuf[*inbuf_idx];
30295bec10aSVikas Gupta 	*inbuf_idx += 1;
30395bec10aSVikas Gupta 
30495bec10aSVikas Gupta 	return c;
30595bec10aSVikas Gupta }
30695bec10aSVikas Gupta 
put_char(uint8_t * outbuf,size_t * outbuf_idx,size_t outbuf_size,uint8_t ch)30795bec10aSVikas Gupta static void put_char(uint8_t *outbuf,
30895bec10aSVikas Gupta 		     size_t *outbuf_idx,
30995bec10aSVikas Gupta 		     size_t outbuf_size,
31095bec10aSVikas Gupta 		     uint8_t ch)
31195bec10aSVikas Gupta {
31295bec10aSVikas Gupta 	if (*outbuf_idx >= outbuf_size)
31395bec10aSVikas Gupta 		return;
31495bec10aSVikas Gupta 
31595bec10aSVikas Gupta 	outbuf[*outbuf_idx] = ch;
31695bec10aSVikas Gupta 	*outbuf_idx += 1;
31795bec10aSVikas Gupta }
31895bec10aSVikas Gupta 
ape_section_uncompress(uint8_t * inbuf,size_t inbuf_size,uint8_t * outbuf,size_t outbuf_size)31995bec10aSVikas Gupta static size_t ape_section_uncompress(uint8_t *inbuf,
32095bec10aSVikas Gupta 				     size_t inbuf_size,
32195bec10aSVikas Gupta 				     uint8_t *outbuf,
32295bec10aSVikas Gupta 				     size_t outbuf_size)
32395bec10aSVikas Gupta {
32495bec10aSVikas Gupta 	int i = 0, j = 0, k = 0, r = 0, c = 0;
32595bec10aSVikas Gupta 	uint32_t flags = 0;
32695bec10aSVikas Gupta 	size_t exp_size = 0, codesize = 0;
32795bec10aSVikas Gupta 	size_t inbuf_idx = 0, outbuf_idx = 0;
32895bec10aSVikas Gupta #define CODE_8U_MASK		0xff00u	/* 8 code units count mask (8 bits) */
32995bec10aSVikas Gupta #define CODE_END_MASK		0x100u	/* End of code units mask */
33095bec10aSVikas Gupta #define CODE_IS_UNENCODED_MASK	1	/* Unencoded code unit mask */
33195bec10aSVikas Gupta #define CODE_POS_MASK		0xe0u	/* Encoded unit position mask and */
33295bec10aSVikas Gupta #define CODE_POS_SHIFT		3	/* Bit shift */
33395bec10aSVikas Gupta #define CODE_LEN_MASK		0x1fu	/* Encoded unit length mask */
33495bec10aSVikas Gupta #define NS			2048	/* Size of ring buffer */
33595bec10aSVikas Gupta #define F			34	/* Upper limit for match_length */
33695bec10aSVikas Gupta #define THRESHOLD		2	/* Encode string into position and
33795bec10aSVikas Gupta 					 *   length, if match_length is
33895bec10aSVikas Gupta 					 *   greater than this.
33995bec10aSVikas Gupta 					 */
34095bec10aSVikas Gupta 	/*
34195bec10aSVikas Gupta 	 * Ring buffer of size NS, with an extra F-1 bytes to facilitate
34295bec10aSVikas Gupta 	 * string comparisons.
34395bec10aSVikas Gupta 	 */
34495bec10aSVikas Gupta 	uint8_t text_buf[NS + F - 1];
34595bec10aSVikas Gupta 
34695bec10aSVikas Gupta 	inbuf_idx = 0;
34795bec10aSVikas Gupta 	outbuf_idx = 0;
34895bec10aSVikas Gupta 
34995bec10aSVikas Gupta 	for (i = 0; i < NS - F; i++)
35095bec10aSVikas Gupta 		text_buf[i] = ' ';
35195bec10aSVikas Gupta 
35295bec10aSVikas Gupta 	r = NS - F;
35395bec10aSVikas Gupta 
35495bec10aSVikas Gupta 	for (;;) {
35595bec10aSVikas Gupta 		if (((flags >>= 1) & CODE_END_MASK) == 0) {
35695bec10aSVikas Gupta 			c = get_char(inbuf, &inbuf_idx, inbuf_size);
35795bec10aSVikas Gupta 			if (c == EOF)
35895bec10aSVikas Gupta 				break;
35995bec10aSVikas Gupta 			++exp_size;
36095bec10aSVikas Gupta 
36195bec10aSVikas Gupta 			if (exp_size > inbuf_size)
36295bec10aSVikas Gupta 				break;
36395bec10aSVikas Gupta 
36495bec10aSVikas Gupta 			/* Use higher byte cleverly to count to eight */
36595bec10aSVikas Gupta 			flags = c | CODE_8U_MASK;
36695bec10aSVikas Gupta 		}
36795bec10aSVikas Gupta 
36895bec10aSVikas Gupta 		if (flags & CODE_IS_UNENCODED_MASK) {
36995bec10aSVikas Gupta 			/* Not encoded; simply copy the unit */
37095bec10aSVikas Gupta 			c = get_char(inbuf, &inbuf_idx, inbuf_size);
37195bec10aSVikas Gupta 			if (c == EOF)
37295bec10aSVikas Gupta 				break;
37395bec10aSVikas Gupta 
37495bec10aSVikas Gupta 			++exp_size;
37595bec10aSVikas Gupta 			if (exp_size > inbuf_size)
37695bec10aSVikas Gupta 				break;
37795bec10aSVikas Gupta 
37895bec10aSVikas Gupta 			put_char(outbuf, &outbuf_idx, outbuf_size, c);
37995bec10aSVikas Gupta 			text_buf[r++] = c;
38095bec10aSVikas Gupta 			r &= (NS - 1);
38195bec10aSVikas Gupta 			++codesize;
38295bec10aSVikas Gupta 		} else {
38395bec10aSVikas Gupta 			/* Encoded; get the position and length & duplicate */
38495bec10aSVikas Gupta 			i = get_char(inbuf, &inbuf_idx, inbuf_size);
38595bec10aSVikas Gupta 			if (i == EOF)
38695bec10aSVikas Gupta 				break;
38795bec10aSVikas Gupta 
38895bec10aSVikas Gupta 			++exp_size;
38995bec10aSVikas Gupta 			if (exp_size > inbuf_size)
39095bec10aSVikas Gupta 				break;
39195bec10aSVikas Gupta 
39295bec10aSVikas Gupta 			j = get_char(inbuf, &inbuf_idx, inbuf_size);
39395bec10aSVikas Gupta 			if (j == EOF)
39495bec10aSVikas Gupta 				break;
39595bec10aSVikas Gupta 
39695bec10aSVikas Gupta 			++exp_size;
39795bec10aSVikas Gupta 			if (exp_size > inbuf_size)
39895bec10aSVikas Gupta 				break;
39995bec10aSVikas Gupta 
40095bec10aSVikas Gupta 			i |= ((j & CODE_POS_MASK) << CODE_POS_SHIFT);
40195bec10aSVikas Gupta 			j = ((j & CODE_LEN_MASK) + THRESHOLD);
40295bec10aSVikas Gupta 
40395bec10aSVikas Gupta 			for (k = 0; k <= j; k++) {
40495bec10aSVikas Gupta 				c = text_buf[((i + k) & (NS - 1))];
40595bec10aSVikas Gupta 				put_char(outbuf, &outbuf_idx, outbuf_size, c);
40695bec10aSVikas Gupta 				text_buf[r++] = c;
40795bec10aSVikas Gupta 				r &= (NS - 1);
40895bec10aSVikas Gupta 				++codesize;
40995bec10aSVikas Gupta 			}
41095bec10aSVikas Gupta 		}
41195bec10aSVikas Gupta 	}
41295bec10aSVikas Gupta 
41395bec10aSVikas Gupta 	return codesize;
41495bec10aSVikas Gupta }
41595bec10aSVikas Gupta 
ape_section_copy(struct ape_bin_hdr_s * bin_hdr,struct ape_section_hdr_s * section)41695bec10aSVikas Gupta static int ape_section_copy(struct ape_bin_hdr_s *bin_hdr,
41795bec10aSVikas Gupta 			    struct ape_section_hdr_s *section)
41895bec10aSVikas Gupta {
41995bec10aSVikas Gupta 	uintptr_t src = 0;
42095bec10aSVikas Gupta 	uintptr_t dst = 0;
42195bec10aSVikas Gupta 	uint32_t checksum = 0;
42295bec10aSVikas Gupta 	uint32_t i = 0;
42395bec10aSVikas Gupta 	size_t size = 0;
42495bec10aSVikas Gupta 	uint8_t *section_data = NULL;
42595bec10aSVikas Gupta 	size_t work_buff_size = 0;
42695bec10aSVikas Gupta 	void *work_buff = NULL;
42795bec10aSVikas Gupta 	int rc = BNXT_FAILURE;
42895bec10aSVikas Gupta 
42995bec10aSVikas Gupta 	if (SECTION_IS_ZIPPED(section)) {
43095bec10aSVikas Gupta 		work_buff_size = section->org_data_len + BUFFER_PADDING;
431c2e4eb43SAnton Rybakov 		work_buff = (void *)phys_to_virt(TEMP_MEM, MEM_AREA_RAM_SEC,
432c2e4eb43SAnton Rybakov 						 work_buff_size);
43395bec10aSVikas Gupta 		if (!work_buff) {
43495bec10aSVikas Gupta 			EMSG("ERROR: buffer allocation");
43595bec10aSVikas Gupta 			return BNXT_FAILURE;
43695bec10aSVikas Gupta 		}
43795bec10aSVikas Gupta 
43895bec10aSVikas Gupta 		section_data = (uint8_t *)((uintptr_t)bin_hdr +
43995bec10aSVikas Gupta 					   SECTION_SRC_OFFSET(section));
44095bec10aSVikas Gupta 		size = ape_section_uncompress(section_data,
44195bec10aSVikas Gupta 					      section->zip_data_len,
44295bec10aSVikas Gupta 					      work_buff,
44395bec10aSVikas Gupta 					      work_buff_size);
44495bec10aSVikas Gupta 		if (size >= work_buff_size) {
44595bec10aSVikas Gupta 			EMSG("ERROR: section uncompress");
44695bec10aSVikas Gupta 			goto ape_section_copy_exit;
44795bec10aSVikas Gupta 		}
44895bec10aSVikas Gupta 		if (size < section->org_data_len) {
44995bec10aSVikas Gupta 			EMSG("ERROR: decompressed data size mismatch ");
45095bec10aSVikas Gupta 			EMSG("(exp: %d, act: %ld)",
45195bec10aSVikas Gupta 			     section->org_data_len, size);
45295bec10aSVikas Gupta 			goto ape_section_copy_exit;
45395bec10aSVikas Gupta 		}
45495bec10aSVikas Gupta 		src = (uintptr_t)work_buff;
45595bec10aSVikas Gupta 	} else {
45695bec10aSVikas Gupta 		src = (uintptr_t)bin_hdr + SECTION_SRC_OFFSET(section);
45795bec10aSVikas Gupta 	}
45895bec10aSVikas Gupta 
45995bec10aSVikas Gupta 	size = section->org_data_len;
46095bec10aSVikas Gupta 
46195bec10aSVikas Gupta 	if (section->flags_src_offset & SECTION_FLAGS_IS_CRC) {
46295bec10aSVikas Gupta 		checksum = CRC32(CRC32_INIT_VAL, (const char *)src, size);
46395bec10aSVikas Gupta 	} else {
46495bec10aSVikas Gupta 		checksum = 0;
46595bec10aSVikas Gupta 		for (i = 0; i < size / sizeof(uint32_t); i++)
46695bec10aSVikas Gupta 			checksum += ((uint32_t *)src)[i];
46795bec10aSVikas Gupta 	}
46895bec10aSVikas Gupta 	if (checksum != section->checksum) {
46995bec10aSVikas Gupta 		EMSG("ERROR: checksum mismatch (exp: %x, act: %x)",
47095bec10aSVikas Gupta 		     section->checksum, checksum);
47195bec10aSVikas Gupta 		goto ape_section_copy_exit;
47295bec10aSVikas Gupta 	}
47395bec10aSVikas Gupta 
47495bec10aSVikas Gupta 	dst = ape_host_view_addr_get(section->dest_addr, size);
47595bec10aSVikas Gupta 	if (dst == 0) {
47695bec10aSVikas Gupta 		EMSG("ERROR: ChiMP-to-host address conversion of %x",
47795bec10aSVikas Gupta 		     section->dest_addr);
47895bec10aSVikas Gupta 		goto ape_section_copy_exit;
47995bec10aSVikas Gupta 	}
48095bec10aSVikas Gupta 
48195bec10aSVikas Gupta 	/* Copy the section */
48295bec10aSVikas Gupta 	size = size / sizeof(uint32_t);
48395bec10aSVikas Gupta 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
48495bec10aSVikas Gupta 
48595bec10aSVikas Gupta 	rc = BNXT_SUCCESS;
48695bec10aSVikas Gupta 
48795bec10aSVikas Gupta ape_section_copy_exit:
48895bec10aSVikas Gupta 	return rc;
48995bec10aSVikas Gupta }
49095bec10aSVikas Gupta 
ape_section_zero(struct ape_section_hdr_s * section)49195bec10aSVikas Gupta static int ape_section_zero(struct ape_section_hdr_s *section)
49295bec10aSVikas Gupta {
49395bec10aSVikas Gupta 	uint32_t dst = 0;
49495bec10aSVikas Gupta 	uint32_t size = section->org_data_len;
49595bec10aSVikas Gupta 	uint32_t zero = 0;
49695bec10aSVikas Gupta 
49795bec10aSVikas Gupta 	if (section->org_data_len == 0)
49895bec10aSVikas Gupta 		return BNXT_SUCCESS;
49995bec10aSVikas Gupta 
50095bec10aSVikas Gupta 	/* Convert ChiMP's view of the address in the image to the host view */
50195bec10aSVikas Gupta 	dst = ape_host_view_addr_get(section->dest_addr, size);
50295bec10aSVikas Gupta 	if (dst == 0) {
50395bec10aSVikas Gupta 		EMSG("ERROR: ChiMP-to-host address conversion of %x",
50495bec10aSVikas Gupta 		     section->dest_addr);
50595bec10aSVikas Gupta 		return BNXT_FAILURE;
50695bec10aSVikas Gupta 	}
50795bec10aSVikas Gupta 
50895bec10aSVikas Gupta 	/*
50995bec10aSVikas Gupta 	 * Zero the section; we simply copy zeros and do not increment the
51095bec10aSVikas Gupta 	 * source buffer address.
51195bec10aSVikas Gupta 	 */
51295bec10aSVikas Gupta 	size = size / sizeof(uint32_t);
51395bec10aSVikas Gupta 	memcpy32_helper((uintptr_t)&zero, dst, size, !INC_SRC_ADDR);
51495bec10aSVikas Gupta 
51595bec10aSVikas Gupta 	return BNXT_SUCCESS;
51695bec10aSVikas Gupta }
51795bec10aSVikas Gupta 
bnxt_load(vaddr_t img_buffer)51895bec10aSVikas Gupta static int bnxt_load(vaddr_t img_buffer)
51995bec10aSVikas Gupta {
52095bec10aSVikas Gupta 	struct ape_bin_hdr_s *bin_hdr = NULL;
52195bec10aSVikas Gupta 	struct ape_section_hdr_s *section = NULL;
52295bec10aSVikas Gupta 	int sidx = 0;
52395bec10aSVikas Gupta 	int rc = BNXT_SUCCESS;
52495bec10aSVikas Gupta 
52595bec10aSVikas Gupta 	bin_hdr = (struct ape_bin_hdr_s *)img_buffer;
52695bec10aSVikas Gupta 	section = (struct ape_section_hdr_s *)(img_buffer +
52795bec10aSVikas Gupta 					       APE_BIN_HDR_SIZE);
52895bec10aSVikas Gupta 
52995bec10aSVikas Gupta 	if (ape_bin_hdr_valid(bin_hdr) != BNXT_SUCCESS)
53095bec10aSVikas Gupta 		return BNXT_FAILURE;
53195bec10aSVikas Gupta 
53295bec10aSVikas Gupta 	for (sidx = 0; sidx < bin_hdr->num_total_sections; sidx++, section++) {
53395bec10aSVikas Gupta 		if (!SECTION_IS_LOADABLE(section))
53495bec10aSVikas Gupta 			continue;
53595bec10aSVikas Gupta 
53695bec10aSVikas Gupta 		if (!ADDR_IS_4BYTE_ALIGNED(section->dest_addr)) {
53795bec10aSVikas Gupta 			EMSG("ERROR: unaligned section dest address 0x%x",
53895bec10aSVikas Gupta 			     section->dest_addr);
53995bec10aSVikas Gupta 			rc = BNXT_FAILURE;
54095bec10aSVikas Gupta 			break;
54195bec10aSVikas Gupta 		}
54295bec10aSVikas Gupta 
54395bec10aSVikas Gupta 		if (!ADDR_IS_4BYTE_ALIGNED(SECTION_SRC_OFFSET(section))) {
54495bec10aSVikas Gupta 			EMSG("ERROR: unaligned section src offset (0x%x)",
54595bec10aSVikas Gupta 			     SECTION_SRC_OFFSET(section));
54695bec10aSVikas Gupta 			rc = BNXT_FAILURE;
54795bec10aSVikas Gupta 			break;
54895bec10aSVikas Gupta 		}
54995bec10aSVikas Gupta 
55095bec10aSVikas Gupta 		if (section->org_data_len % sizeof(uint32_t)) {
55195bec10aSVikas Gupta 			EMSG("ERROR: section size (%d) not divisible by 4",
55295bec10aSVikas Gupta 			     section->org_data_len);
55395bec10aSVikas Gupta 			rc = BNXT_FAILURE;
55495bec10aSVikas Gupta 			break;
55595bec10aSVikas Gupta 		}
55695bec10aSVikas Gupta 
55795bec10aSVikas Gupta 		if (SECTION_IS_TOBE_COPIED(section)) {
55895bec10aSVikas Gupta 			rc = ape_section_copy(bin_hdr, section);
55995bec10aSVikas Gupta 			if (rc != BNXT_SUCCESS)
56095bec10aSVikas Gupta 				break;
56195bec10aSVikas Gupta 		} else if (SECTION_IS_TOBE_ZEROED(section)) {
56295bec10aSVikas Gupta 			rc = ape_section_zero(section);
56395bec10aSVikas Gupta 			if (rc != BNXT_SUCCESS)
56495bec10aSVikas Gupta 				break;
56595bec10aSVikas Gupta 		}
56695bec10aSVikas Gupta 	}
56795bec10aSVikas Gupta 
56895bec10aSVikas Gupta 	/* Set up boot mode and take BNXT out of reset */
56995bec10aSVikas Gupta 	if (rc == BNXT_SUCCESS) {
57095bec10aSVikas Gupta 		bnxt_fastboot((bin_hdr->entry_address &
57195bec10aSVikas Gupta 			       ~BCM_BNXT_FASTBOOT_MASK) |
57295bec10aSVikas Gupta 			       BCM_BNXT_FASTBOOT_TYPE_1);
57395bec10aSVikas Gupta 	}
57495bec10aSVikas Gupta 
57595bec10aSVikas Gupta 	return rc;
57695bec10aSVikas Gupta }
57795bec10aSVikas Gupta 
bnxt_crash_config(uintptr_t info_dst,uint32_t crash_area_start,uint32_t crash_len)57895bec10aSVikas Gupta static TEE_Result bnxt_crash_config(uintptr_t info_dst,
57995bec10aSVikas Gupta 				    uint32_t crash_area_start,
58095bec10aSVikas Gupta 				    uint32_t crash_len)
58195bec10aSVikas Gupta {
58295bec10aSVikas Gupta 	struct nitro_crash_addr_item *item = NULL;
58395bec10aSVikas Gupta 	uintptr_t dst = 0;
58495bec10aSVikas Gupta 	struct nitro_crash_addr_info *info = NULL;
58595bec10aSVikas Gupta 	uintptr_t src = 0;
58695bec10aSVikas Gupta 	uint32_t crc = 0;
58795bec10aSVikas Gupta 	size_t size = 0;
58895bec10aSVikas Gupta 
58995bec10aSVikas Gupta 	/*
59095bec10aSVikas Gupta 	 * First we write into local memory to calculate CRC before
59195bec10aSVikas Gupta 	 * updating into Nitro memory
59295bec10aSVikas Gupta 	 */
59395bec10aSVikas Gupta 	info = malloc(sizeof(struct nitro_crash_addr_info));
59495bec10aSVikas Gupta 	if (!info) {
59595bec10aSVikas Gupta 		EMSG("ERROR: buffer allocation");
59695bec10aSVikas Gupta 		return TEE_ERROR_OUT_OF_MEMORY;
59795bec10aSVikas Gupta 	}
59895bec10aSVikas Gupta 
59995bec10aSVikas Gupta 	memset(info, 0, sizeof(struct nitro_crash_addr_info));
60095bec10aSVikas Gupta 
60195bec10aSVikas Gupta 	info->signature = BNXT_CRASH_INFO_SIGNATURE;
60295bec10aSVikas Gupta 	info->version = 0x01000000 | MAX_CRASH_ADDR_ITEM;
60395bec10aSVikas Gupta 
60495bec10aSVikas Gupta 	/* As of now only one item is filled */
60595bec10aSVikas Gupta 	item = &info->table[0];
60695bec10aSVikas Gupta 	item->info = 0;
60795bec10aSVikas Gupta 	item->size = crash_len | BNXT_CRASH_INFO_VALID;
60895bec10aSVikas Gupta 	item->addr_hi = 0;
60995bec10aSVikas Gupta 	item->addr_lo = crash_area_start;
61095bec10aSVikas Gupta 
61195bec10aSVikas Gupta 	/* Checksum calculation  */
61295bec10aSVikas Gupta 	crc = CRC32(CRC32_INIT_VAL,
61395bec10aSVikas Gupta 		    (const char *)info + sizeof(uint32_t),
61495bec10aSVikas Gupta 		     sizeof(struct nitro_crash_addr_info) - sizeof(uint32_t));
61595bec10aSVikas Gupta 	info->crc = crc;
61695bec10aSVikas Gupta 
61795bec10aSVikas Gupta 	/* First we write the contents and then set valid bit */
61895bec10aSVikas Gupta 	item->size &= ~BNXT_CRASH_INFO_VALID;
61995bec10aSVikas Gupta 
62095bec10aSVikas Gupta 	size = sizeof(struct nitro_crash_addr_info) / sizeof(uint32_t);
62195bec10aSVikas Gupta 	dst = info_dst;
62295bec10aSVikas Gupta 	src = (uintptr_t)info;
62395bec10aSVikas Gupta 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
62495bec10aSVikas Gupta 
62595bec10aSVikas Gupta 	/* Set the valid bit */
62695bec10aSVikas Gupta 	item->size |= BNXT_CRASH_INFO_VALID;
62795bec10aSVikas Gupta 	dst = info_dst + offsetof(struct nitro_crash_addr_info, table) +
62895bec10aSVikas Gupta 	      offsetof(struct nitro_crash_addr_item, size);
62995bec10aSVikas Gupta 	bnxt_write32_multiple(dst, (uintptr_t)&item->size, 1, 1);
63095bec10aSVikas Gupta 
63195bec10aSVikas Gupta 	free(info);
63295bec10aSVikas Gupta 
63395bec10aSVikas Gupta 	return TEE_SUCCESS;
63495bec10aSVikas Gupta }
63595bec10aSVikas Gupta 
bnxt_load_fw(int chip_type)63695bec10aSVikas Gupta TEE_Result bnxt_load_fw(int chip_type)
63795bec10aSVikas Gupta {
63895bec10aSVikas Gupta 	uint32_t size = 0;
63995bec10aSVikas Gupta 	uintptr_t dst = 0;
64095bec10aSVikas Gupta 	uintptr_t src = 0;
64195bec10aSVikas Gupta 	struct bnxt_images_info bnxt_src_image_info;
6425f2bc144SVikas Gupta 	vaddr_t sec_mem_dest = (vaddr_t)phys_to_virt(BNXT_BUFFER_SEC_MEM,
643c2e4eb43SAnton Rybakov 						     MEM_AREA_RAM_SEC, 1);
64495bec10aSVikas Gupta 
64595bec10aSVikas Gupta 	memset(&bnxt_src_image_info, 0, sizeof(struct bnxt_images_info));
64695bec10aSVikas Gupta 
6475f2bc144SVikas Gupta 	if (get_bnxt_images_info(&bnxt_src_image_info,
6485f2bc144SVikas Gupta 				 chip_type, sec_mem_dest) != BNXT_SUCCESS)
64995bec10aSVikas Gupta 		return TEE_ERROR_ITEM_NOT_FOUND;
65095bec10aSVikas Gupta 
6519b726349SSheetal Tigadoli 	bnxt_handshake_clear();
65295bec10aSVikas Gupta 	bnxt_kong_halt();
65395bec10aSVikas Gupta 	bnxt_chimp_halt();
65495bec10aSVikas Gupta 
65595bec10aSVikas Gupta 	/* Copy the configs */
65695bec10aSVikas Gupta 	src = (uintptr_t)bnxt_src_image_info.bnxt_cfg_vaddr;
65795bec10aSVikas Gupta 	dst = (uintptr_t)BNXT_CONFIG_NS3_DEST;
65895bec10aSVikas Gupta 	size = bnxt_src_image_info.bnxt_cfg_len;
65995bec10aSVikas Gupta 	size = size / sizeof(uint32_t);
66095bec10aSVikas Gupta 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
66195bec10aSVikas Gupta 
66295bec10aSVikas Gupta 	/* Copy bspd config */
66395bec10aSVikas Gupta 	src = (uintptr_t)bnxt_src_image_info.bnxt_bspd_cfg_vaddr;
66495bec10aSVikas Gupta 	size = bnxt_src_image_info.bnxt_bspd_cfg_len;
66595bec10aSVikas Gupta 	dst = (uintptr_t)BNXT_CONFIG_NS3_BSPD_DEST;
66695bec10aSVikas Gupta 
66795bec10aSVikas Gupta 	size = size / sizeof(uint32_t);
66895bec10aSVikas Gupta 	memcpy32_helper(src, dst, size, INC_SRC_ADDR);
66995bec10aSVikas Gupta 
67095bec10aSVikas Gupta 	/* Fill the bnxt crash dump info */
67195bec10aSVikas Gupta 	bnxt_crash_config((uintptr_t)BNXT_CRASH_DUMP_INFO_NS3_BASE,
67295bec10aSVikas Gupta 			  BNXT_CRASH_SEC_MEM,
67395bec10aSVikas Gupta 			  BNXT_CRASH_LEN);
67495bec10aSVikas Gupta 
67595bec10aSVikas Gupta 	/* Load bnxt firmware and fastboot */
67695bec10aSVikas Gupta 	bnxt_load(bnxt_src_image_info.bnxt_fw_vaddr);
67795bec10aSVikas Gupta 
6789b726349SSheetal Tigadoli 	return TEE_SUCCESS;
6799b726349SSheetal Tigadoli }
6809b726349SSheetal Tigadoli 
bnxt_copy_crash_dump(uint8_t * d,uint32_t offset,uint32_t len)6819b726349SSheetal Tigadoli TEE_Result bnxt_copy_crash_dump(uint8_t *d, uint32_t offset, uint32_t len)
6829b726349SSheetal Tigadoli {
683b5735546SJens Wiklander 	size_t crash_len = 0;
6849b726349SSheetal Tigadoli 	void *s = NULL;
6859b726349SSheetal Tigadoli 
686b5735546SJens Wiklander 	if (ADD_OVERFLOW(offset, len, &crash_len) ||
687b5735546SJens Wiklander 	    crash_len > BNXT_CRASH_LEN)
6889b726349SSheetal Tigadoli 		return TEE_ERROR_BAD_PARAMETERS;
6899b726349SSheetal Tigadoli 
690c2e4eb43SAnton Rybakov 	s = phys_to_virt(BNXT_CRASH_SEC_MEM + offset, MEM_AREA_RAM_SEC, len);
6919b726349SSheetal Tigadoli 
6929b726349SSheetal Tigadoli 	cache_op_inner(DCACHE_AREA_INVALIDATE, s, len);
6939b726349SSheetal Tigadoli 
6949b726349SSheetal Tigadoli 	memcpy(d, s, len);
69595bec10aSVikas Gupta 
69695bec10aSVikas Gupta 	return TEE_SUCCESS;
69795bec10aSVikas Gupta }
698