1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * System Control and Management Interface (SCMI) support
9 * resource management support.
10 */
11
12 #include <mod_resource_perms.h>
13 #include <mod_scmi_std.h>
14
15 #include <fwk_assert.h>
16 #include <fwk_log.h>
17 #include <fwk_mm.h>
18 #include <fwk_module.h>
19 #include <fwk_module_idx.h>
20 #include <fwk_status.h>
21 #include <fwk_string.h>
22
23 #include <inttypes.h>
24
25 struct res_perms_ctx {
26 /*! platform config data */
27 struct mod_res_resource_perms_config *config;
28
29 /*! Number of agents for the platform. */
30 uint32_t agent_count;
31
32 /*! Number of protocols for the platform. */
33 uint32_t protocol_count;
34
35 /*! Number of clock resources for the platform. */
36 uint32_t clock_count;
37
38 /*! Number of sensor resources for the platform. */
39 uint32_t sensor_count;
40
41 /*! Number of power domain resources for the platform. */
42 uint32_t pd_count;
43
44 /*! Number of performance domain resources for the platform. */
45 uint32_t perf_count;
46
47 /*! Number of devices for the platform. */
48 uint32_t device_count;
49
50 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
51 /*! Number of reset domain resources for the platform. */
52 uint32_t reset_domain_count;
53 #endif
54
55 /*! Number of voltage domain resources for the platform. */
56 uint32_t voltd_count;
57
58 /*!
59 * The default is for an agent to have permission to access any
60 * resource. In order to deny permissions to an agent the table
61 * must be created and the relevant bit SET. If the table is not
62 * created then all agents have access to all resources.
63 *
64 * The agent_permissions table can be created in the SCMI config
65 * file.
66 *
67 * If the agent_permissions table was not set up in the config,
68 * the agent will not be able to allocate permissions at run-time.
69 *
70 * Note that if the agent wants to set permissions at run-time
71 * the agent_permissions[] tables must be allocated in writable
72 * memory.
73 */
74 struct mod_res_agent_permission *agent_permissions;
75
76 /*!
77 * The list of domain devices in the system. If this is not set then setting
78 * device permissions for an agent is not supported.
79 */
80 struct mod_res_device *domain_devices;
81 };
82
83 struct res_perms_backup {
84 /*! \brief Power Domain:Resource permissions. */
85 mod_res_perms_t *scmi_pd_perms;
86
87 /*! Performance:Resource permissions. */
88 mod_res_perms_t *scmi_perf_perms;
89
90 /*! \brief Clock:Resource permissions. */
91 mod_res_perms_t *scmi_clock_perms;
92
93 /*! \brief Sensor:Resource permissions. */
94 mod_res_perms_t *scmi_sensor_perms;
95
96 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
97 /*! \brief Reset Domain:Resource permissions. */
98 mod_res_perms_t *scmi_reset_domain_perms;
99 #endif
100
101 /*! \brief Voltage Domain:Resource permissions. */
102 mod_res_perms_t *scmi_voltd_perms;
103 };
104
105 static struct res_perms_ctx resources_perms_ctx;
106 static struct res_perms_backup resources_perms_backup;
107
108 /*
109 * Map the agent-id to the corresponding index in the table.
110 *
111 * Returns FWK_SUCCESS if the agent_id is valid for the platform.
112 * Returns FWK_E_PARAM if the agent_is id not valid for the platform.
113 *
114 * This is a weak definition to allow the platform override the function
115 * to deal with platform-specific agent mappings, eg, for non-sequential
116 * agent IDs or for sharing a single set of permissions between multiple
117 * agents, etc.
118 */
mod_res_agent_id_to_index(uint32_t agent_id,uint32_t * agent_idx)119 __attribute((weak)) int mod_res_agent_id_to_index(
120 uint32_t agent_id,
121 uint32_t *agent_idx)
122 {
123 uint32_t idx = agent_id - 1;
124
125 if (idx < resources_perms_ctx.agent_count) {
126 *agent_idx = idx;
127 return FWK_SUCCESS;
128 }
129
130 return FWK_E_PARAM;
131 }
132
133 /*
134 * Map the protocol-id to the corresponding index in the table.
135 *
136 * Returns true if the protocol_id is valid for the platform.
137 * Returns false if the protocol_is id not valid for the platform.
138 *
139 * This is a weak definition to allow the platform override the function
140 * to deal with platform-specific protocol mappings, eg, for non-contiguous
141 * protocol IDs.
142 */
mod_res_plat_protocol_id_to_index(uint32_t protocol_id,uint32_t * protocol_idx)143 __attribute((weak)) int mod_res_plat_protocol_id_to_index(
144 uint32_t protocol_id,
145 uint32_t *protocol_idx)
146 {
147 return FWK_E_PARAM;
148 }
149
mod_res_protocol_id_to_index(uint32_t protocol_id,uint32_t * protocol_idx)150 static int mod_res_protocol_id_to_index(
151 uint32_t protocol_id,
152 uint32_t *protocol_idx)
153 {
154 if ((protocol_id >= MOD_SCMI_PLATFORM_PROTOCOL_ID_MIN) &&
155 (protocol_id <= MOD_SCMI_PLATFORM_PROTOCOL_ID_MAX)) {
156 return mod_res_plat_protocol_id_to_index(protocol_id, protocol_idx);
157 }
158
159 switch (protocol_id) {
160 case MOD_SCMI_PROTOCOL_ID_BASE:
161 case MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN:
162 case MOD_SCMI_PROTOCOL_ID_SYS_POWER:
163 case MOD_SCMI_PROTOCOL_ID_PERF:
164 case MOD_SCMI_PROTOCOL_ID_CLOCK:
165 case MOD_SCMI_PROTOCOL_ID_SENSOR:
166 case MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN:
167 case MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
168 *protocol_idx = protocol_id - MOD_SCMI_PROTOCOL_ID_BASE;
169 return FWK_SUCCESS;
170 default:
171 return FWK_E_PARAM;
172 }
173 }
174
175 /*
176 * Map the message-id to the corresponding index in the resources
177 * table.
178 *
179 * Returns FWK_SUCCESS if the message_id is valid for the protocol.
180 * Returns FWK_E_PARAM if the message_id not valid for the protocol.
181 *
182 * Contents of idx are only valid if >= 0.
183 *
184 * This is a weak definition to allow the platform override the function
185 * to deal with platform-specific message ID mappings, eg, for non-contiguous
186 * message IDs.
187 */
mod_res_plat_message_id_to_index(uint32_t protocol_id,uint32_t message_id,int32_t * message_idx)188 __attribute((weak)) int mod_res_plat_message_id_to_index(
189 uint32_t protocol_id,
190 uint32_t message_id,
191 int32_t *message_idx)
192 {
193 return FWK_E_PARAM;
194 }
195
mod_res_message_id_to_index(uint32_t protocol_id,uint32_t message_id,int32_t * message_idx)196 static int mod_res_message_id_to_index(
197 uint32_t protocol_id,
198 uint32_t message_id,
199 int32_t *message_idx)
200 {
201 /*
202 * All protocols have
203 *
204 * 0: VERSION
205 * 1: ATTRIBUTES
206 * 2: MSG_ATTRIBUTES
207 *
208 * messages which are available to all agents.
209 *
210 * If the message is not managed in the permissions
211 * we return false and idx == -1.
212 */
213 *message_idx = -1;
214
215 if ((protocol_id >= MOD_SCMI_PLATFORM_PROTOCOL_ID_MIN) &&
216 (protocol_id <= MOD_SCMI_PLATFORM_PROTOCOL_ID_MAX)) {
217 return mod_res_plat_message_id_to_index(
218 protocol_id, message_id, message_idx);
219 }
220
221 if (message_id < 3) {
222 return FWK_SUCCESS;
223 }
224
225 switch (protocol_id) {
226 case MOD_SCMI_PROTOCOL_ID_BASE:
227 if (message_id >= MOD_SCMI_BASE_COMMAND_COUNT) {
228 return FWK_E_PARAM;
229 }
230 if (message_id == MOD_SCMI_BASE_NOTIFY_ERRORS) {
231 *message_idx = 0;
232 }
233 return FWK_SUCCESS;
234
235 case MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN:
236 if (message_id >= MOD_SCMI_PD_POWER_COMMAND_COUNT) {
237 return FWK_E_PARAM;
238 }
239 if ((message_id >= MOD_SCMI_PD_POWER_DOMAIN_ATTRIBUTES) &&
240 (message_id <= MOD_SCMI_PD_POWER_STATE_NOTIFY)) {
241 *message_idx = (int32_t)(
242 message_id - (uint32_t)MOD_SCMI_PD_POWER_DOMAIN_ATTRIBUTES);
243 }
244 return FWK_SUCCESS;
245
246 case MOD_SCMI_PROTOCOL_ID_SYS_POWER:
247 if (message_id >= MOD_SCMI_SYS_POWER_COMMAND_COUNT) {
248 return FWK_E_PARAM;
249 }
250 if ((message_id >= MOD_SCMI_SYS_POWER_STATE_SET) &&
251 (message_id <= MOD_SCMI_SYS_POWER_STATE_NOTIFY)) {
252 *message_idx =
253 (int32_t)(message_id - (uint32_t)MOD_SCMI_SYS_POWER_STATE_SET);
254 }
255 return FWK_SUCCESS;
256
257 case MOD_SCMI_PROTOCOL_ID_PERF:
258 if (message_id >= MOD_SCMI_PERF_COMMAND_COUNT) {
259 return FWK_E_PARAM;
260 }
261 if ((message_id >= MOD_SCMI_PERF_DOMAIN_ATTRIBUTES) &&
262 (message_id <= MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL)) {
263 *message_idx = (int32_t)(
264 message_id - (uint32_t)MOD_SCMI_PERF_DOMAIN_ATTRIBUTES);
265 }
266 return FWK_SUCCESS;
267
268 case MOD_SCMI_PROTOCOL_ID_CLOCK:
269 if (message_id >= MOD_SCMI_CLOCK_COMMAND_COUNT) {
270 return FWK_E_PARAM;
271 }
272 if ((message_id >= MOD_SCMI_CLOCK_ATTRIBUTES) &&
273 (message_id <= MOD_SCMI_CLOCK_CONFIG_SET)) {
274 *message_idx =
275 (int32_t)(message_id - (uint32_t)MOD_SCMI_CLOCK_ATTRIBUTES);
276 }
277 return FWK_SUCCESS;
278
279 case MOD_SCMI_PROTOCOL_ID_SENSOR:
280 if (message_id >= MOD_SCMI_SENSOR_COMMAND_COUNT) {
281 return FWK_E_PARAM;
282 }
283 if ((message_id >= MOD_SCMI_SENSOR_DESCRIPTION_GET) &&
284 (message_id <= MOD_SCMI_SENSOR_READING_GET)) {
285 *message_idx = (int32_t)(
286 message_id - (uint32_t)MOD_SCMI_SENSOR_DESCRIPTION_GET);
287 }
288 return FWK_SUCCESS;
289
290 case MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN:
291 if (message_id >= MOD_SCMI_RESET_COMMAND_COUNT) {
292 return FWK_E_PARAM;
293 }
294 if ((message_id >= MOD_SCMI_RESET_DOMAIN_ATTRIBUTES) &&
295 (message_id <= MOD_SCMI_RESET_NOTIFY)) {
296 *message_idx = (int32_t)(
297 message_id - (uint32_t)MOD_SCMI_RESET_DOMAIN_ATTRIBUTES);
298 }
299 return FWK_SUCCESS;
300
301 case MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
302 if (message_id >= MOD_SCMI_VOLTD_COMMAND_COUNT) {
303 return FWK_E_PARAM;
304 }
305 if ((message_id >= MOD_SCMI_VOLTD_DOMAIN_ATTRIBUTES) &&
306 (message_id <= MOD_SCMI_VOLTD_LEVEL_GET)) {
307 *message_idx = (int32_t)(
308 message_id - (uint32_t)MOD_SCMI_VOLTD_DOMAIN_ATTRIBUTES);
309 }
310 return FWK_SUCCESS;
311
312 default:
313 return FWK_E_PARAM;
314 }
315 }
316
317 /*
318 * Map the resource-id to the corresponding element index in the resources
319 * table.
320 *
321 * Returns FWK_SUCCESS if the resource_id is valid for the protocol.
322 * Returns FWK_E_PARAM if the resource_id not valid for the protocol.
323 *
324 * Contents of resource_idx are only valid if >= 0.
325 *
326 * This is a weak definition to allow the platform override the function
327 * to deal with platform-specific ID mappings, eg, for non-contiguous
328 * IDs.
329 */
mod_res_plat_resource_id_to_index(uint32_t agent_id,uint32_t protocol_id,uint32_t message_id,uint32_t resource_id,int32_t * resource_idx)330 __attribute((weak)) int mod_res_plat_resource_id_to_index(
331 uint32_t agent_id,
332 uint32_t protocol_id,
333 uint32_t message_id,
334 uint32_t resource_id,
335 int32_t *resource_idx)
336 {
337 return FWK_E_PARAM;
338 }
339
mod_res_resource_id_to_index(uint32_t agent_id,uint32_t protocol_id,uint32_t message_id,uint32_t resource_id,int32_t * resource_idx)340 static int mod_res_resource_id_to_index(
341 uint32_t agent_id,
342 uint32_t protocol_id,
343 uint32_t message_id,
344 uint32_t resource_id,
345 int32_t *resource_idx)
346 {
347 uint32_t agent_idx;
348 int message_count;
349 int message_offset;
350 int resource_size;
351 int status;
352
353 /*
354 * All protocols have
355 *
356 * 0: VERSION
357 * 1: ATTRIBUTES
358 * 2: MSG_ATTRIBUTES
359 *
360 * messages which are available to all agents.
361 *
362 * If the message is not managed in the permissions
363 * we return false and idx == -1.
364 */
365 *resource_idx = -1;
366
367 if ((protocol_id >= MOD_SCMI_PLATFORM_PROTOCOL_ID_MIN) &&
368 (protocol_id <= MOD_SCMI_PLATFORM_PROTOCOL_ID_MAX)) {
369 return mod_res_plat_resource_id_to_index(
370 agent_id, protocol_id, message_id, resource_id, resource_idx);
371 }
372
373 if (message_id < 3) {
374 return FWK_SUCCESS;
375 }
376
377 /*
378 * Each table is organised as
379 *
380 * agent[number_of_agents].commands[number_of_commands_for_protocol]
381 */
382
383 switch (protocol_id) {
384 case MOD_SCMI_PROTOCOL_ID_BASE:
385 /* No per-resource managemment for SCMI Base Protocol */
386 return FWK_E_PARAM;
387
388 case MOD_SCMI_PROTOCOL_ID_SYS_POWER:
389 /* No per-resource managemment for SCMI System Power Protocol */
390 return FWK_E_PARAM;
391
392 case MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN:
393 if ((message_id >= MOD_SCMI_PD_POWER_DOMAIN_ATTRIBUTES) &&
394 (message_id <= MOD_SCMI_PD_POWER_STATE_NOTIFY)) {
395 message_count = (int)MOD_SCMI_PD_POWER_STATE_NOTIFY -
396 (int)MOD_SCMI_PD_POWER_DOMAIN_ATTRIBUTES + 1;
397 message_offset =
398 (int)(message_id - (uint32_t)MOD_SCMI_PD_POWER_DOMAIN_ATTRIBUTES);
399 resource_size = (int)resources_perms_ctx.pd_count;
400 break;
401 }
402 return FWK_E_PARAM;
403
404 case MOD_SCMI_PROTOCOL_ID_PERF:
405 if ((message_id >= MOD_SCMI_PERF_DOMAIN_ATTRIBUTES) &&
406 (message_id <= MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL)) {
407 message_count = (int)MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL -
408 (int)MOD_SCMI_PERF_DOMAIN_ATTRIBUTES + 1;
409 message_offset =
410 (int)(message_id - (uint32_t)MOD_SCMI_PERF_DOMAIN_ATTRIBUTES);
411 resource_size = (int)resources_perms_ctx.perf_count;
412 break;
413 }
414 return FWK_E_PARAM;
415
416 case MOD_SCMI_PROTOCOL_ID_CLOCK:
417 if ((message_id >= MOD_SCMI_CLOCK_ATTRIBUTES) &&
418 (message_id <= MOD_SCMI_CLOCK_CONFIG_SET)) {
419 message_count = (int)MOD_SCMI_CLOCK_CONFIG_SET -
420 (int)MOD_SCMI_CLOCK_ATTRIBUTES + 1;
421 message_offset =
422 (int)(message_id - (uint32_t)MOD_SCMI_CLOCK_ATTRIBUTES);
423 resource_size = (int)resources_perms_ctx.clock_count;
424 break;
425 }
426 return FWK_E_PARAM;
427
428 case MOD_SCMI_PROTOCOL_ID_SENSOR:
429 if ((message_id >= MOD_SCMI_SENSOR_DESCRIPTION_GET) &&
430 (message_id <= MOD_SCMI_SENSOR_READING_GET)) {
431 message_count = (int)MOD_SCMI_SENSOR_READING_GET -
432 (int)MOD_SCMI_SENSOR_DESCRIPTION_GET + 1;
433 message_offset =
434 (int)(message_id - (uint32_t)MOD_SCMI_SENSOR_DESCRIPTION_GET);
435 resource_size = (int)resources_perms_ctx.sensor_count;
436 break;
437 }
438 return FWK_E_PARAM;
439
440 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
441 case MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN:
442 if ((message_id >= MOD_SCMI_RESET_DOMAIN_ATTRIBUTES) &&
443 (message_id <= MOD_SCMI_RESET_NOTIFY)) {
444 message_count = (int)MOD_SCMI_RESET_NOTIFY -
445 (int)MOD_SCMI_RESET_DOMAIN_ATTRIBUTES + 1;
446 message_offset =
447 (int)(message_id - (uint32_t)MOD_SCMI_RESET_DOMAIN_ATTRIBUTES);
448 resource_size = (int)resources_perms_ctx.reset_domain_count;
449 break;
450 }
451 return FWK_E_PARAM;
452 #endif
453
454 case MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
455 if ((message_id >= MOD_SCMI_VOLTD_DOMAIN_ATTRIBUTES) &&
456 (message_id <= MOD_SCMI_VOLTD_LEVEL_GET)) {
457 message_count = (int)MOD_SCMI_VOLTD_LEVEL_GET -
458 (int)MOD_SCMI_VOLTD_DOMAIN_ATTRIBUTES + 1;
459 message_offset =
460 (int)(message_id - (uint32_t)MOD_SCMI_VOLTD_DOMAIN_ATTRIBUTES);
461 resource_size = (int)resources_perms_ctx.voltd_count;
462 break;
463 }
464 return FWK_E_PARAM;
465
466 default:
467 return FWK_E_PARAM;
468 }
469
470 status = mod_res_agent_id_to_index(agent_id, &agent_idx);
471 if ((status != FWK_SUCCESS) ||
472 (agent_idx >= resources_perms_ctx.agent_count)) {
473 return FWK_E_PARAM;
474 }
475
476 resource_size =
477 (int)MOD_RES_PERMS_RESOURCE_ELEMENT((unsigned int)resource_size) + 1;
478
479 /*
480 * message_count: the number of messages for the agent.
481 * resource_size: the number of resource elements per message type.
482 * message_offset: the offset of this message from message 0.
483 *
484 * [1]: &agent[agent_idx].message[0]
485 * [2]: &agent[agent_idx].message[message_id]
486 * [3]: &agent[agent_idx].message[message_id].resource[resource_id]
487 */
488 *resource_idx = (int32_t)(
489 (agent_idx * message_count * resource_size) + /* [1] */
490 (message_offset * resource_size) + /* [2] */
491 MOD_RES_PERMS_RESOURCE_ELEMENT(resource_id)); /* [3] */
492
493 return FWK_SUCCESS;
494 }
495
496 /*
497 * Check whether an agent has access to a protocol.
498 *
499 * Note that we will always check the higher permissions levels
500 * when called, so
501 *
502 * protocol -> message -> resource
503 */
504
505 /*
506 * Check whether an agent has access to a protocol.
507 *
508 * Note that we will always check the higher permissions levels
509 * when called, so
510 *
511 * protocol -> message -> resource
512 */
513 __attribute((weak)) enum mod_res_perms_permissions
mod_res_plat_agent_protocol_permissions(uint32_t agent_id,uint32_t protocol_id)514 mod_res_plat_agent_protocol_permissions(
515 uint32_t agent_id,
516 uint32_t protocol_id)
517 {
518 return MOD_RES_PERMS_ACCESS_DENIED;
519 }
520
agent_protocol_permissions(uint32_t agent_id,uint32_t protocol_id)521 static enum mod_res_perms_permissions agent_protocol_permissions(
522 uint32_t agent_id,
523 uint32_t protocol_id)
524 {
525 uint32_t agent_idx;
526 uint32_t protocol_idx;
527 mod_res_perms_t perms;
528 int status;
529
530 /* No Agent:Protocol permissions management */
531 if ((agent_id == 0) || (resources_perms_ctx.agent_permissions == NULL) ||
532 (resources_perms_ctx.agent_permissions->agent_protocol_permissions ==
533 NULL)) {
534 return MOD_RES_PERMS_ACCESS_ALLOWED;
535 }
536
537 if ((protocol_id >= MOD_SCMI_PLATFORM_PROTOCOL_ID_MIN) &&
538 (protocol_id <= MOD_SCMI_PLATFORM_PROTOCOL_ID_MAX)) {
539 return mod_res_plat_agent_protocol_permissions(agent_id, protocol_id);
540 }
541
542 status = mod_res_agent_id_to_index(agent_id, &agent_idx);
543 if ((status != FWK_SUCCESS) ||
544 (agent_idx >= resources_perms_ctx.agent_count)) {
545 return MOD_RES_PERMS_ACCESS_DENIED;
546 }
547
548 status = mod_res_protocol_id_to_index(protocol_id, &protocol_idx);
549 if ((status != FWK_SUCCESS) ||
550 (protocol_idx >= resources_perms_ctx.protocol_count)) {
551 return MOD_RES_PERMS_ACCESS_DENIED;
552 }
553
554 perms = resources_perms_ctx.agent_permissions
555 ->agent_protocol_permissions[agent_idx]
556 .protocols;
557
558 /* Agent:Protocol access denied */
559 if (perms & (1U << protocol_idx)) {
560 return MOD_RES_PERMS_ACCESS_DENIED;
561 }
562
563 return MOD_RES_PERMS_ACCESS_ALLOWED;
564 }
565
566 /*
567 * Check whether an agent can access a protocol:message.
568 */
569 __attribute((weak)) enum mod_res_perms_permissions
mod_res_plat_agent_message_permissions(uint32_t agent_id,uint32_t protocol_id,uint32_t message_id)570 mod_res_plat_agent_message_permissions(
571 uint32_t agent_id,
572 uint32_t protocol_id,
573 uint32_t message_id)
574 {
575 return MOD_RES_PERMS_ACCESS_DENIED;
576 }
577
agent_message_permissions(uint32_t agent_id,uint32_t protocol_id,uint32_t message_id)578 static enum mod_res_perms_permissions agent_message_permissions(
579 uint32_t agent_id,
580 uint32_t protocol_id,
581 uint32_t message_id)
582 {
583 enum mod_res_perms_permissions protocol_perms;
584 uint32_t agent_idx;
585 uint32_t protocol_idx;
586 int32_t message_idx;
587 mod_res_perms_t perms;
588 int status;
589
590 /* No permissions management */
591 if ((agent_id == 0) || (resources_perms_ctx.agent_permissions == NULL)) {
592 return MOD_RES_PERMS_ACCESS_ALLOWED;
593 }
594
595 if ((protocol_id >= MOD_SCMI_PLATFORM_PROTOCOL_ID_MIN) &&
596 (protocol_id <= MOD_SCMI_PLATFORM_PROTOCOL_ID_MAX)) {
597 return mod_res_plat_agent_message_permissions(
598 agent_id, protocol_id, message_id);
599 }
600
601 /* Agent:Protocol access denied */
602 protocol_perms = agent_protocol_permissions(agent_id, protocol_id);
603 if (protocol_perms == MOD_RES_PERMS_ACCESS_DENIED) {
604 return MOD_RES_PERMS_ACCESS_DENIED;
605 }
606
607 /* No Agent:Protocol:command permissions management */
608 if (resources_perms_ctx.agent_permissions->agent_msg_permissions == NULL) {
609 return MOD_RES_PERMS_ACCESS_ALLOWED;
610 }
611
612 status = mod_res_message_id_to_index(protocol_id, message_id, &message_idx);
613 if (status != FWK_SUCCESS) {
614 return MOD_RES_PERMS_ACCESS_DENIED;
615 }
616
617 if (message_idx < 0) {
618 return MOD_RES_PERMS_ACCESS_ALLOWED;
619 }
620
621 status = mod_res_agent_id_to_index(agent_id, &agent_idx);
622 if (status != FWK_SUCCESS) {
623 return MOD_RES_PERMS_ACCESS_DENIED;
624 }
625
626 status = mod_res_protocol_id_to_index(protocol_id, &protocol_idx);
627 if (status != FWK_SUCCESS) {
628 return MOD_RES_PERMS_ACCESS_DENIED;
629 }
630
631 perms =
632 resources_perms_ctx.agent_permissions->agent_msg_permissions[agent_idx]
633 .messages[protocol_idx];
634
635 /* Agent:Protocol:message access denied */
636 if (perms & (1U << (uint32_t)message_idx)) {
637 return MOD_RES_PERMS_ACCESS_DENIED;
638 }
639
640 return MOD_RES_PERMS_ACCESS_ALLOWED;
641 }
642
643 /*
644 * Check the permissions for agent:protocol:message:resource.
645 *
646 * Note that BASE and SYSTEM_POWER protocols do not support
647 * resource-level permissions checking, these protocols are
648 * managed at the agent:protocol:message level.
649 */
650 __attribute((weak)) enum mod_res_perms_permissions
mod_res_plat_agent_resource_permissions(uint32_t agent_id,uint32_t protocol_id,uint32_t message_id,uint32_t resource_id)651 mod_res_plat_agent_resource_permissions(
652 uint32_t agent_id,
653 uint32_t protocol_id,
654 uint32_t message_id,
655 uint32_t resource_id)
656 {
657 return MOD_RES_PERMS_ACCESS_DENIED;
658 }
659
agent_resource_permissions(uint32_t agent_id,uint32_t protocol_id,uint32_t message_id,uint32_t resource_id)660 static enum mod_res_perms_permissions agent_resource_permissions(
661 uint32_t agent_id,
662 uint32_t protocol_id,
663 uint32_t message_id,
664 uint32_t resource_id)
665 {
666 enum mod_res_perms_permissions message_perms;
667 uint32_t agent_idx;
668 int32_t message_idx;
669 int32_t resource_idx;
670 mod_res_perms_t perms;
671 int status;
672
673 /* No permissions management */
674 if ((agent_id == 0) || (resources_perms_ctx.agent_permissions == NULL)) {
675 return MOD_RES_PERMS_ACCESS_ALLOWED;
676 }
677
678 if ((protocol_id >= MOD_SCMI_PLATFORM_PROTOCOL_ID_MIN) &&
679 (protocol_id <= MOD_SCMI_PLATFORM_PROTOCOL_ID_MAX)) {
680 return mod_res_plat_agent_resource_permissions(
681 agent_id, protocol_id, message_id, resource_id);
682 }
683
684 /* Agent:Protocol:command access denied */
685 message_perms =
686 agent_message_permissions(agent_id, protocol_id, message_id);
687 if (message_perms == MOD_RES_PERMS_ACCESS_DENIED) {
688 return MOD_RES_PERMS_ACCESS_DENIED;
689 }
690
691 status = mod_res_message_id_to_index(protocol_id, message_id, &message_idx);
692 if (status != FWK_SUCCESS) {
693 return MOD_RES_PERMS_ACCESS_DENIED;
694 }
695 if (message_idx < 0) {
696 return MOD_RES_PERMS_ACCESS_ALLOWED;
697 }
698
699 status = mod_res_agent_id_to_index(agent_id, &agent_idx);
700 if (status != FWK_SUCCESS) {
701 return MOD_RES_PERMS_ACCESS_DENIED;
702 }
703
704 status = mod_res_resource_id_to_index(
705 agent_id, protocol_id, message_id, resource_id, &resource_idx);
706 if (status != FWK_SUCCESS) {
707 return MOD_RES_PERMS_ACCESS_DENIED;
708 }
709 if (resource_idx < 0) {
710 return MOD_RES_PERMS_ACCESS_ALLOWED;
711 }
712
713 switch (protocol_id) {
714 case MOD_SCMI_PROTOCOL_ID_BASE:
715 return MOD_RES_PERMS_ACCESS_DENIED;
716
717 case MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN:
718 if (resources_perms_ctx.agent_permissions->scmi_pd_perms == NULL) {
719 return MOD_RES_PERMS_ACCESS_ALLOWED;
720 }
721 if (resource_id >= resources_perms_ctx.pd_count) {
722 return MOD_RES_PERMS_ACCESS_DENIED;
723 }
724 perms =
725 resources_perms_ctx.agent_permissions->scmi_pd_perms[resource_idx];
726 break;
727
728 case MOD_SCMI_PROTOCOL_ID_SYS_POWER:
729 return MOD_RES_PERMS_ACCESS_DENIED;
730
731 case MOD_SCMI_PROTOCOL_ID_PERF:
732 if (resources_perms_ctx.agent_permissions->scmi_perf_perms == NULL) {
733 return MOD_RES_PERMS_ACCESS_ALLOWED;
734 }
735 if (resource_id >= resources_perms_ctx.perf_count) {
736 return MOD_RES_PERMS_ACCESS_DENIED;
737 }
738 perms = resources_perms_ctx.agent_permissions
739 ->scmi_perf_perms[resource_idx];
740 break;
741
742 case MOD_SCMI_PROTOCOL_ID_CLOCK:
743 if (resources_perms_ctx.agent_permissions->scmi_clock_perms == NULL) {
744 return MOD_RES_PERMS_ACCESS_ALLOWED;
745 }
746 if (resource_id >= resources_perms_ctx.clock_count) {
747 return MOD_RES_PERMS_ACCESS_DENIED;
748 }
749 perms = resources_perms_ctx.agent_permissions
750 ->scmi_clock_perms[resource_idx];
751 break;
752
753 case MOD_SCMI_PROTOCOL_ID_SENSOR:
754 if (resources_perms_ctx.agent_permissions->scmi_sensor_perms == NULL) {
755 return MOD_RES_PERMS_ACCESS_ALLOWED;
756 }
757 if (resource_id >= resources_perms_ctx.sensor_count) {
758 return MOD_RES_PERMS_ACCESS_DENIED;
759 }
760 perms = resources_perms_ctx.agent_permissions
761 ->scmi_sensor_perms[resource_idx];
762 break;
763
764 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
765 case MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN:
766 if (resources_perms_ctx.agent_permissions->scmi_reset_domain_perms ==
767 NULL) {
768 return MOD_RES_PERMS_ACCESS_ALLOWED;
769 }
770 if (resource_id >= resources_perms_ctx.reset_domain_count) {
771 return MOD_RES_PERMS_ACCESS_DENIED;
772 }
773 perms = resources_perms_ctx.agent_permissions
774 ->scmi_reset_domain_perms[resource_idx];
775 break;
776 #endif
777
778 case MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
779 if (resources_perms_ctx.agent_permissions->scmi_voltd_perms == NULL) {
780 return MOD_RES_PERMS_ACCESS_ALLOWED;
781 }
782 if (resource_id >= resources_perms_ctx.voltd_count) {
783 return MOD_RES_PERMS_ACCESS_DENIED;
784 }
785 perms = resources_perms_ctx.agent_permissions
786 ->scmi_voltd_perms[resource_idx];
787 break;
788
789 default:
790 return MOD_RES_PERMS_ACCESS_DENIED;
791 }
792
793 /* Agent:Protocol:message:resource access denied */
794 if ((perms & (1U << (MOD_RES_PERMS_RESOURCE_BIT(resource_id))))) {
795 return MOD_RES_PERMS_ACCESS_DENIED;
796 }
797
798 return MOD_RES_PERMS_ACCESS_ALLOWED;
799 }
800
801 /*
802 * Set the permissions for an agent:device.
803 */
set_agent_resource_message_perms(uint32_t agent_id,uint32_t protocol_id,uint32_t message_idx,uint32_t resource_id,mod_res_perms_t * perms,enum mod_res_perms_permissions flags)804 static int set_agent_resource_message_perms(
805 uint32_t agent_id,
806 uint32_t protocol_id,
807 uint32_t message_idx,
808 uint32_t resource_id,
809 mod_res_perms_t *perms,
810 enum mod_res_perms_permissions flags)
811 {
812 int status;
813 int32_t resource_idx;
814 mod_res_perms_t permissions;
815
816 status = mod_res_resource_id_to_index(
817 agent_id, protocol_id, message_idx, resource_id, &resource_idx);
818 if (status != FWK_SUCCESS) {
819 return status;
820 }
821
822 permissions = perms[resource_idx];
823
824 flags =
825 ((flags == 0) ? MOD_RES_PERMS_ACCESS_DENIED :
826 MOD_RES_PERMS_ACCESS_ALLOWED);
827
828 if (flags == MOD_RES_PERMS_ACCESS_ALLOWED) {
829 permissions &= ~(1U << (MOD_RES_PERMS_RESOURCE_BIT(resource_id)));
830 } else {
831 permissions |= (1U << (MOD_RES_PERMS_RESOURCE_BIT(resource_id)));
832 }
833
834 perms[resource_idx] = permissions;
835
836 return FWK_SUCCESS;
837 }
838
set_agent_resource_pd_permissions(uint32_t agent_id,uint32_t resource_id,enum mod_res_perms_permissions flags)839 static int set_agent_resource_pd_permissions(
840 uint32_t agent_id,
841 uint32_t resource_id,
842 enum mod_res_perms_permissions flags)
843 {
844 int status;
845 int32_t message_idx;
846
847 if (resources_perms_ctx.agent_permissions->scmi_pd_perms == NULL) {
848 return FWK_SUCCESS;
849 }
850 if (resource_id >= resources_perms_ctx.pd_count) {
851 return FWK_E_ACCESS;
852 }
853
854 /* Do a backup before making the changes if required */
855 if ((resources_perms_ctx.config->pd_cmd_count != 0) &&
856 (resources_perms_ctx.config->pd_resource_count != 0) &&
857 (resources_perms_backup.scmi_pd_perms == NULL)) {
858 resources_perms_backup.scmi_pd_perms = (mod_res_perms_t *)fwk_mm_alloc(
859 resources_perms_ctx.agent_count *
860 resources_perms_ctx.config->pd_cmd_count *
861 resources_perms_ctx.config->pd_resource_count,
862 sizeof(mod_res_perms_t));
863 fwk_str_memcpy(
864 resources_perms_backup.scmi_pd_perms,
865 resources_perms_ctx.agent_permissions->scmi_pd_perms,
866 resources_perms_ctx.agent_count *
867 resources_perms_ctx.config->pd_cmd_count *
868 resources_perms_ctx.config->pd_resource_count *
869 sizeof(mod_res_perms_t));
870 }
871
872 for (message_idx = (int32_t)MOD_SCMI_PD_POWER_DOMAIN_ATTRIBUTES;
873 message_idx <= MOD_SCMI_PD_POWER_STATE_NOTIFY;
874 message_idx++) {
875 status = set_agent_resource_message_perms(
876 agent_id,
877 MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN,
878 (uint32_t)message_idx,
879 resource_id,
880 resources_perms_ctx.agent_permissions->scmi_pd_perms,
881 flags);
882
883 if (status != FWK_SUCCESS) {
884 return status;
885 }
886 }
887
888 return FWK_SUCCESS;
889 }
890
set_agent_resource_perf_permissions(uint32_t agent_id,uint32_t resource_id,enum mod_res_perms_permissions flags)891 static int set_agent_resource_perf_permissions(
892 uint32_t agent_id,
893 uint32_t resource_id,
894 enum mod_res_perms_permissions flags)
895 {
896 int status;
897 int32_t message_idx;
898
899 if (resources_perms_ctx.agent_permissions->scmi_perf_perms == NULL) {
900 return FWK_SUCCESS;
901 }
902 if (resource_id >= resources_perms_ctx.perf_count) {
903 return FWK_E_ACCESS;
904 }
905
906 /* Do a backup before making the changes if required */
907 if ((resources_perms_ctx.config->perf_cmd_count != 0) &&
908 (resources_perms_ctx.config->perf_resource_count != 0) &&
909 (resources_perms_backup.scmi_perf_perms == NULL)) {
910 resources_perms_backup.scmi_perf_perms =
911 (mod_res_perms_t *)fwk_mm_alloc(
912 resources_perms_ctx.agent_count *
913 resources_perms_ctx.config->perf_cmd_count *
914 resources_perms_ctx.config->perf_resource_count,
915 sizeof(mod_res_perms_t));
916 fwk_str_memcpy(
917 resources_perms_backup.scmi_perf_perms,
918 resources_perms_ctx.agent_permissions->scmi_perf_perms,
919 resources_perms_ctx.agent_count *
920 resources_perms_ctx.config->perf_cmd_count *
921 resources_perms_ctx.config->perf_resource_count *
922 sizeof(mod_res_perms_t));
923 }
924
925 for (message_idx = (int32_t)MOD_SCMI_PERF_DOMAIN_ATTRIBUTES;
926 message_idx <= MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL;
927 message_idx++) {
928 status = set_agent_resource_message_perms(
929 agent_id,
930 MOD_SCMI_PROTOCOL_ID_PERF,
931 (uint32_t)message_idx,
932 resource_id,
933 resources_perms_ctx.agent_permissions->scmi_perf_perms,
934 flags);
935
936 if (status != FWK_SUCCESS) {
937 return status;
938 }
939 }
940
941 return FWK_SUCCESS;
942 }
943
set_agent_resource_clock_permissions(uint32_t agent_id,uint32_t resource_id,enum mod_res_perms_permissions flags)944 static int set_agent_resource_clock_permissions(
945 uint32_t agent_id,
946 uint32_t resource_id,
947 enum mod_res_perms_permissions flags)
948 {
949 int status;
950 int32_t message_idx;
951
952 if (resources_perms_ctx.agent_permissions->scmi_clock_perms == NULL) {
953 return FWK_SUCCESS;
954 }
955 if (resource_id >= resources_perms_ctx.clock_count) {
956 return FWK_E_ACCESS;
957 }
958
959 /* Do a backup before making the changes if required */
960 if ((resources_perms_ctx.config->clock_cmd_count != 0) &&
961 (resources_perms_ctx.config->clock_resource_count != 0) &&
962 (resources_perms_backup.scmi_clock_perms == NULL)) {
963 resources_perms_backup.scmi_clock_perms =
964 (mod_res_perms_t *)fwk_mm_alloc(
965 resources_perms_ctx.agent_count *
966 resources_perms_ctx.config->clock_cmd_count *
967 resources_perms_ctx.config->clock_resource_count,
968 sizeof(mod_res_perms_t));
969 fwk_str_memcpy(
970 resources_perms_backup.scmi_clock_perms,
971 resources_perms_ctx.agent_permissions->scmi_clock_perms,
972 resources_perms_ctx.agent_count *
973 resources_perms_ctx.config->clock_cmd_count *
974 resources_perms_ctx.config->clock_resource_count *
975 sizeof(mod_res_perms_t));
976 }
977
978 for (message_idx = (int32_t)MOD_SCMI_CLOCK_ATTRIBUTES;
979 message_idx <= MOD_SCMI_CLOCK_CONFIG_SET;
980 message_idx++) {
981 status = set_agent_resource_message_perms(
982 agent_id,
983 MOD_SCMI_PROTOCOL_ID_CLOCK,
984 (uint32_t)message_idx,
985 resource_id,
986 resources_perms_ctx.agent_permissions->scmi_clock_perms,
987 flags);
988
989 if (status != FWK_SUCCESS) {
990 return status;
991 }
992 }
993
994 return FWK_SUCCESS;
995 }
996
997 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
998
set_agent_resource_reset_permissions(uint32_t agent_id,uint32_t resource_id,enum mod_res_perms_permissions flags)999 static int set_agent_resource_reset_permissions(
1000 uint32_t agent_id,
1001 uint32_t resource_id,
1002 enum mod_res_perms_permissions flags)
1003 {
1004 int status;
1005 int32_t message_idx;
1006
1007 if (resources_perms_ctx.agent_permissions->scmi_reset_domain_perms ==
1008 NULL) {
1009 return FWK_SUCCESS;
1010 }
1011 if (resource_id >= resources_perms_ctx.reset_domain_count) {
1012 return FWK_E_ACCESS;
1013 }
1014
1015 /* Do a backup before making the changes if required */
1016 if ((resources_perms_ctx.config->reset_domain_cmd_count != 0) &&
1017 (resources_perms_ctx.config->reset_domain_resource_count != 0) &&
1018 (resources_perms_backup.scmi_reset_domain_perms == NULL)) {
1019 resources_perms_backup.scmi_reset_domain_perms =
1020 (mod_res_perms_t *)fwk_mm_alloc(
1021 resources_perms_ctx.agent_count *
1022 resources_perms_ctx.config->reset_domain_cmd_count *
1023 resources_perms_ctx.config->reset_domain_resource_count,
1024 sizeof(mod_res_perms_t));
1025 fwk_str_memcpy(
1026 resources_perms_backup.scmi_reset_domain_perms,
1027 resources_perms_ctx.agent_permissions->scmi_reset_domain_perms,
1028 resources_perms_ctx.agent_count *
1029 resources_perms_ctx.config->reset_domain_cmd_count *
1030 resources_perms_ctx.config->reset_domain_cmd_count *
1031 sizeof(mod_res_perms_t));
1032 }
1033
1034 for (message_idx = MOD_SCMI_RESET_DOMAIN_ATTRIBUTES;
1035 message_idx <= MOD_SCMI_RESET_NOTIFY;
1036 message_idx++) {
1037 status = set_agent_resource_message_perms(
1038 agent_id,
1039 MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN,
1040 message_idx,
1041 resource_id,
1042 resources_perms_ctx.agent_permissions->scmi_reset_domain_perms,
1043 flags);
1044
1045 if (status != FWK_SUCCESS) {
1046 return status;
1047 }
1048 }
1049
1050 return FWK_SUCCESS;
1051 }
1052
1053 #endif
1054
set_agent_resource_voltd_permissions(uint32_t agent_id,uint32_t resource_id,enum mod_res_perms_permissions flags)1055 static int set_agent_resource_voltd_permissions(
1056 uint32_t agent_id,
1057 uint32_t resource_id,
1058 enum mod_res_perms_permissions flags)
1059 {
1060 int status;
1061 int32_t message_idx;
1062
1063 if (resources_perms_ctx.agent_permissions->scmi_voltd_perms == NULL) {
1064 return FWK_SUCCESS;
1065 }
1066 if (resource_id >= resources_perms_ctx.voltd_count) {
1067 return FWK_E_ACCESS;
1068 }
1069
1070 /* Do a backup before making the changes if required */
1071 if ((resources_perms_ctx.config->voltd_cmd_count != 0) &&
1072 (resources_perms_ctx.config->voltd_resource_count != 0) &&
1073 (resources_perms_backup.scmi_voltd_perms == NULL)) {
1074 resources_perms_backup.scmi_voltd_perms =
1075 (mod_res_perms_t *)fwk_mm_alloc(
1076 resources_perms_ctx.agent_count *
1077 resources_perms_ctx.config->voltd_cmd_count *
1078 resources_perms_ctx.config->voltd_resource_count,
1079 sizeof(mod_res_perms_t));
1080 fwk_str_memcpy(
1081 resources_perms_backup.scmi_voltd_perms,
1082 resources_perms_ctx.agent_permissions->scmi_voltd_perms,
1083 resources_perms_ctx.agent_count *
1084 resources_perms_ctx.config->voltd_cmd_count *
1085 resources_perms_ctx.config->voltd_resource_count *
1086 sizeof(mod_res_perms_t));
1087 }
1088
1089 for (message_idx = (int32_t)MOD_SCMI_VOLTD_DOMAIN_ATTRIBUTES;
1090 message_idx <= MOD_SCMI_VOLTD_LEVEL_GET;
1091 message_idx++) {
1092 status = set_agent_resource_message_perms(
1093 agent_id,
1094 MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
1095 (uint32_t)message_idx,
1096 resource_id,
1097 resources_perms_ctx.agent_permissions->scmi_voltd_perms,
1098 flags);
1099
1100 if (status != FWK_SUCCESS) {
1101 return status;
1102 }
1103 }
1104
1105 return FWK_SUCCESS;
1106 }
1107
set_agent_resource_sensor_permissions(uint32_t agent_id,uint32_t resource_id,enum mod_res_perms_permissions flags)1108 static int set_agent_resource_sensor_permissions(
1109 uint32_t agent_id,
1110 uint32_t resource_id,
1111 enum mod_res_perms_permissions flags)
1112 {
1113 int status;
1114 int32_t message_idx;
1115
1116 if (resources_perms_ctx.agent_permissions->scmi_sensor_perms == NULL) {
1117 return FWK_SUCCESS;
1118 }
1119 if (resource_id >= resources_perms_ctx.sensor_count) {
1120 return FWK_E_ACCESS;
1121 }
1122
1123 /* Do a backup before making the changes if required */
1124 if ((resources_perms_ctx.config->sensor_cmd_count != 0) &&
1125 (resources_perms_ctx.config->sensor_resource_count != 0) &&
1126 (resources_perms_backup.scmi_sensor_perms == NULL)) {
1127 resources_perms_backup.scmi_sensor_perms =
1128 (mod_res_perms_t *)fwk_mm_alloc(
1129 resources_perms_ctx.agent_count *
1130 resources_perms_ctx.config->sensor_cmd_count *
1131 resources_perms_ctx.config->sensor_resource_count,
1132 sizeof(mod_res_perms_t));
1133 fwk_str_memcpy(
1134 resources_perms_backup.scmi_sensor_perms,
1135 resources_perms_ctx.agent_permissions->scmi_sensor_perms,
1136 resources_perms_ctx.agent_count *
1137 resources_perms_ctx.config->sensor_cmd_count *
1138 resources_perms_ctx.config->sensor_resource_count *
1139 sizeof(mod_res_perms_t));
1140 }
1141
1142 for (message_idx = (int32_t)MOD_SCMI_SENSOR_DESCRIPTION_GET;
1143 message_idx <= MOD_SCMI_SENSOR_READING_GET;
1144 message_idx++) {
1145 status = set_agent_resource_message_perms(
1146 agent_id,
1147 MOD_SCMI_PROTOCOL_ID_SENSOR,
1148 (uint32_t)message_idx,
1149 resource_id,
1150 resources_perms_ctx.agent_permissions->scmi_sensor_perms,
1151 flags);
1152
1153 if (status != FWK_SUCCESS) {
1154 return status;
1155 }
1156 }
1157
1158 return FWK_SUCCESS;
1159 }
1160
mod_res_agent_set_permissions(enum mod_res_domain_device_types type,uint32_t agent_id,uint32_t resource_id,enum mod_res_perms_permissions flags)1161 static int mod_res_agent_set_permissions(
1162 enum mod_res_domain_device_types type,
1163 uint32_t agent_id,
1164 uint32_t resource_id,
1165 enum mod_res_perms_permissions flags)
1166 {
1167 int status;
1168
1169 switch (type) {
1170 case MOD_RES_POWER_DOMAIN_DEVICE:
1171 status =
1172 set_agent_resource_pd_permissions(agent_id, resource_id, flags);
1173 break;
1174
1175 case MOD_RES_PERF_DOMAIN_DEVICE:
1176 status =
1177 set_agent_resource_perf_permissions(agent_id, resource_id, flags);
1178 break;
1179
1180 case MOD_RES_CLOCK_DOMAIN_DEVICE:
1181 status =
1182 set_agent_resource_clock_permissions(agent_id, resource_id, flags);
1183 break;
1184
1185 case MOD_RES_SENSOR_DOMAIN_DEVICE:
1186 status =
1187 set_agent_resource_sensor_permissions(agent_id, resource_id, flags);
1188 break;
1189
1190 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
1191 case MOD_RES_RESET_DOMAIN_DEVICE:
1192 status =
1193 set_agent_resource_reset_permissions(agent_id, resource_id, flags);
1194 break;
1195 #endif
1196
1197 case MOD_RES_VOLTAGE_DOMAIN_DEVICE:
1198 status =
1199 set_agent_resource_voltd_permissions(agent_id, resource_id, flags);
1200 break;
1201
1202 default:
1203 status = FWK_E_ACCESS;
1204 break;
1205 }
1206
1207 if (status != FWK_SUCCESS) {
1208 FWK_LOG_WARN(
1209 "[perms] set_permissions for agent %d type %d device %d failed\n",
1210 (int)agent_id,
1211 (int)type,
1212 (int)resource_id);
1213 }
1214
1215 return status;
1216 }
1217
mod_res_agent_set_device_permission(uint32_t agent_id,uint32_t device_id,uint32_t flags)1218 static int mod_res_agent_set_device_permission(
1219 uint32_t agent_id,
1220 uint32_t device_id,
1221 uint32_t flags)
1222 {
1223 struct mod_res_domain_device *dev;
1224 uint32_t resource_id;
1225 int status;
1226 uint32_t i;
1227
1228 /* No device permissons */
1229 if ((resources_perms_ctx.device_count == 0) ||
1230 (resources_perms_ctx.domain_devices == NULL)) {
1231 return FWK_E_ACCESS;
1232 }
1233
1234 if (device_id >= resources_perms_ctx.device_count) {
1235 return FWK_E_PARAM;
1236 }
1237
1238 if ((flags != 0) && (flags != 1)) {
1239 return FWK_E_PARAM;
1240 }
1241
1242 /* Find device */
1243 for (i = 0; i < resources_perms_ctx.device_count; i++) {
1244 if (resources_perms_ctx.domain_devices[i].device_id == device_id) {
1245 break;
1246 }
1247 }
1248
1249 if (i == resources_perms_ctx.device_count) {
1250 return FWK_E_ACCESS;
1251 }
1252
1253 dev = resources_perms_ctx.domain_devices[i].domain_devices;
1254 while (dev->type != MOD_RES_DOMAIN_DEVICE_INVALID) {
1255 if (fwk_id_is_equal(dev->device_id, FWK_ID_NONE)) {
1256 return FWK_SUCCESS;
1257 }
1258
1259 resource_id = fwk_id_get_element_idx(dev->device_id);
1260
1261 status = mod_res_agent_set_permissions(
1262 dev->type,
1263 agent_id,
1264 resource_id,
1265 (enum mod_res_perms_permissions)flags);
1266
1267 if (status != FWK_SUCCESS) {
1268 FWK_LOG_WARN(
1269 "[perms] set_permissions for agent %d device %d failed\n",
1270 (int)agent_id,
1271 (int)i);
1272 }
1273
1274 /* next domain device */
1275 dev++;
1276 };
1277
1278 return FWK_SUCCESS;
1279 }
1280
1281 /*
1282 * Set the permissions for an agent:device:protocol.
1283 */
mod_res_agent_set_device_protocol_permission(uint32_t agent_id,uint32_t device_id,uint32_t protocol_id,uint32_t flags)1284 static int mod_res_agent_set_device_protocol_permission(
1285 uint32_t agent_id,
1286 uint32_t device_id,
1287 uint32_t protocol_id,
1288 uint32_t flags)
1289 {
1290 enum mod_res_domain_device_types dev_type;
1291 struct mod_res_domain_device *dev;
1292 uint32_t resource_id;
1293 int status;
1294 uint32_t i;
1295
1296 /* No device permissons */
1297 if ((resources_perms_ctx.device_count == 0) ||
1298 (resources_perms_ctx.domain_devices == NULL)) {
1299 return FWK_E_ACCESS;
1300 }
1301
1302 if (device_id >= resources_perms_ctx.device_count) {
1303 return FWK_E_PARAM;
1304 }
1305
1306 if ((flags != 0) && (flags != 1)) {
1307 return FWK_E_PARAM;
1308 }
1309
1310 /* Find device */
1311 for (i = 0; i < resources_perms_ctx.device_count; i++) {
1312 if (resources_perms_ctx.domain_devices[i].device_id == device_id) {
1313 break;
1314 }
1315 }
1316
1317 if (i == resources_perms_ctx.device_count) {
1318 return FWK_E_ACCESS;
1319 }
1320
1321 switch (protocol_id) {
1322 case MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN:
1323 dev_type = MOD_RES_POWER_DOMAIN_DEVICE;
1324 break;
1325 case MOD_SCMI_PROTOCOL_ID_PERF:
1326 dev_type = MOD_RES_PERF_DOMAIN_DEVICE;
1327 break;
1328 case MOD_SCMI_PROTOCOL_ID_CLOCK:
1329 dev_type = MOD_RES_CLOCK_DOMAIN_DEVICE;
1330 break;
1331 case MOD_SCMI_PROTOCOL_ID_SENSOR:
1332 dev_type = MOD_RES_SENSOR_DOMAIN_DEVICE;
1333 break;
1334 case MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN:
1335 dev_type = MOD_RES_RESET_DOMAIN_DEVICE;
1336 break;
1337 case MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
1338 dev_type = MOD_RES_VOLTAGE_DOMAIN_DEVICE;
1339 break;
1340 case MOD_SCMI_PROTOCOL_ID_BASE:
1341 case MOD_SCMI_PROTOCOL_ID_SYS_POWER:
1342 default:
1343 return FWK_E_ACCESS;
1344 }
1345
1346 dev = resources_perms_ctx.domain_devices[i].domain_devices;
1347 while (dev->type != MOD_RES_DOMAIN_DEVICE_INVALID) {
1348 if (fwk_id_is_equal(dev->device_id, FWK_ID_NONE)) {
1349 return FWK_SUCCESS;
1350 }
1351
1352 if (dev->type != dev_type) {
1353 dev++;
1354 continue;
1355 }
1356
1357 resource_id = fwk_id_get_element_idx(dev->device_id);
1358
1359 status = mod_res_agent_set_permissions(
1360 dev->type,
1361 agent_id,
1362 resource_id,
1363 (enum mod_res_perms_permissions)flags);
1364
1365 if (status != FWK_SUCCESS) {
1366 FWK_LOG_WARN(
1367 "[perms] set_permissions for agent %d device %d failed\n",
1368 (int)agent_id,
1369 (int)i);
1370 }
1371
1372 /* next domain device */
1373 dev++;
1374 };
1375
1376 return FWK_SUCCESS;
1377 }
1378
1379 /*
1380 * Reset the permissions for an agent to the default configuration.
1381 * Note that we only save and restore the permissions for protocols
1382 * which have set <protocol>_cmd_count and <protocol>_resource_count
1383 * in the platform config data. Also, the backup copies of the
1384 * permissions are not cleared after they are restored, the backup may
1385 * be re-used for any future reset requests.
1386 */
mod_res_agent_copy_config(uint32_t agent_id,mod_res_perms_t * perms,mod_res_perms_t * backup_perms,uint32_t protocol_id)1387 static void mod_res_agent_copy_config(
1388 uint32_t agent_id,
1389 mod_res_perms_t *perms,
1390 mod_res_perms_t *backup_perms,
1391 uint32_t protocol_id)
1392 {
1393 int cmd_count;
1394 int resource_count;
1395 int32_t resource_idx;
1396 int i, j;
1397 int status;
1398
1399 switch (protocol_id) {
1400 case MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN:
1401 cmd_count = (int)MOD_SCMI_PD_POWER_COMMAND_COUNT;
1402 resource_count = (int)resources_perms_ctx.config->pd_resource_count;
1403 break;
1404 case MOD_SCMI_PROTOCOL_ID_PERF:
1405 cmd_count = (int)MOD_SCMI_PERF_COMMAND_COUNT;
1406 resource_count = (int)resources_perms_ctx.config->perf_resource_count;
1407 break;
1408 case MOD_SCMI_PROTOCOL_ID_CLOCK:
1409 cmd_count = (int)MOD_SCMI_CLOCK_COMMAND_COUNT;
1410 resource_count = (int)resources_perms_ctx.config->clock_resource_count;
1411 break;
1412 case MOD_SCMI_PROTOCOL_ID_SENSOR:
1413 cmd_count = (int)MOD_SCMI_SENSOR_COMMAND_COUNT;
1414 resource_count = (int)resources_perms_ctx.config->sensor_resource_count;
1415 break;
1416 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
1417 case MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN:
1418 cmd_count = (int)MOD_SCMI_RESET_COMMAND_COUNT;
1419 resource_count =
1420 (int)resources_perms_ctx.config->reset_domain_resource_count;
1421 break;
1422 #endif
1423 case MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
1424 cmd_count = (int)MOD_SCMI_VOLTD_COMMAND_COUNT;
1425 resource_count = (int)resources_perms_ctx.config->voltd_resource_count;
1426 break;
1427 default:
1428 return;
1429 }
1430
1431 for (i = 3; i < cmd_count; i++) { /* commands < 3 are excluded */
1432 for (j = 0; j < resource_count; j++) {
1433 status = mod_res_resource_id_to_index(
1434 agent_id,
1435 protocol_id,
1436 (uint32_t)i, /* message id */
1437 (uint32_t)j, /* resource id */
1438 &resource_idx);
1439 if ((status != FWK_SUCCESS) || (resource_idx < 0)) {
1440 continue;
1441 }
1442 perms[resource_idx] = backup_perms[resource_idx];
1443 }
1444 }
1445 }
1446
mod_res_agent_reset_config(uint32_t agent_id,uint32_t flags)1447 static int mod_res_agent_reset_config(uint32_t agent_id, uint32_t flags)
1448 {
1449 /* No device permissons */
1450 if ((resources_perms_ctx.device_count == 0) ||
1451 (resources_perms_ctx.domain_devices == NULL)) {
1452 return FWK_E_ACCESS;
1453 }
1454
1455 if (flags == 0) {
1456 return FWK_SUCCESS;
1457 }
1458
1459 if (agent_id >= resources_perms_ctx.agent_count) {
1460 return FWK_E_ACCESS;
1461 }
1462
1463 if (resources_perms_backup.scmi_pd_perms != NULL) {
1464 mod_res_agent_copy_config(
1465 agent_id,
1466 resources_perms_ctx.agent_permissions->scmi_pd_perms,
1467 resources_perms_backup.scmi_pd_perms,
1468 MOD_SCMI_PROTOCOL_ID_POWER_DOMAIN);
1469 }
1470
1471 if (resources_perms_backup.scmi_perf_perms != NULL) {
1472 mod_res_agent_copy_config(
1473 agent_id,
1474 resources_perms_ctx.agent_permissions->scmi_perf_perms,
1475 resources_perms_backup.scmi_perf_perms,
1476 MOD_SCMI_PROTOCOL_ID_PERF);
1477 }
1478
1479 if (resources_perms_backup.scmi_clock_perms != NULL) {
1480 mod_res_agent_copy_config(
1481 agent_id,
1482 resources_perms_ctx.agent_permissions->scmi_clock_perms,
1483 resources_perms_backup.scmi_clock_perms,
1484 MOD_SCMI_PROTOCOL_ID_CLOCK);
1485 }
1486
1487 if (resources_perms_backup.scmi_sensor_perms != NULL) {
1488 mod_res_agent_copy_config(
1489 agent_id,
1490 resources_perms_ctx.agent_permissions->scmi_sensor_perms,
1491 resources_perms_backup.scmi_sensor_perms,
1492 MOD_SCMI_PROTOCOL_ID_SENSOR);
1493 }
1494
1495 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
1496 if (resources_perms_backup.scmi_reset_domain_perms != NULL) {
1497 mod_res_agent_copy_config(
1498 agent_id,
1499 resources_perms_ctx.agent_permissions->scmi_reset_domain_perms,
1500 resources_perms_backup.scmi_reset_domain_perms,
1501 MOD_SCMI_PROTOCOL_ID_RESET_DOMAIN);
1502 }
1503 #endif
1504
1505 if (resources_perms_backup.scmi_voltd_perms != NULL) {
1506 mod_res_agent_copy_config(
1507 agent_id,
1508 resources_perms_ctx.agent_permissions->scmi_voltd_perms,
1509 resources_perms_backup.scmi_voltd_perms,
1510 MOD_SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN);
1511 }
1512
1513 return FWK_SUCCESS;
1514 }
1515
1516 static const struct mod_res_permissions_api res_perms_api = {
1517 .agent_has_protocol_permission = agent_protocol_permissions,
1518 .agent_has_message_permission = agent_message_permissions,
1519 .agent_has_resource_permission = agent_resource_permissions,
1520 .agent_set_device_permission = mod_res_agent_set_device_permission,
1521 .agent_set_device_protocol_permission =
1522 mod_res_agent_set_device_protocol_permission,
1523 .agent_reset_config = mod_res_agent_reset_config,
1524 };
1525
1526 /*
1527 * Module Framework support
1528 */
mod_res_perms_process_bind_request(fwk_id_t source_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)1529 static int mod_res_perms_process_bind_request(
1530 fwk_id_t source_id,
1531 fwk_id_t target_id,
1532 fwk_id_t api_id,
1533 const void **api)
1534 {
1535 /* Only allow binding to the module */
1536 if (!fwk_id_is_equal(target_id, fwk_module_id_resource_perms)) {
1537 return FWK_E_PARAM;
1538 }
1539
1540 /* We don't do any permissions management */
1541 *api = &res_perms_api;
1542
1543 return FWK_SUCCESS;
1544 }
1545
mod_res_perms_resources_init(fwk_id_t module_id,unsigned int element_count,const void * data)1546 static int mod_res_perms_resources_init(
1547 fwk_id_t module_id,
1548 unsigned int element_count,
1549 const void *data)
1550 {
1551 struct mod_res_resource_perms_config *config;
1552
1553 config = (struct mod_res_resource_perms_config *)data;
1554 if (config->agent_permissions != 0x0) {
1555 resources_perms_ctx.agent_permissions =
1556 (struct mod_res_agent_permission *)config->agent_permissions;
1557 resources_perms_ctx.agent_count = config->agent_count;
1558 resources_perms_ctx.protocol_count = config->protocol_count;
1559 resources_perms_ctx.clock_count = config->clock_count;
1560 resources_perms_ctx.sensor_count = config->sensor_count;
1561 resources_perms_ctx.pd_count = config->pd_count;
1562 resources_perms_ctx.perf_count = config->perf_count;
1563 resources_perms_ctx.device_count = config->device_count;
1564 #ifdef BUILD_HAS_MOD_SCMI_RESET_DOMAIN
1565 resources_perms_ctx.reset_domain_count = config->reset_domain_count;
1566 #endif
1567 resources_perms_ctx.voltd_count = config->voltd_count;
1568 resources_perms_ctx.domain_devices =
1569 (struct mod_res_device *)config->domain_devices;
1570 }
1571 resources_perms_ctx.config = config;
1572 return FWK_SUCCESS;
1573 }
1574
1575 /* Module description */
1576 const struct fwk_module module_resource_perms = {
1577 .type = FWK_MODULE_TYPE_SERVICE,
1578 .init = mod_res_perms_resources_init,
1579 .process_bind_request = mod_res_perms_process_bind_request,
1580 .api_count = (unsigned int)MOD_RES_PERM_API_IDX_COUNT,
1581 };
1582