xref: /optee_os/core/pta/bcm/elog.c (revision e605fbdfd7a0a046e686222e857192bc97c070fd)
1*e605fbdfSSheetal Tigadoli // SPDX-License-Identifier: BSD-2-Clause
2*e605fbdfSSheetal Tigadoli /*
3*e605fbdfSSheetal Tigadoli  * Copyright 2019 Broadcom.
4*e605fbdfSSheetal Tigadoli  */
5*e605fbdfSSheetal Tigadoli 
6*e605fbdfSSheetal Tigadoli #include <drivers/bcm/bnxt.h>
7*e605fbdfSSheetal Tigadoli #include <io.h>
8*e605fbdfSSheetal Tigadoli #include <kernel/pseudo_ta.h>
9*e605fbdfSSheetal Tigadoli #include <mm/core_memprot.h>
10*e605fbdfSSheetal Tigadoli #include <mm/core_mmu.h>
11*e605fbdfSSheetal Tigadoli #include <string.h>
12*e605fbdfSSheetal Tigadoli #include <trace.h>
13*e605fbdfSSheetal Tigadoli 
14*e605fbdfSSheetal Tigadoli #define ELOG_SERVICE_UUID \
15*e605fbdfSSheetal Tigadoli 		{ 0x6272636D, 0x2019, 0x0701, \
16*e605fbdfSSheetal Tigadoli 		{ 0x42, 0x43, 0x4D, 0x5F, 0x45, 0x4C, 0x4F, 0x47 } }
17*e605fbdfSSheetal Tigadoli 
18*e605fbdfSSheetal Tigadoli #define ELOG_TA_NAME			"pta_bcm_elog.ta"
19*e605fbdfSSheetal Tigadoli 
20*e605fbdfSSheetal Tigadoli #define BCM_NITRO_FW_LOAD_ADDR			0x8ae00000
21*e605fbdfSSheetal Tigadoli #define BCM_NITRO_CRASH_DUMP_BASE_ADDR		0x8b000000
22*e605fbdfSSheetal Tigadoli 
23*e605fbdfSSheetal Tigadoli /* Default ELOG buffer size 1MB */
24*e605fbdfSSheetal Tigadoli #define DEFAULT_ELOG_BUFFER_SIZE		0x100000
25*e605fbdfSSheetal Tigadoli 
26*e605fbdfSSheetal Tigadoli /*
27*e605fbdfSSheetal Tigadoli  * Get Error log memory dump
28*e605fbdfSSheetal Tigadoli  *
29*e605fbdfSSheetal Tigadoli  * [out]    memref[0]:    Destination
30*e605fbdfSSheetal Tigadoli  * [in]     value[1].a:   Offset
31*e605fbdfSSheetal Tigadoli  */
32*e605fbdfSSheetal Tigadoli #define PTA_BCM_ELOG_CMD_GET_ELOG_MEM		1
33*e605fbdfSSheetal Tigadoli 
34*e605fbdfSSheetal Tigadoli /*
35*e605fbdfSSheetal Tigadoli  * Get nitro crash_dump memory
36*e605fbdfSSheetal Tigadoli  *
37*e605fbdfSSheetal Tigadoli  * [out]    memref[0]:    Destination
38*e605fbdfSSheetal Tigadoli  * [in]     value[1].a:   Offset
39*e605fbdfSSheetal Tigadoli  */
40*e605fbdfSSheetal Tigadoli #define PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP	2
41*e605fbdfSSheetal Tigadoli 
42*e605fbdfSSheetal Tigadoli /*
43*e605fbdfSSheetal Tigadoli  * Load nitro firmware memory
44*e605fbdfSSheetal Tigadoli  *
45*e605fbdfSSheetal Tigadoli  * [in]     memref[0]:    Nitro f/w image data
46*e605fbdfSSheetal Tigadoli  * [in]     value[1].a:   Offset for loading f/w image
47*e605fbdfSSheetal Tigadoli  * [in]     value[2].a:   Firmware image size
48*e605fbdfSSheetal Tigadoli  */
49*e605fbdfSSheetal Tigadoli #define PTA_BCM_ELOG_CMD_LOAD_NITRO_FW		3
50*e605fbdfSSheetal Tigadoli 
51*e605fbdfSSheetal Tigadoli #define BCM_ELOG_GLOBAL_METADATA_SIG		0x45524c47
52*e605fbdfSSheetal Tigadoli 
53*e605fbdfSSheetal Tigadoli #define MAX_NITRO_CRASH_DUMP_MEM_SIZE		0x2000000
54*e605fbdfSSheetal Tigadoli #define MAX_NITRO_FW_LOAD_MEM_SIZE		0x200000
55*e605fbdfSSheetal Tigadoli 
56*e605fbdfSSheetal Tigadoli /* Load Nitro fw image to SEC DDR memory */
57*e605fbdfSSheetal Tigadoli static TEE_Result pta_elog_load_nitro_fw(uint32_t param_types,
58*e605fbdfSSheetal Tigadoli 					 TEE_Param params[TEE_NUM_PARAMS])
59*e605fbdfSSheetal Tigadoli {
60*e605fbdfSSheetal Tigadoli 	TEE_Result res = TEE_SUCCESS;
61*e605fbdfSSheetal Tigadoli 	paddr_t src_paddr = BCM_NITRO_FW_LOAD_ADDR + BNXT_IMG_SECMEM_OFFSET;
62*e605fbdfSSheetal Tigadoli 	vaddr_t src_vaddr = 0;
63*e605fbdfSSheetal Tigadoli 	uint32_t offset = 0, sz = 0;
64*e605fbdfSSheetal Tigadoli 	char *buf = NULL;
65*e605fbdfSSheetal Tigadoli 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
66*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_VALUE_INPUT,
67*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_VALUE_INPUT,
68*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE);
69*e605fbdfSSheetal Tigadoli 
70*e605fbdfSSheetal Tigadoli 	if (exp_param_types != param_types) {
71*e605fbdfSSheetal Tigadoli 		EMSG("Invalid Param types");
72*e605fbdfSSheetal Tigadoli 		return TEE_ERROR_BAD_PARAMETERS;
73*e605fbdfSSheetal Tigadoli 	}
74*e605fbdfSSheetal Tigadoli 
75*e605fbdfSSheetal Tigadoli 	/* Check if firmware file size exceeds reserved memory size */
76*e605fbdfSSheetal Tigadoli 	if (params[2].value.a > MAX_NITRO_FW_LOAD_MEM_SIZE) {
77*e605fbdfSSheetal Tigadoli 		EMSG("Invalid access");
78*e605fbdfSSheetal Tigadoli 		return TEE_ERROR_EXCESS_DATA;
79*e605fbdfSSheetal Tigadoli 	}
80*e605fbdfSSheetal Tigadoli 
81*e605fbdfSSheetal Tigadoli 	offset = params[1].value.a;
82*e605fbdfSSheetal Tigadoli 
83*e605fbdfSSheetal Tigadoli 	/*
84*e605fbdfSSheetal Tigadoli 	 * Check if offset is within memory range reserved for nitro firmware
85*e605fbdfSSheetal Tigadoli 	 * minus default size of buffer
86*e605fbdfSSheetal Tigadoli 	 */
87*e605fbdfSSheetal Tigadoli 	if (offset > MAX_NITRO_FW_LOAD_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) {
88*e605fbdfSSheetal Tigadoli 		EMSG("Invalid access");
89*e605fbdfSSheetal Tigadoli 		return TEE_ERROR_ACCESS_DENIED;
90*e605fbdfSSheetal Tigadoli 	}
91*e605fbdfSSheetal Tigadoli 
92*e605fbdfSSheetal Tigadoli 	src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset,
93*e605fbdfSSheetal Tigadoli 					  MEM_AREA_RAM_SEC);
94*e605fbdfSSheetal Tigadoli 
95*e605fbdfSSheetal Tigadoli 	buf = params[0].memref.buffer;
96*e605fbdfSSheetal Tigadoli 	sz = params[0].memref.size;
97*e605fbdfSSheetal Tigadoli 
98*e605fbdfSSheetal Tigadoli 	memcpy((char *)src_vaddr, buf, sz);
99*e605fbdfSSheetal Tigadoli 
100*e605fbdfSSheetal Tigadoli 	cache_op_inner(DCACHE_AREA_CLEAN, (void *)src_vaddr, sz);
101*e605fbdfSSheetal Tigadoli 
102*e605fbdfSSheetal Tigadoli 	return res;
103*e605fbdfSSheetal Tigadoli }
104*e605fbdfSSheetal Tigadoli 
105*e605fbdfSSheetal Tigadoli static uint32_t get_dump_data(vaddr_t src, TEE_Param params[TEE_NUM_PARAMS])
106*e605fbdfSSheetal Tigadoli {
107*e605fbdfSSheetal Tigadoli 	char *buf = NULL;
108*e605fbdfSSheetal Tigadoli 	uint32_t sz = 0;
109*e605fbdfSSheetal Tigadoli 
110*e605fbdfSSheetal Tigadoli 	buf = params[0].memref.buffer;
111*e605fbdfSSheetal Tigadoli 	sz = params[0].memref.size;
112*e605fbdfSSheetal Tigadoli 
113*e605fbdfSSheetal Tigadoli 	/*
114*e605fbdfSSheetal Tigadoli 	 * If request size exceeds default buf size
115*e605fbdfSSheetal Tigadoli 	 * override request size to default DEFAULT_ELOG_BUFFER_SIZE
116*e605fbdfSSheetal Tigadoli 	 */
117*e605fbdfSSheetal Tigadoli 	if (sz > DEFAULT_ELOG_BUFFER_SIZE)
118*e605fbdfSSheetal Tigadoli 		sz = DEFAULT_ELOG_BUFFER_SIZE;
119*e605fbdfSSheetal Tigadoli 
120*e605fbdfSSheetal Tigadoli 	DMSG("buf %p sz 0x%x", buf, sz);
121*e605fbdfSSheetal Tigadoli 
122*e605fbdfSSheetal Tigadoli 	memcpy(buf, (char *)src, sz);
123*e605fbdfSSheetal Tigadoli 
124*e605fbdfSSheetal Tigadoli 	params[0].memref.size = sz;
125*e605fbdfSSheetal Tigadoli 
126*e605fbdfSSheetal Tigadoli 	return sz;
127*e605fbdfSSheetal Tigadoli }
128*e605fbdfSSheetal Tigadoli 
129*e605fbdfSSheetal Tigadoli /* Copy nitro crash dump data */
130*e605fbdfSSheetal Tigadoli static TEE_Result pta_elog_nitro_crash_dump(uint32_t param_types,
131*e605fbdfSSheetal Tigadoli 					    TEE_Param params[TEE_NUM_PARAMS])
132*e605fbdfSSheetal Tigadoli {
133*e605fbdfSSheetal Tigadoli 	TEE_Result res = TEE_SUCCESS;
134*e605fbdfSSheetal Tigadoli 	paddr_t src_paddr = BCM_NITRO_CRASH_DUMP_BASE_ADDR;
135*e605fbdfSSheetal Tigadoli 	vaddr_t src_vaddr = 0;
136*e605fbdfSSheetal Tigadoli 	uint32_t offset = 0;
137*e605fbdfSSheetal Tigadoli 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
138*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_VALUE_INPUT,
139*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE,
140*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE);
141*e605fbdfSSheetal Tigadoli 
142*e605fbdfSSheetal Tigadoli 	if (exp_param_types != param_types) {
143*e605fbdfSSheetal Tigadoli 		EMSG("Invalid Param types");
144*e605fbdfSSheetal Tigadoli 		return TEE_ERROR_BAD_PARAMETERS;
145*e605fbdfSSheetal Tigadoli 	}
146*e605fbdfSSheetal Tigadoli 
147*e605fbdfSSheetal Tigadoli 	offset = params[1].value.a;
148*e605fbdfSSheetal Tigadoli 
149*e605fbdfSSheetal Tigadoli 	/*
150*e605fbdfSSheetal Tigadoli 	 * Check if offset is within memory range reserved for nitro crash dump
151*e605fbdfSSheetal Tigadoli 	 * minus default size of buffer
152*e605fbdfSSheetal Tigadoli 	 */
153*e605fbdfSSheetal Tigadoli 	if (offset > MAX_NITRO_CRASH_DUMP_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) {
154*e605fbdfSSheetal Tigadoli 		EMSG("Invalid access");
155*e605fbdfSSheetal Tigadoli 		return TEE_ERROR_ACCESS_DENIED;
156*e605fbdfSSheetal Tigadoli 	}
157*e605fbdfSSheetal Tigadoli 
158*e605fbdfSSheetal Tigadoli 	src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset,
159*e605fbdfSSheetal Tigadoli 					  MEM_AREA_RAM_SEC);
160*e605fbdfSSheetal Tigadoli 
161*e605fbdfSSheetal Tigadoli 	/* TODO : check if NITRO_CRASH_DUMP is available */
162*e605fbdfSSheetal Tigadoli 
163*e605fbdfSSheetal Tigadoli 	cache_op_inner(DCACHE_AREA_INVALIDATE,
164*e605fbdfSSheetal Tigadoli 		       (void *)src_vaddr, DEFAULT_ELOG_BUFFER_SIZE);
165*e605fbdfSSheetal Tigadoli 
166*e605fbdfSSheetal Tigadoli 	get_dump_data(src_vaddr, params);
167*e605fbdfSSheetal Tigadoli 
168*e605fbdfSSheetal Tigadoli 	return res;
169*e605fbdfSSheetal Tigadoli }
170*e605fbdfSSheetal Tigadoli 
171*e605fbdfSSheetal Tigadoli /* Copy soc error log data */
172*e605fbdfSSheetal Tigadoli static TEE_Result pta_elog_dump(uint32_t param_types,
173*e605fbdfSSheetal Tigadoli 				TEE_Param params[TEE_NUM_PARAMS])
174*e605fbdfSSheetal Tigadoli {
175*e605fbdfSSheetal Tigadoli 	TEE_Result res = TEE_SUCCESS;
176*e605fbdfSSheetal Tigadoli 	paddr_t src_paddr = CFG_BCM_ELOG_BASE;
177*e605fbdfSSheetal Tigadoli 	vaddr_t src_vaddr = 0;
178*e605fbdfSSheetal Tigadoli 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
179*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_VALUE_INPUT,
180*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE,
181*e605fbdfSSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE);
182*e605fbdfSSheetal Tigadoli 
183*e605fbdfSSheetal Tigadoli 	if (exp_param_types != param_types) {
184*e605fbdfSSheetal Tigadoli 		EMSG("Invalid Param types");
185*e605fbdfSSheetal Tigadoli 		return TEE_ERROR_BAD_PARAMETERS;
186*e605fbdfSSheetal Tigadoli 	}
187*e605fbdfSSheetal Tigadoli 
188*e605fbdfSSheetal Tigadoli 	src_vaddr = (vaddr_t)phys_to_virt(src_paddr, MEM_AREA_RAM_NSEC);
189*e605fbdfSSheetal Tigadoli 
190*e605fbdfSSheetal Tigadoli 	/* Validate if Error logs are present */
191*e605fbdfSSheetal Tigadoli 	if ((*(uint32_t *)src_vaddr) != BCM_ELOG_GLOBAL_METADATA_SIG) {
192*e605fbdfSSheetal Tigadoli 		EMSG("Elog Not setup");
193*e605fbdfSSheetal Tigadoli 		return TEE_ERROR_NOT_SUPPORTED;
194*e605fbdfSSheetal Tigadoli 	}
195*e605fbdfSSheetal Tigadoli 
196*e605fbdfSSheetal Tigadoli 	get_dump_data(src_vaddr, params);
197*e605fbdfSSheetal Tigadoli 
198*e605fbdfSSheetal Tigadoli 	return res;
199*e605fbdfSSheetal Tigadoli }
200*e605fbdfSSheetal Tigadoli 
201*e605fbdfSSheetal Tigadoli static TEE_Result invoke_command(void *session_context __unused,
202*e605fbdfSSheetal Tigadoli 				 uint32_t cmd_id,
203*e605fbdfSSheetal Tigadoli 				 uint32_t param_types,
204*e605fbdfSSheetal Tigadoli 				 TEE_Param params[TEE_NUM_PARAMS])
205*e605fbdfSSheetal Tigadoli {
206*e605fbdfSSheetal Tigadoli 	TEE_Result res = TEE_SUCCESS;
207*e605fbdfSSheetal Tigadoli 
208*e605fbdfSSheetal Tigadoli 	DMSG("command entry point[%d] for \"%s\"", cmd_id, ELOG_TA_NAME);
209*e605fbdfSSheetal Tigadoli 
210*e605fbdfSSheetal Tigadoli 	switch (cmd_id) {
211*e605fbdfSSheetal Tigadoli 	case PTA_BCM_ELOG_CMD_GET_ELOG_MEM:
212*e605fbdfSSheetal Tigadoli 		res = pta_elog_dump(param_types, params);
213*e605fbdfSSheetal Tigadoli 		break;
214*e605fbdfSSheetal Tigadoli 	case PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP:
215*e605fbdfSSheetal Tigadoli 		res = pta_elog_nitro_crash_dump(param_types, params);
216*e605fbdfSSheetal Tigadoli 		break;
217*e605fbdfSSheetal Tigadoli 	case PTA_BCM_ELOG_CMD_LOAD_NITRO_FW:
218*e605fbdfSSheetal Tigadoli 		res = pta_elog_load_nitro_fw(param_types, params);
219*e605fbdfSSheetal Tigadoli 		break;
220*e605fbdfSSheetal Tigadoli 	default:
221*e605fbdfSSheetal Tigadoli 		EMSG("cmd: %d Not supported %s", cmd_id, ELOG_TA_NAME);
222*e605fbdfSSheetal Tigadoli 		res = TEE_ERROR_NOT_SUPPORTED;
223*e605fbdfSSheetal Tigadoli 		break;
224*e605fbdfSSheetal Tigadoli 	}
225*e605fbdfSSheetal Tigadoli 
226*e605fbdfSSheetal Tigadoli 	return res;
227*e605fbdfSSheetal Tigadoli }
228*e605fbdfSSheetal Tigadoli 
229*e605fbdfSSheetal Tigadoli pseudo_ta_register(.uuid = ELOG_SERVICE_UUID,
230*e605fbdfSSheetal Tigadoli 		   .name = ELOG_TA_NAME,
231*e605fbdfSSheetal Tigadoli 		   .flags = PTA_DEFAULT_FLAGS,
232*e605fbdfSSheetal Tigadoli 		   .invoke_command_entry_point = invoke_command);
233