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
read_dt_tpm_log_info(void * fdt,int node,paddr_t * buf,size_t * size)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 = reg_pair_to_64(fdt32_to_cpu(property[0]),
50 fdt32_to_cpu(property[1]));
51
52 if (!IS_ENABLED(CFG_CORE_FFA)) {
53 err = fdt_setprop(fdt, node, dt_tpm_event_log_addr, &zero_addr,
54 sizeof(uint32_t) * 2);
55 if (err < 0) {
56 EMSG("Error setting property DTB to zero");
57 return err;
58 }
59 }
60
61 /*
62 * Get the TPM Log size.
63 */
64 property = fdt_getprop(fdt, node, "tpm_event_log_size", &len_prop);
65
66 if (!property || len_prop != sizeof(uint32_t))
67 return -1;
68
69 *size = fdt32_to_cpu(property[0]);
70 *buf = log_addr;
71
72 return *size;
73 }
74 #endif
75
get_tpm_phys_params(void * fdt __maybe_unused,paddr_t * addr,size_t * size)76 static void get_tpm_phys_params(void *fdt __maybe_unused,
77 paddr_t *addr, size_t *size)
78 {
79 #ifdef CFG_DT
80 int node = 0;
81 const char *dt_tpm_match_table = {
82 "arm,tpm_event_log",
83 };
84
85 if (!fdt) {
86 EMSG("TPM: No DTB found");
87 return;
88 }
89
90 node = fdt_node_offset_by_compatible(fdt, -1, dt_tpm_match_table);
91
92 if (node < 0) {
93 EMSG("TPM: Fail to find TPM node %i", node);
94 return;
95 }
96
97 if (read_dt_tpm_log_info((void *)fdt, node, addr, size) < 0) {
98 EMSG("TPM: Fail to retrieve DTB properties from node %i",
99 node);
100 return;
101 }
102 #else
103 *size = CFG_TPM_MAX_LOG_SIZE;
104 *addr = CFG_TPM_LOG_BASE_ADDR;
105 #endif /* CFG_DT */
106 }
107
tpm_get_event_log(void * buf,size_t * size)108 TEE_Result tpm_get_event_log(void *buf, size_t *size)
109 {
110 const size_t buf_size = *size;
111
112 *size = tpm_log_size;
113 if (!buf) {
114 EMSG("TPM: Invalid buffer");
115 return TEE_ERROR_BAD_PARAMETERS;
116 }
117
118 if (buf_size < tpm_log_size) {
119 EMSG("TPM: Not enough space for the log: %zu, %zu",
120 buf_size, tpm_log_size);
121 return TEE_ERROR_SHORT_BUFFER;
122 }
123
124 memcpy(buf, tpm_log_addr, tpm_log_size);
125
126 return TEE_SUCCESS;
127 }
128
tpm_get_event_log_size(size_t * size)129 TEE_Result tpm_get_event_log_size(size_t *size)
130 {
131 *size = tpm_log_size;
132
133 return TEE_SUCCESS;
134 }
135
tpm_map_log_area(void * fdt)136 void tpm_map_log_area(void *fdt)
137 {
138 paddr_t log_addr = 0;
139 unsigned int rounded_size = 0;
140
141 get_tpm_phys_params(fdt, &log_addr, &tpm_log_size);
142
143 DMSG("TPM Event log PA: %#" PRIxPA, log_addr);
144 DMSG("TPM Event log size: %zu Bytes", tpm_log_size);
145
146 rounded_size = ROUNDUP(tpm_log_size, SMALL_PAGE_SIZE);
147
148 tpm_log_addr = core_mmu_add_mapping(MEM_AREA_RAM_SEC, log_addr,
149 rounded_size);
150 if (!tpm_log_addr) {
151 EMSG("TPM: Failed to map TPM log memory");
152 return;
153 }
154 }
155