]>
Commit | Line | Data |
---|---|---|
bfe8fa26 SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright 2019 Google LLC | |
4 | */ | |
5 | ||
6 | #include <common.h> | |
7 | #include <dm.h> | |
8 | #include <log.h> | |
9 | #include <tpm_api.h> | |
10 | #include <tpm-v1.h> | |
11 | #include <tpm-v2.h> | |
12 | #include <tpm_api.h> | |
13 | ||
14 | static bool is_tpm1(struct udevice *dev) | |
15 | { | |
16 | return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1; | |
17 | } | |
18 | ||
b8eb9210 SG |
19 | static bool is_tpm2(struct udevice *dev) |
20 | { | |
21 | return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2; | |
22 | } | |
23 | ||
bfe8fa26 SG |
24 | u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) |
25 | { | |
b8eb9210 | 26 | if (is_tpm1(dev)) { |
bfe8fa26 | 27 | return tpm1_startup(dev, mode); |
b8eb9210 SG |
28 | } else if (is_tpm2(dev)) { |
29 | enum tpm2_startup_types type; | |
30 | ||
31 | switch (mode) { | |
32 | case TPM_ST_CLEAR: | |
33 | type = TPM2_SU_CLEAR; | |
34 | break; | |
35 | case TPM_ST_STATE: | |
36 | type = TPM2_SU_STATE; | |
37 | break; | |
38 | default: | |
39 | case TPM_ST_DEACTIVATED: | |
40 | return -EINVAL; | |
41 | } | |
42 | return tpm2_startup(dev, type); | |
43 | } else { | |
bfe8fa26 | 44 | return -ENOSYS; |
b8eb9210 | 45 | } |
bfe8fa26 SG |
46 | } |
47 | ||
48 | u32 tpm_resume(struct udevice *dev) | |
49 | { | |
50 | if (is_tpm1(dev)) | |
51 | return tpm1_startup(dev, TPM_ST_STATE); | |
b8eb9210 SG |
52 | else if (is_tpm2(dev)) |
53 | return tpm2_startup(dev, TPM2_SU_STATE); | |
bfe8fa26 SG |
54 | else |
55 | return -ENOSYS; | |
56 | } | |
57 | ||
58 | u32 tpm_self_test_full(struct udevice *dev) | |
59 | { | |
60 | if (is_tpm1(dev)) | |
61 | return tpm1_self_test_full(dev); | |
b8eb9210 SG |
62 | else if (is_tpm2(dev)) |
63 | return tpm2_self_test(dev, TPMI_YES); | |
bfe8fa26 SG |
64 | else |
65 | return -ENOSYS; | |
66 | } | |
67 | ||
68 | u32 tpm_continue_self_test(struct udevice *dev) | |
69 | { | |
70 | if (is_tpm1(dev)) | |
71 | return tpm1_continue_self_test(dev); | |
b8eb9210 SG |
72 | else if (is_tpm2(dev)) |
73 | return tpm2_self_test(dev, TPMI_NO); | |
bfe8fa26 SG |
74 | else |
75 | return -ENOSYS; | |
76 | } | |
77 | ||
78 | u32 tpm_clear_and_reenable(struct udevice *dev) | |
79 | { | |
80 | u32 ret; | |
81 | ||
82 | log_info("TPM: Clear and re-enable\n"); | |
83 | ret = tpm_force_clear(dev); | |
84 | if (ret != TPM_SUCCESS) { | |
85 | log_err("Can't initiate a force clear\n"); | |
86 | return ret; | |
87 | } | |
88 | ||
89 | if (is_tpm1(dev)) { | |
90 | ret = tpm1_physical_enable(dev); | |
91 | if (ret != TPM_SUCCESS) { | |
92 | log_err("TPM: Can't set enabled state\n"); | |
93 | return ret; | |
94 | } | |
95 | ||
96 | ret = tpm1_physical_set_deactivated(dev, 0); | |
97 | if (ret != TPM_SUCCESS) { | |
98 | log_err("TPM: Can't set deactivated state\n"); | |
99 | return ret; | |
100 | } | |
bfe8fa26 SG |
101 | } |
102 | ||
103 | return TPM_SUCCESS; | |
104 | } | |
105 | ||
106 | u32 tpm_nv_enable_locking(struct udevice *dev) | |
107 | { | |
108 | if (is_tpm1(dev)) | |
109 | return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0); | |
b8eb9210 SG |
110 | else if (is_tpm2(dev)) |
111 | return -ENOSYS; | |
bfe8fa26 SG |
112 | else |
113 | return -ENOSYS; | |
114 | } | |
115 | ||
116 | u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) | |
117 | { | |
118 | if (is_tpm1(dev)) | |
119 | return tpm1_nv_read_value(dev, index, data, count); | |
b8eb9210 | 120 | else if (is_tpm2(dev)) |
6719cbe3 | 121 | return tpm2_nv_read_value(dev, index, data, count); |
bfe8fa26 SG |
122 | else |
123 | return -ENOSYS; | |
124 | } | |
125 | ||
126 | u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, | |
127 | u32 count) | |
128 | { | |
129 | if (is_tpm1(dev)) | |
130 | return tpm1_nv_write_value(dev, index, data, count); | |
b8eb9210 | 131 | else if (is_tpm2(dev)) |
6719cbe3 | 132 | return tpm2_nv_write_value(dev, index, data, count); |
bfe8fa26 SG |
133 | else |
134 | return -ENOSYS; | |
135 | } | |
136 | ||
137 | u32 tpm_set_global_lock(struct udevice *dev) | |
138 | { | |
139 | return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0); | |
140 | } | |
141 | ||
142 | u32 tpm_write_lock(struct udevice *dev, u32 index) | |
143 | { | |
144 | if (is_tpm1(dev)) | |
145 | return -ENOSYS; | |
b8eb9210 | 146 | else if (is_tpm2(dev)) |
7785bc1d | 147 | return tpm2_write_lock(dev, index); |
bfe8fa26 SG |
148 | else |
149 | return -ENOSYS; | |
150 | } | |
151 | ||
152 | u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest, | |
153 | void *out_digest) | |
154 | { | |
155 | if (is_tpm1(dev)) | |
156 | return tpm1_extend(dev, index, in_digest, out_digest); | |
b8eb9210 SG |
157 | else if (is_tpm2(dev)) |
158 | return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest, | |
159 | TPM2_DIGEST_LEN); | |
bfe8fa26 SG |
160 | else |
161 | return -ENOSYS; | |
162 | } | |
163 | ||
164 | u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count) | |
165 | { | |
166 | if (is_tpm1(dev)) | |
167 | return tpm1_pcr_read(dev, index, data, count); | |
b8eb9210 SG |
168 | else if (is_tpm2(dev)) |
169 | return -ENOSYS; | |
bfe8fa26 SG |
170 | else |
171 | return -ENOSYS; | |
172 | } | |
173 | ||
174 | u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence) | |
175 | { | |
176 | if (is_tpm1(dev)) | |
177 | return tpm1_tsc_physical_presence(dev, presence); | |
b8eb9210 SG |
178 | |
179 | /* | |
180 | * Nothing to do on TPM2 for this; use platform hierarchy availability | |
181 | * instead. | |
182 | */ | |
183 | else if (is_tpm2(dev)) | |
184 | return 0; | |
bfe8fa26 SG |
185 | else |
186 | return -ENOSYS; | |
187 | } | |
188 | ||
189 | u32 tpm_finalise_physical_presence(struct udevice *dev) | |
190 | { | |
191 | if (is_tpm1(dev)) | |
192 | return tpm1_finalise_physical_presence(dev); | |
b8eb9210 SG |
193 | |
194 | /* Nothing needs to be done with tpm2 */ | |
195 | else if (is_tpm2(dev)) | |
196 | return 0; | |
bfe8fa26 SG |
197 | else |
198 | return -ENOSYS; | |
199 | } | |
200 | ||
201 | u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count) | |
202 | { | |
203 | if (is_tpm1(dev)) | |
204 | return tpm1_read_pubek(dev, data, count); | |
b8eb9210 | 205 | else if (is_tpm2(dev)) |
bfe8fa26 | 206 | return -ENOSYS; /* not implemented yet */ |
b8eb9210 SG |
207 | else |
208 | return -ENOSYS; | |
bfe8fa26 SG |
209 | } |
210 | ||
211 | u32 tpm_force_clear(struct udevice *dev) | |
212 | { | |
213 | if (is_tpm1(dev)) | |
214 | return tpm1_force_clear(dev); | |
b8eb9210 SG |
215 | else if (is_tpm2(dev)) |
216 | return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0); | |
bfe8fa26 SG |
217 | else |
218 | return -ENOSYS; | |
219 | } | |
220 | ||
221 | u32 tpm_physical_enable(struct udevice *dev) | |
222 | { | |
223 | if (is_tpm1(dev)) | |
224 | return tpm1_physical_enable(dev); | |
b8eb9210 SG |
225 | |
226 | /* Nothing needs to be done with tpm2 */ | |
227 | else if (is_tpm2(dev)) | |
228 | return 0; | |
bfe8fa26 SG |
229 | else |
230 | return -ENOSYS; | |
231 | } | |
232 | ||
233 | u32 tpm_physical_disable(struct udevice *dev) | |
234 | { | |
235 | if (is_tpm1(dev)) | |
236 | return tpm1_physical_disable(dev); | |
b8eb9210 SG |
237 | |
238 | /* Nothing needs to be done with tpm2 */ | |
239 | else if (is_tpm2(dev)) | |
240 | return 0; | |
bfe8fa26 SG |
241 | else |
242 | return -ENOSYS; | |
243 | } | |
244 | ||
245 | u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state) | |
246 | { | |
247 | if (is_tpm1(dev)) | |
248 | return tpm1_physical_set_deactivated(dev, state); | |
b8eb9210 SG |
249 | /* Nothing needs to be done with tpm2 */ |
250 | else if (is_tpm2(dev)) | |
251 | return 0; | |
bfe8fa26 SG |
252 | else |
253 | return -ENOSYS; | |
254 | } | |
255 | ||
256 | u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, | |
257 | void *cap, size_t count) | |
258 | { | |
259 | if (is_tpm1(dev)) | |
260 | return tpm1_get_capability(dev, cap_area, sub_cap, cap, count); | |
b8eb9210 SG |
261 | else if (is_tpm2(dev)) |
262 | return tpm2_get_capability(dev, cap_area, sub_cap, cap, count); | |
bfe8fa26 SG |
263 | else |
264 | return -ENOSYS; | |
265 | } | |
266 | ||
267 | u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm) | |
268 | { | |
269 | if (is_tpm1(dev)) | |
270 | return tpm1_get_permissions(dev, index, perm); | |
b8eb9210 | 271 | else if (is_tpm2(dev)) |
bfe8fa26 | 272 | return -ENOSYS; /* not implemented yet */ |
b8eb9210 SG |
273 | else |
274 | return -ENOSYS; | |
bfe8fa26 SG |
275 | } |
276 | ||
277 | u32 tpm_get_random(struct udevice *dev, void *data, u32 count) | |
278 | { | |
279 | if (is_tpm1(dev)) | |
280 | return tpm1_get_random(dev, data, count); | |
b8eb9210 | 281 | else if (is_tpm2(dev)) |
bfe8fa26 | 282 | return -ENOSYS; /* not implemented yet */ |
b8eb9210 SG |
283 | else |
284 | return -ENOSYS; | |
bfe8fa26 | 285 | } |