]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - drivers/acpi/nfit/intel.c
Merge tag 'sh-pfc-for-v5.1-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-focal-kernel.git] / drivers / acpi / nfit / intel.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2018 Intel Corporation. All rights reserved. */
3 #include <linux/libnvdimm.h>
4 #include <linux/ndctl.h>
5 #include <linux/acpi.h>
6 #include <asm/smp.h>
7 #include "intel.h"
8 #include "nfit.h"
9
10 static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm,
11 enum nvdimm_passphrase_type ptype)
12 {
13 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
14 struct {
15 struct nd_cmd_pkg pkg;
16 struct nd_intel_get_security_state cmd;
17 } nd_cmd = {
18 .pkg = {
19 .nd_command = NVDIMM_INTEL_GET_SECURITY_STATE,
20 .nd_family = NVDIMM_FAMILY_INTEL,
21 .nd_size_out =
22 sizeof(struct nd_intel_get_security_state),
23 .nd_fw_size =
24 sizeof(struct nd_intel_get_security_state),
25 },
26 };
27 int rc;
28
29 if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask))
30 return -ENXIO;
31
32 /*
33 * Short circuit the state retrieval while we are doing overwrite.
34 * The DSM spec states that the security state is indeterminate
35 * until the overwrite DSM completes.
36 */
37 if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER)
38 return NVDIMM_SECURITY_OVERWRITE;
39
40 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
41 if (rc < 0)
42 return rc;
43 if (nd_cmd.cmd.status)
44 return -EIO;
45
46 /* check and see if security is enabled and locked */
47 if (ptype == NVDIMM_MASTER) {
48 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED)
49 return NVDIMM_SECURITY_UNLOCKED;
50 else if (nd_cmd.cmd.extended_state &
51 ND_INTEL_SEC_ESTATE_PLIMIT)
52 return NVDIMM_SECURITY_FROZEN;
53 } else {
54 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
55 return -ENXIO;
56 else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
57 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
58 return NVDIMM_SECURITY_LOCKED;
59 else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN
60 || nd_cmd.cmd.state &
61 ND_INTEL_SEC_STATE_PLIMIT)
62 return NVDIMM_SECURITY_FROZEN;
63 else
64 return NVDIMM_SECURITY_UNLOCKED;
65 }
66 }
67
68 /* this should cover master security disabled as well */
69 return NVDIMM_SECURITY_DISABLED;
70 }
71
72 static int intel_security_freeze(struct nvdimm *nvdimm)
73 {
74 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
75 struct {
76 struct nd_cmd_pkg pkg;
77 struct nd_intel_freeze_lock cmd;
78 } nd_cmd = {
79 .pkg = {
80 .nd_command = NVDIMM_INTEL_FREEZE_LOCK,
81 .nd_family = NVDIMM_FAMILY_INTEL,
82 .nd_size_out = ND_INTEL_STATUS_SIZE,
83 .nd_fw_size = ND_INTEL_STATUS_SIZE,
84 },
85 };
86 int rc;
87
88 if (!test_bit(NVDIMM_INTEL_FREEZE_LOCK, &nfit_mem->dsm_mask))
89 return -ENOTTY;
90
91 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
92 if (rc < 0)
93 return rc;
94 if (nd_cmd.cmd.status)
95 return -EIO;
96 return 0;
97 }
98
99 static int intel_security_change_key(struct nvdimm *nvdimm,
100 const struct nvdimm_key_data *old_data,
101 const struct nvdimm_key_data *new_data,
102 enum nvdimm_passphrase_type ptype)
103 {
104 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
105 unsigned int cmd = ptype == NVDIMM_MASTER ?
106 NVDIMM_INTEL_SET_MASTER_PASSPHRASE :
107 NVDIMM_INTEL_SET_PASSPHRASE;
108 struct {
109 struct nd_cmd_pkg pkg;
110 struct nd_intel_set_passphrase cmd;
111 } nd_cmd = {
112 .pkg = {
113 .nd_family = NVDIMM_FAMILY_INTEL,
114 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE * 2,
115 .nd_size_out = ND_INTEL_STATUS_SIZE,
116 .nd_fw_size = ND_INTEL_STATUS_SIZE,
117 .nd_command = cmd,
118 },
119 };
120 int rc;
121
122 if (!test_bit(cmd, &nfit_mem->dsm_mask))
123 return -ENOTTY;
124
125 if (old_data)
126 memcpy(nd_cmd.cmd.old_pass, old_data->data,
127 sizeof(nd_cmd.cmd.old_pass));
128 memcpy(nd_cmd.cmd.new_pass, new_data->data,
129 sizeof(nd_cmd.cmd.new_pass));
130 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
131 if (rc < 0)
132 return rc;
133
134 switch (nd_cmd.cmd.status) {
135 case 0:
136 return 0;
137 case ND_INTEL_STATUS_INVALID_PASS:
138 return -EINVAL;
139 case ND_INTEL_STATUS_NOT_SUPPORTED:
140 return -EOPNOTSUPP;
141 case ND_INTEL_STATUS_INVALID_STATE:
142 default:
143 return -EIO;
144 }
145 }
146
147 static void nvdimm_invalidate_cache(void);
148
149 static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
150 const struct nvdimm_key_data *key_data)
151 {
152 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
153 struct {
154 struct nd_cmd_pkg pkg;
155 struct nd_intel_unlock_unit cmd;
156 } nd_cmd = {
157 .pkg = {
158 .nd_command = NVDIMM_INTEL_UNLOCK_UNIT,
159 .nd_family = NVDIMM_FAMILY_INTEL,
160 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
161 .nd_size_out = ND_INTEL_STATUS_SIZE,
162 .nd_fw_size = ND_INTEL_STATUS_SIZE,
163 },
164 };
165 int rc;
166
167 if (!test_bit(NVDIMM_INTEL_UNLOCK_UNIT, &nfit_mem->dsm_mask))
168 return -ENOTTY;
169
170 memcpy(nd_cmd.cmd.passphrase, key_data->data,
171 sizeof(nd_cmd.cmd.passphrase));
172 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
173 if (rc < 0)
174 return rc;
175 switch (nd_cmd.cmd.status) {
176 case 0:
177 break;
178 case ND_INTEL_STATUS_INVALID_PASS:
179 return -EINVAL;
180 default:
181 return -EIO;
182 }
183
184 /* DIMM unlocked, invalidate all CPU caches before we read it */
185 nvdimm_invalidate_cache();
186
187 return 0;
188 }
189
190 static int intel_security_disable(struct nvdimm *nvdimm,
191 const struct nvdimm_key_data *key_data)
192 {
193 int rc;
194 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
195 struct {
196 struct nd_cmd_pkg pkg;
197 struct nd_intel_disable_passphrase cmd;
198 } nd_cmd = {
199 .pkg = {
200 .nd_command = NVDIMM_INTEL_DISABLE_PASSPHRASE,
201 .nd_family = NVDIMM_FAMILY_INTEL,
202 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
203 .nd_size_out = ND_INTEL_STATUS_SIZE,
204 .nd_fw_size = ND_INTEL_STATUS_SIZE,
205 },
206 };
207
208 if (!test_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE, &nfit_mem->dsm_mask))
209 return -ENOTTY;
210
211 memcpy(nd_cmd.cmd.passphrase, key_data->data,
212 sizeof(nd_cmd.cmd.passphrase));
213 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
214 if (rc < 0)
215 return rc;
216
217 switch (nd_cmd.cmd.status) {
218 case 0:
219 break;
220 case ND_INTEL_STATUS_INVALID_PASS:
221 return -EINVAL;
222 case ND_INTEL_STATUS_INVALID_STATE:
223 default:
224 return -ENXIO;
225 }
226
227 return 0;
228 }
229
230 static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
231 const struct nvdimm_key_data *key,
232 enum nvdimm_passphrase_type ptype)
233 {
234 int rc;
235 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
236 unsigned int cmd = ptype == NVDIMM_MASTER ?
237 NVDIMM_INTEL_MASTER_SECURE_ERASE : NVDIMM_INTEL_SECURE_ERASE;
238 struct {
239 struct nd_cmd_pkg pkg;
240 struct nd_intel_secure_erase cmd;
241 } nd_cmd = {
242 .pkg = {
243 .nd_family = NVDIMM_FAMILY_INTEL,
244 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
245 .nd_size_out = ND_INTEL_STATUS_SIZE,
246 .nd_fw_size = ND_INTEL_STATUS_SIZE,
247 .nd_command = cmd,
248 },
249 };
250
251 if (!test_bit(cmd, &nfit_mem->dsm_mask))
252 return -ENOTTY;
253
254 /* flush all cache before we erase DIMM */
255 nvdimm_invalidate_cache();
256 memcpy(nd_cmd.cmd.passphrase, key->data,
257 sizeof(nd_cmd.cmd.passphrase));
258 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
259 if (rc < 0)
260 return rc;
261
262 switch (nd_cmd.cmd.status) {
263 case 0:
264 break;
265 case ND_INTEL_STATUS_NOT_SUPPORTED:
266 return -EOPNOTSUPP;
267 case ND_INTEL_STATUS_INVALID_PASS:
268 return -EINVAL;
269 case ND_INTEL_STATUS_INVALID_STATE:
270 default:
271 return -ENXIO;
272 }
273
274 /* DIMM erased, invalidate all CPU caches before we read it */
275 nvdimm_invalidate_cache();
276 return 0;
277 }
278
279 static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
280 {
281 int rc;
282 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
283 struct {
284 struct nd_cmd_pkg pkg;
285 struct nd_intel_query_overwrite cmd;
286 } nd_cmd = {
287 .pkg = {
288 .nd_command = NVDIMM_INTEL_QUERY_OVERWRITE,
289 .nd_family = NVDIMM_FAMILY_INTEL,
290 .nd_size_out = ND_INTEL_STATUS_SIZE,
291 .nd_fw_size = ND_INTEL_STATUS_SIZE,
292 },
293 };
294
295 if (!test_bit(NVDIMM_INTEL_QUERY_OVERWRITE, &nfit_mem->dsm_mask))
296 return -ENOTTY;
297
298 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
299 if (rc < 0)
300 return rc;
301
302 switch (nd_cmd.cmd.status) {
303 case 0:
304 break;
305 case ND_INTEL_STATUS_OQUERY_INPROGRESS:
306 return -EBUSY;
307 default:
308 return -ENXIO;
309 }
310
311 /* flush all cache before we make the nvdimms available */
312 nvdimm_invalidate_cache();
313 return 0;
314 }
315
316 static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
317 const struct nvdimm_key_data *nkey)
318 {
319 int rc;
320 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
321 struct {
322 struct nd_cmd_pkg pkg;
323 struct nd_intel_overwrite cmd;
324 } nd_cmd = {
325 .pkg = {
326 .nd_command = NVDIMM_INTEL_OVERWRITE,
327 .nd_family = NVDIMM_FAMILY_INTEL,
328 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
329 .nd_size_out = ND_INTEL_STATUS_SIZE,
330 .nd_fw_size = ND_INTEL_STATUS_SIZE,
331 },
332 };
333
334 if (!test_bit(NVDIMM_INTEL_OVERWRITE, &nfit_mem->dsm_mask))
335 return -ENOTTY;
336
337 /* flush all cache before we erase DIMM */
338 nvdimm_invalidate_cache();
339 if (nkey)
340 memcpy(nd_cmd.cmd.passphrase, nkey->data,
341 sizeof(nd_cmd.cmd.passphrase));
342 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
343 if (rc < 0)
344 return rc;
345
346 switch (nd_cmd.cmd.status) {
347 case 0:
348 return 0;
349 case ND_INTEL_STATUS_OVERWRITE_UNSUPPORTED:
350 return -ENOTSUPP;
351 case ND_INTEL_STATUS_INVALID_PASS:
352 return -EINVAL;
353 case ND_INTEL_STATUS_INVALID_STATE:
354 default:
355 return -ENXIO;
356 }
357 }
358
359 /*
360 * TODO: define a cross arch wbinvd equivalent when/if
361 * NVDIMM_FAMILY_INTEL command support arrives on another arch.
362 */
363 #ifdef CONFIG_X86
364 static void nvdimm_invalidate_cache(void)
365 {
366 wbinvd_on_all_cpus();
367 }
368 #else
369 static void nvdimm_invalidate_cache(void)
370 {
371 WARN_ON_ONCE("cache invalidation required after unlock\n");
372 }
373 #endif
374
375 static const struct nvdimm_security_ops __intel_security_ops = {
376 .state = intel_security_state,
377 .freeze = intel_security_freeze,
378 .change_key = intel_security_change_key,
379 .disable = intel_security_disable,
380 #ifdef CONFIG_X86
381 .unlock = intel_security_unlock,
382 .erase = intel_security_erase,
383 .overwrite = intel_security_overwrite,
384 .query_overwrite = intel_security_query_overwrite,
385 #endif
386 };
387
388 const struct nvdimm_security_ops *intel_security_ops = &__intel_security_ops;