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(¤t_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(¤t_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