Merge tag 'linux-kselftest-5.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.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;