xref: /rk3399_ARM-atf/lib/debugfs/debugfs_smc.c (revision 992f091b5de3b0837c95a338a4e739f6ca2f254f)
1*992f091bSAmbroise Vincent /*
2*992f091bSAmbroise Vincent  * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
3*992f091bSAmbroise Vincent  *
4*992f091bSAmbroise Vincent  * SPDX-License-Identifier: BSD-3-Clause
5*992f091bSAmbroise Vincent  */
6*992f091bSAmbroise Vincent 
7*992f091bSAmbroise Vincent #include <stdint.h>
8*992f091bSAmbroise Vincent #include <stdbool.h>
9*992f091bSAmbroise Vincent #include <string.h>
10*992f091bSAmbroise Vincent 
11*992f091bSAmbroise Vincent #include <lib/debugfs.h>
12*992f091bSAmbroise Vincent #include <lib/smccc.h>
13*992f091bSAmbroise Vincent #include <lib/spinlock.h>
14*992f091bSAmbroise Vincent #include <lib/xlat_tables/xlat_tables_v2.h>
15*992f091bSAmbroise Vincent #include <smccc_helpers.h>
16*992f091bSAmbroise Vincent 
17*992f091bSAmbroise Vincent #define MAX_PATH_LEN	256
18*992f091bSAmbroise Vincent 
19*992f091bSAmbroise Vincent #define MOUNT		0
20*992f091bSAmbroise Vincent #define CREATE		1
21*992f091bSAmbroise Vincent #define OPEN		2
22*992f091bSAmbroise Vincent #define CLOSE		3
23*992f091bSAmbroise Vincent #define READ		4
24*992f091bSAmbroise Vincent #define WRITE		5
25*992f091bSAmbroise Vincent #define SEEK		6
26*992f091bSAmbroise Vincent #define BIND		7
27*992f091bSAmbroise Vincent #define STAT		8
28*992f091bSAmbroise Vincent #define INIT		10
29*992f091bSAmbroise Vincent #define VERSION		11
30*992f091bSAmbroise Vincent 
31*992f091bSAmbroise Vincent /* This is the virtual address to which we map the NS shared buffer */
32*992f091bSAmbroise Vincent #define DEBUGFS_SHARED_BUF_VIRT		((void *)0x81000000U)
33*992f091bSAmbroise Vincent 
34*992f091bSAmbroise Vincent static union debugfs_parms {
35*992f091bSAmbroise Vincent 	struct {
36*992f091bSAmbroise Vincent 		char fname[MAX_PATH_LEN];
37*992f091bSAmbroise Vincent 	} open;
38*992f091bSAmbroise Vincent 
39*992f091bSAmbroise Vincent 	struct {
40*992f091bSAmbroise Vincent 		char srv[MAX_PATH_LEN];
41*992f091bSAmbroise Vincent 		char where[MAX_PATH_LEN];
42*992f091bSAmbroise Vincent 		char spec[MAX_PATH_LEN];
43*992f091bSAmbroise Vincent 	} mount;
44*992f091bSAmbroise Vincent 
45*992f091bSAmbroise Vincent 	struct {
46*992f091bSAmbroise Vincent 		char path[MAX_PATH_LEN];
47*992f091bSAmbroise Vincent 		dir_t dir;
48*992f091bSAmbroise Vincent 	} stat;
49*992f091bSAmbroise Vincent 
50*992f091bSAmbroise Vincent 	struct {
51*992f091bSAmbroise Vincent 		char oldpath[MAX_PATH_LEN];
52*992f091bSAmbroise Vincent 		char newpath[MAX_PATH_LEN];
53*992f091bSAmbroise Vincent 	} bind;
54*992f091bSAmbroise Vincent } parms;
55*992f091bSAmbroise Vincent 
56*992f091bSAmbroise Vincent /* debugfs_access_lock protects shared buffer and internal */
57*992f091bSAmbroise Vincent /* FS functions from concurrent acccesses.                 */
58*992f091bSAmbroise Vincent static spinlock_t debugfs_access_lock;
59*992f091bSAmbroise Vincent 
60*992f091bSAmbroise Vincent static bool debugfs_initialized;
61*992f091bSAmbroise Vincent 
62*992f091bSAmbroise Vincent uintptr_t debugfs_smc_handler(unsigned int smc_fid,
63*992f091bSAmbroise Vincent 			      u_register_t cmd,
64*992f091bSAmbroise Vincent 			      u_register_t arg2,
65*992f091bSAmbroise Vincent 			      u_register_t arg3,
66*992f091bSAmbroise Vincent 			      u_register_t arg4,
67*992f091bSAmbroise Vincent 			      void *cookie,
68*992f091bSAmbroise Vincent 			      void *handle,
69*992f091bSAmbroise Vincent 			      u_register_t flags)
70*992f091bSAmbroise Vincent {
71*992f091bSAmbroise Vincent 	int64_t smc_ret = DEBUGFS_E_INVALID_PARAMS, smc_resp = 0;
72*992f091bSAmbroise Vincent 	int ret;
73*992f091bSAmbroise Vincent 
74*992f091bSAmbroise Vincent 	/* Allow calls from non-secure only */
75*992f091bSAmbroise Vincent 	if (is_caller_secure(flags)) {
76*992f091bSAmbroise Vincent 		SMC_RET1(handle, DEBUGFS_E_DENIED);
77*992f091bSAmbroise Vincent 	}
78*992f091bSAmbroise Vincent 
79*992f091bSAmbroise Vincent 	/* Expect a SiP service fast call */
80*992f091bSAmbroise Vincent 	if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
81*992f091bSAmbroise Vincent 		(GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
82*992f091bSAmbroise Vincent 		SMC_RET1(handle, SMC_UNK);
83*992f091bSAmbroise Vincent 	}
84*992f091bSAmbroise Vincent 
85*992f091bSAmbroise Vincent 	/* Truncate parameters if 32b SMC convention call */
86*992f091bSAmbroise Vincent 	if (GET_SMC_CC(smc_fid) == SMC_32) {
87*992f091bSAmbroise Vincent 		arg2 &= 0xffffffff;
88*992f091bSAmbroise Vincent 		arg3 &= 0xffffffff;
89*992f091bSAmbroise Vincent 		arg4 &= 0xffffffff;
90*992f091bSAmbroise Vincent 	}
91*992f091bSAmbroise Vincent 
92*992f091bSAmbroise Vincent 	spin_lock(&debugfs_access_lock);
93*992f091bSAmbroise Vincent 
94*992f091bSAmbroise Vincent 	if (debugfs_initialized == true) {
95*992f091bSAmbroise Vincent 		/* Copy NS shared buffer to internal secure location */
96*992f091bSAmbroise Vincent 		memcpy(&parms, (void *)DEBUGFS_SHARED_BUF_VIRT,
97*992f091bSAmbroise Vincent 		       sizeof(union debugfs_parms));
98*992f091bSAmbroise Vincent 	}
99*992f091bSAmbroise Vincent 
100*992f091bSAmbroise Vincent 	switch (cmd) {
101*992f091bSAmbroise Vincent 	case INIT:
102*992f091bSAmbroise Vincent 		if (debugfs_initialized == false) {
103*992f091bSAmbroise Vincent 			/* TODO: check PA validity e.g. whether */
104*992f091bSAmbroise Vincent 			/* it is an NS region.                  */
105*992f091bSAmbroise Vincent 			ret = mmap_add_dynamic_region(arg2,
106*992f091bSAmbroise Vincent 				(uintptr_t)DEBUGFS_SHARED_BUF_VIRT,
107*992f091bSAmbroise Vincent 				PAGE_SIZE_4KB,
108*992f091bSAmbroise Vincent 				MT_MEMORY | MT_RW | MT_NS);
109*992f091bSAmbroise Vincent 			if (ret == 0) {
110*992f091bSAmbroise Vincent 				debugfs_initialized = true;
111*992f091bSAmbroise Vincent 				smc_ret = SMC_OK;
112*992f091bSAmbroise Vincent 				smc_resp = 0;
113*992f091bSAmbroise Vincent 			}
114*992f091bSAmbroise Vincent 		}
115*992f091bSAmbroise Vincent 		break;
116*992f091bSAmbroise Vincent 
117*992f091bSAmbroise Vincent 	case VERSION:
118*992f091bSAmbroise Vincent 		smc_ret = SMC_OK;
119*992f091bSAmbroise Vincent 		smc_resp = DEBUGFS_VERSION;
120*992f091bSAmbroise Vincent 		break;
121*992f091bSAmbroise Vincent 
122*992f091bSAmbroise Vincent 	case MOUNT:
123*992f091bSAmbroise Vincent 		ret = mount(parms.mount.srv,
124*992f091bSAmbroise Vincent 			    parms.mount.where,
125*992f091bSAmbroise Vincent 			    parms.mount.spec);
126*992f091bSAmbroise Vincent 		if (ret == 0) {
127*992f091bSAmbroise Vincent 			smc_ret = SMC_OK;
128*992f091bSAmbroise Vincent 			smc_resp = 0;
129*992f091bSAmbroise Vincent 		}
130*992f091bSAmbroise Vincent 		break;
131*992f091bSAmbroise Vincent 
132*992f091bSAmbroise Vincent 	case OPEN:
133*992f091bSAmbroise Vincent 		ret = open(parms.open.fname, arg2);
134*992f091bSAmbroise Vincent 		if (ret >= 0) {
135*992f091bSAmbroise Vincent 			smc_ret = SMC_OK;
136*992f091bSAmbroise Vincent 			smc_resp = ret;
137*992f091bSAmbroise Vincent 		}
138*992f091bSAmbroise Vincent 		break;
139*992f091bSAmbroise Vincent 
140*992f091bSAmbroise Vincent 	case CLOSE:
141*992f091bSAmbroise Vincent 		ret = close(arg2);
142*992f091bSAmbroise Vincent 		if (ret == 0) {
143*992f091bSAmbroise Vincent 			smc_ret = SMC_OK;
144*992f091bSAmbroise Vincent 			smc_resp = 0;
145*992f091bSAmbroise Vincent 		}
146*992f091bSAmbroise Vincent 		break;
147*992f091bSAmbroise Vincent 
148*992f091bSAmbroise Vincent 	case READ:
149*992f091bSAmbroise Vincent 		ret = read(arg2, DEBUGFS_SHARED_BUF_VIRT, arg3);
150*992f091bSAmbroise Vincent 		if (ret >= 0) {
151*992f091bSAmbroise Vincent 			smc_ret = SMC_OK;
152*992f091bSAmbroise Vincent 			smc_resp = ret;
153*992f091bSAmbroise Vincent 		}
154*992f091bSAmbroise Vincent 		break;
155*992f091bSAmbroise Vincent 
156*992f091bSAmbroise Vincent 	case SEEK:
157*992f091bSAmbroise Vincent 		ret = seek(arg2, arg3, arg4);
158*992f091bSAmbroise Vincent 		if (ret == 0) {
159*992f091bSAmbroise Vincent 			smc_ret = SMC_OK;
160*992f091bSAmbroise Vincent 			smc_resp = 0;
161*992f091bSAmbroise Vincent 		}
162*992f091bSAmbroise Vincent 		break;
163*992f091bSAmbroise Vincent 
164*992f091bSAmbroise Vincent 	case BIND:
165*992f091bSAmbroise Vincent 		ret = bind(parms.bind.oldpath, parms.bind.newpath);
166*992f091bSAmbroise Vincent 		if (ret == 0) {
167*992f091bSAmbroise Vincent 			smc_ret = SMC_OK;
168*992f091bSAmbroise Vincent 			smc_resp = 0;
169*992f091bSAmbroise Vincent 		}
170*992f091bSAmbroise Vincent 		break;
171*992f091bSAmbroise Vincent 
172*992f091bSAmbroise Vincent 	case STAT:
173*992f091bSAmbroise Vincent 		ret = stat(parms.stat.path, &parms.stat.dir);
174*992f091bSAmbroise Vincent 		if (ret == 0) {
175*992f091bSAmbroise Vincent 			memcpy((void *)DEBUGFS_SHARED_BUF_VIRT, &parms,
176*992f091bSAmbroise Vincent 			       sizeof(union debugfs_parms));
177*992f091bSAmbroise Vincent 			smc_ret = SMC_OK;
178*992f091bSAmbroise Vincent 			smc_resp = 0;
179*992f091bSAmbroise Vincent 		}
180*992f091bSAmbroise Vincent 		break;
181*992f091bSAmbroise Vincent 
182*992f091bSAmbroise Vincent 	/* Not implemented */
183*992f091bSAmbroise Vincent 	case CREATE:
184*992f091bSAmbroise Vincent 		/* Intentional fall-through */
185*992f091bSAmbroise Vincent 
186*992f091bSAmbroise Vincent 	/* Not implemented */
187*992f091bSAmbroise Vincent 	case WRITE:
188*992f091bSAmbroise Vincent 		/* Intentional fall-through */
189*992f091bSAmbroise Vincent 
190*992f091bSAmbroise Vincent 	default:
191*992f091bSAmbroise Vincent 		smc_ret = SMC_UNK;
192*992f091bSAmbroise Vincent 		smc_resp = 0;
193*992f091bSAmbroise Vincent 	}
194*992f091bSAmbroise Vincent 
195*992f091bSAmbroise Vincent 	spin_unlock(&debugfs_access_lock);
196*992f091bSAmbroise Vincent 
197*992f091bSAmbroise Vincent 	SMC_RET2(handle, smc_ret, smc_resp);
198*992f091bSAmbroise Vincent 
199*992f091bSAmbroise Vincent 	/* Not reached */
200*992f091bSAmbroise Vincent 	return smc_ret;
201*992f091bSAmbroise Vincent }
202*992f091bSAmbroise Vincent 
203*992f091bSAmbroise Vincent int debugfs_smc_setup(void)
204*992f091bSAmbroise Vincent {
205*992f091bSAmbroise Vincent 	debugfs_initialized = false;
206*992f091bSAmbroise Vincent 	debugfs_access_lock.lock = 0;
207*992f091bSAmbroise Vincent 
208*992f091bSAmbroise Vincent 	return 0;
209*992f091bSAmbroise Vincent }
210