1*dd333f03SJavier Almansa Sobrino // SPDX-License-Identifier: BSD-3-Clause 2*dd333f03SJavier Almansa Sobrino /* 3*dd333f03SJavier Almansa Sobrino * Copyright (c) 2020, ARM Limited. All rights reserved. 4*dd333f03SJavier Almansa Sobrino */ 5*dd333f03SJavier Almansa Sobrino 6*dd333f03SJavier Almansa Sobrino #include <mm/core_memprot.h> 7*dd333f03SJavier Almansa Sobrino #include <kernel/tpm.h> 8*dd333f03SJavier Almansa Sobrino #include <compiler.h> 9*dd333f03SJavier Almansa Sobrino #include <string.h> 10*dd333f03SJavier Almansa Sobrino #ifdef CFG_DT 11*dd333f03SJavier Almansa Sobrino #include <kernel/dt.h> 12*dd333f03SJavier Almansa Sobrino #include <libfdt.h> 13*dd333f03SJavier Almansa Sobrino #endif 14*dd333f03SJavier Almansa Sobrino 15*dd333f03SJavier Almansa Sobrino static void *tpm_log_addr; 16*dd333f03SJavier Almansa Sobrino static size_t tpm_log_size; 17*dd333f03SJavier Almansa Sobrino 18*dd333f03SJavier Almansa Sobrino /* 19*dd333f03SJavier Almansa Sobrino * Check whether the node at @offs contains TPM Event Log information or not. 20*dd333f03SJavier Almansa Sobrino * 21*dd333f03SJavier Almansa Sobrino * @offs is the offset of the node that describes the device in @fdt. 22*dd333f03SJavier Almansa Sobrino * @buf will contain the phy address of the TPM Event log. 23*dd333f03SJavier Almansa Sobrino * @size will contain the size of the mapped area. 24*dd333f03SJavier Almansa Sobrino * 25*dd333f03SJavier Almansa Sobrino * Returns the size of the mapped area or < 0 on failure. 26*dd333f03SJavier Almansa Sobrino */ 27*dd333f03SJavier Almansa Sobrino #ifdef CFG_DT 28*dd333f03SJavier Almansa Sobrino static int read_dt_tpm_log_info(void *fdt, int node, paddr_t *buf, 29*dd333f03SJavier Almansa Sobrino size_t *size) 30*dd333f03SJavier Almansa Sobrino { 31*dd333f03SJavier Almansa Sobrino const uint32_t *property = NULL; 32*dd333f03SJavier Almansa Sobrino const uint64_t zero_addr = 0; 33*dd333f03SJavier Almansa Sobrino int len_prop = 0; 34*dd333f03SJavier Almansa Sobrino paddr_t log_addr = 0; 35*dd333f03SJavier Almansa Sobrino int err = 0; 36*dd333f03SJavier Almansa Sobrino 37*dd333f03SJavier Almansa Sobrino /* 38*dd333f03SJavier Almansa Sobrino * Get the TPM Log address. 39*dd333f03SJavier Almansa Sobrino */ 40*dd333f03SJavier Almansa Sobrino property = fdt_getprop(fdt, node, "tpm_event_log_sm_addr", &len_prop); 41*dd333f03SJavier Almansa Sobrino 42*dd333f03SJavier Almansa Sobrino if (!property || len_prop != sizeof(uint32_t) * 2) 43*dd333f03SJavier Almansa Sobrino return -1; 44*dd333f03SJavier Almansa Sobrino 45*dd333f03SJavier Almansa Sobrino log_addr = fdt32_to_cpu(property[1]); 46*dd333f03SJavier Almansa Sobrino 47*dd333f03SJavier Almansa Sobrino err = fdt_setprop(fdt, node, "tpm_event_log_sm_addr", &zero_addr, 48*dd333f03SJavier Almansa Sobrino sizeof(uint32_t) * 2); 49*dd333f03SJavier Almansa Sobrino if (err < 0) { 50*dd333f03SJavier Almansa Sobrino EMSG("Error setting property DTB to zero\n"); 51*dd333f03SJavier Almansa Sobrino return err; 52*dd333f03SJavier Almansa Sobrino } 53*dd333f03SJavier Almansa Sobrino 54*dd333f03SJavier Almansa Sobrino /* 55*dd333f03SJavier Almansa Sobrino * Get the TPM Log size. 56*dd333f03SJavier Almansa Sobrino */ 57*dd333f03SJavier Almansa Sobrino property = fdt_getprop(fdt, node, "tpm_event_log_size", &len_prop); 58*dd333f03SJavier Almansa Sobrino 59*dd333f03SJavier Almansa Sobrino if (!property || len_prop != sizeof(uint32_t)) 60*dd333f03SJavier Almansa Sobrino return -1; 61*dd333f03SJavier Almansa Sobrino 62*dd333f03SJavier Almansa Sobrino *size = fdt32_to_cpu(property[0]); 63*dd333f03SJavier Almansa Sobrino *buf = log_addr; 64*dd333f03SJavier Almansa Sobrino 65*dd333f03SJavier Almansa Sobrino return *size; 66*dd333f03SJavier Almansa Sobrino } 67*dd333f03SJavier Almansa Sobrino #endif 68*dd333f03SJavier Almansa Sobrino 69*dd333f03SJavier Almansa Sobrino static void get_tpm_phys_params(void *fdt __maybe_unused, 70*dd333f03SJavier Almansa Sobrino paddr_t *addr, size_t *size) 71*dd333f03SJavier Almansa Sobrino { 72*dd333f03SJavier Almansa Sobrino #ifdef CFG_DT 73*dd333f03SJavier Almansa Sobrino int node = 0; 74*dd333f03SJavier Almansa Sobrino const char *dt_tpm_match_table = { 75*dd333f03SJavier Almansa Sobrino "arm,nt_fw", 76*dd333f03SJavier Almansa Sobrino }; 77*dd333f03SJavier Almansa Sobrino 78*dd333f03SJavier Almansa Sobrino if (!fdt) { 79*dd333f03SJavier Almansa Sobrino EMSG("TPM: No DTB found"); 80*dd333f03SJavier Almansa Sobrino return; 81*dd333f03SJavier Almansa Sobrino } 82*dd333f03SJavier Almansa Sobrino 83*dd333f03SJavier Almansa Sobrino node = fdt_node_offset_by_compatible(fdt, -1, dt_tpm_match_table); 84*dd333f03SJavier Almansa Sobrino 85*dd333f03SJavier Almansa Sobrino if (node < 0) { 86*dd333f03SJavier Almansa Sobrino EMSG("TPM: Fail to find TPM node %i", node); 87*dd333f03SJavier Almansa Sobrino return; 88*dd333f03SJavier Almansa Sobrino } 89*dd333f03SJavier Almansa Sobrino 90*dd333f03SJavier Almansa Sobrino if (read_dt_tpm_log_info((void *)fdt, node, addr, size) < 0) { 91*dd333f03SJavier Almansa Sobrino EMSG("TPM: Fail to retrieve DTB properties from node %i", 92*dd333f03SJavier Almansa Sobrino node); 93*dd333f03SJavier Almansa Sobrino return; 94*dd333f03SJavier Almansa Sobrino } 95*dd333f03SJavier Almansa Sobrino #else 96*dd333f03SJavier Almansa Sobrino *size = CFG_TPM_MAX_LOG_SIZE; 97*dd333f03SJavier Almansa Sobrino *addr = CFG_TPM_LOG_BASE_ADDR; 98*dd333f03SJavier Almansa Sobrino #endif /* CFG_DT */ 99*dd333f03SJavier Almansa Sobrino } 100*dd333f03SJavier Almansa Sobrino 101*dd333f03SJavier Almansa Sobrino TEE_Result tpm_get_event_log(void *buf, size_t *size) 102*dd333f03SJavier Almansa Sobrino { 103*dd333f03SJavier Almansa Sobrino const size_t buf_size = *size; 104*dd333f03SJavier Almansa Sobrino 105*dd333f03SJavier Almansa Sobrino *size = tpm_log_size; 106*dd333f03SJavier Almansa Sobrino if (!buf) { 107*dd333f03SJavier Almansa Sobrino EMSG("TPM: Invalid buffer"); 108*dd333f03SJavier Almansa Sobrino return TEE_ERROR_BAD_PARAMETERS; 109*dd333f03SJavier Almansa Sobrino } 110*dd333f03SJavier Almansa Sobrino 111*dd333f03SJavier Almansa Sobrino if (buf_size < tpm_log_size) { 112*dd333f03SJavier Almansa Sobrino EMSG("TPM: Not enough space for the log: %zu, %lu", 113*dd333f03SJavier Almansa Sobrino buf_size, tpm_log_size); 114*dd333f03SJavier Almansa Sobrino return TEE_ERROR_SHORT_BUFFER; 115*dd333f03SJavier Almansa Sobrino } 116*dd333f03SJavier Almansa Sobrino 117*dd333f03SJavier Almansa Sobrino memcpy(buf, tpm_log_addr, tpm_log_size); 118*dd333f03SJavier Almansa Sobrino 119*dd333f03SJavier Almansa Sobrino return TEE_SUCCESS; 120*dd333f03SJavier Almansa Sobrino } 121*dd333f03SJavier Almansa Sobrino 122*dd333f03SJavier Almansa Sobrino void tpm_map_log_area(void *fdt) 123*dd333f03SJavier Almansa Sobrino { 124*dd333f03SJavier Almansa Sobrino paddr_t log_addr = 0; 125*dd333f03SJavier Almansa Sobrino unsigned int rounded_size = 0; 126*dd333f03SJavier Almansa Sobrino 127*dd333f03SJavier Almansa Sobrino get_tpm_phys_params(fdt, &log_addr, &tpm_log_size); 128*dd333f03SJavier Almansa Sobrino 129*dd333f03SJavier Almansa Sobrino DMSG("TPM Event log PA: %#" PRIxPA, log_addr); 130*dd333f03SJavier Almansa Sobrino DMSG("TPM Event log size: %zu Bytes", tpm_log_size); 131*dd333f03SJavier Almansa Sobrino 132*dd333f03SJavier Almansa Sobrino rounded_size = ROUNDUP(tpm_log_size, SMALL_PAGE_SIZE); 133*dd333f03SJavier Almansa Sobrino 134*dd333f03SJavier Almansa Sobrino if (!core_mmu_add_mapping(MEM_AREA_RAM_SEC, log_addr, rounded_size)) { 135*dd333f03SJavier Almansa Sobrino EMSG("TPM: Failed to map TPM log memory"); 136*dd333f03SJavier Almansa Sobrino return; 137*dd333f03SJavier Almansa Sobrino } 138*dd333f03SJavier Almansa Sobrino 139*dd333f03SJavier Almansa Sobrino tpm_log_addr = phys_to_virt(log_addr, MEM_AREA_RAM_SEC); 140*dd333f03SJavier Almansa Sobrino 141*dd333f03SJavier Almansa Sobrino if (!tpm_log_addr) 142*dd333f03SJavier Almansa Sobrino EMSG("TPM: Error mapping phys mem to va space"); 143*dd333f03SJavier Almansa Sobrino } 144