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