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