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