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