blob: cbe66ce8e49a339ee899404990dfa0dd25d062af [file] [log] [blame]
Imre Kis66321592020-11-23 03:15:50 +01001// SPDX-License-Identifier: BSD-3-Clause
2/*
Jelle Sels318263e2022-12-07 14:15:39 +01003 * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
Imre Kis66321592020-11-23 03:15:50 +01004 */
5
6#include "sp_discovery.h"
7#include "ffa_api.h"
8#include "sp_rxtx.h"
9#include "util.h"
10#include <string.h>
11
Imre Kisc81995e2021-01-12 22:28:21 +010012static const struct sp_uuid uuid_nil = { 0 };
Imre Kis66321592020-11-23 03:15:50 +010013
14sp_result sp_discovery_ffa_version_get(uint16_t *major, uint16_t *minor)
15{
16 uint32_t version = 0;
17 ffa_result ffa_res = FFA_OK;
18
19 ffa_res = ffa_version(&version);
20 if (ffa_res != FFA_OK) {
21 *major = UINT16_C(0);
22 *minor = UINT16_C(0);
23
24 return SP_RESULT_FFA(ffa_res);
25 }
26
27 *major = (version >> FFA_VERSION_MAJOR_SHIFT) & FFA_VERSION_MAJOR_MASK;
28 *minor = (version >> FFA_VERSION_MINOR_SHIFT) & FFA_VERSION_MINOR_MASK;
29
30 return SP_RESULT_OK;
31}
32
33sp_result sp_discovery_own_id_get(uint16_t *id)
34{
35 ffa_result ffa_res = FFA_OK;
36
37 ffa_res = ffa_id_get(id);
38 return SP_RESULT_FFA(ffa_res);
39}
40
Jelle Sels318263e2022-12-07 14:15:39 +010041static void unpack_ffa_info(const struct ffa_partition_information *ffa_info,
Imre Kis66321592020-11-23 03:15:50 +010042 struct sp_partition_info *sp_info)
43{
44 uint32_t props = ffa_info->partition_properties;
45
46 sp_info->partition_id = ffa_info->partition_id;
47 sp_info->execution_context_count = ffa_info->execution_context_count;
48 sp_info->supports_direct_requests =
Imre Kisc81995e2021-01-12 22:28:21 +010049 props & FFA_PARTITION_SUPPORTS_DIRECT_REQUESTS;
Imre Kis66321592020-11-23 03:15:50 +010050 sp_info->can_send_direct_requests =
Imre Kisc81995e2021-01-12 22:28:21 +010051 props & FFA_PARTITION_CAN_SEND_DIRECT_REQUESTS;
Imre Kis66321592020-11-23 03:15:50 +010052 sp_info->supports_indirect_requests =
Imre Kisc81995e2021-01-12 22:28:21 +010053 props & FFA_PARTITION_SUPPORTS_INDIRECT_REQUESTS;
Imre Kis595c5d02024-01-15 15:28:19 +010054#if CFG_FFA_VERSION >= FFA_VERSION_1_1
55 sp_info->partition_id_type =
56 (props >> FFA_PARTITION_PART_ID_SHIFT) & FFA_PARTITION_PART_ID_MASK;
57 sp_info->inform_vm_create = props & FFA_PARTITION_INFORM_VM_CREATE;
58 sp_info->inform_vm_destroy = props & FFA_PARTITION_INFORM_VM_DESTROY;
59 if (props & FFA_PARTITION_AARCH64_EXECUTION_STATE)
60 sp_info->execution_state = sp_execution_state_aarch64;
61 else
62 sp_info->execution_state = sp_execution_state_aarch32;
63 memcpy(sp_info->uuid.uuid, ffa_info->uuid.uuid, sizeof(sp_info->uuid.uuid));
64
65#endif /* CFG_FFA_VERSION */
Imre Kis66321592020-11-23 03:15:50 +010066}
67
Imre Kis595c5d02024-01-15 15:28:19 +010068static sp_result partition_info_get(const struct sp_uuid *uuid, struct sp_partition_info info[],
69 uint32_t *count, bool allow_nil_uuid)
Imre Kis66321592020-11-23 03:15:50 +010070{
71 const struct ffa_partition_information *ffa_info = NULL;
72 uint32_t ffa_count = 0;
73 uint32_t i = 0;
74 sp_result sp_res = SP_RESULT_OK;
Jelle Sels318263e2022-12-07 14:15:39 +010075 const void *buffer = NULL;
76 size_t buffer_size = 0;
77 struct ffa_uuid ffa_uuid = { 0 };
78 ffa_result ffa_res = FFA_OK;
Imre Kis595c5d02024-01-15 15:28:19 +010079 uint32_t __maybe_unused ffa_size = 0;
Imre Kis66321592020-11-23 03:15:50 +010080
Imre Kisc81995e2021-01-12 22:28:21 +010081 if (count == NULL)
Imre Kis66321592020-11-23 03:15:50 +010082 return SP_RESULT_INVALID_PARAMETERS;
83
Imre Kisc81995e2021-01-12 22:28:21 +010084 if (info == NULL) {
85 *count = UINT32_C(0);
86 return SP_RESULT_INVALID_PARAMETERS;
87 }
88
Jelle Sels318263e2022-12-07 14:15:39 +010089 if (uuid == NULL || (!allow_nil_uuid &&
90 memcmp(&uuid_nil, uuid, sizeof(struct sp_uuid)) == 0)) {
91 sp_res = SP_RESULT_INVALID_PARAMETERS;
92 goto out;
93 }
94
95 sp_res = sp_rxtx_buffer_rx_get(&buffer, &buffer_size);
Imre Kis66321592020-11-23 03:15:50 +010096 if (sp_res != SP_RESULT_OK) {
Jelle Sels318263e2022-12-07 14:15:39 +010097 goto out;
98 }
99
100 /* Safely convert to FF-A UUID format */
101 memcpy(&ffa_uuid.uuid, uuid->uuid, sizeof(ffa_uuid.uuid));
102
Imre Kis595c5d02024-01-15 15:28:19 +0100103#if CFG_FFA_VERSION == FFA_VERSION_1_0
Jelle Sels318263e2022-12-07 14:15:39 +0100104 ffa_res = ffa_partition_info_get(&ffa_uuid, &ffa_count);
105 if (ffa_res != FFA_OK) {
106 sp_res = SP_RESULT_FFA(ffa_res);
107 goto out;
108 }
Imre Kis595c5d02024-01-15 15:28:19 +0100109#elif CFG_FFA_VERSION >= FFA_VERSION_1_1
110 ffa_res = ffa_partition_info_get(&ffa_uuid, 0, &ffa_count, &ffa_size);
111 if (ffa_res != FFA_OK) {
112 sp_res = SP_RESULT_FFA(ffa_res);
113 goto out;
114 }
115
116 if (ffa_size != sizeof(struct ffa_partition_information)) {
117 /* Non-matching structure size, this may happen in future FF-A versions */
118 sp_res = SP_RESULT_INTERNAL_ERROR;
119 goto out;
120 }
121#endif
Jelle Sels318263e2022-12-07 14:15:39 +0100122
123 if ((ffa_count * sizeof(struct ffa_partition_information)) > buffer_size) {
Imre Kis595c5d02024-01-15 15:28:19 +0100124 /* The indicated amount of info structures doesn't fit into the RX buffer */
Jelle Sels318263e2022-12-07 14:15:39 +0100125 sp_res = SP_RESULT_INTERNAL_ERROR;
126 goto out;
127 }
128
129 ffa_info = (const struct ffa_partition_information *)buffer;
130
131 if (ffa_count == 0) {
132 sp_res = SP_RESULT_NOT_FOUND;
133 goto out;
Imre Kis66321592020-11-23 03:15:50 +0100134 }
135
136 *count = MIN(*count, ffa_count);
137 for (i = 0; i < *count; i++)
138 unpack_ffa_info(&ffa_info[i], &info[i]);
139
140 return SP_RESULT_OK;
Jelle Sels318263e2022-12-07 14:15:39 +0100141
142out:
143 for (i = 0; i < *count; i++)
144 info[i] = (struct sp_partition_info){ 0 };
145 *count = UINT32_C(0);
146
147 return sp_res;
148}
149
150sp_result sp_discovery_partition_id_get(const struct sp_uuid *uuid,
151 uint16_t *id)
152{
153 struct sp_partition_info sp_info = { 0 };
154 sp_result sp_res = SP_RESULT_OK;
155 uint32_t count = 1;
156
157 if (id == NULL)
158 return SP_RESULT_INVALID_PARAMETERS;
159
160 *id = FFA_ID_GET_ID_MASK;
161
162 if (uuid == NULL || memcmp(&uuid_nil, uuid, sizeof(struct sp_uuid)) == 0)
163 return SP_RESULT_INVALID_PARAMETERS;
164
165 sp_res = partition_info_get(uuid, &sp_info, &count, false);
166 if (sp_res != SP_RESULT_OK)
167 return sp_res;
168
169 *id = sp_info.partition_id;
170
171 return SP_RESULT_OK;
172}
173
174sp_result sp_discovery_partition_info_get(const struct sp_uuid *uuid,
175 struct sp_partition_info info[],
176 uint32_t *count)
177{
178 return partition_info_get(uuid, info, count, false);
179}
180
181sp_result sp_discovery_partition_info_get_all(struct sp_partition_info info[],
182 uint32_t *count)
183{
184 return partition_info_get(&uuid_nil, info, count, true);
Imre Kis66321592020-11-23 03:15:50 +0100185}
Imre Kis595c5d02024-01-15 15:28:19 +0100186
187#if CFG_FFA_VERSION >= FFA_VERSION_1_1
188sp_result sp_discovery_partition_info_get_count(const struct sp_uuid *uuid, uint32_t *count)
189{
190 struct ffa_uuid ffa_uuid = { 0 };
191 ffa_result ffa_res = FFA_OK;
192 uint32_t ffa_size = 0;
193
194 if (count == NULL)
195 return SP_RESULT_INVALID_PARAMETERS;
196
197 *count = 0;
198
199 if (uuid == NULL)
200 return SP_RESULT_INVALID_PARAMETERS;
201
202 /* Safely convert to FF-A UUID format */
203 memcpy(&ffa_uuid.uuid, uuid->uuid, sizeof(ffa_uuid.uuid));
204
205 ffa_res = ffa_partition_info_get(&ffa_uuid, FFA_PARTITION_INFO_GET_FLAG_COUNT_ONLY, count,
206 &ffa_size);
207 if (ffa_res != FFA_OK)
208 return SP_RESULT_FFA(ffa_res);
209
210 if (ffa_size != 0)
211 /* Size is MBZ if FFA_PARTITION_INFO_GET_FLAG_COUNT_ONLY is set */
212 return SP_RESULT_INTERNAL_ERROR;
213
214 return SP_RESULT_OK;
215}
216#endif /* CFG_FFA_VERSION */