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