14d9f825aSVenkatesh Yadav Abbarapu /* 2619bc13eSMichal Simek * Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved. 3c8be2240SPrasad Kummari * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved. 44d9f825aSVenkatesh Yadav Abbarapu * 54d9f825aSVenkatesh Yadav Abbarapu * SPDX-License-Identifier: BSD-3-Clause 64d9f825aSVenkatesh Yadav Abbarapu */ 74d9f825aSVenkatesh Yadav Abbarapu 84d9f825aSVenkatesh Yadav Abbarapu #include <assert.h> 94ce3e99aSScott Branden #include <inttypes.h> 104ce3e99aSScott Branden #include <stdint.h> 114d9f825aSVenkatesh Yadav Abbarapu 124d9f825aSVenkatesh Yadav Abbarapu #include <arch_helpers.h> 134d9f825aSVenkatesh Yadav Abbarapu #include <common/debug.h> 144d9f825aSVenkatesh Yadav Abbarapu #include <plat_startup.h> 154d9f825aSVenkatesh Yadav Abbarapu 164d9f825aSVenkatesh Yadav Abbarapu 174d9f825aSVenkatesh Yadav Abbarapu /* 18*b9d26cd3SPrasad Kummari * HandoffParams 194d9f825aSVenkatesh Yadav Abbarapu * Parameter bitfield encoding 204d9f825aSVenkatesh Yadav Abbarapu * ----------------------------------------------------------------------------- 214d9f825aSVenkatesh Yadav Abbarapu * Exec State 0 0 -> Aarch64, 1-> Aarch32 224d9f825aSVenkatesh Yadav Abbarapu * endianness 1 0 -> LE, 1 -> BE 234d9f825aSVenkatesh Yadav Abbarapu * secure (TZ) 2 0 -> Non secure, 1 -> secure 244d9f825aSVenkatesh Yadav Abbarapu * EL 3:4 00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3 254d9f825aSVenkatesh Yadav Abbarapu * CPU# 5:6 00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3 264d9f825aSVenkatesh Yadav Abbarapu */ 274d9f825aSVenkatesh Yadav Abbarapu 28*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ESTATE_SHIFT 0U 29*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ESTATE_MASK (1U << XBL_FLAGS_ESTATE_SHIFT) 30*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ESTATE_A64 0U 31*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ESTATE_A32 1U 324d9f825aSVenkatesh Yadav Abbarapu 33*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ENDIAN_SHIFT 1U 34*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ENDIAN_MASK (1U << XBL_FLAGS_ENDIAN_SHIFT) 35*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ENDIAN_LE 0U 36*b9d26cd3SPrasad Kummari #define XBL_FLAGS_ENDIAN_BE 1U 374d9f825aSVenkatesh Yadav Abbarapu 38*b9d26cd3SPrasad Kummari #define XBL_FLAGS_TZ_SHIFT 2U 39*b9d26cd3SPrasad Kummari #define XBL_FLAGS_TZ_MASK (1U << XBL_FLAGS_TZ_SHIFT) 40*b9d26cd3SPrasad Kummari #define XBL_FLAGS_NON_SECURE 0U 41*b9d26cd3SPrasad Kummari #define XBL_FLAGS_SECURE 1U 424d9f825aSVenkatesh Yadav Abbarapu 43*b9d26cd3SPrasad Kummari #define XBL_FLAGS_EL_SHIFT 3U 44*b9d26cd3SPrasad Kummari #define XBL_FLAGS_EL_MASK (3U << XBL_FLAGS_EL_SHIFT) 45*b9d26cd3SPrasad Kummari #define XBL_FLAGS_EL0 0U 46*b9d26cd3SPrasad Kummari #define XBL_FLAGS_EL1 1U 47*b9d26cd3SPrasad Kummari #define XBL_FLAGS_EL2 2U 48*b9d26cd3SPrasad Kummari #define XBL_FLAGS_EL3 3U 494d9f825aSVenkatesh Yadav Abbarapu 50*b9d26cd3SPrasad Kummari #define XBL_FLAGS_CPU_SHIFT 5U 51*b9d26cd3SPrasad Kummari #define XBL_FLAGS_CPU_MASK (3U << XBL_FLAGS_CPU_SHIFT) 52*b9d26cd3SPrasad Kummari #define XBL_FLAGS_A53_0 0U 53*b9d26cd3SPrasad Kummari #define XBL_FLAGS_A53_1 1U 54*b9d26cd3SPrasad Kummari #define XBL_FLAGS_A53_2 2U 55*b9d26cd3SPrasad Kummari #define XBL_FLAGS_A53_3 3U 564d9f825aSVenkatesh Yadav Abbarapu 574d9f825aSVenkatesh Yadav Abbarapu /** 58*b9d26cd3SPrasad Kummari * get_xbl_cpu() - Get the target CPU for partition. 59de7ed953SPrasad Kummari * @partition: Pointer to partition struct. 604d9f825aSVenkatesh Yadav Abbarapu * 61*b9d26cd3SPrasad Kummari * Return: XBL_FLAGS_A53_0, XBL_FLAGS_A53_1, XBL_FLAGS_A53_2 or XBL_FLAGS_A53_3. 624d9f825aSVenkatesh Yadav Abbarapu * 634d9f825aSVenkatesh Yadav Abbarapu */ 64*b9d26cd3SPrasad Kummari static int32_t get_xbl_cpu(const struct xbl_partition *partition) 654d9f825aSVenkatesh Yadav Abbarapu { 66*b9d26cd3SPrasad Kummari uint64_t flags = partition->flags & XBL_FLAGS_CPU_MASK; 674d9f825aSVenkatesh Yadav Abbarapu 68*b9d26cd3SPrasad Kummari return flags >> XBL_FLAGS_CPU_SHIFT; 694d9f825aSVenkatesh Yadav Abbarapu } 704d9f825aSVenkatesh Yadav Abbarapu 714d9f825aSVenkatesh Yadav Abbarapu /** 72*b9d26cd3SPrasad Kummari * get_xbl_el() - Get the target exception level for partition. 73de7ed953SPrasad Kummari * @partition: Pointer to partition struct. 744d9f825aSVenkatesh Yadav Abbarapu * 75*b9d26cd3SPrasad Kummari * Return: XBL_FLAGS_EL0, XBL_FLAGS_EL1, XBL_FLAGS_EL2 or XBL_FLAGS_EL3. 764d9f825aSVenkatesh Yadav Abbarapu * 774d9f825aSVenkatesh Yadav Abbarapu */ 78*b9d26cd3SPrasad Kummari static int32_t get_xbl_el(const struct xbl_partition *partition) 794d9f825aSVenkatesh Yadav Abbarapu { 80*b9d26cd3SPrasad Kummari uint64_t flags = partition->flags & XBL_FLAGS_EL_MASK; 814d9f825aSVenkatesh Yadav Abbarapu 82*b9d26cd3SPrasad Kummari return flags >> XBL_FLAGS_EL_SHIFT; 834d9f825aSVenkatesh Yadav Abbarapu } 844d9f825aSVenkatesh Yadav Abbarapu 854d9f825aSVenkatesh Yadav Abbarapu /** 86*b9d26cd3SPrasad Kummari * get_xbl_ss() - Get the target security state for partition. 87de7ed953SPrasad Kummari * @partition: Pointer to partition struct. 884d9f825aSVenkatesh Yadav Abbarapu * 89*b9d26cd3SPrasad Kummari * Return: XBL_FLAGS_NON_SECURE or XBL_FLAGS_SECURE. 904d9f825aSVenkatesh Yadav Abbarapu * 914d9f825aSVenkatesh Yadav Abbarapu */ 92*b9d26cd3SPrasad Kummari static int32_t get_xbl_ss(const struct xbl_partition *partition) 934d9f825aSVenkatesh Yadav Abbarapu { 94*b9d26cd3SPrasad Kummari uint64_t flags = partition->flags & XBL_FLAGS_TZ_MASK; 954d9f825aSVenkatesh Yadav Abbarapu 96*b9d26cd3SPrasad Kummari return flags >> XBL_FLAGS_TZ_SHIFT; 974d9f825aSVenkatesh Yadav Abbarapu } 984d9f825aSVenkatesh Yadav Abbarapu 994d9f825aSVenkatesh Yadav Abbarapu /** 100*b9d26cd3SPrasad Kummari * get_xbl_endian() - Get the target endianness for partition. 101de7ed953SPrasad Kummari * @partition: Pointer to partition struct. 1024d9f825aSVenkatesh Yadav Abbarapu * 103de7ed953SPrasad Kummari * Return: SPSR_E_LITTLE or SPSR_E_BIG. 1044d9f825aSVenkatesh Yadav Abbarapu * 1054d9f825aSVenkatesh Yadav Abbarapu */ 106*b9d26cd3SPrasad Kummari static int32_t get_xbl_endian(const struct xbl_partition *partition) 1074d9f825aSVenkatesh Yadav Abbarapu { 108*b9d26cd3SPrasad Kummari uint64_t flags = partition->flags & XBL_FLAGS_ENDIAN_MASK; 1094d9f825aSVenkatesh Yadav Abbarapu 110*b9d26cd3SPrasad Kummari flags >>= XBL_FLAGS_ENDIAN_SHIFT; 1114d9f825aSVenkatesh Yadav Abbarapu 112*b9d26cd3SPrasad Kummari if (flags == XBL_FLAGS_ENDIAN_BE) { 1134d9f825aSVenkatesh Yadav Abbarapu return SPSR_E_BIG; 114eb0d2b17SVenkatesh Yadav Abbarapu } else { 1154d9f825aSVenkatesh Yadav Abbarapu return SPSR_E_LITTLE; 1164d9f825aSVenkatesh Yadav Abbarapu } 117eb0d2b17SVenkatesh Yadav Abbarapu } 1184d9f825aSVenkatesh Yadav Abbarapu 1194d9f825aSVenkatesh Yadav Abbarapu /** 120*b9d26cd3SPrasad Kummari * get_xbl_estate() - Get the target execution state for partition. 121de7ed953SPrasad Kummari * @partition: Pointer to partition struct. 1224d9f825aSVenkatesh Yadav Abbarapu * 123*b9d26cd3SPrasad Kummari * Return: XBL_FLAGS_ESTATE_A32 or XBL_FLAGS_ESTATE_A64. 1244d9f825aSVenkatesh Yadav Abbarapu * 1254d9f825aSVenkatesh Yadav Abbarapu */ 126*b9d26cd3SPrasad Kummari static int32_t get_xbl_estate(const struct xbl_partition *partition) 1274d9f825aSVenkatesh Yadav Abbarapu { 128*b9d26cd3SPrasad Kummari uint64_t flags = partition->flags & XBL_FLAGS_ESTATE_MASK; 1294d9f825aSVenkatesh Yadav Abbarapu 130*b9d26cd3SPrasad Kummari return flags >> XBL_FLAGS_ESTATE_SHIFT; 1314d9f825aSVenkatesh Yadav Abbarapu } 1324d9f825aSVenkatesh Yadav Abbarapu 1334d9f825aSVenkatesh Yadav Abbarapu /** 134*b9d26cd3SPrasad Kummari * xbl_tfa_handover() - Populates the bl32 and bl33 image info structures. 135de7ed953SPrasad Kummari * @bl32: BL32 image info structure. 136de7ed953SPrasad Kummari * @bl33: BL33 image info structure. 137de7ed953SPrasad Kummari * @tfa_handoff_addr: TF-A handoff address. 1384d9f825aSVenkatesh Yadav Abbarapu * 139*b9d26cd3SPrasad Kummari * Process the handoff parameters from the XBL and populate the BL32 and BL33 1404d9f825aSVenkatesh Yadav Abbarapu * image info structures accordingly. 1414d9f825aSVenkatesh Yadav Abbarapu * 1424d9f825aSVenkatesh Yadav Abbarapu * Return: Return the status of the handoff. The value will be from the 143*b9d26cd3SPrasad Kummari * xbl_handoff enum. 144de7ed953SPrasad Kummari * 1454d9f825aSVenkatesh Yadav Abbarapu */ 146*b9d26cd3SPrasad Kummari enum xbl_handoff xbl_handover(entry_point_info_t *bl32, 1474d9f825aSVenkatesh Yadav Abbarapu entry_point_info_t *bl33, 148*b9d26cd3SPrasad Kummari uint64_t handoff_addr) 1494d9f825aSVenkatesh Yadav Abbarapu { 150*b9d26cd3SPrasad Kummari const struct xbl_handoff_params *HandoffParams; 151*b9d26cd3SPrasad Kummari 152*b9d26cd3SPrasad Kummari if (!handoff_addr) { 153*b9d26cd3SPrasad Kummari WARN("BL31: No handoff structure passed\n"); 154*b9d26cd3SPrasad Kummari return XBL_HANDOFF_NO_STRUCT; 1554d9f825aSVenkatesh Yadav Abbarapu } 1564d9f825aSVenkatesh Yadav Abbarapu 157*b9d26cd3SPrasad Kummari HandoffParams = (struct xbl_handoff_params *)handoff_addr; 158*b9d26cd3SPrasad Kummari if ((HandoffParams->magic[0] != 'X') || 159*b9d26cd3SPrasad Kummari (HandoffParams->magic[1] != 'L') || 160*b9d26cd3SPrasad Kummari (HandoffParams->magic[2] != 'N') || 161*b9d26cd3SPrasad Kummari (HandoffParams->magic[3] != 'X')) { 162*b9d26cd3SPrasad Kummari ERROR("BL31: invalid handoff structure at %" PRIx64 "\n", handoff_addr); 163*b9d26cd3SPrasad Kummari return XBL_HANDOFF_INVAL_STRUCT; 1644d9f825aSVenkatesh Yadav Abbarapu } 1654d9f825aSVenkatesh Yadav Abbarapu 166c8be2240SPrasad Kummari VERBOSE("BL31: TF-A handoff params at:0x%" PRIx64 ", entries:%u\n", 167*b9d26cd3SPrasad Kummari handoff_addr, HandoffParams->num_entries); 168*b9d26cd3SPrasad Kummari if (HandoffParams->num_entries > XBL_MAX_PARTITIONS) { 169c8be2240SPrasad Kummari ERROR("BL31: TF-A handoff params: too many partitions (%u/%u)\n", 170*b9d26cd3SPrasad Kummari HandoffParams->num_entries, XBL_MAX_PARTITIONS); 171*b9d26cd3SPrasad Kummari return XBL_HANDOFF_TOO_MANY_PARTS; 1724d9f825aSVenkatesh Yadav Abbarapu } 1734d9f825aSVenkatesh Yadav Abbarapu 1744d9f825aSVenkatesh Yadav Abbarapu /* 1754d9f825aSVenkatesh Yadav Abbarapu * we loop over all passed entries but only populate two image structs 1764d9f825aSVenkatesh Yadav Abbarapu * (bl32, bl33). I.e. the last applicable images in the handoff 1774d9f825aSVenkatesh Yadav Abbarapu * structure will be used for the hand off 1784d9f825aSVenkatesh Yadav Abbarapu */ 179*b9d26cd3SPrasad Kummari for (size_t i = 0; i < HandoffParams->num_entries; i++) { 1804d9f825aSVenkatesh Yadav Abbarapu entry_point_info_t *image; 181bfd7c881SVenkatesh Yadav Abbarapu int32_t target_estate, target_secure, target_cpu; 182bfd7c881SVenkatesh Yadav Abbarapu uint32_t target_endianness, target_el; 1834d9f825aSVenkatesh Yadav Abbarapu 1844ce3e99aSScott Branden VERBOSE("BL31: %zd: entry:0x%" PRIx64 ", flags:0x%" PRIx64 "\n", i, 185*b9d26cd3SPrasad Kummari HandoffParams->partition[i].entry_point, 186*b9d26cd3SPrasad Kummari HandoffParams->partition[i].flags); 1874d9f825aSVenkatesh Yadav Abbarapu 188*b9d26cd3SPrasad Kummari target_cpu = get_xbl_cpu(&HandoffParams->partition[i]); 189*b9d26cd3SPrasad Kummari if (target_cpu != XBL_FLAGS_A53_0) { 1904d9f825aSVenkatesh Yadav Abbarapu WARN("BL31: invalid target CPU (%i)\n", target_cpu); 1914d9f825aSVenkatesh Yadav Abbarapu continue; 1924d9f825aSVenkatesh Yadav Abbarapu } 1934d9f825aSVenkatesh Yadav Abbarapu 194*b9d26cd3SPrasad Kummari target_el = get_xbl_el(&HandoffParams->partition[i]); 195*b9d26cd3SPrasad Kummari if ((target_el == XBL_FLAGS_EL3) || 196*b9d26cd3SPrasad Kummari (target_el == XBL_FLAGS_EL0)) { 1974d9f825aSVenkatesh Yadav Abbarapu WARN("BL31: invalid exception level (%i)\n", target_el); 1984d9f825aSVenkatesh Yadav Abbarapu continue; 1994d9f825aSVenkatesh Yadav Abbarapu } 2004d9f825aSVenkatesh Yadav Abbarapu 201*b9d26cd3SPrasad Kummari target_secure = get_xbl_ss(&HandoffParams->partition[i]); 202*b9d26cd3SPrasad Kummari if (target_secure == XBL_FLAGS_SECURE && 203*b9d26cd3SPrasad Kummari target_el == XBL_FLAGS_EL2) { 2044d9f825aSVenkatesh Yadav Abbarapu WARN("BL31: invalid security state (%i) for exception level (%i)\n", 2054d9f825aSVenkatesh Yadav Abbarapu target_secure, target_el); 2064d9f825aSVenkatesh Yadav Abbarapu continue; 2074d9f825aSVenkatesh Yadav Abbarapu } 2084d9f825aSVenkatesh Yadav Abbarapu 209*b9d26cd3SPrasad Kummari target_estate = get_xbl_estate(&HandoffParams->partition[i]); 210*b9d26cd3SPrasad Kummari target_endianness = get_xbl_endian(&HandoffParams->partition[i]); 2114d9f825aSVenkatesh Yadav Abbarapu 212*b9d26cd3SPrasad Kummari if (target_secure == XBL_FLAGS_SECURE) { 2134d9f825aSVenkatesh Yadav Abbarapu image = bl32; 2144d9f825aSVenkatesh Yadav Abbarapu 215*b9d26cd3SPrasad Kummari if (target_estate == XBL_FLAGS_ESTATE_A32) { 2164d9f825aSVenkatesh Yadav Abbarapu bl32->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, 2174d9f825aSVenkatesh Yadav Abbarapu target_endianness, 2184d9f825aSVenkatesh Yadav Abbarapu DISABLE_ALL_EXCEPTIONS); 219eb0d2b17SVenkatesh Yadav Abbarapu } else { 2204d9f825aSVenkatesh Yadav Abbarapu bl32->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 2214d9f825aSVenkatesh Yadav Abbarapu DISABLE_ALL_EXCEPTIONS); 222eb0d2b17SVenkatesh Yadav Abbarapu } 2234d9f825aSVenkatesh Yadav Abbarapu } else { 2244d9f825aSVenkatesh Yadav Abbarapu image = bl33; 2254d9f825aSVenkatesh Yadav Abbarapu 226*b9d26cd3SPrasad Kummari if (target_estate == XBL_FLAGS_ESTATE_A32) { 227*b9d26cd3SPrasad Kummari if (target_el == XBL_FLAGS_EL2) { 2284d9f825aSVenkatesh Yadav Abbarapu target_el = MODE32_hyp; 229eb0d2b17SVenkatesh Yadav Abbarapu } else { 2304d9f825aSVenkatesh Yadav Abbarapu target_el = MODE32_sys; 231eb0d2b17SVenkatesh Yadav Abbarapu } 2324d9f825aSVenkatesh Yadav Abbarapu 2334d9f825aSVenkatesh Yadav Abbarapu bl33->spsr = SPSR_MODE32(target_el, SPSR_T_ARM, 2344d9f825aSVenkatesh Yadav Abbarapu target_endianness, 2354d9f825aSVenkatesh Yadav Abbarapu DISABLE_ALL_EXCEPTIONS); 2364d9f825aSVenkatesh Yadav Abbarapu } else { 237*b9d26cd3SPrasad Kummari if (target_el == XBL_FLAGS_EL2) { 2384d9f825aSVenkatesh Yadav Abbarapu target_el = MODE_EL2; 239eb0d2b17SVenkatesh Yadav Abbarapu } else { 2404d9f825aSVenkatesh Yadav Abbarapu target_el = MODE_EL1; 241eb0d2b17SVenkatesh Yadav Abbarapu } 2424d9f825aSVenkatesh Yadav Abbarapu 2434d9f825aSVenkatesh Yadav Abbarapu bl33->spsr = SPSR_64(target_el, MODE_SP_ELX, 2444d9f825aSVenkatesh Yadav Abbarapu DISABLE_ALL_EXCEPTIONS); 2454d9f825aSVenkatesh Yadav Abbarapu } 2464d9f825aSVenkatesh Yadav Abbarapu } 2474d9f825aSVenkatesh Yadav Abbarapu 2484ce3e99aSScott Branden VERBOSE("Setting up %s entry point to:%" PRIx64 ", el:%x\n", 249*b9d26cd3SPrasad Kummari target_secure == XBL_FLAGS_SECURE ? "BL32" : "BL33", 250*b9d26cd3SPrasad Kummari HandoffParams->partition[i].entry_point, 2514d9f825aSVenkatesh Yadav Abbarapu target_el); 252*b9d26cd3SPrasad Kummari image->pc = HandoffParams->partition[i].entry_point; 2534d9f825aSVenkatesh Yadav Abbarapu 254eb0d2b17SVenkatesh Yadav Abbarapu if (target_endianness == SPSR_E_BIG) { 2554d9f825aSVenkatesh Yadav Abbarapu EP_SET_EE(image->h.attr, EP_EE_BIG); 256eb0d2b17SVenkatesh Yadav Abbarapu } else { 2574d9f825aSVenkatesh Yadav Abbarapu EP_SET_EE(image->h.attr, EP_EE_LITTLE); 2584d9f825aSVenkatesh Yadav Abbarapu } 259eb0d2b17SVenkatesh Yadav Abbarapu } 2604d9f825aSVenkatesh Yadav Abbarapu 261*b9d26cd3SPrasad Kummari return XBL_HANDOFF_SUCCESS; 2624d9f825aSVenkatesh Yadav Abbarapu } 263