blob: d518c96353061e39c312f35eb3f504a69fa59346 [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
24static bool lfa_initialize_components(void)
25{
26 lfa_component_count = plat_lfa_get_components(&lfa_components);
27
28 if (lfa_component_count == 0U || lfa_components == NULL) {
29 /* unlikely to reach here */
30 ERROR("Invalid LFA component setup: count = 0 or components are NULL");
31 return false;
32 }
33
34 return true;
35}
36
Manish V Badarkhe06a6f292025-04-15 20:16:34 +010037static uint64_t get_fw_activation_flags(uint32_t fw_seq_id)
38{
39 const plat_lfa_component_info_t *comp =
40 &lfa_components[fw_seq_id];
41 uint64_t flags = 0ULL;
42
43 flags |= ((comp->activator == NULL ? 0ULL : 1ULL)
44 << LFA_ACTIVATION_CAPABLE_SHIFT);
45 flags |= (uint64_t)(comp->activation_pending)
46 << LFA_ACTIVATION_PENDING_SHIFT;
47
48 if (comp->activator != NULL) {
49 flags |= ((comp->activator->may_reset_cpu ? 1ULL : 0ULL)
50 << LFA_MAY_RESET_CPU_SHIFT);
51 flags |= ((comp->activator->cpu_rendezvous_required ? 0ULL : 1ULL)
52 << LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT);
53 }
54
55 return flags;
56}
57
Manish V Badarkhe3f7b2862025-04-15 20:16:35 +010058static int lfa_cancel(uint32_t component_id)
59{
60 int ret = LFA_SUCCESS;
61
62 if (lfa_component_count == 0U) {
63 return LFA_WRONG_STATE;
64 }
65
66 /* Check if component ID is in range. */
67 if ((component_id >= lfa_component_count) ||
68 (component_id != current_activation.component_id)) {
69 return LFA_INVALID_PARAMETERS;
70 }
71
72 ret = plat_lfa_cancel(component_id);
73 if (ret != LFA_SUCCESS) {
74 return LFA_BUSY;
75 }
76
77 /* TODO: add proper termination prime and activate phases */
78 lfa_reset_activation();
79
80 return ret;
81}
82
Manish V Badarkhecf48f492025-04-15 20:16:32 +010083int lfa_setup(void)
84{
Manish V Badarkheb9dee502025-05-30 13:17:05 +010085 is_lfa_initialized = lfa_initialize_components();
86 if (!is_lfa_initialized) {
87 return -1;
88 }
89
90 lfa_reset_activation();
91
92 return 0;
Manish V Badarkhecf48f492025-04-15 20:16:32 +010093}
94
95uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
96 u_register_t x3, u_register_t x4, void *cookie,
97 void *handle, u_register_t flags)
98{
Manish V Badarkhe06a6f292025-04-15 20:16:34 +010099 uint64_t retx1, retx2;
100 uint8_t *uuid_p;
101 uint32_t fw_seq_id = (uint32_t)x1;
Manish V Badarkhe3f7b2862025-04-15 20:16:35 +0100102 int ret;
Manish V Badarkhe06a6f292025-04-15 20:16:34 +0100103
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100104 /**
105 * TODO: Acquire serialization lock.
106 */
Manish V Badarkheb9dee502025-05-30 13:17:05 +0100107
108 if (!is_lfa_initialized) {
109 return LFA_NOT_SUPPORTED;
110 }
111
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100112 switch (smc_fid) {
113 case LFA_VERSION:
114 SMC_RET1(handle, LFA_VERSION_VAL);
115 break;
116
117 case LFA_FEATURES:
118 SMC_RET1(handle, is_lfa_fid(x1) ? LFA_SUCCESS : LFA_NOT_SUPPORTED);
119 break;
120
121 case LFA_GET_INFO:
Manish V Badarkheb9dee502025-05-30 13:17:05 +0100122 /**
123 * The current specification limits this input parameter to be zero for
124 * version 1.0 of LFA
125 */
126 if (x1 == 0ULL) {
127 SMC_RET3(handle, LFA_SUCCESS, lfa_component_count, 0);
128 } else {
129 SMC_RET1(handle, LFA_INVALID_PARAMETERS);
130 }
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100131 break;
132
133 case LFA_GET_INVENTORY:
Manish V Badarkhe06a6f292025-04-15 20:16:34 +0100134 if (lfa_component_count == 0U) {
135 SMC_RET1(handle, LFA_WRONG_STATE);
136 }
137
138 /*
139 * Check if fw_seq_id is in range. LFA_GET_INFO must be called first to scan
140 * platform firmware and create a valid number of firmware components.
141 */
142 if (fw_seq_id >= lfa_component_count) {
143 SMC_RET1(handle, LFA_INVALID_PARAMETERS);
144 }
145
146 /*
147 * grab the UUID of asked fw_seq_id and set the return UUID
148 * variables
149 */
150 uuid_p = (uint8_t *)&lfa_components[fw_seq_id].uuid;
151 memcpy(&retx1, uuid_p, sizeof(uint64_t));
152 memcpy(&retx2, uuid_p + sizeof(uint64_t), sizeof(uint64_t));
153
154 /*
155 * check the given fw_seq_id's update available
156 * and accordingly set the active_pending flag
157 */
158 lfa_components[fw_seq_id].activation_pending =
159 is_plat_lfa_activation_pending(fw_seq_id);
160
161 INFO("Component %lu %s live activation:\n", x1,
162 lfa_components[fw_seq_id].activator ? "supports" :
163 "does not support");
164
165 if (lfa_components[fw_seq_id].activator != NULL) {
166 INFO("Activation pending: %s\n",
167 lfa_components[fw_seq_id].activation_pending ? "true" : "false");
168 }
169
170 INFO("x1 = 0x%016lx, x2 = 0x%016lx\n", retx1, retx2);
171
172 SMC_RET4(handle, LFA_SUCCESS, retx1, retx2, get_fw_activation_flags(fw_seq_id));
173
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100174 break;
175
176 case LFA_PRIME:
177 break;
178
179 case LFA_ACTIVATE:
180 break;
181
182 case LFA_CANCEL:
Manish V Badarkhe3f7b2862025-04-15 20:16:35 +0100183 ret = lfa_cancel(x1);
184 SMC_RET1(handle, ret);
Manish V Badarkhecf48f492025-04-15 20:16:32 +0100185 break;
186
187 default:
188 WARN("Unimplemented LFA Service Call: 0x%x\n", smc_fid);
189 SMC_RET1(handle, SMC_UNK);
190 break; /* unreachable */
191
192 }
193
194 SMC_RET1(handle, SMC_UNK);
195
196 return 0;
197}