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