xref: /rk3399_ARM-atf/services/std_svc/lfa/lfa_main.c (revision b67e984664a8644d6cfd1812cabaa02cf24f09c9)
1 /*
2  * Copyright (c) 2025, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 
9 #include <plat/common/platform.h>
10 #include <services/bl31_lfa.h>
11 #include <services/lfa_svc.h>
12 #include <services/rmmd_rmm_lfa.h>
13 #include <smccc_helpers.h>
14 
15 static uint32_t lfa_component_count;
16 static plat_lfa_component_info_t *lfa_components;
17 static struct lfa_component_status current_activation;
18 static bool is_lfa_initialized;
19 
20 void lfa_reset_activation(void)
21 {
22 	current_activation.component_id = LFA_INVALID_COMPONENT;
23 	current_activation.prime_status = PRIME_NONE;
24 	current_activation.cpu_rendezvous_required = false;
25 }
26 
27 static int convert_to_lfa_error(int ret)
28 {
29 	switch (ret) {
30 	case 0:
31 		return LFA_SUCCESS;
32 	case -EAUTH:
33 		return LFA_AUTH_ERROR;
34 	case -ENOMEM:
35 		return LFA_NO_MEMORY;
36 	default:
37 		return LFA_DEVICE_ERROR;
38 	}
39 }
40 
41 static bool lfa_initialize_components(void)
42 {
43 	lfa_component_count = plat_lfa_get_components(&lfa_components);
44 
45 	if (lfa_component_count == 0U || lfa_components == NULL) {
46 		/* unlikely to reach here */
47 		ERROR("Invalid LFA component setup: count = 0 or components are NULL");
48 		return false;
49 	}
50 
51 	return true;
52 }
53 
54 static uint64_t get_fw_activation_flags(uint32_t fw_seq_id)
55 {
56 	const plat_lfa_component_info_t *comp =
57 				&lfa_components[fw_seq_id];
58 	uint64_t flags = 0ULL;
59 
60 	flags |= ((comp->activator == NULL ? 0ULL : 1ULL)
61 		 << LFA_ACTIVATION_CAPABLE_SHIFT);
62 	flags |= (uint64_t)(comp->activation_pending)
63 		 << LFA_ACTIVATION_PENDING_SHIFT;
64 
65 	if (comp->activator != NULL) {
66 		flags |= ((comp->activator->may_reset_cpu ? 1ULL : 0ULL)
67 			 << LFA_MAY_RESET_CPU_SHIFT);
68 		flags |= ((comp->activator->cpu_rendezvous_required ? 0ULL : 1ULL)
69 			 << LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT);
70 	}
71 
72 	return flags;
73 }
74 
75 static int lfa_cancel(uint32_t component_id)
76 {
77 	int ret = LFA_SUCCESS;
78 
79 	if (lfa_component_count == 0U) {
80 		return LFA_WRONG_STATE;
81 	}
82 
83 	/* Check if component ID is in range. */
84 	if ((component_id >= lfa_component_count) ||
85 	    (component_id != current_activation.component_id)) {
86 		return LFA_INVALID_PARAMETERS;
87 	}
88 
89 	ret = plat_lfa_cancel(component_id);
90 	if (ret != LFA_SUCCESS) {
91 		return LFA_BUSY;
92 	}
93 
94 	/* TODO: add proper termination prime and activate phases */
95 	lfa_reset_activation();
96 
97 	return ret;
98 }
99 
100 static int lfa_activate(uint32_t component_id, uint64_t flags,
101 			uint64_t ep_address, uint64_t context_id)
102 {
103 	int ret = LFA_ACTIVATION_FAILED;
104 	struct lfa_component_ops *activator;
105 
106 	if ((lfa_component_count == 0U) ||
107 	    (!lfa_components[component_id].activation_pending) ||
108 	    (current_activation.prime_status != PRIME_COMPLETE)) {
109 		return LFA_COMPONENT_WRONG_STATE;
110 	}
111 
112 	/* Check if fw_seq_id is in range. */
113 	if ((component_id >= lfa_component_count) ||
114 	    (current_activation.component_id != component_id)) {
115 		return LFA_INVALID_PARAMETERS;
116 	}
117 
118 	if (lfa_components[component_id].activator == NULL) {
119 		return LFA_NOT_SUPPORTED;
120 	}
121 
122 	activator = lfa_components[component_id].activator;
123 	if (activator->activate != NULL) {
124 		/*
125 		 * Pass skip_cpu_rendezvous (flag[0]) only if flag[0]==1
126 		 * & CPU_RENDEZVOUS is not required.
127 		 */
128 		if (flags & LFA_SKIP_CPU_RENDEZVOUS_BIT) {
129 			if (!activator->cpu_rendezvous_required) {
130 				INFO("Skipping rendezvous requested by caller.\n");
131 				current_activation.cpu_rendezvous_required = false;
132 			}
133 			/*
134 			 * Return error if caller tries to skip rendezvous when
135 			 * it is required.
136 			 */
137 			else {
138 				ERROR("CPU Rendezvous is required, can't skip.\n");
139 				return LFA_INVALID_PARAMETERS;
140 			}
141 		}
142 
143 		ret = activator->activate(&current_activation, ep_address,
144 					  context_id);
145 	}
146 
147 	lfa_components[component_id].activation_pending = false;
148 
149 	return ret;
150 }
151 
152 static int lfa_prime(uint32_t component_id, uint64_t *flags)
153 {
154 	int ret = LFA_SUCCESS;
155 	struct lfa_component_ops *activator;
156 
157 	if (lfa_component_count == 0U ||
158 	    !lfa_components[component_id].activation_pending) {
159 		return LFA_WRONG_STATE;
160 	}
161 
162 	/* Check if fw_seq_id is in range. */
163 	if (component_id >= lfa_component_count) {
164 		return LFA_INVALID_PARAMETERS;
165 	}
166 
167 	if (lfa_components[component_id].activator == NULL) {
168 		return LFA_NOT_SUPPORTED;
169 	}
170 
171 	switch (current_activation.prime_status) {
172 	case PRIME_NONE:
173 		current_activation.component_id = component_id;
174 		current_activation.prime_status = PRIME_STARTED;
175 		break;
176 
177 	case PRIME_STARTED:
178 		if (current_activation.component_id != component_id) {
179 			/* Mismatched component trying to continue PRIME - error */
180 			return LFA_WRONG_STATE;
181 		}
182 		break;
183 
184 	case PRIME_COMPLETE:
185 	default:
186 		break;
187 	}
188 
189 	ret = plat_lfa_load_auth_image(component_id);
190 	ret = convert_to_lfa_error(ret);
191 
192 	activator = lfa_components[component_id].activator;
193 	if (activator->prime != NULL) {
194 		ret = activator->prime(&current_activation);
195 		if (ret != LFA_SUCCESS) {
196 			/*
197 			 * TODO: it should be LFA_PRIME_FAILED but specification
198 			 * has not define this error yet
199 			 */
200 			return ret;
201 		}
202 	}
203 
204 	current_activation.prime_status = PRIME_COMPLETE;
205 
206 	/* TODO: split this into multiple PRIME calls */
207 	*flags = 0ULL;
208 
209 	return ret;
210 }
211 
212 int lfa_setup(void)
213 {
214 	is_lfa_initialized = lfa_initialize_components();
215 	if (!is_lfa_initialized) {
216 		return -1;
217 	}
218 
219 	lfa_reset_activation();
220 
221 	return 0;
222 }
223 
224 uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
225 			 u_register_t x3, u_register_t x4, void *cookie,
226 			 void *handle, u_register_t flags)
227 {
228 	uint64_t retx1, retx2;
229 	uint64_t lfa_flags;
230 	uint8_t *uuid_p;
231 	uint32_t fw_seq_id = (uint32_t)x1;
232 	int ret;
233 
234 	/**
235 	 * TODO: Acquire serialization lock.
236 	 */
237 
238 	if (!is_lfa_initialized) {
239 		return LFA_NOT_SUPPORTED;
240 	}
241 
242 	switch (smc_fid) {
243 	case LFA_VERSION:
244 		SMC_RET1(handle, LFA_VERSION_VAL);
245 		break;
246 
247 	case LFA_FEATURES:
248 		SMC_RET1(handle, is_lfa_fid(x1) ? LFA_SUCCESS : LFA_NOT_SUPPORTED);
249 		break;
250 
251 	case LFA_GET_INFO:
252 		/**
253 		 * The current specification limits this input parameter to be zero for
254 		 * version 1.0 of LFA
255 		 */
256 		if (x1 == 0ULL) {
257 			SMC_RET3(handle, LFA_SUCCESS, lfa_component_count, 0);
258 		} else {
259 			SMC_RET1(handle, LFA_INVALID_PARAMETERS);
260 		}
261 		break;
262 
263 	case LFA_GET_INVENTORY:
264 		if (lfa_component_count == 0U) {
265 			SMC_RET1(handle, LFA_WRONG_STATE);
266 		}
267 
268 		/*
269 		 * Check if fw_seq_id is in range. LFA_GET_INFO must be called first to scan
270 		 * platform firmware and create a valid number of firmware components.
271 		 */
272 		if (fw_seq_id >= lfa_component_count) {
273 			SMC_RET1(handle, LFA_INVALID_PARAMETERS);
274 		}
275 
276 		/*
277 		 * grab the UUID of asked fw_seq_id and set the return UUID
278 		 * variables
279 		 */
280 		uuid_p = (uint8_t *)&lfa_components[fw_seq_id].uuid;
281 		memcpy(&retx1, uuid_p, sizeof(uint64_t));
282 		memcpy(&retx2, uuid_p + sizeof(uint64_t), sizeof(uint64_t));
283 
284 		/*
285 		 * check the given fw_seq_id's update available
286 		 * and accordingly set the active_pending flag
287 		 */
288 		lfa_components[fw_seq_id].activation_pending =
289 				is_plat_lfa_activation_pending(fw_seq_id);
290 
291 		INFO("Component %lu %s live activation:\n", x1,
292 		      lfa_components[fw_seq_id].activator ? "supports" :
293 		      "does not support");
294 
295 		if (lfa_components[fw_seq_id].activator != NULL) {
296 			INFO("Activation pending: %s\n",
297 			      lfa_components[fw_seq_id].activation_pending ? "true" : "false");
298 		}
299 
300 		INFO("x1 = 0x%016lx, x2 = 0x%016lx\n", retx1, retx2);
301 
302 		SMC_RET4(handle, LFA_SUCCESS, retx1, retx2, get_fw_activation_flags(fw_seq_id));
303 
304 		break;
305 
306 	case LFA_PRIME:
307 		ret = lfa_prime(x1, &lfa_flags);
308 		if (ret != LFA_SUCCESS) {
309 			SMC_RET1(handle, ret);
310 		} else {
311 			SMC_RET2(handle, ret, lfa_flags);
312 		}
313 		break;
314 
315 	case LFA_ACTIVATE:
316 		ret = lfa_activate(fw_seq_id, x2, x3, x4);
317 		/* TODO: implement activate again */
318 		SMC_RET2(handle, ret, 0ULL);
319 
320 		break;
321 
322 	case LFA_CANCEL:
323 		ret = lfa_cancel(x1);
324 		SMC_RET1(handle, ret);
325 		break;
326 
327 	default:
328 		WARN("Unimplemented LFA Service Call: 0x%x\n", smc_fid);
329 		SMC_RET1(handle, SMC_UNK);
330 		break; /* unreachable */
331 
332 	}
333 
334 	SMC_RET1(handle, SMC_UNK);
335 
336 	return 0;
337 }
338