blob: d0d3bf401dc07805ecc2744f90861e47cbd0cd50 [file] [log] [blame]
Manish V Badarkhecf48f492025-04-15 20:16:32 +01001/*
2 * Copyright (c) 2025, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Manish V Badarkheb9dee502025-05-30 13:17:05 +01007#include <plat/common/platform.h>
8#include <services/bl31_lfa.h>
Manish V Badarkhecf48f492025-04-15 20:16:32 +01009#include <services/lfa_svc.h>
Manish V Badarkheb9dee502025-05-30 13:17:05 +010010#include <services/rmmd_rmm_lfa.h>
Manish V Badarkhecf48f492025-04-15 20:16:32 +010011#include <smccc_helpers.h>
12
Manish V Badarkheb9dee502025-05-30 13:17:05 +010013static uint32_t lfa_component_count;
14static plat_lfa_component_info_t *lfa_components;
15static struct lfa_component_status current_activation;
16static bool is_lfa_initialized;
17
18void lfa_reset_activation(void)
19{
20 current_activation.component_id = LFA_INVALID_COMPONENT;
21 current_activation.prime_status = PRIME_NONE;
22}
23
Manish V Badarkhe67fa1822025-04-15 20:16:36 +010024static int convert_to_lfa_error(int ret)
25{
26 switch (ret) {
27 case 0:
28 return LFA_SUCCESS;
29 case -EAUTH:
30 return LFA_AUTH_ERROR;
31 case -ENOMEM:
32 return LFA_NO_MEMORY;
33 default:
34 return LFA_DEVICE_ERROR;
35 }
36}
37
Manish V Badarkheb9dee502025-05-30 13:17:05 +010038static bool lfa_initialize_components(void)
39{
40 lfa_component_count = plat_lfa_get_components(&lfa_components);
41
42 if (lfa_component_count == 0U || lfa_components == NULL) {
43 /* unlikely to reach here */
44 ERROR("Invalid LFA component setup: count = 0 or components are NULL");
45 return false;
46 }
47
48 return true;
49}
50
Manish V Badarkhe06a6f292025-04-15 20:16:34 +010051static uint64_t get_fw_activation_flags(uint32_t fw_seq_id)
52{
53 const plat_lfa_component_info_t *comp =
54 &lfa_components[fw_seq_id];
55 uint64_t flags = 0ULL;
56
57 flags |= ((comp->activator == NULL ? 0ULL : 1ULL)
58 << LFA_ACTIVATION_CAPABLE_SHIFT);
59 flags |= (uint64_t)(comp->activation_pending)
60 << LFA_ACTIVATION_PENDING_SHIFT;
61
62 if (comp->activator != NULL) {
63 flags |= ((comp->activator->may_reset_cpu ? 1ULL : 0ULL)
64 << LFA_MAY_RESET_CPU_SHIFT);
65 flags |= ((comp->activator->cpu_rendezvous_required ? 0ULL : 1ULL)
66 << LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT);
67 }
68
69 return flags;
70}
71
Manish V Badarkhe3f7b2862025-04-15 20:16:35 +010072static int lfa_cancel(uint32_t component_id)
73{
74 int ret = LFA_SUCCESS;
75
76 if (lfa_component_count == 0U) {
77 return LFA_WRONG_STATE;
78 }
79
80 /* Check if component ID is in range. */
81 if ((component_id >= lfa_component_count) ||
82 (component_id != current_activation.component_id)) {
83 return LFA_INVALID_PARAMETERS;
84 }
85
86 ret = plat_lfa_cancel(component_id);
87 if (ret != LFA_SUCCESS) {
88 return LFA_BUSY;
89 }
90
91 /* TODO: add proper termination prime and activate phases */
92 lfa_reset_activation();
93
94 return ret;
95}
96
Manish V Badarkhe67fa1822025-04-15 20:16:36 +010097static int lfa_prime(uint32_t component_id, uint64_t *flags)
98{
99 int ret = LFA_SUCCESS;
100 struct lfa_component_ops *activator;
101
102 if (lfa_component_count == 0U ||
103 !lfa_components[component_id].activation_pending) {
104 return LFA_WRONG_STATE;
105 }
106
107 /* Check if fw_seq_id is in range. */
108 if (component_id >= lfa_component_count) {
109 return LFA_INVALID_PARAMETERS;
110 }
111
112 if (lfa_components[component_id].activator == NULL) {
113 return LFA_NOT_SUPPORTED;
114 }
115
116 switch (current_activation.prime_status) {
117 case PRIME_NONE:
118 current_activation.component_id = component_id;
119 current_activation.prime_status = PRIME_STARTED;
120 break;
121
122 case PRIME_STARTED:
123 if (current_activation.component_id != component_id) {
124 /* Mismatched component trying to continue PRIME - error */
125 return LFA_WRONG_STATE;
126 }
127 break;
128
129 case PRIME_COMPLETE:
130 default:
131 break;
132 }
133
134 ret = plat_lfa_load_auth_image(component_id);
135 ret = convert_to_lfa_error(ret);
136
137 activator = lfa_components[component_id].activator;
138 if (activator->prime != NULL) {
139 ret = activator->prime(&current_activation);
140 if (ret != LFA_SUCCESS) {
141 /*
142 * TODO: it should be LFA_PRIME_FAILED but specification
143 * has not define this error yet
144 */
145 return ret;
146 }
147 }
148
149 current_activation.prime_status = PRIME_COMPLETE;
150
151 /* TODO: split this into multiple PRIME calls */
152 *flags = 0ULL;
153
154 return ret;
155}
156
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100157int lfa_setup(void)
158{
Manish V Badarkheb9dee502025-05-30 13:17:05 +0100159 is_lfa_initialized = lfa_initialize_components();
160 if (!is_lfa_initialized) {
161 return -1;
162 }
163
164 lfa_reset_activation();
165
166 return 0;
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100167}
168
169uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
170 u_register_t x3, u_register_t x4, void *cookie,
171 void *handle, u_register_t flags)
172{
Manish V Badarkhe06a6f292025-04-15 20:16:34 +0100173 uint64_t retx1, retx2;
Manish V Badarkhe67fa1822025-04-15 20:16:36 +0100174 uint64_t lfa_flags;
Manish V Badarkhe06a6f292025-04-15 20:16:34 +0100175 uint8_t *uuid_p;
176 uint32_t fw_seq_id = (uint32_t)x1;
Manish V Badarkhe3f7b2862025-04-15 20:16:35 +0100177 int ret;
Manish V Badarkhe06a6f292025-04-15 20:16:34 +0100178
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100179 /**
180 * TODO: Acquire serialization lock.
181 */
Manish V Badarkheb9dee502025-05-30 13:17:05 +0100182
183 if (!is_lfa_initialized) {
184 return LFA_NOT_SUPPORTED;
185 }
186
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100187 switch (smc_fid) {
188 case LFA_VERSION:
189 SMC_RET1(handle, LFA_VERSION_VAL);
190 break;
191
192 case LFA_FEATURES:
193 SMC_RET1(handle, is_lfa_fid(x1) ? LFA_SUCCESS : LFA_NOT_SUPPORTED);
194 break;
195
196 case LFA_GET_INFO:
Manish V Badarkheb9dee502025-05-30 13:17:05 +0100197 /**
198 * The current specification limits this input parameter to be zero for
199 * version 1.0 of LFA
200 */
201 if (x1 == 0ULL) {
202 SMC_RET3(handle, LFA_SUCCESS, lfa_component_count, 0);
203 } else {
204 SMC_RET1(handle, LFA_INVALID_PARAMETERS);
205 }
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100206 break;
207
208 case LFA_GET_INVENTORY:
Manish V Badarkhe06a6f292025-04-15 20:16:34 +0100209 if (lfa_component_count == 0U) {
210 SMC_RET1(handle, LFA_WRONG_STATE);
211 }
212
213 /*
214 * Check if fw_seq_id is in range. LFA_GET_INFO must be called first to scan
215 * platform firmware and create a valid number of firmware components.
216 */
217 if (fw_seq_id >= lfa_component_count) {
218 SMC_RET1(handle, LFA_INVALID_PARAMETERS);
219 }
220
221 /*
222 * grab the UUID of asked fw_seq_id and set the return UUID
223 * variables
224 */
225 uuid_p = (uint8_t *)&lfa_components[fw_seq_id].uuid;
226 memcpy(&retx1, uuid_p, sizeof(uint64_t));
227 memcpy(&retx2, uuid_p + sizeof(uint64_t), sizeof(uint64_t));
228
229 /*
230 * check the given fw_seq_id's update available
231 * and accordingly set the active_pending flag
232 */
233 lfa_components[fw_seq_id].activation_pending =
234 is_plat_lfa_activation_pending(fw_seq_id);
235
236 INFO("Component %lu %s live activation:\n", x1,
237 lfa_components[fw_seq_id].activator ? "supports" :
238 "does not support");
239
240 if (lfa_components[fw_seq_id].activator != NULL) {
241 INFO("Activation pending: %s\n",
242 lfa_components[fw_seq_id].activation_pending ? "true" : "false");
243 }
244
245 INFO("x1 = 0x%016lx, x2 = 0x%016lx\n", retx1, retx2);
246
247 SMC_RET4(handle, LFA_SUCCESS, retx1, retx2, get_fw_activation_flags(fw_seq_id));
248
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100249 break;
250
251 case LFA_PRIME:
Manish V Badarkhe67fa1822025-04-15 20:16:36 +0100252 ret = lfa_prime(x1, &lfa_flags);
253 if (ret != LFA_SUCCESS) {
254 SMC_RET1(handle, ret);
255 } else {
256 SMC_RET2(handle, ret, lfa_flags);
257 }
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100258 break;
259
260 case LFA_ACTIVATE:
261 break;
262
263 case LFA_CANCEL:
Manish V Badarkhe3f7b2862025-04-15 20:16:35 +0100264 ret = lfa_cancel(x1);
265 SMC_RET1(handle, ret);
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100266 break;
267
268 default:
269 WARN("Unimplemented LFA Service Call: 0x%x\n", smc_fid);
270 SMC_RET1(handle, SMC_UNK);
271 break; /* unreachable */
272
273 }
274
275 SMC_RET1(handle, SMC_UNK);
276
277 return 0;
278}