xref: /optee_os/core/kernel/tpm.c (revision dd333f03ab1978903f4c98cee84547391bd4d21a)
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