xref: /rk3399_ARM-atf/services/std_svc/spmd/spmd_logical_sp.c (revision 890b5088203e990d683a9c837e976be62c6501aa)
1 /*
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
16 static bool is_spmd_lp_inited;
17 static bool is_spmc_inited;
18 
19 /*
20  * Helper function to obtain the array storing the EL3
21  * SPMD Logical Partition descriptors.
22  */
23 static 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  ******************************************************************************/
32 static 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  */
108 int32_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 
153 void spmd_logical_sp_set_spmc_initialized(void)
154 {
155 #if ENABLE_SPMD_LP
156 	is_spmc_inited = true;
157 #endif
158 }
159 
160 void spmd_logical_sp_set_spmc_failure(void)
161 {
162 #if ENABLE_SPMD_LP
163 	is_spmc_inited = false;
164 #endif
165 }
166