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