File: tpm.c

package info (click to toggle)
optee-os 4.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 31,960 kB
  • sloc: ansic: 444,388; asm: 12,922; python: 3,719; makefile: 1,681; sh: 238
file content (154 lines) | stat: -rw-r--r-- 3,428 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// SPDX-License-Identifier: BSD-3-Clause
/*
 * Copyright (c) 2020-2023, ARM Limited. All rights reserved.
 * Copyright (c) 2025, NVIDIA Corporation & AFFILIATES.
 */

#include <compiler.h>
#include <kernel/dt.h>
#include <kernel/tpm.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
#include <string.h>

static void *tpm_log_addr;
static size_t tpm_log_size;

/*
 * Check whether the node at @offs contains TPM Event Log information or not.
 *
 * @offs is the offset of the node that describes the device in @fdt.
 * @buf will contain the phy address of the TPM Event log.
 * @size will contain the size of the mapped area.
 *
 * Returns the size of the mapped area or < 0 on failure.
 */
#ifdef CFG_DT
static int read_dt_tpm_log_info(void *fdt, int node, paddr_t *buf,
				size_t *size)
{
	const uint32_t *property = NULL;
	const uint64_t zero_addr = 0;
	int len_prop = 0;
	paddr_t log_addr = 0;
	int err = 0;
#ifdef CFG_MAP_EXT_DT_SECURE
	const char *dt_tpm_event_log_addr = "tpm_event_log_addr";
#else
	const char *dt_tpm_event_log_addr = "tpm_event_log_sm_addr";
#endif

	/*
	 * Get the TPM Log address.
	 */
	property = fdt_getprop(fdt, node, dt_tpm_event_log_addr, &len_prop);

	if (!property  || len_prop != sizeof(uint32_t) * 2)
		return -1;

	log_addr = reg_pair_to_64(fdt32_to_cpu(property[0]),
				  fdt32_to_cpu(property[1]));

	if (!IS_ENABLED(CFG_CORE_FFA)) {
		err = fdt_setprop(fdt, node, dt_tpm_event_log_addr, &zero_addr,
				  sizeof(uint32_t) * 2);
		if (err < 0) {
			EMSG("Error setting property DTB to zero");
			return err;
		}
	}

	/*
	 * Get the TPM Log size.
	 */
	property = fdt_getprop(fdt, node, "tpm_event_log_size", &len_prop);

	if (!property || len_prop != sizeof(uint32_t))
		return -1;

	*size = fdt32_to_cpu(property[0]);
	*buf = log_addr;

	return *size;
}
#endif

static void get_tpm_phys_params(void *fdt __maybe_unused,
				paddr_t *addr, size_t *size)
{
#ifdef CFG_DT
	int node = 0;
	const char *dt_tpm_match_table = {
		"arm,tpm_event_log",
	};

	if (!fdt) {
		EMSG("TPM: No DTB found");
		return;
	}

	node = fdt_node_offset_by_compatible(fdt, -1, dt_tpm_match_table);

	if (node < 0) {
		EMSG("TPM: Fail to find TPM node %i", node);
		return;
	}

	if (read_dt_tpm_log_info((void *)fdt, node, addr, size) < 0) {
		EMSG("TPM: Fail to retrieve DTB properties from node %i",
		     node);
		return;
	}
#else
	*size = CFG_TPM_MAX_LOG_SIZE;
	*addr = CFG_TPM_LOG_BASE_ADDR;
#endif /* CFG_DT */
}

TEE_Result tpm_get_event_log(void *buf, size_t *size)
{
	const size_t buf_size = *size;

	*size = tpm_log_size;
	if (!buf) {
		EMSG("TPM: Invalid buffer");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	if (buf_size < tpm_log_size) {
		EMSG("TPM: Not enough space for the log: %zu, %zu",
		     buf_size, tpm_log_size);
		return TEE_ERROR_SHORT_BUFFER;
	}

	memcpy(buf, tpm_log_addr, tpm_log_size);

	return TEE_SUCCESS;
}

TEE_Result tpm_get_event_log_size(size_t *size)
{
	*size = tpm_log_size;

	return TEE_SUCCESS;
}

void tpm_map_log_area(void *fdt)
{
	paddr_t log_addr = 0;
	unsigned int rounded_size = 0;

	get_tpm_phys_params(fdt, &log_addr, &tpm_log_size);

	DMSG("TPM Event log PA: %#" PRIxPA, log_addr);
	DMSG("TPM Event log size: %zu Bytes", tpm_log_size);

	rounded_size = ROUNDUP(tpm_log_size, SMALL_PAGE_SIZE);

	tpm_log_addr = core_mmu_add_mapping(MEM_AREA_RAM_SEC, log_addr,
					    rounded_size);
	if (!tpm_log_addr) {
		EMSG("TPM: Failed to map TPM log memory");
		return;
	}
}