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