blob: f3089c659c2ddaf878b5b8505e1f674d955b5b70 [file] [log] [blame]
Raghu Krishnamurthy7f046c12023-02-25 13:26:10 -08001/*
2 * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
9#include <string.h>
10
11#include <common/debug.h>
12#include <services/el3_spmd_logical_sp.h>
13#include <services/ffa_svc.h>
14
15#if ENABLE_SPMD_LP
16static bool is_spmd_lp_inited;
17static bool is_spmc_inited;
18
19/*
20 * Helper function to obtain the array storing the EL3
21 * SPMD Logical Partition descriptors.
22 */
23static struct spmd_lp_desc *get_spmd_el3_lp_array(void)
24{
25 return (struct spmd_lp_desc *) SPMD_LP_DESCS_START;
26}
27
28/*******************************************************************************
29 * Validate any logical partition descriptors before we initialize.
30 * Initialization of said partitions will be taken care of during SPMD boot.
31 ******************************************************************************/
32static int el3_spmd_sp_desc_validate(struct spmd_lp_desc *lp_array)
33{
34 /* Check the array bounds are valid. */
35 assert(SPMD_LP_DESCS_END > SPMD_LP_DESCS_START);
36
37 /* If no SPMD logical partitions are implemented then simply bail out. */
38 if (SPMD_LP_DESCS_COUNT == 0U) {
39 return -1;
40 }
41
42 for (uint32_t index = 0U; index < SPMD_LP_DESCS_COUNT; index++) {
43 struct spmd_lp_desc *lp_desc = &lp_array[index];
44
45 /* Validate our logical partition descriptors. */
46 if (lp_desc == NULL) {
47 ERROR("Invalid SPMD Logical SP Descriptor\n");
48 return -EINVAL;
49 }
50
51 /*
52 * Ensure the ID follows the convention to indicate it resides
53 * in the secure world.
54 */
55 if (!ffa_is_secure_world_id(lp_desc->sp_id)) {
56 ERROR("Invalid SPMD Logical SP ID (0x%x)\n",
57 lp_desc->sp_id);
58 return -EINVAL;
59 }
60
61 /* Ensure SPMD logical partition is in valid range. */
62 if (!is_spmd_lp_id(lp_desc->sp_id)) {
63 ERROR("Invalid SPMD Logical Partition ID (0x%x)\n",
64 lp_desc->sp_id);
65 return -EINVAL;
66 }
67
68 /* Ensure the UUID is not the NULL UUID. */
69 if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 &&
70 lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) {
71 ERROR("Invalid UUID for SPMD Logical SP (0x%x)\n",
72 lp_desc->sp_id);
73 return -EINVAL;
74 }
75
76 /* Ensure init function callback is registered. */
77 if (lp_desc->init == NULL) {
78 ERROR("Missing init function for Logical SP(0x%x)\n",
79 lp_desc->sp_id);
80 return -EINVAL;
81 }
82
83 /* Ensure that SPMD LP only supports sending direct requests. */
84 if (lp_desc->properties != FFA_PARTITION_DIRECT_REQ_SEND) {
85 ERROR("Invalid SPMD logical partition properties (0x%x)\n",
86 lp_desc->properties);
87 return -EINVAL;
88 }
89
90 /* Ensure that all partition IDs are unique. */
91 for (uint32_t inner_idx = index + 1;
92 inner_idx < SPMD_LP_DESCS_COUNT; inner_idx++) {
93 if (lp_desc->sp_id == lp_array[inner_idx].sp_id) {
94 ERROR("Duplicate SPMD logical SP ID Detected (0x%x)\n",
95 lp_desc->sp_id);
96 return -EINVAL;
97 }
98 }
99 }
100 return 0;
101}
102#endif
103
104/*
105 * Initialize SPMD logical partitions. This function assumes that it is called
106 * only after the SPMC has successfully initialized.
107 */
108int32_t spmd_logical_sp_init(void)
109{
110#if ENABLE_SPMD_LP
111 int32_t rc = 0;
112 struct spmd_lp_desc *spmd_lp_descs;
113
114 if (is_spmd_lp_inited == true) {
115 return 0;
116 }
117
118 if (is_spmc_inited == false) {
119 return -1;
120 }
121
122 spmd_lp_descs = get_spmd_el3_lp_array();
123
124 /* Perform initial validation of the SPMD Logical Partitions. */
125 rc = el3_spmd_sp_desc_validate(spmd_lp_descs);
126 if (rc != 0) {
127 ERROR("Logical SPMD Partition validation failed!\n");
128 return rc;
129 }
130
131 VERBOSE("SPMD Logical Secure Partition init start.\n");
132 for (unsigned int i = 0U; i < SPMD_LP_DESCS_COUNT; i++) {
133 rc = spmd_lp_descs[i].init();
134 if (rc != 0) {
135 ERROR("SPMD Logical SP (0x%x) failed to initialize\n",
136 spmd_lp_descs[i].sp_id);
137 return rc;
138 }
139 VERBOSE("SPMD Logical SP (0x%x) Initialized\n",
140 spmd_lp_descs[i].sp_id);
141 }
142
143 INFO("SPMD Logical Secure Partition init completed.\n");
144 if (rc == 0) {
145 is_spmd_lp_inited = true;
146 }
147 return rc;
148#else
149 return 0;
150#endif
151}
152
153void spmd_logical_sp_set_spmc_initialized(void)
154{
155#if ENABLE_SPMD_LP
156 is_spmc_inited = true;
157#endif
158}
159
160void spmd_logical_sp_set_spmc_failure(void)
161{
162#if ENABLE_SPMD_LP
163 is_spmc_inited = false;
164#endif
165}