1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <string.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <common/debug.h> 12*91f16700Schasinglulu #include <services/el3_spmc_logical_sp.h> 13*91f16700Schasinglulu #include <services/ffa_svc.h> 14*91f16700Schasinglulu #include "spmc.h" 15*91f16700Schasinglulu 16*91f16700Schasinglulu /******************************************************************************* 17*91f16700Schasinglulu * Validate any logical partition descriptors before we initialise. 18*91f16700Schasinglulu * Initialization of said partitions will be taken care of during SPMC boot. 19*91f16700Schasinglulu ******************************************************************************/ 20*91f16700Schasinglulu int el3_sp_desc_validate(void) 21*91f16700Schasinglulu { 22*91f16700Schasinglulu struct el3_lp_desc *lp_array; 23*91f16700Schasinglulu 24*91f16700Schasinglulu /* 25*91f16700Schasinglulu * Assert the number of descriptors is less than maximum allowed. 26*91f16700Schasinglulu * This constant should be define on a per platform basis. 27*91f16700Schasinglulu */ 28*91f16700Schasinglulu assert(EL3_LP_DESCS_COUNT <= MAX_EL3_LP_DESCS_COUNT); 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* Check the array bounds are valid. */ 31*91f16700Schasinglulu assert(EL3_LP_DESCS_END >= EL3_LP_DESCS_START); 32*91f16700Schasinglulu 33*91f16700Schasinglulu /* If no logical partitions are implemented then simply bail out. */ 34*91f16700Schasinglulu if (EL3_LP_DESCS_COUNT == 0U) { 35*91f16700Schasinglulu return 0; 36*91f16700Schasinglulu } 37*91f16700Schasinglulu 38*91f16700Schasinglulu lp_array = get_el3_lp_array(); 39*91f16700Schasinglulu 40*91f16700Schasinglulu for (unsigned int index = 0; index < EL3_LP_DESCS_COUNT; index++) { 41*91f16700Schasinglulu struct el3_lp_desc *lp_desc = &lp_array[index]; 42*91f16700Schasinglulu 43*91f16700Schasinglulu /* Validate our logical partition descriptors. */ 44*91f16700Schasinglulu if (lp_desc == NULL) { 45*91f16700Schasinglulu ERROR("Invalid Logical SP Descriptor\n"); 46*91f16700Schasinglulu return -EINVAL; 47*91f16700Schasinglulu } 48*91f16700Schasinglulu 49*91f16700Schasinglulu /* 50*91f16700Schasinglulu * Ensure the ID follows the convention to indidate it resides 51*91f16700Schasinglulu * in the secure world. 52*91f16700Schasinglulu */ 53*91f16700Schasinglulu if (!ffa_is_secure_world_id(lp_desc->sp_id)) { 54*91f16700Schasinglulu ERROR("Invalid Logical SP ID (0x%x)\n", 55*91f16700Schasinglulu lp_desc->sp_id); 56*91f16700Schasinglulu return -EINVAL; 57*91f16700Schasinglulu } 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* Ensure we don't conflict with the SPMC partition ID. */ 60*91f16700Schasinglulu if (lp_desc->sp_id == FFA_SPMC_ID) { 61*91f16700Schasinglulu ERROR("Logical SP ID clashes with SPMC ID(0x%x)\n", 62*91f16700Schasinglulu lp_desc->sp_id); 63*91f16700Schasinglulu return -EINVAL; 64*91f16700Schasinglulu } 65*91f16700Schasinglulu 66*91f16700Schasinglulu /* Ensure the UUID is not the NULL UUID. */ 67*91f16700Schasinglulu if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 && 68*91f16700Schasinglulu lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) { 69*91f16700Schasinglulu ERROR("Invalid UUID for Logical SP (0x%x)\n", 70*91f16700Schasinglulu lp_desc->sp_id); 71*91f16700Schasinglulu return -EINVAL; 72*91f16700Schasinglulu } 73*91f16700Schasinglulu 74*91f16700Schasinglulu /* Ensure init function callback is registered. */ 75*91f16700Schasinglulu if (lp_desc->init == NULL) { 76*91f16700Schasinglulu ERROR("Missing init function for Logical SP(0x%x)\n", 77*91f16700Schasinglulu lp_desc->sp_id); 78*91f16700Schasinglulu return -EINVAL; 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu /* Ensure that LP only supports receiving direct requests. */ 82*91f16700Schasinglulu if (lp_desc->properties & 83*91f16700Schasinglulu ~(FFA_PARTITION_DIRECT_REQ_RECV)) { 84*91f16700Schasinglulu ERROR("Invalid partition properties (0x%x)\n", 85*91f16700Schasinglulu lp_desc->properties); 86*91f16700Schasinglulu return -EINVAL; 87*91f16700Schasinglulu } 88*91f16700Schasinglulu 89*91f16700Schasinglulu /* Ensure direct request function callback is registered. */ 90*91f16700Schasinglulu if (lp_desc->direct_req == NULL) { 91*91f16700Schasinglulu ERROR("No Direct Req handler for Logical SP (0x%x)\n", 92*91f16700Schasinglulu lp_desc->sp_id); 93*91f16700Schasinglulu return -EINVAL; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu /* Ensure that all partition IDs are unique. */ 97*91f16700Schasinglulu for (unsigned int inner_idx = index + 1; 98*91f16700Schasinglulu inner_idx < EL3_LP_DESCS_COUNT; inner_idx++) { 99*91f16700Schasinglulu if (lp_desc->sp_id == lp_array[inner_idx].sp_id) { 100*91f16700Schasinglulu ERROR("Duplicate SP ID Detected (0x%x)\n", 101*91f16700Schasinglulu lp_desc->sp_id); 102*91f16700Schasinglulu return -EINVAL; 103*91f16700Schasinglulu } 104*91f16700Schasinglulu } 105*91f16700Schasinglulu } 106*91f16700Schasinglulu return 0; 107*91f16700Schasinglulu } 108