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