1*6a7e8ebfSLeon Chen /* 2*6a7e8ebfSLeon Chen * Copyright (c) 2022, MediaTek Inc. All rights reserved. 3*6a7e8ebfSLeon Chen * 4*6a7e8ebfSLeon Chen * SPDX-License-Identifier: BSD-3-Clause 5*6a7e8ebfSLeon Chen */ 6*6a7e8ebfSLeon Chen 7*6a7e8ebfSLeon Chen #include <assert.h> 8*6a7e8ebfSLeon Chen #include <errno.h> 9*6a7e8ebfSLeon Chen #include <common/debug.h> 10*6a7e8ebfSLeon Chen #include <common/runtime_svc.h> 11*6a7e8ebfSLeon Chen #include <cold_boot.h> 12*6a7e8ebfSLeon Chen #include <lib/mtk_init/mtk_init.h> 13*6a7e8ebfSLeon Chen #include <mtk_sip_svc.h> 14*6a7e8ebfSLeon Chen 15*6a7e8ebfSLeon Chen #define SMC_HANDLER_DEBUG(...) VERBOSE(__VA_ARGS__) 16*6a7e8ebfSLeon Chen #define SMC_HANDLER_DEBUG_NOT_IMP_MSG "%s[0x%x] smc handler not implemented\n" 17*6a7e8ebfSLeon Chen #define SMC_HANDLER_DEBUG_START_MSG "%s[0x%x] smc handler start, smc desc. index:%d\n" 18*6a7e8ebfSLeon Chen #define SMC_HANDLER_DEBUG_END_MSG "%s[0x%x] smc handler end\n" 19*6a7e8ebfSLeon Chen 20*6a7e8ebfSLeon Chen /* 21*6a7e8ebfSLeon Chen * These macros below are used to identify SIP calls from Kernel, 22*6a7e8ebfSLeon Chen * Hypervisor, or 2ndBootloader 23*6a7e8ebfSLeon Chen */ 24*6a7e8ebfSLeon Chen #define SIP_FID_ORI_MASK (0xc000) 25*6a7e8ebfSLeon Chen #define SIP_FID_ORI_SHIFT (14) 26*6a7e8ebfSLeon Chen #define SIP_FID_KERNEL (0x0) 27*6a7e8ebfSLeon Chen #define SIP_FID_KERNEL_VIA_GZ (0x1) 28*6a7e8ebfSLeon Chen #define SIP_FID_GZ (0x2) 29*6a7e8ebfSLeon Chen 30*6a7e8ebfSLeon Chen #define GET_SMC_ORI(_fid) (((_fid) & SIP_FID_ORI_MASK) >> SIP_FID_ORI_SHIFT) 31*6a7e8ebfSLeon Chen #define GET_SMC_ORI_NUM(_fid) ((_fid) & ~(SIP_FID_ORI_MASK)) 32*6a7e8ebfSLeon Chen 33*6a7e8ebfSLeon Chen #define is_from_nsel2(_ori) (_ori == SIP_FID_GZ) 34*6a7e8ebfSLeon Chen #define is_from_bl33(_ori) \ 35*6a7e8ebfSLeon Chen ((_ori != SIP_FID_GZ) && (is_el1_2nd_bootloader() == 1)) 36*6a7e8ebfSLeon Chen #define is_from_nsel1(_ori) \ 37*6a7e8ebfSLeon Chen (((_ori == SIP_FID_KERNEL) || \ 38*6a7e8ebfSLeon Chen (_ori == SIP_FID_KERNEL_VIA_GZ)) && \ 39*6a7e8ebfSLeon Chen (is_el1_2nd_bootloader() == 0)) 40*6a7e8ebfSLeon Chen 41*6a7e8ebfSLeon Chen #define is_smc_forbidden(_ori) (_ori == SIP_FID_KERNEL_VIA_GZ) 42*6a7e8ebfSLeon Chen 43*6a7e8ebfSLeon Chen #define MASK_32_BIT (0xffffffffU) 44*6a7e8ebfSLeon Chen #define SMC_ID_EXPAND_AS_SMC_OPERATION(_smc_id, _smc_num) \ 45*6a7e8ebfSLeon Chen case _smc_id##_AARCH32: \ 46*6a7e8ebfSLeon Chen { \ 47*6a7e8ebfSLeon Chen x1 = x1 & MASK_32_BIT; \ 48*6a7e8ebfSLeon Chen x2 = x2 & MASK_32_BIT; \ 49*6a7e8ebfSLeon Chen x3 = x3 & MASK_32_BIT; \ 50*6a7e8ebfSLeon Chen x4 = x4 & MASK_32_BIT; \ 51*6a7e8ebfSLeon Chen } \ 52*6a7e8ebfSLeon Chen case _smc_id##_AARCH64: \ 53*6a7e8ebfSLeon Chen { \ 54*6a7e8ebfSLeon Chen if (_smc_id##_descriptor_index < 0) { \ 55*6a7e8ebfSLeon Chen SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_NOT_IMP_MSG, #_smc_id, smc_id); \ 56*6a7e8ebfSLeon Chen break; \ 57*6a7e8ebfSLeon Chen } \ 58*6a7e8ebfSLeon Chen if (_smc_id##_descriptor_index >= smc_id_descriptor_max) { \ 59*6a7e8ebfSLeon Chen SMC_HANDLER_DEBUG("smc descriptor index[%d] exceed max[%d]\n", \ 60*6a7e8ebfSLeon Chen _smc_id##_descriptor_index, smc_id_descriptor_max); \ 61*6a7e8ebfSLeon Chen break; \ 62*6a7e8ebfSLeon Chen } \ 63*6a7e8ebfSLeon Chen SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_START_MSG, #_smc_id, smc_id, \ 64*6a7e8ebfSLeon Chen _smc_id##_descriptor_index); \ 65*6a7e8ebfSLeon Chen ret = smc_handler_pool[_smc_id##_descriptor_index].smc_handler(x1,\ 66*6a7e8ebfSLeon Chen x2, x3, x4, handle, &smc_ret); \ 67*6a7e8ebfSLeon Chen SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_END_MSG, #_smc_id, smc_id); \ 68*6a7e8ebfSLeon Chen break; \ 69*6a7e8ebfSLeon Chen } 70*6a7e8ebfSLeon Chen 71*6a7e8ebfSLeon Chen #define SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX(_smc_id, _smc_num) \ 72*6a7e8ebfSLeon Chen short _smc_id##_descriptor_index __section("mtk_plat_ro") = -1; 73*6a7e8ebfSLeon Chen 74*6a7e8ebfSLeon Chen MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX); 75*6a7e8ebfSLeon Chen MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX); 76*6a7e8ebfSLeon Chen 77*6a7e8ebfSLeon Chen IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_START__, MTK_SMC_POOL_START); 78*6a7e8ebfSLeon Chen IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_END_UNALIGNED__, MTK_SMC_POOL_END_UNALIGNED); 79*6a7e8ebfSLeon Chen 80*6a7e8ebfSLeon Chen static const struct smc_descriptor *smc_handler_pool; 81*6a7e8ebfSLeon Chen static short smc_id_descriptor_max; 82*6a7e8ebfSLeon Chen 83*6a7e8ebfSLeon Chen #if !MTK_SIP_KERNEL_BOOT_ENABLE 84*6a7e8ebfSLeon Chen /* 85*6a7e8ebfSLeon Chen * If there is no SMC request needs to be served in 2nd bootloader, 86*6a7e8ebfSLeon Chen * disable the service path inherently. 87*6a7e8ebfSLeon Chen */ 88*6a7e8ebfSLeon Chen bool is_el1_2nd_bootloader(void) 89*6a7e8ebfSLeon Chen { 90*6a7e8ebfSLeon Chen return false; 91*6a7e8ebfSLeon Chen } 92*6a7e8ebfSLeon Chen #endif 93*6a7e8ebfSLeon Chen 94*6a7e8ebfSLeon Chen static void print_smc_descriptor(const struct smc_descriptor pool[]) 95*6a7e8ebfSLeon Chen { 96*6a7e8ebfSLeon Chen const struct smc_descriptor *p_smc_desc; 97*6a7e8ebfSLeon Chen 98*6a7e8ebfSLeon Chen INFO("print smc descriptor pool\n"); 99*6a7e8ebfSLeon Chen for (p_smc_desc = &pool[0]; 100*6a7e8ebfSLeon Chen (char *)p_smc_desc < (char *)MTK_SMC_POOL_END_UNALIGNED; 101*6a7e8ebfSLeon Chen p_smc_desc++) { 102*6a7e8ebfSLeon Chen INFO("descriptor name:%s\n", p_smc_desc->smc_name); 103*6a7e8ebfSLeon Chen INFO("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index); 104*6a7e8ebfSLeon Chen INFO("smc id 32:0x%x, smc id 64:0x%x\n", 105*6a7e8ebfSLeon Chen p_smc_desc->smc_id_aarch32, p_smc_desc->smc_id_aarch64); 106*6a7e8ebfSLeon Chen } 107*6a7e8ebfSLeon Chen } 108*6a7e8ebfSLeon Chen 109*6a7e8ebfSLeon Chen static int mtk_smc_handler_init(void) 110*6a7e8ebfSLeon Chen { 111*6a7e8ebfSLeon Chen const struct smc_descriptor *iter; 112*6a7e8ebfSLeon Chen short index_cnt; 113*6a7e8ebfSLeon Chen int ret = 0; 114*6a7e8ebfSLeon Chen 115*6a7e8ebfSLeon Chen smc_handler_pool = (const struct smc_descriptor *)MTK_SMC_POOL_START; 116*6a7e8ebfSLeon Chen /* Designate descriptor index point to smc_handler_pool */ 117*6a7e8ebfSLeon Chen for (index_cnt = 0, iter = &smc_handler_pool[0]; 118*6a7e8ebfSLeon Chen (char *)iter < (char *)MTK_SMC_POOL_END_UNALIGNED; 119*6a7e8ebfSLeon Chen iter++, index_cnt++) { 120*6a7e8ebfSLeon Chen if (index_cnt < 0) { 121*6a7e8ebfSLeon Chen SMC_HANDLER_DEBUG("smc handler pool index overflow!\n"); 122*6a7e8ebfSLeon Chen ret = -EPERM; 123*6a7e8ebfSLeon Chen assert(0); 124*6a7e8ebfSLeon Chen break; 125*6a7e8ebfSLeon Chen } 126*6a7e8ebfSLeon Chen *(iter->smc_descriptor_index) = index_cnt; 127*6a7e8ebfSLeon Chen } 128*6a7e8ebfSLeon Chen smc_id_descriptor_max = index_cnt; 129*6a7e8ebfSLeon Chen print_smc_descriptor(smc_handler_pool); 130*6a7e8ebfSLeon Chen return ret; 131*6a7e8ebfSLeon Chen } 132*6a7e8ebfSLeon Chen MTK_EARLY_PLAT_INIT(mtk_smc_handler_init); 133*6a7e8ebfSLeon Chen 134*6a7e8ebfSLeon Chen /* This function handles Mediatek defined SiP Calls from Bootloader */ 135*6a7e8ebfSLeon Chen static uintptr_t mtk_smc_handler_bl33(uint32_t smc_id, 136*6a7e8ebfSLeon Chen u_register_t x1, 137*6a7e8ebfSLeon Chen u_register_t x2, 138*6a7e8ebfSLeon Chen u_register_t x3, 139*6a7e8ebfSLeon Chen u_register_t x4, 140*6a7e8ebfSLeon Chen void *cookie, 141*6a7e8ebfSLeon Chen void *handle, 142*6a7e8ebfSLeon Chen u_register_t flags) 143*6a7e8ebfSLeon Chen { 144*6a7e8ebfSLeon Chen uintptr_t ret = MTK_SIP_E_SUCCESS; 145*6a7e8ebfSLeon Chen struct smccc_res smc_ret = {0}; 146*6a7e8ebfSLeon Chen 147*6a7e8ebfSLeon Chen switch (smc_id) { 148*6a7e8ebfSLeon Chen MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION); 149*6a7e8ebfSLeon Chen default: 150*6a7e8ebfSLeon Chen INFO("BL33 SMC ID:0x%x not supported\n", smc_id); 151*6a7e8ebfSLeon Chen ret = SMC_UNK; 152*6a7e8ebfSLeon Chen break; 153*6a7e8ebfSLeon Chen } 154*6a7e8ebfSLeon Chen SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3); 155*6a7e8ebfSLeon Chen } 156*6a7e8ebfSLeon Chen 157*6a7e8ebfSLeon Chen /* This function handles Mediatek defined SiP Calls from Kernel */ 158*6a7e8ebfSLeon Chen static uintptr_t mtk_smc_handler_nsel1(uint32_t smc_id, 159*6a7e8ebfSLeon Chen u_register_t x1, 160*6a7e8ebfSLeon Chen u_register_t x2, 161*6a7e8ebfSLeon Chen u_register_t x3, 162*6a7e8ebfSLeon Chen u_register_t x4, 163*6a7e8ebfSLeon Chen void *cookie, 164*6a7e8ebfSLeon Chen void *handle, 165*6a7e8ebfSLeon Chen u_register_t flags) 166*6a7e8ebfSLeon Chen { 167*6a7e8ebfSLeon Chen uintptr_t ret = MTK_SIP_E_SUCCESS; 168*6a7e8ebfSLeon Chen struct smccc_res smc_ret = {0}; 169*6a7e8ebfSLeon Chen 170*6a7e8ebfSLeon Chen switch (smc_id) { 171*6a7e8ebfSLeon Chen MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION); 172*6a7e8ebfSLeon Chen default: 173*6a7e8ebfSLeon Chen INFO("NSEL1 SMC ID:0x%x not supported\n", smc_id); 174*6a7e8ebfSLeon Chen ret = SMC_UNK; 175*6a7e8ebfSLeon Chen break; 176*6a7e8ebfSLeon Chen } 177*6a7e8ebfSLeon Chen SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3); 178*6a7e8ebfSLeon Chen } 179*6a7e8ebfSLeon Chen 180*6a7e8ebfSLeon Chen static uintptr_t mtk_smc_handler(uint32_t smc_id, 181*6a7e8ebfSLeon Chen u_register_t x1, 182*6a7e8ebfSLeon Chen u_register_t x2, 183*6a7e8ebfSLeon Chen u_register_t x3, 184*6a7e8ebfSLeon Chen u_register_t x4, 185*6a7e8ebfSLeon Chen void *cookie, 186*6a7e8ebfSLeon Chen void *handle, 187*6a7e8ebfSLeon Chen u_register_t flags) 188*6a7e8ebfSLeon Chen { 189*6a7e8ebfSLeon Chen uintptr_t ret = SMC_UNK; 190*6a7e8ebfSLeon Chen uint32_t ns; 191*6a7e8ebfSLeon Chen uint32_t smc_ori; 192*6a7e8ebfSLeon Chen uint32_t smc_num; 193*6a7e8ebfSLeon Chen 194*6a7e8ebfSLeon Chen /* Get SMC Originator bit 14.15 */ 195*6a7e8ebfSLeon Chen smc_ori = GET_SMC_ORI(smc_id); 196*6a7e8ebfSLeon Chen /* Get SMC Number. Clean bit 14.15 */ 197*6a7e8ebfSLeon Chen smc_num = GET_SMC_ORI_NUM(smc_id); 198*6a7e8ebfSLeon Chen 199*6a7e8ebfSLeon Chen /* Determine which security state this SMC originated from */ 200*6a7e8ebfSLeon Chen ns = is_caller_non_secure(flags); 201*6a7e8ebfSLeon Chen 202*6a7e8ebfSLeon Chen if (ns && is_smc_forbidden(smc_ori)) { 203*6a7e8ebfSLeon Chen ERROR("%s: Forbidden SMC call (0x%x)\n", __func__, smc_id); 204*6a7e8ebfSLeon Chen SMC_RET1(handle, ret); 205*6a7e8ebfSLeon Chen } 206*6a7e8ebfSLeon Chen 207*6a7e8ebfSLeon Chen if (!ns) { 208*6a7e8ebfSLeon Chen /* SiP SMC service secure world's call */ 209*6a7e8ebfSLeon Chen INFO("Secure SMC ID:0x%x not supported\n", smc_id); 210*6a7e8ebfSLeon Chen SMC_RET1(handle, ret); 211*6a7e8ebfSLeon Chen } 212*6a7e8ebfSLeon Chen if (is_from_bl33(smc_ori)) { 213*6a7e8ebfSLeon Chen /* SiP SMC service secure bootloader's call */ 214*6a7e8ebfSLeon Chen return mtk_smc_handler_bl33(smc_num, x1, x2, x3, x4, 215*6a7e8ebfSLeon Chen cookie, handle, flags); 216*6a7e8ebfSLeon Chen } else if (is_from_nsel1(smc_ori)) { 217*6a7e8ebfSLeon Chen /* SiP SMC service kernel's call */ 218*6a7e8ebfSLeon Chen return mtk_smc_handler_nsel1(smc_num, x1, x2, x3, x4, 219*6a7e8ebfSLeon Chen cookie, handle, flags); 220*6a7e8ebfSLeon Chen } 221*6a7e8ebfSLeon Chen INFO("SMC ID:0x%x not supported\n", smc_id); 222*6a7e8ebfSLeon Chen SMC_RET1(handle, ret); 223*6a7e8ebfSLeon Chen } 224*6a7e8ebfSLeon Chen 225*6a7e8ebfSLeon Chen /* Define a runtime service descriptor for fast SMC calls */ 226*6a7e8ebfSLeon Chen DECLARE_RT_SVC( 227*6a7e8ebfSLeon Chen mtk_smc_handler, 228*6a7e8ebfSLeon Chen OEN_SIP_START, 229*6a7e8ebfSLeon Chen OEN_SIP_END, 230*6a7e8ebfSLeon Chen SMC_TYPE_FAST, 231*6a7e8ebfSLeon Chen NULL, 232*6a7e8ebfSLeon Chen mtk_smc_handler 233*6a7e8ebfSLeon Chen ); 234