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