1*e605fbdfSSheetal Tigadoli // SPDX-License-Identifier: BSD-2-Clause 2*e605fbdfSSheetal Tigadoli /* 3*e605fbdfSSheetal Tigadoli * Copyright 2019 Broadcom. 4*e605fbdfSSheetal Tigadoli */ 5*e605fbdfSSheetal Tigadoli 6*e605fbdfSSheetal Tigadoli #include <drivers/bcm/bnxt.h> 7*e605fbdfSSheetal Tigadoli #include <io.h> 8*e605fbdfSSheetal Tigadoli #include <kernel/pseudo_ta.h> 9*e605fbdfSSheetal Tigadoli #include <mm/core_memprot.h> 10*e605fbdfSSheetal Tigadoli #include <mm/core_mmu.h> 11*e605fbdfSSheetal Tigadoli #include <string.h> 12*e605fbdfSSheetal Tigadoli #include <trace.h> 13*e605fbdfSSheetal Tigadoli 14*e605fbdfSSheetal Tigadoli #define ELOG_SERVICE_UUID \ 15*e605fbdfSSheetal Tigadoli { 0x6272636D, 0x2019, 0x0701, \ 16*e605fbdfSSheetal Tigadoli { 0x42, 0x43, 0x4D, 0x5F, 0x45, 0x4C, 0x4F, 0x47 } } 17*e605fbdfSSheetal Tigadoli 18*e605fbdfSSheetal Tigadoli #define ELOG_TA_NAME "pta_bcm_elog.ta" 19*e605fbdfSSheetal Tigadoli 20*e605fbdfSSheetal Tigadoli #define BCM_NITRO_FW_LOAD_ADDR 0x8ae00000 21*e605fbdfSSheetal Tigadoli #define BCM_NITRO_CRASH_DUMP_BASE_ADDR 0x8b000000 22*e605fbdfSSheetal Tigadoli 23*e605fbdfSSheetal Tigadoli /* Default ELOG buffer size 1MB */ 24*e605fbdfSSheetal Tigadoli #define DEFAULT_ELOG_BUFFER_SIZE 0x100000 25*e605fbdfSSheetal Tigadoli 26*e605fbdfSSheetal Tigadoli /* 27*e605fbdfSSheetal Tigadoli * Get Error log memory dump 28*e605fbdfSSheetal Tigadoli * 29*e605fbdfSSheetal Tigadoli * [out] memref[0]: Destination 30*e605fbdfSSheetal Tigadoli * [in] value[1].a: Offset 31*e605fbdfSSheetal Tigadoli */ 32*e605fbdfSSheetal Tigadoli #define PTA_BCM_ELOG_CMD_GET_ELOG_MEM 1 33*e605fbdfSSheetal Tigadoli 34*e605fbdfSSheetal Tigadoli /* 35*e605fbdfSSheetal Tigadoli * Get nitro crash_dump memory 36*e605fbdfSSheetal Tigadoli * 37*e605fbdfSSheetal Tigadoli * [out] memref[0]: Destination 38*e605fbdfSSheetal Tigadoli * [in] value[1].a: Offset 39*e605fbdfSSheetal Tigadoli */ 40*e605fbdfSSheetal Tigadoli #define PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP 2 41*e605fbdfSSheetal Tigadoli 42*e605fbdfSSheetal Tigadoli /* 43*e605fbdfSSheetal Tigadoli * Load nitro firmware memory 44*e605fbdfSSheetal Tigadoli * 45*e605fbdfSSheetal Tigadoli * [in] memref[0]: Nitro f/w image data 46*e605fbdfSSheetal Tigadoli * [in] value[1].a: Offset for loading f/w image 47*e605fbdfSSheetal Tigadoli * [in] value[2].a: Firmware image size 48*e605fbdfSSheetal Tigadoli */ 49*e605fbdfSSheetal Tigadoli #define PTA_BCM_ELOG_CMD_LOAD_NITRO_FW 3 50*e605fbdfSSheetal Tigadoli 51*e605fbdfSSheetal Tigadoli #define BCM_ELOG_GLOBAL_METADATA_SIG 0x45524c47 52*e605fbdfSSheetal Tigadoli 53*e605fbdfSSheetal Tigadoli #define MAX_NITRO_CRASH_DUMP_MEM_SIZE 0x2000000 54*e605fbdfSSheetal Tigadoli #define MAX_NITRO_FW_LOAD_MEM_SIZE 0x200000 55*e605fbdfSSheetal Tigadoli 56*e605fbdfSSheetal Tigadoli /* Load Nitro fw image to SEC DDR memory */ 57*e605fbdfSSheetal Tigadoli static TEE_Result pta_elog_load_nitro_fw(uint32_t param_types, 58*e605fbdfSSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS]) 59*e605fbdfSSheetal Tigadoli { 60*e605fbdfSSheetal Tigadoli TEE_Result res = TEE_SUCCESS; 61*e605fbdfSSheetal Tigadoli paddr_t src_paddr = BCM_NITRO_FW_LOAD_ADDR + BNXT_IMG_SECMEM_OFFSET; 62*e605fbdfSSheetal Tigadoli vaddr_t src_vaddr = 0; 63*e605fbdfSSheetal Tigadoli uint32_t offset = 0, sz = 0; 64*e605fbdfSSheetal Tigadoli char *buf = NULL; 65*e605fbdfSSheetal Tigadoli uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 66*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_VALUE_INPUT, 67*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_VALUE_INPUT, 68*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_NONE); 69*e605fbdfSSheetal Tigadoli 70*e605fbdfSSheetal Tigadoli if (exp_param_types != param_types) { 71*e605fbdfSSheetal Tigadoli EMSG("Invalid Param types"); 72*e605fbdfSSheetal Tigadoli return TEE_ERROR_BAD_PARAMETERS; 73*e605fbdfSSheetal Tigadoli } 74*e605fbdfSSheetal Tigadoli 75*e605fbdfSSheetal Tigadoli /* Check if firmware file size exceeds reserved memory size */ 76*e605fbdfSSheetal Tigadoli if (params[2].value.a > MAX_NITRO_FW_LOAD_MEM_SIZE) { 77*e605fbdfSSheetal Tigadoli EMSG("Invalid access"); 78*e605fbdfSSheetal Tigadoli return TEE_ERROR_EXCESS_DATA; 79*e605fbdfSSheetal Tigadoli } 80*e605fbdfSSheetal Tigadoli 81*e605fbdfSSheetal Tigadoli offset = params[1].value.a; 82*e605fbdfSSheetal Tigadoli 83*e605fbdfSSheetal Tigadoli /* 84*e605fbdfSSheetal Tigadoli * Check if offset is within memory range reserved for nitro firmware 85*e605fbdfSSheetal Tigadoli * minus default size of buffer 86*e605fbdfSSheetal Tigadoli */ 87*e605fbdfSSheetal Tigadoli if (offset > MAX_NITRO_FW_LOAD_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) { 88*e605fbdfSSheetal Tigadoli EMSG("Invalid access"); 89*e605fbdfSSheetal Tigadoli return TEE_ERROR_ACCESS_DENIED; 90*e605fbdfSSheetal Tigadoli } 91*e605fbdfSSheetal Tigadoli 92*e605fbdfSSheetal Tigadoli src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset, 93*e605fbdfSSheetal Tigadoli MEM_AREA_RAM_SEC); 94*e605fbdfSSheetal Tigadoli 95*e605fbdfSSheetal Tigadoli buf = params[0].memref.buffer; 96*e605fbdfSSheetal Tigadoli sz = params[0].memref.size; 97*e605fbdfSSheetal Tigadoli 98*e605fbdfSSheetal Tigadoli memcpy((char *)src_vaddr, buf, sz); 99*e605fbdfSSheetal Tigadoli 100*e605fbdfSSheetal Tigadoli cache_op_inner(DCACHE_AREA_CLEAN, (void *)src_vaddr, sz); 101*e605fbdfSSheetal Tigadoli 102*e605fbdfSSheetal Tigadoli return res; 103*e605fbdfSSheetal Tigadoli } 104*e605fbdfSSheetal Tigadoli 105*e605fbdfSSheetal Tigadoli static uint32_t get_dump_data(vaddr_t src, TEE_Param params[TEE_NUM_PARAMS]) 106*e605fbdfSSheetal Tigadoli { 107*e605fbdfSSheetal Tigadoli char *buf = NULL; 108*e605fbdfSSheetal Tigadoli uint32_t sz = 0; 109*e605fbdfSSheetal Tigadoli 110*e605fbdfSSheetal Tigadoli buf = params[0].memref.buffer; 111*e605fbdfSSheetal Tigadoli sz = params[0].memref.size; 112*e605fbdfSSheetal Tigadoli 113*e605fbdfSSheetal Tigadoli /* 114*e605fbdfSSheetal Tigadoli * If request size exceeds default buf size 115*e605fbdfSSheetal Tigadoli * override request size to default DEFAULT_ELOG_BUFFER_SIZE 116*e605fbdfSSheetal Tigadoli */ 117*e605fbdfSSheetal Tigadoli if (sz > DEFAULT_ELOG_BUFFER_SIZE) 118*e605fbdfSSheetal Tigadoli sz = DEFAULT_ELOG_BUFFER_SIZE; 119*e605fbdfSSheetal Tigadoli 120*e605fbdfSSheetal Tigadoli DMSG("buf %p sz 0x%x", buf, sz); 121*e605fbdfSSheetal Tigadoli 122*e605fbdfSSheetal Tigadoli memcpy(buf, (char *)src, sz); 123*e605fbdfSSheetal Tigadoli 124*e605fbdfSSheetal Tigadoli params[0].memref.size = sz; 125*e605fbdfSSheetal Tigadoli 126*e605fbdfSSheetal Tigadoli return sz; 127*e605fbdfSSheetal Tigadoli } 128*e605fbdfSSheetal Tigadoli 129*e605fbdfSSheetal Tigadoli /* Copy nitro crash dump data */ 130*e605fbdfSSheetal Tigadoli static TEE_Result pta_elog_nitro_crash_dump(uint32_t param_types, 131*e605fbdfSSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS]) 132*e605fbdfSSheetal Tigadoli { 133*e605fbdfSSheetal Tigadoli TEE_Result res = TEE_SUCCESS; 134*e605fbdfSSheetal Tigadoli paddr_t src_paddr = BCM_NITRO_CRASH_DUMP_BASE_ADDR; 135*e605fbdfSSheetal Tigadoli vaddr_t src_vaddr = 0; 136*e605fbdfSSheetal Tigadoli uint32_t offset = 0; 137*e605fbdfSSheetal Tigadoli uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 138*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_VALUE_INPUT, 139*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_NONE, 140*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_NONE); 141*e605fbdfSSheetal Tigadoli 142*e605fbdfSSheetal Tigadoli if (exp_param_types != param_types) { 143*e605fbdfSSheetal Tigadoli EMSG("Invalid Param types"); 144*e605fbdfSSheetal Tigadoli return TEE_ERROR_BAD_PARAMETERS; 145*e605fbdfSSheetal Tigadoli } 146*e605fbdfSSheetal Tigadoli 147*e605fbdfSSheetal Tigadoli offset = params[1].value.a; 148*e605fbdfSSheetal Tigadoli 149*e605fbdfSSheetal Tigadoli /* 150*e605fbdfSSheetal Tigadoli * Check if offset is within memory range reserved for nitro crash dump 151*e605fbdfSSheetal Tigadoli * minus default size of buffer 152*e605fbdfSSheetal Tigadoli */ 153*e605fbdfSSheetal Tigadoli if (offset > MAX_NITRO_CRASH_DUMP_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) { 154*e605fbdfSSheetal Tigadoli EMSG("Invalid access"); 155*e605fbdfSSheetal Tigadoli return TEE_ERROR_ACCESS_DENIED; 156*e605fbdfSSheetal Tigadoli } 157*e605fbdfSSheetal Tigadoli 158*e605fbdfSSheetal Tigadoli src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset, 159*e605fbdfSSheetal Tigadoli MEM_AREA_RAM_SEC); 160*e605fbdfSSheetal Tigadoli 161*e605fbdfSSheetal Tigadoli /* TODO : check if NITRO_CRASH_DUMP is available */ 162*e605fbdfSSheetal Tigadoli 163*e605fbdfSSheetal Tigadoli cache_op_inner(DCACHE_AREA_INVALIDATE, 164*e605fbdfSSheetal Tigadoli (void *)src_vaddr, DEFAULT_ELOG_BUFFER_SIZE); 165*e605fbdfSSheetal Tigadoli 166*e605fbdfSSheetal Tigadoli get_dump_data(src_vaddr, params); 167*e605fbdfSSheetal Tigadoli 168*e605fbdfSSheetal Tigadoli return res; 169*e605fbdfSSheetal Tigadoli } 170*e605fbdfSSheetal Tigadoli 171*e605fbdfSSheetal Tigadoli /* Copy soc error log data */ 172*e605fbdfSSheetal Tigadoli static TEE_Result pta_elog_dump(uint32_t param_types, 173*e605fbdfSSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS]) 174*e605fbdfSSheetal Tigadoli { 175*e605fbdfSSheetal Tigadoli TEE_Result res = TEE_SUCCESS; 176*e605fbdfSSheetal Tigadoli paddr_t src_paddr = CFG_BCM_ELOG_BASE; 177*e605fbdfSSheetal Tigadoli vaddr_t src_vaddr = 0; 178*e605fbdfSSheetal Tigadoli uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 179*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_VALUE_INPUT, 180*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_NONE, 181*e605fbdfSSheetal Tigadoli TEE_PARAM_TYPE_NONE); 182*e605fbdfSSheetal Tigadoli 183*e605fbdfSSheetal Tigadoli if (exp_param_types != param_types) { 184*e605fbdfSSheetal Tigadoli EMSG("Invalid Param types"); 185*e605fbdfSSheetal Tigadoli return TEE_ERROR_BAD_PARAMETERS; 186*e605fbdfSSheetal Tigadoli } 187*e605fbdfSSheetal Tigadoli 188*e605fbdfSSheetal Tigadoli src_vaddr = (vaddr_t)phys_to_virt(src_paddr, MEM_AREA_RAM_NSEC); 189*e605fbdfSSheetal Tigadoli 190*e605fbdfSSheetal Tigadoli /* Validate if Error logs are present */ 191*e605fbdfSSheetal Tigadoli if ((*(uint32_t *)src_vaddr) != BCM_ELOG_GLOBAL_METADATA_SIG) { 192*e605fbdfSSheetal Tigadoli EMSG("Elog Not setup"); 193*e605fbdfSSheetal Tigadoli return TEE_ERROR_NOT_SUPPORTED; 194*e605fbdfSSheetal Tigadoli } 195*e605fbdfSSheetal Tigadoli 196*e605fbdfSSheetal Tigadoli get_dump_data(src_vaddr, params); 197*e605fbdfSSheetal Tigadoli 198*e605fbdfSSheetal Tigadoli return res; 199*e605fbdfSSheetal Tigadoli } 200*e605fbdfSSheetal Tigadoli 201*e605fbdfSSheetal Tigadoli static TEE_Result invoke_command(void *session_context __unused, 202*e605fbdfSSheetal Tigadoli uint32_t cmd_id, 203*e605fbdfSSheetal Tigadoli uint32_t param_types, 204*e605fbdfSSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS]) 205*e605fbdfSSheetal Tigadoli { 206*e605fbdfSSheetal Tigadoli TEE_Result res = TEE_SUCCESS; 207*e605fbdfSSheetal Tigadoli 208*e605fbdfSSheetal Tigadoli DMSG("command entry point[%d] for \"%s\"", cmd_id, ELOG_TA_NAME); 209*e605fbdfSSheetal Tigadoli 210*e605fbdfSSheetal Tigadoli switch (cmd_id) { 211*e605fbdfSSheetal Tigadoli case PTA_BCM_ELOG_CMD_GET_ELOG_MEM: 212*e605fbdfSSheetal Tigadoli res = pta_elog_dump(param_types, params); 213*e605fbdfSSheetal Tigadoli break; 214*e605fbdfSSheetal Tigadoli case PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP: 215*e605fbdfSSheetal Tigadoli res = pta_elog_nitro_crash_dump(param_types, params); 216*e605fbdfSSheetal Tigadoli break; 217*e605fbdfSSheetal Tigadoli case PTA_BCM_ELOG_CMD_LOAD_NITRO_FW: 218*e605fbdfSSheetal Tigadoli res = pta_elog_load_nitro_fw(param_types, params); 219*e605fbdfSSheetal Tigadoli break; 220*e605fbdfSSheetal Tigadoli default: 221*e605fbdfSSheetal Tigadoli EMSG("cmd: %d Not supported %s", cmd_id, ELOG_TA_NAME); 222*e605fbdfSSheetal Tigadoli res = TEE_ERROR_NOT_SUPPORTED; 223*e605fbdfSSheetal Tigadoli break; 224*e605fbdfSSheetal Tigadoli } 225*e605fbdfSSheetal Tigadoli 226*e605fbdfSSheetal Tigadoli return res; 227*e605fbdfSSheetal Tigadoli } 228*e605fbdfSSheetal Tigadoli 229*e605fbdfSSheetal Tigadoli pseudo_ta_register(.uuid = ELOG_SERVICE_UUID, 230*e605fbdfSSheetal Tigadoli .name = ELOG_TA_NAME, 231*e605fbdfSSheetal Tigadoli .flags = PTA_DEFAULT_FLAGS, 232*e605fbdfSSheetal Tigadoli .invoke_command_entry_point = invoke_command); 233