blob: e59ae364f1efb9044a43b8335bb841b1219fd7ea [file] [log] [blame]
Scott Bauer455a7b22017-02-03 12:50:31 -07001/*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Authors:
5 * Scott Bauer <scott.bauer@intel.com>
6 * Rafael Antognolli <rafael.antognolli@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 */
17
18#define pr_fmt(fmt) KBUILD_MODNAME ":OPAL: " fmt
19
20#include <linux/delay.h>
21#include <linux/device.h>
22#include <linux/kernel.h>
23#include <linux/list.h>
24#include <linux/genhd.h>
25#include <linux/slab.h>
26#include <linux/uaccess.h>
27#include <uapi/linux/sed-opal.h>
28#include <linux/sed-opal.h>
29#include <linux/string.h>
30#include <linux/kdev_t.h>
31
32#include "opal_proto.h"
33
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010034#define IO_BUFFER_LENGTH 2048
35#define MAX_TOKS 64
36
Jon Derrickeed64952017-02-22 07:55:13 -070037struct opal_step {
38 int (*fn)(struct opal_dev *dev, void *data);
39 void *data;
40};
41typedef int (cont_fn)(struct opal_dev *dev);
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010042
43enum opal_atom_width {
44 OPAL_WIDTH_TINY,
45 OPAL_WIDTH_SHORT,
46 OPAL_WIDTH_MEDIUM,
47 OPAL_WIDTH_LONG,
48 OPAL_WIDTH_TOKEN
49};
50
51/*
52 * On the parsed response, we don't store again the toks that are already
53 * stored in the response buffer. Instead, for each token, we just store a
54 * pointer to the position in the buffer where the token starts, and the size
55 * of the token in bytes.
56 */
57struct opal_resp_tok {
58 const u8 *pos;
59 size_t len;
60 enum opal_response_token type;
61 enum opal_atom_width width;
62 union {
63 u64 u;
64 s64 s;
65 } stored;
66};
67
68/*
69 * From the response header it's not possible to know how many tokens there are
70 * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later
71 * if we start dealing with messages that have more than that, we can increase
72 * this number. This is done to avoid having to make two passes through the
73 * response, the first one counting how many tokens we have and the second one
74 * actually storing the positions.
75 */
76struct parsed_resp {
77 int num;
78 struct opal_resp_tok toks[MAX_TOKS];
79};
80
81struct opal_dev {
82 bool supported;
Scott Bauerdbec491b2017-09-01 08:53:35 -060083 bool mbr_enabled;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010084
85 void *data;
86 sec_send_recv *send_recv;
87
Jon Derrickeed64952017-02-22 07:55:13 -070088 const struct opal_step *steps;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010089 struct mutex dev_lock;
90 u16 comid;
91 u32 hsn;
92 u32 tsn;
93 u64 align;
94 u64 lowest_lba;
95
96 size_t pos;
97 u8 cmd[IO_BUFFER_LENGTH];
98 u8 resp[IO_BUFFER_LENGTH];
99
100 struct parsed_resp parsed;
101 size_t prev_d_len;
102 void *prev_data;
103
104 struct list_head unlk_lst;
105};
106
107
Scott Bauer455a7b22017-02-03 12:50:31 -0700108static const u8 opaluid[][OPAL_UID_LENGTH] = {
109 /* users */
110 [OPAL_SMUID_UID] =
111 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
112 [OPAL_THISSP_UID] =
113 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
114 [OPAL_ADMINSP_UID] =
115 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },
116 [OPAL_LOCKINGSP_UID] =
117 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },
118 [OPAL_ENTERPRISE_LOCKINGSP_UID] =
119 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 },
120 [OPAL_ANYBODY_UID] =
121 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },
122 [OPAL_SID_UID] =
123 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },
124 [OPAL_ADMIN1_UID] =
125 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },
126 [OPAL_USER1_UID] =
127 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },
128 [OPAL_USER2_UID] =
129 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },
130 [OPAL_PSID_UID] =
131 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },
132 [OPAL_ENTERPRISE_BANDMASTER0_UID] =
133 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 },
134 [OPAL_ENTERPRISE_ERASEMASTER_UID] =
135 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 },
136
137 /* tables */
138
139 [OPAL_LOCKINGRANGE_GLOBAL] =
140 { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 },
141 [OPAL_LOCKINGRANGE_ACE_RDLOCKED] =
142 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 },
143 [OPAL_LOCKINGRANGE_ACE_WRLOCKED] =
144 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 },
145 [OPAL_MBRCONTROL] =
146 { 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 },
147 [OPAL_MBR] =
148 { 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 },
149 [OPAL_AUTHORITY_TABLE] =
150 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00},
151 [OPAL_C_PIN_TABLE] =
152 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00},
153 [OPAL_LOCKING_INFO_TABLE] =
154 { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 },
155 [OPAL_ENTERPRISE_LOCKING_INFO_TABLE] =
156 { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
157
158 /* C_PIN_TABLE object ID's */
159
David Kozub1e815b32019-02-14 01:15:54 +0100160 [OPAL_C_PIN_MSID] =
Scott Bauer455a7b22017-02-03 12:50:31 -0700161 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02},
162 [OPAL_C_PIN_SID] =
163 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01},
164 [OPAL_C_PIN_ADMIN1] =
165 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01},
166
167 /* half UID's (only first 4 bytes used) */
168
169 [OPAL_HALF_UID_AUTHORITY_OBJ_REF] =
170 { 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff },
171 [OPAL_HALF_UID_BOOLEAN_ACE] =
172 { 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff },
173
174 /* special value for omitted optional parameter */
175 [OPAL_UID_HEXFF] =
176 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
177};
178
179/*
180 * TCG Storage SSC Methods.
181 * Derived from: TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
182 * Section: 6.3 Assigned UIDs
183 */
Jonas Rabenstein1b6b75b2019-02-14 01:15:55 +0100184static const u8 opalmethod[][OPAL_METHOD_LENGTH] = {
Scott Bauer455a7b22017-02-03 12:50:31 -0700185 [OPAL_PROPERTIES] =
186 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 },
187 [OPAL_STARTSESSION] =
188 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 },
189 [OPAL_REVERT] =
190 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 },
191 [OPAL_ACTIVATE] =
192 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 },
193 [OPAL_EGET] =
194 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 },
195 [OPAL_ESET] =
196 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 },
197 [OPAL_NEXT] =
198 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 },
199 [OPAL_EAUTHENTICATE] =
200 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c },
201 [OPAL_GETACL] =
202 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d },
203 [OPAL_GENKEY] =
204 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 },
205 [OPAL_REVERTSP] =
206 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 },
207 [OPAL_GET] =
208 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 },
209 [OPAL_SET] =
210 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 },
211 [OPAL_AUTHENTICATE] =
212 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c },
213 [OPAL_RANDOM] =
214 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },
215 [OPAL_ERASE] =
216 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 },
217};
218
Scott Bauer455a7b22017-02-03 12:50:31 -0700219static int end_opal_session_error(struct opal_dev *dev);
220
221struct opal_suspend_data {
222 struct opal_lock_unlock unlk;
223 u8 lr;
224 struct list_head node;
225};
226
227/*
228 * Derived from:
229 * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
230 * Section: 5.1.5 Method Status Codes
231 */
232static const char * const opal_errors[] = {
233 "Success",
234 "Not Authorized",
235 "Unknown Error",
236 "SP Busy",
237 "SP Failed",
238 "SP Disabled",
239 "SP Frozen",
240 "No Sessions Available",
241 "Uniqueness Conflict",
242 "Insufficient Space",
243 "Insufficient Rows",
244 "Invalid Function",
245 "Invalid Parameter",
246 "Invalid Reference",
247 "Unknown Error",
248 "TPER Malfunction",
249 "Transaction Failure",
250 "Response Overflow",
251 "Authority Locked Out",
252};
253
254static const char *opal_error_to_human(int error)
255{
256 if (error == 0x3f)
257 return "Failed";
258
259 if (error >= ARRAY_SIZE(opal_errors) || error < 0)
260 return "Unknown Error";
261
262 return opal_errors[error];
263}
264
265static void print_buffer(const u8 *ptr, u32 length)
266{
267#ifdef DEBUG
268 print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length);
269 pr_debug("\n");
270#endif
271}
272
273static bool check_tper(const void *data)
274{
275 const struct d0_tper_features *tper = data;
276 u8 flags = tper->supported_features;
277
278 if (!(flags & TPER_SYNC_SUPPORTED)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600279 pr_debug("TPer sync not supported. flags = %d\n",
280 tper->supported_features);
Scott Bauer455a7b22017-02-03 12:50:31 -0700281 return false;
282 }
283
284 return true;
285}
286
Scott Bauerdbec491b2017-09-01 08:53:35 -0600287static bool check_mbrenabled(const void *data)
288{
289 const struct d0_locking_features *lfeat = data;
290 u8 sup_feat = lfeat->supported_features;
291
292 return !!(sup_feat & MBR_ENABLED_MASK);
293}
294
Scott Bauer455a7b22017-02-03 12:50:31 -0700295static bool check_sum(const void *data)
296{
297 const struct d0_single_user_mode *sum = data;
298 u32 nlo = be32_to_cpu(sum->num_locking_objects);
299
300 if (nlo == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600301 pr_debug("Need at least one locking object.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700302 return false;
303 }
304
305 pr_debug("Number of locking objects: %d\n", nlo);
306
307 return true;
308}
309
310static u16 get_comid_v100(const void *data)
311{
312 const struct d0_opal_v100 *v100 = data;
313
314 return be16_to_cpu(v100->baseComID);
315}
316
317static u16 get_comid_v200(const void *data)
318{
319 const struct d0_opal_v200 *v200 = data;
320
321 return be16_to_cpu(v200->baseComID);
322}
323
324static int opal_send_cmd(struct opal_dev *dev)
325{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +0100326 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
Scott Bauer455a7b22017-02-03 12:50:31 -0700327 dev->cmd, IO_BUFFER_LENGTH,
328 true);
329}
330
331static int opal_recv_cmd(struct opal_dev *dev)
332{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +0100333 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
Scott Bauer455a7b22017-02-03 12:50:31 -0700334 dev->resp, IO_BUFFER_LENGTH,
335 false);
336}
337
338static int opal_recv_check(struct opal_dev *dev)
339{
340 size_t buflen = IO_BUFFER_LENGTH;
341 void *buffer = dev->resp;
342 struct opal_header *hdr = buffer;
343 int ret;
344
345 do {
346 pr_debug("Sent OPAL command: outstanding=%d, minTransfer=%d\n",
347 hdr->cp.outstandingData,
348 hdr->cp.minTransfer);
349
350 if (hdr->cp.outstandingData == 0 ||
351 hdr->cp.minTransfer != 0)
352 return 0;
353
354 memset(buffer, 0, buflen);
355 ret = opal_recv_cmd(dev);
356 } while (!ret);
357
358 return ret;
359}
360
361static int opal_send_recv(struct opal_dev *dev, cont_fn *cont)
362{
363 int ret;
364
365 ret = opal_send_cmd(dev);
366 if (ret)
367 return ret;
368 ret = opal_recv_cmd(dev);
369 if (ret)
370 return ret;
371 ret = opal_recv_check(dev);
372 if (ret)
373 return ret;
374 return cont(dev);
375}
376
377static void check_geometry(struct opal_dev *dev, const void *data)
378{
379 const struct d0_geometry_features *geo = data;
380
381 dev->align = geo->alignment_granularity;
382 dev->lowest_lba = geo->lowest_aligned_lba;
383}
384
385static int next(struct opal_dev *dev)
386{
Jon Derrickeed64952017-02-22 07:55:13 -0700387 const struct opal_step *step;
388 int state = 0, error = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700389
390 do {
Jon Derrickeed64952017-02-22 07:55:13 -0700391 step = &dev->steps[state];
392 if (!step->fn)
Scott Bauer455a7b22017-02-03 12:50:31 -0700393 break;
394
Jon Derrickeed64952017-02-22 07:55:13 -0700395 error = step->fn(dev, step->data);
Scott Bauer455a7b22017-02-03 12:50:31 -0700396 if (error) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600397 pr_debug("Error on step function: %d with error %d: %s\n",
398 state, error,
399 opal_error_to_human(error));
Scott Bauer455a7b22017-02-03 12:50:31 -0700400
401 /* For each OPAL command we do a discovery0 then we
402 * start some sort of session.
403 * If we haven't passed state 1 then there was an error
404 * on discovery0 or during the attempt to start a
405 * session. Therefore we shouldn't attempt to terminate
406 * a session, as one has not yet been created.
407 */
Scott Bauer2d190202017-02-22 10:15:08 -0700408 if (state > 1) {
409 end_opal_session_error(dev);
410 return error;
411 }
412
Scott Bauer455a7b22017-02-03 12:50:31 -0700413 }
Jon Derrickeed64952017-02-22 07:55:13 -0700414 state++;
Scott Bauer455a7b22017-02-03 12:50:31 -0700415 } while (!error);
416
417 return error;
418}
419
420static int opal_discovery0_end(struct opal_dev *dev)
421{
422 bool found_com_id = false, supported = true, single_user = false;
423 const struct d0_header *hdr = (struct d0_header *)dev->resp;
424 const u8 *epos = dev->resp, *cpos = dev->resp;
425 u16 comid = 0;
Jon Derrick77039b92017-02-21 11:59:15 -0700426 u32 hlen = be32_to_cpu(hdr->length);
Scott Bauer455a7b22017-02-03 12:50:31 -0700427
Jon Derrick77039b92017-02-21 11:59:15 -0700428 print_buffer(dev->resp, hlen);
Scott Bauerdbec491b2017-09-01 08:53:35 -0600429 dev->mbr_enabled = false;
Scott Bauer455a7b22017-02-03 12:50:31 -0700430
Jon Derrick77039b92017-02-21 11:59:15 -0700431 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600432 pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n",
433 sizeof(*hdr), hlen, IO_BUFFER_LENGTH);
Jon Derrick77039b92017-02-21 11:59:15 -0700434 return -EFAULT;
435 }
436
437 epos += hlen; /* end of buffer */
Scott Bauer455a7b22017-02-03 12:50:31 -0700438 cpos += sizeof(*hdr); /* current position on buffer */
439
440 while (cpos < epos && supported) {
441 const struct d0_features *body =
442 (const struct d0_features *)cpos;
443
444 switch (be16_to_cpu(body->code)) {
445 case FC_TPER:
446 supported = check_tper(body->features);
447 break;
448 case FC_SINGLEUSER:
449 single_user = check_sum(body->features);
450 break;
451 case FC_GEOMETRY:
452 check_geometry(dev, body);
453 break;
454 case FC_LOCKING:
Scott Bauerdbec491b2017-09-01 08:53:35 -0600455 dev->mbr_enabled = check_mbrenabled(body->features);
456 break;
Scott Bauer455a7b22017-02-03 12:50:31 -0700457 case FC_ENTERPRISE:
458 case FC_DATASTORE:
459 /* some ignored properties */
460 pr_debug("Found OPAL feature description: %d\n",
461 be16_to_cpu(body->code));
462 break;
463 case FC_OPALV100:
464 comid = get_comid_v100(body->features);
465 found_com_id = true;
466 break;
467 case FC_OPALV200:
468 comid = get_comid_v200(body->features);
469 found_com_id = true;
470 break;
471 case 0xbfff ... 0xffff:
472 /* vendor specific, just ignore */
473 break;
474 default:
475 pr_debug("OPAL Unknown feature: %d\n",
476 be16_to_cpu(body->code));
477
478 }
479 cpos += body->length + 4;
480 }
481
482 if (!supported) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100483 pr_debug("This device is not Opal enabled. Not Supported!\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700484 return -EOPNOTSUPP;
485 }
486
487 if (!single_user)
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100488 pr_debug("Device doesn't support single user mode\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700489
490
491 if (!found_com_id) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100492 pr_debug("Could not find OPAL comid for device. Returning early\n");
Ingo Molnared7158b2018-02-22 10:54:55 +0100493 return -EOPNOTSUPP;
Scott Bauer455a7b22017-02-03 12:50:31 -0700494 }
495
496 dev->comid = comid;
497
498 return 0;
499}
500
Jon Derrickeed64952017-02-22 07:55:13 -0700501static int opal_discovery0(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -0700502{
503 int ret;
504
505 memset(dev->resp, 0, IO_BUFFER_LENGTH);
506 dev->comid = OPAL_DISCOVERY_COMID;
507 ret = opal_recv_cmd(dev);
508 if (ret)
509 return ret;
510 return opal_discovery0_end(dev);
511}
512
513static void add_token_u8(int *err, struct opal_dev *cmd, u8 tok)
514{
515 if (*err)
516 return;
517 if (cmd->pos >= IO_BUFFER_LENGTH - 1) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600518 pr_debug("Error adding u8: end of buffer.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700519 *err = -ERANGE;
520 return;
521 }
522 cmd->cmd[cmd->pos++] = tok;
523}
524
525static void add_short_atom_header(struct opal_dev *cmd, bool bytestring,
526 bool has_sign, int len)
527{
528 u8 atom;
529 int err = 0;
530
531 atom = SHORT_ATOM_ID;
532 atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;
533 atom |= has_sign ? SHORT_ATOM_SIGNED : 0;
534 atom |= len & SHORT_ATOM_LEN_MASK;
535
536 add_token_u8(&err, cmd, atom);
537}
538
539static void add_medium_atom_header(struct opal_dev *cmd, bool bytestring,
540 bool has_sign, int len)
541{
542 u8 header0;
543
544 header0 = MEDIUM_ATOM_ID;
545 header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;
546 header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;
547 header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;
548 cmd->cmd[cmd->pos++] = header0;
549 cmd->cmd[cmd->pos++] = len;
550}
551
552static void add_token_u64(int *err, struct opal_dev *cmd, u64 number)
553{
Scott Bauer455a7b22017-02-03 12:50:31 -0700554 size_t len;
555 int msb;
Scott Bauer455a7b22017-02-03 12:50:31 -0700556
557 if (!(number & ~TINY_ATOM_DATA_MASK)) {
558 add_token_u8(err, cmd, number);
559 return;
560 }
561
Jonas Rabenstein5f990d32018-03-07 17:55:56 +0100562 msb = fls64(number);
563 len = DIV_ROUND_UP(msb, 8);
Scott Bauer455a7b22017-02-03 12:50:31 -0700564
565 if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600566 pr_debug("Error adding u64: end of buffer.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700567 *err = -ERANGE;
568 return;
569 }
570 add_short_atom_header(cmd, false, false, len);
Jonas Rabenstein5f990d32018-03-07 17:55:56 +0100571 while (len--)
572 add_token_u8(err, cmd, number >> (len * 8));
Scott Bauer455a7b22017-02-03 12:50:31 -0700573}
574
575static void add_token_bytestring(int *err, struct opal_dev *cmd,
576 const u8 *bytestring, size_t len)
577{
578 size_t header_len = 1;
579 bool is_short_atom = true;
580
581 if (*err)
582 return;
583
584 if (len & ~SHORT_ATOM_LEN_MASK) {
585 header_len = 2;
586 is_short_atom = false;
587 }
588
589 if (len >= IO_BUFFER_LENGTH - cmd->pos - header_len) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600590 pr_debug("Error adding bytestring: end of buffer.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700591 *err = -ERANGE;
592 return;
593 }
594
595 if (is_short_atom)
596 add_short_atom_header(cmd, true, false, len);
597 else
598 add_medium_atom_header(cmd, true, false, len);
599
600 memcpy(&cmd->cmd[cmd->pos], bytestring, len);
601 cmd->pos += len;
602
603}
604
605static int build_locking_range(u8 *buffer, size_t length, u8 lr)
606{
607 if (length > OPAL_UID_LENGTH) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600608 pr_debug("Can't build locking range. Length OOB\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700609 return -ERANGE;
610 }
611
612 memcpy(buffer, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
613
614 if (lr == 0)
615 return 0;
616 buffer[5] = LOCKING_RANGE_NON_GLOBAL;
617 buffer[7] = lr;
618
619 return 0;
620}
621
622static int build_locking_user(u8 *buffer, size_t length, u8 lr)
623{
624 if (length > OPAL_UID_LENGTH) {
David Kozub1e815b32019-02-14 01:15:54 +0100625 pr_debug("Can't build locking range user. Length OOB\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700626 return -ERANGE;
627 }
628
629 memcpy(buffer, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
630
631 buffer[7] = lr + 1;
632
633 return 0;
634}
635
636static void set_comid(struct opal_dev *cmd, u16 comid)
637{
638 struct opal_header *hdr = (struct opal_header *)cmd->cmd;
639
640 hdr->cp.extendedComID[0] = comid >> 8;
641 hdr->cp.extendedComID[1] = comid;
642 hdr->cp.extendedComID[2] = 0;
643 hdr->cp.extendedComID[3] = 0;
644}
645
646static int cmd_finalize(struct opal_dev *cmd, u32 hsn, u32 tsn)
647{
648 struct opal_header *hdr;
649 int err = 0;
650
651 add_token_u8(&err, cmd, OPAL_ENDOFDATA);
652 add_token_u8(&err, cmd, OPAL_STARTLIST);
653 add_token_u8(&err, cmd, 0);
654 add_token_u8(&err, cmd, 0);
655 add_token_u8(&err, cmd, 0);
656 add_token_u8(&err, cmd, OPAL_ENDLIST);
657
658 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600659 pr_debug("Error finalizing command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700660 return -EFAULT;
661 }
662
663 hdr = (struct opal_header *) cmd->cmd;
664
665 hdr->pkt.tsn = cpu_to_be32(tsn);
666 hdr->pkt.hsn = cpu_to_be32(hsn);
667
668 hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
669 while (cmd->pos % 4) {
670 if (cmd->pos >= IO_BUFFER_LENGTH) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600671 pr_debug("Error: Buffer overrun\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700672 return -ERANGE;
673 }
674 cmd->cmd[cmd->pos++] = 0;
675 }
676 hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
677 sizeof(hdr->pkt));
678 hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
679
680 return 0;
681}
682
Jon Derrickcccb9242017-02-21 11:59:14 -0700683static const struct opal_resp_tok *response_get_token(
684 const struct parsed_resp *resp,
685 int n)
Scott Bauer455a7b22017-02-03 12:50:31 -0700686{
687 const struct opal_resp_tok *tok;
688
689 if (n >= resp->num) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600690 pr_debug("Token number doesn't exist: %d, resp: %d\n",
691 n, resp->num);
Jon Derrickcccb9242017-02-21 11:59:14 -0700692 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700693 }
694
695 tok = &resp->toks[n];
696 if (tok->len == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600697 pr_debug("Token length must be non-zero\n");
Jon Derrickcccb9242017-02-21 11:59:14 -0700698 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700699 }
700
Jon Derrickcccb9242017-02-21 11:59:14 -0700701 return tok;
Scott Bauer455a7b22017-02-03 12:50:31 -0700702}
703
Jon Derrickaedb6e22017-02-21 11:59:13 -0700704static ssize_t response_parse_tiny(struct opal_resp_tok *tok,
705 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700706{
707 tok->pos = pos;
708 tok->len = 1;
709 tok->width = OPAL_WIDTH_TINY;
710
711 if (pos[0] & TINY_ATOM_SIGNED) {
712 tok->type = OPAL_DTA_TOKENID_SINT;
713 } else {
714 tok->type = OPAL_DTA_TOKENID_UINT;
715 tok->stored.u = pos[0] & 0x3f;
716 }
717
718 return tok->len;
719}
720
Jon Derrickaedb6e22017-02-21 11:59:13 -0700721static ssize_t response_parse_short(struct opal_resp_tok *tok,
722 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700723{
724 tok->pos = pos;
725 tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
726 tok->width = OPAL_WIDTH_SHORT;
727
728 if (pos[0] & SHORT_ATOM_BYTESTRING) {
729 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
730 } else if (pos[0] & SHORT_ATOM_SIGNED) {
731 tok->type = OPAL_DTA_TOKENID_SINT;
732 } else {
733 u64 u_integer = 0;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700734 ssize_t i, b = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700735
736 tok->type = OPAL_DTA_TOKENID_UINT;
737 if (tok->len > 9) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600738 pr_debug("uint64 with more than 8 bytes\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700739 return -EINVAL;
740 }
741 for (i = tok->len - 1; i > 0; i--) {
742 u_integer |= ((u64)pos[i] << (8 * b));
743 b++;
744 }
745 tok->stored.u = u_integer;
746 }
747
748 return tok->len;
749}
750
Jon Derrickaedb6e22017-02-21 11:59:13 -0700751static ssize_t response_parse_medium(struct opal_resp_tok *tok,
752 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700753{
754 tok->pos = pos;
755 tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
756 tok->width = OPAL_WIDTH_MEDIUM;
757
758 if (pos[0] & MEDIUM_ATOM_BYTESTRING)
759 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
760 else if (pos[0] & MEDIUM_ATOM_SIGNED)
761 tok->type = OPAL_DTA_TOKENID_SINT;
762 else
763 tok->type = OPAL_DTA_TOKENID_UINT;
764
765 return tok->len;
766}
767
Jon Derrickaedb6e22017-02-21 11:59:13 -0700768static ssize_t response_parse_long(struct opal_resp_tok *tok,
769 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700770{
771 tok->pos = pos;
772 tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
773 tok->width = OPAL_WIDTH_LONG;
774
775 if (pos[0] & LONG_ATOM_BYTESTRING)
776 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
777 else if (pos[0] & LONG_ATOM_SIGNED)
778 tok->type = OPAL_DTA_TOKENID_SINT;
779 else
780 tok->type = OPAL_DTA_TOKENID_UINT;
781
782 return tok->len;
783}
784
Jon Derrickaedb6e22017-02-21 11:59:13 -0700785static ssize_t response_parse_token(struct opal_resp_tok *tok,
786 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700787{
788 tok->pos = pos;
789 tok->len = 1;
790 tok->type = OPAL_DTA_TOKENID_TOKEN;
791 tok->width = OPAL_WIDTH_TOKEN;
792
793 return tok->len;
794}
795
796static int response_parse(const u8 *buf, size_t length,
797 struct parsed_resp *resp)
798{
799 const struct opal_header *hdr;
800 struct opal_resp_tok *iter;
801 int num_entries = 0;
802 int total;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700803 ssize_t token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700804 const u8 *pos;
Jon Derrick77039b92017-02-21 11:59:15 -0700805 u32 clen, plen, slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700806
807 if (!buf)
808 return -EFAULT;
809
810 if (!resp)
811 return -EFAULT;
812
813 hdr = (struct opal_header *)buf;
814 pos = buf;
815 pos += sizeof(*hdr);
816
Jon Derrick77039b92017-02-21 11:59:15 -0700817 clen = be32_to_cpu(hdr->cp.length);
818 plen = be32_to_cpu(hdr->pkt.length);
819 slen = be32_to_cpu(hdr->subpkt.length);
820 pr_debug("Response size: cp: %u, pkt: %u, subpkt: %u\n",
821 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700822
Jon Derrick77039b92017-02-21 11:59:15 -0700823 if (clen == 0 || plen == 0 || slen == 0 ||
824 slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600825 pr_debug("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
826 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700827 print_buffer(pos, sizeof(*hdr));
828 return -EINVAL;
829 }
830
831 if (pos > buf + length)
832 return -EFAULT;
833
834 iter = resp->toks;
Jon Derrick77039b92017-02-21 11:59:15 -0700835 total = slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700836 print_buffer(pos, total);
837 while (total > 0) {
838 if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */
839 token_length = response_parse_tiny(iter, pos);
840 else if (pos[0] <= SHORT_ATOM_BYTE) /* short atom */
841 token_length = response_parse_short(iter, pos);
842 else if (pos[0] <= MEDIUM_ATOM_BYTE) /* medium atom */
843 token_length = response_parse_medium(iter, pos);
844 else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
845 token_length = response_parse_long(iter, pos);
846 else /* TOKEN */
847 token_length = response_parse_token(iter, pos);
848
Jon Derrickaedb6e22017-02-21 11:59:13 -0700849 if (token_length < 0)
850 return token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700851
852 pos += token_length;
853 total -= token_length;
854 iter++;
855 num_entries++;
856 }
857
858 if (num_entries == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600859 pr_debug("Couldn't parse response.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700860 return -EINVAL;
861 }
862 resp->num = num_entries;
863
864 return 0;
865}
866
867static size_t response_get_string(const struct parsed_resp *resp, int n,
868 const char **store)
869{
Jonas Rabensteind15e11752018-03-01 14:26:37 +0100870 u8 skip;
871 const struct opal_resp_tok *token;
872
Scott Bauer455a7b22017-02-03 12:50:31 -0700873 *store = NULL;
874 if (!resp) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600875 pr_debug("Response is NULL\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700876 return 0;
877 }
878
Dan Carpenterce042c12018-06-20 13:41:51 +0300879 if (n >= resp->num) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600880 pr_debug("Response has %d tokens. Can't access %d\n",
881 resp->num, n);
Scott Bauer455a7b22017-02-03 12:50:31 -0700882 return 0;
883 }
884
Jonas Rabensteind15e11752018-03-01 14:26:37 +0100885 token = &resp->toks[n];
886 if (token->type != OPAL_DTA_TOKENID_BYTESTRING) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600887 pr_debug("Token is not a byte string!\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700888 return 0;
889 }
890
Jonas Rabensteind15e11752018-03-01 14:26:37 +0100891 switch (token->width) {
892 case OPAL_WIDTH_TINY:
893 case OPAL_WIDTH_SHORT:
894 skip = 1;
895 break;
896 case OPAL_WIDTH_MEDIUM:
897 skip = 2;
898 break;
899 case OPAL_WIDTH_LONG:
900 skip = 4;
901 break;
902 default:
903 pr_debug("Token has invalid width!\n");
904 return 0;
905 }
906
907 *store = token->pos + skip;
908 return token->len - skip;
Scott Bauer455a7b22017-02-03 12:50:31 -0700909}
910
911static u64 response_get_u64(const struct parsed_resp *resp, int n)
912{
913 if (!resp) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600914 pr_debug("Response is NULL\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700915 return 0;
916 }
917
Dan Carpenterce042c12018-06-20 13:41:51 +0300918 if (n >= resp->num) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600919 pr_debug("Response has %d tokens. Can't access %d\n",
920 resp->num, n);
Scott Bauer455a7b22017-02-03 12:50:31 -0700921 return 0;
922 }
923
924 if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600925 pr_debug("Token is not unsigned it: %d\n",
926 resp->toks[n].type);
Scott Bauer455a7b22017-02-03 12:50:31 -0700927 return 0;
928 }
929
930 if (!(resp->toks[n].width == OPAL_WIDTH_TINY ||
931 resp->toks[n].width == OPAL_WIDTH_SHORT)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600932 pr_debug("Atom is not short or tiny: %d\n",
933 resp->toks[n].width);
Scott Bauer455a7b22017-02-03 12:50:31 -0700934 return 0;
935 }
936
937 return resp->toks[n].stored.u;
938}
939
Jon Derrickcccb9242017-02-21 11:59:14 -0700940static bool response_token_matches(const struct opal_resp_tok *token, u8 match)
941{
942 if (IS_ERR(token) ||
943 token->type != OPAL_DTA_TOKENID_TOKEN ||
944 token->pos[0] != match)
945 return false;
946 return true;
947}
948
Scott Bauer455a7b22017-02-03 12:50:31 -0700949static u8 response_status(const struct parsed_resp *resp)
950{
Jon Derrickcccb9242017-02-21 11:59:14 -0700951 const struct opal_resp_tok *tok;
952
953 tok = response_get_token(resp, 0);
954 if (response_token_matches(tok, OPAL_ENDOFSESSION))
Scott Bauer455a7b22017-02-03 12:50:31 -0700955 return 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700956
957 if (resp->num < 5)
958 return DTAERROR_NO_METHOD_STATUS;
959
Jon Derrickcccb9242017-02-21 11:59:14 -0700960 tok = response_get_token(resp, resp->num - 5);
961 if (!response_token_matches(tok, OPAL_STARTLIST))
962 return DTAERROR_NO_METHOD_STATUS;
963
964 tok = response_get_token(resp, resp->num - 1);
965 if (!response_token_matches(tok, OPAL_ENDLIST))
Scott Bauer455a7b22017-02-03 12:50:31 -0700966 return DTAERROR_NO_METHOD_STATUS;
967
968 return response_get_u64(resp, resp->num - 4);
969}
970
971/* Parses and checks for errors */
972static int parse_and_check_status(struct opal_dev *dev)
973{
974 int error;
975
976 print_buffer(dev->cmd, dev->pos);
977
978 error = response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed);
979 if (error) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600980 pr_debug("Couldn't parse response.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700981 return error;
982 }
983
984 return response_status(&dev->parsed);
985}
986
987static void clear_opal_cmd(struct opal_dev *dev)
988{
989 dev->pos = sizeof(struct opal_header);
990 memset(dev->cmd, 0, IO_BUFFER_LENGTH);
991}
992
993static int start_opal_session_cont(struct opal_dev *dev)
994{
995 u32 hsn, tsn;
996 int error = 0;
997
998 error = parse_and_check_status(dev);
999 if (error)
1000 return error;
1001
1002 hsn = response_get_u64(&dev->parsed, 4);
1003 tsn = response_get_u64(&dev->parsed, 5);
1004
1005 if (hsn == 0 && tsn == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001006 pr_debug("Couldn't authenticate session\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001007 return -EPERM;
1008 }
1009
1010 dev->hsn = hsn;
1011 dev->tsn = tsn;
1012 return 0;
1013}
1014
1015static void add_suspend_info(struct opal_dev *dev,
1016 struct opal_suspend_data *sus)
1017{
1018 struct opal_suspend_data *iter;
1019
1020 list_for_each_entry(iter, &dev->unlk_lst, node) {
1021 if (iter->lr == sus->lr) {
1022 list_del(&iter->node);
1023 kfree(iter);
1024 break;
1025 }
1026 }
1027 list_add_tail(&sus->node, &dev->unlk_lst);
1028}
1029
1030static int end_session_cont(struct opal_dev *dev)
1031{
1032 dev->hsn = 0;
1033 dev->tsn = 0;
1034 return parse_and_check_status(dev);
1035}
1036
1037static int finalize_and_send(struct opal_dev *dev, cont_fn cont)
1038{
1039 int ret;
1040
1041 ret = cmd_finalize(dev, dev->hsn, dev->tsn);
1042 if (ret) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001043 pr_debug("Error finalizing command buffer: %d\n", ret);
Scott Bauer455a7b22017-02-03 12:50:31 -07001044 return ret;
1045 }
1046
1047 print_buffer(dev->cmd, dev->pos);
1048
1049 return opal_send_recv(dev, cont);
1050}
1051
Jon Derrickeed64952017-02-22 07:55:13 -07001052static int gen_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001053{
Scott Bauer455a7b22017-02-03 12:50:31 -07001054 u8 uid[OPAL_UID_LENGTH];
1055 int err = 0;
1056
1057 clear_opal_cmd(dev);
1058 set_comid(dev, dev->comid);
1059
1060 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
Scott Bauer455a7b22017-02-03 12:50:31 -07001061 kfree(dev->prev_data);
1062 dev->prev_data = NULL;
1063
1064 add_token_u8(&err, dev, OPAL_CALL);
1065 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1066 add_token_bytestring(&err, dev, opalmethod[OPAL_GENKEY],
1067 OPAL_UID_LENGTH);
1068 add_token_u8(&err, dev, OPAL_STARTLIST);
1069 add_token_u8(&err, dev, OPAL_ENDLIST);
1070
1071 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001072 pr_debug("Error building gen key command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001073 return err;
1074
1075 }
1076 return finalize_and_send(dev, parse_and_check_status);
1077}
1078
1079static int get_active_key_cont(struct opal_dev *dev)
1080{
1081 const char *activekey;
1082 size_t keylen;
1083 int error = 0;
1084
1085 error = parse_and_check_status(dev);
1086 if (error)
1087 return error;
1088 keylen = response_get_string(&dev->parsed, 4, &activekey);
1089 if (!activekey) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001090 pr_debug("%s: Couldn't extract the Activekey from the response\n",
1091 __func__);
Scott Bauer455a7b22017-02-03 12:50:31 -07001092 return OPAL_INVAL_PARAM;
1093 }
1094 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1095
1096 if (!dev->prev_data)
1097 return -ENOMEM;
1098
1099 dev->prev_d_len = keylen;
1100
1101 return 0;
1102}
1103
Jon Derrickeed64952017-02-22 07:55:13 -07001104static int get_active_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001105{
1106 u8 uid[OPAL_UID_LENGTH];
1107 int err = 0;
Jon Derrickeed64952017-02-22 07:55:13 -07001108 u8 *lr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001109
1110 clear_opal_cmd(dev);
1111 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001112
1113 err = build_locking_range(uid, sizeof(uid), *lr);
1114 if (err)
1115 return err;
1116
1117 err = 0;
1118 add_token_u8(&err, dev, OPAL_CALL);
1119 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1120 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1121 add_token_u8(&err, dev, OPAL_STARTLIST);
1122 add_token_u8(&err, dev, OPAL_STARTLIST);
1123 add_token_u8(&err, dev, OPAL_STARTNAME);
1124 add_token_u8(&err, dev, 3); /* startCloumn */
1125 add_token_u8(&err, dev, 10); /* ActiveKey */
1126 add_token_u8(&err, dev, OPAL_ENDNAME);
1127 add_token_u8(&err, dev, OPAL_STARTNAME);
1128 add_token_u8(&err, dev, 4); /* endColumn */
1129 add_token_u8(&err, dev, 10); /* ActiveKey */
1130 add_token_u8(&err, dev, OPAL_ENDNAME);
1131 add_token_u8(&err, dev, OPAL_ENDLIST);
1132 add_token_u8(&err, dev, OPAL_ENDLIST);
1133 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001134 pr_debug("Error building get active key command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001135 return err;
1136 }
1137
1138 return finalize_and_send(dev, get_active_key_cont);
1139}
1140
1141static int generic_lr_enable_disable(struct opal_dev *dev,
1142 u8 *uid, bool rle, bool wle,
1143 bool rl, bool wl)
1144{
1145 int err = 0;
1146
1147 add_token_u8(&err, dev, OPAL_CALL);
1148 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1149 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1150
1151 add_token_u8(&err, dev, OPAL_STARTLIST);
1152 add_token_u8(&err, dev, OPAL_STARTNAME);
1153 add_token_u8(&err, dev, OPAL_VALUES);
1154 add_token_u8(&err, dev, OPAL_STARTLIST);
1155
1156 add_token_u8(&err, dev, OPAL_STARTNAME);
1157 add_token_u8(&err, dev, 5); /* ReadLockEnabled */
1158 add_token_u8(&err, dev, rle);
1159 add_token_u8(&err, dev, OPAL_ENDNAME);
1160
1161 add_token_u8(&err, dev, OPAL_STARTNAME);
1162 add_token_u8(&err, dev, 6); /* WriteLockEnabled */
1163 add_token_u8(&err, dev, wle);
1164 add_token_u8(&err, dev, OPAL_ENDNAME);
1165
1166 add_token_u8(&err, dev, OPAL_STARTNAME);
1167 add_token_u8(&err, dev, OPAL_READLOCKED);
1168 add_token_u8(&err, dev, rl);
1169 add_token_u8(&err, dev, OPAL_ENDNAME);
1170
1171 add_token_u8(&err, dev, OPAL_STARTNAME);
1172 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1173 add_token_u8(&err, dev, wl);
1174 add_token_u8(&err, dev, OPAL_ENDNAME);
1175
1176 add_token_u8(&err, dev, OPAL_ENDLIST);
1177 add_token_u8(&err, dev, OPAL_ENDNAME);
1178 add_token_u8(&err, dev, OPAL_ENDLIST);
1179 return err;
1180}
1181
1182static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1183 struct opal_user_lr_setup *setup)
1184{
1185 int err;
1186
1187 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1188 0, 0);
1189 if (err)
Scott Bauer591c59d2017-04-07 13:58:50 -06001190 pr_debug("Failed to create enable global lr command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001191 return err;
1192}
1193
Jon Derrickeed64952017-02-22 07:55:13 -07001194static int setup_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001195{
1196 u8 uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001197 struct opal_user_lr_setup *setup = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001198 u8 lr;
1199 int err = 0;
1200
1201 clear_opal_cmd(dev);
1202 set_comid(dev, dev->comid);
1203
Scott Bauer455a7b22017-02-03 12:50:31 -07001204 lr = setup->session.opal_key.lr;
1205 err = build_locking_range(uid, sizeof(uid), lr);
1206 if (err)
1207 return err;
1208
1209 if (lr == 0)
1210 err = enable_global_lr(dev, uid, setup);
1211 else {
1212 add_token_u8(&err, dev, OPAL_CALL);
1213 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1214 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1215 OPAL_UID_LENGTH);
1216
1217 add_token_u8(&err, dev, OPAL_STARTLIST);
1218 add_token_u8(&err, dev, OPAL_STARTNAME);
1219 add_token_u8(&err, dev, OPAL_VALUES);
1220 add_token_u8(&err, dev, OPAL_STARTLIST);
1221
1222 add_token_u8(&err, dev, OPAL_STARTNAME);
1223 add_token_u8(&err, dev, 3); /* Ranges Start */
1224 add_token_u64(&err, dev, setup->range_start);
1225 add_token_u8(&err, dev, OPAL_ENDNAME);
1226
1227 add_token_u8(&err, dev, OPAL_STARTNAME);
1228 add_token_u8(&err, dev, 4); /* Ranges length */
1229 add_token_u64(&err, dev, setup->range_length);
1230 add_token_u8(&err, dev, OPAL_ENDNAME);
1231
1232 add_token_u8(&err, dev, OPAL_STARTNAME);
1233 add_token_u8(&err, dev, 5); /*ReadLockEnabled */
1234 add_token_u64(&err, dev, !!setup->RLE);
1235 add_token_u8(&err, dev, OPAL_ENDNAME);
1236
1237 add_token_u8(&err, dev, OPAL_STARTNAME);
1238 add_token_u8(&err, dev, 6); /*WriteLockEnabled*/
1239 add_token_u64(&err, dev, !!setup->WLE);
1240 add_token_u8(&err, dev, OPAL_ENDNAME);
1241
1242 add_token_u8(&err, dev, OPAL_ENDLIST);
1243 add_token_u8(&err, dev, OPAL_ENDNAME);
1244 add_token_u8(&err, dev, OPAL_ENDLIST);
1245
1246 }
1247 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001248 pr_debug("Error building Setup Locking range command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001249 return err;
1250
1251 }
1252
1253 return finalize_and_send(dev, parse_and_check_status);
1254}
1255
1256static int start_generic_opal_session(struct opal_dev *dev,
1257 enum opal_uid auth,
1258 enum opal_uid sp_type,
1259 const char *key,
1260 u8 key_len)
1261{
1262 u32 hsn;
1263 int err = 0;
1264
Scott Bauer591c59d2017-04-07 13:58:50 -06001265 if (key == NULL && auth != OPAL_ANYBODY_UID)
Scott Bauer455a7b22017-02-03 12:50:31 -07001266 return OPAL_INVAL_PARAM;
Scott Bauer455a7b22017-02-03 12:50:31 -07001267
1268 clear_opal_cmd(dev);
1269
1270 set_comid(dev, dev->comid);
1271 hsn = GENERIC_HOST_SESSION_NUM;
1272
1273 add_token_u8(&err, dev, OPAL_CALL);
1274 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1275 OPAL_UID_LENGTH);
1276 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1277 OPAL_UID_LENGTH);
1278 add_token_u8(&err, dev, OPAL_STARTLIST);
1279 add_token_u64(&err, dev, hsn);
1280 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1281 add_token_u8(&err, dev, 1);
1282
1283 switch (auth) {
1284 case OPAL_ANYBODY_UID:
1285 add_token_u8(&err, dev, OPAL_ENDLIST);
1286 break;
1287 case OPAL_ADMIN1_UID:
1288 case OPAL_SID_UID:
1289 add_token_u8(&err, dev, OPAL_STARTNAME);
1290 add_token_u8(&err, dev, 0); /* HostChallenge */
1291 add_token_bytestring(&err, dev, key, key_len);
1292 add_token_u8(&err, dev, OPAL_ENDNAME);
1293 add_token_u8(&err, dev, OPAL_STARTNAME);
1294 add_token_u8(&err, dev, 3); /* HostSignAuth */
1295 add_token_bytestring(&err, dev, opaluid[auth],
1296 OPAL_UID_LENGTH);
1297 add_token_u8(&err, dev, OPAL_ENDNAME);
1298 add_token_u8(&err, dev, OPAL_ENDLIST);
1299 break;
1300 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06001301 pr_debug("Cannot start Admin SP session with auth %d\n", auth);
Scott Bauer455a7b22017-02-03 12:50:31 -07001302 return OPAL_INVAL_PARAM;
1303 }
1304
1305 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001306 pr_debug("Error building start adminsp session command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001307 return err;
1308 }
1309
1310 return finalize_and_send(dev, start_opal_session_cont);
1311}
1312
Jon Derrickeed64952017-02-22 07:55:13 -07001313static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001314{
1315 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1316 OPAL_ADMINSP_UID, NULL, 0);
1317}
1318
Jon Derrickeed64952017-02-22 07:55:13 -07001319static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001320{
1321 int ret;
1322 const u8 *key = dev->prev_data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001323
1324 if (!key) {
Jon Derrickeed64952017-02-22 07:55:13 -07001325 const struct opal_key *okey = data;
David Kozub1e815b32019-02-14 01:15:54 +01001326
Scott Bauer455a7b22017-02-03 12:50:31 -07001327 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1328 OPAL_ADMINSP_UID,
1329 okey->key,
1330 okey->key_len);
1331 } else {
1332 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1333 OPAL_ADMINSP_UID,
1334 key, dev->prev_d_len);
1335 kfree(key);
1336 dev->prev_data = NULL;
1337 }
1338 return ret;
1339}
1340
Jon Derrickeed64952017-02-22 07:55:13 -07001341static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001342{
Jon Derrickeed64952017-02-22 07:55:13 -07001343 struct opal_key *key = data;
David Kozub1e815b32019-02-14 01:15:54 +01001344
Scott Bauer455a7b22017-02-03 12:50:31 -07001345 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1346 OPAL_LOCKINGSP_UID,
1347 key->key, key->key_len);
1348}
1349
Jon Derrickeed64952017-02-22 07:55:13 -07001350static int start_auth_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001351{
Jon Derrickeed64952017-02-22 07:55:13 -07001352 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001353 u8 lk_ul_user[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001354 size_t keylen = session->opal_key.key_len;
Scott Bauer455a7b22017-02-03 12:50:31 -07001355 int err = 0;
1356
Scott Bauer455a7b22017-02-03 12:50:31 -07001357 u8 *key = session->opal_key.key;
1358 u32 hsn = GENERIC_HOST_SESSION_NUM;
1359
1360 clear_opal_cmd(dev);
1361 set_comid(dev, dev->comid);
1362
1363 if (session->sum) {
1364 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1365 session->opal_key.lr);
1366 if (err)
1367 return err;
1368
1369 } else if (session->who != OPAL_ADMIN1 && !session->sum) {
1370 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1371 session->who - 1);
1372 if (err)
1373 return err;
1374 } else
1375 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1376
1377 add_token_u8(&err, dev, OPAL_CALL);
1378 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1379 OPAL_UID_LENGTH);
1380 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1381 OPAL_UID_LENGTH);
1382
1383 add_token_u8(&err, dev, OPAL_STARTLIST);
1384 add_token_u64(&err, dev, hsn);
1385 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1386 OPAL_UID_LENGTH);
1387 add_token_u8(&err, dev, 1);
1388 add_token_u8(&err, dev, OPAL_STARTNAME);
1389 add_token_u8(&err, dev, 0);
1390 add_token_bytestring(&err, dev, key, keylen);
1391 add_token_u8(&err, dev, OPAL_ENDNAME);
1392 add_token_u8(&err, dev, OPAL_STARTNAME);
1393 add_token_u8(&err, dev, 3);
1394 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1395 add_token_u8(&err, dev, OPAL_ENDNAME);
1396 add_token_u8(&err, dev, OPAL_ENDLIST);
1397
1398 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001399 pr_debug("Error building STARTSESSION command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001400 return err;
1401 }
1402
1403 return finalize_and_send(dev, start_opal_session_cont);
1404}
1405
Jon Derrickeed64952017-02-22 07:55:13 -07001406static int revert_tper(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001407{
1408 int err = 0;
1409
1410 clear_opal_cmd(dev);
1411 set_comid(dev, dev->comid);
1412
1413 add_token_u8(&err, dev, OPAL_CALL);
1414 add_token_bytestring(&err, dev, opaluid[OPAL_ADMINSP_UID],
1415 OPAL_UID_LENGTH);
1416 add_token_bytestring(&err, dev, opalmethod[OPAL_REVERT],
1417 OPAL_UID_LENGTH);
1418 add_token_u8(&err, dev, OPAL_STARTLIST);
1419 add_token_u8(&err, dev, OPAL_ENDLIST);
1420 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001421 pr_debug("Error building REVERT TPER command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001422 return err;
1423 }
1424
1425 return finalize_and_send(dev, parse_and_check_status);
1426}
1427
Jon Derrickeed64952017-02-22 07:55:13 -07001428static int internal_activate_user(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001429{
Jon Derrickeed64952017-02-22 07:55:13 -07001430 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001431 u8 uid[OPAL_UID_LENGTH];
1432 int err = 0;
1433
1434 clear_opal_cmd(dev);
1435 set_comid(dev, dev->comid);
1436
1437 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1438 uid[7] = session->who;
1439
1440 add_token_u8(&err, dev, OPAL_CALL);
1441 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1442 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1443 add_token_u8(&err, dev, OPAL_STARTLIST);
1444 add_token_u8(&err, dev, OPAL_STARTNAME);
1445 add_token_u8(&err, dev, OPAL_VALUES);
1446 add_token_u8(&err, dev, OPAL_STARTLIST);
1447 add_token_u8(&err, dev, OPAL_STARTNAME);
1448 add_token_u8(&err, dev, 5); /* Enabled */
1449 add_token_u8(&err, dev, OPAL_TRUE);
1450 add_token_u8(&err, dev, OPAL_ENDNAME);
1451 add_token_u8(&err, dev, OPAL_ENDLIST);
1452 add_token_u8(&err, dev, OPAL_ENDNAME);
1453 add_token_u8(&err, dev, OPAL_ENDLIST);
1454
1455 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001456 pr_debug("Error building Activate UserN command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001457 return err;
1458 }
1459
1460 return finalize_and_send(dev, parse_and_check_status);
1461}
1462
Jon Derrickeed64952017-02-22 07:55:13 -07001463static int erase_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001464{
Jon Derrickeed64952017-02-22 07:55:13 -07001465 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001466 u8 uid[OPAL_UID_LENGTH];
1467 int err = 0;
1468
1469 clear_opal_cmd(dev);
1470 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001471
1472 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1473 return -ERANGE;
1474
1475 add_token_u8(&err, dev, OPAL_CALL);
1476 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1477 add_token_bytestring(&err, dev, opalmethod[OPAL_ERASE],
1478 OPAL_UID_LENGTH);
1479 add_token_u8(&err, dev, OPAL_STARTLIST);
1480 add_token_u8(&err, dev, OPAL_ENDLIST);
1481
1482 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001483 pr_debug("Error building Erase Locking Range Command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001484 return err;
1485 }
1486 return finalize_and_send(dev, parse_and_check_status);
1487}
1488
Jon Derrickeed64952017-02-22 07:55:13 -07001489static int set_mbr_done(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001490{
Jon Derrickeed64952017-02-22 07:55:13 -07001491 u8 *mbr_done_tf = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001492 int err = 0;
1493
1494 clear_opal_cmd(dev);
1495 set_comid(dev, dev->comid);
1496
1497 add_token_u8(&err, dev, OPAL_CALL);
1498 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1499 OPAL_UID_LENGTH);
1500 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1501 add_token_u8(&err, dev, OPAL_STARTLIST);
1502 add_token_u8(&err, dev, OPAL_STARTNAME);
1503 add_token_u8(&err, dev, OPAL_VALUES);
1504 add_token_u8(&err, dev, OPAL_STARTLIST);
1505 add_token_u8(&err, dev, OPAL_STARTNAME);
1506 add_token_u8(&err, dev, 2); /* Done */
Jon Derrickeed64952017-02-22 07:55:13 -07001507 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
Scott Bauer455a7b22017-02-03 12:50:31 -07001508 add_token_u8(&err, dev, OPAL_ENDNAME);
1509 add_token_u8(&err, dev, OPAL_ENDLIST);
1510 add_token_u8(&err, dev, OPAL_ENDNAME);
1511 add_token_u8(&err, dev, OPAL_ENDLIST);
1512
1513 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001514 pr_debug("Error Building set MBR Done command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001515 return err;
1516 }
1517
1518 return finalize_and_send(dev, parse_and_check_status);
1519}
1520
Jon Derrickeed64952017-02-22 07:55:13 -07001521static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001522{
Jon Derrickeed64952017-02-22 07:55:13 -07001523 u8 *mbr_en_dis = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001524 int err = 0;
1525
1526 clear_opal_cmd(dev);
1527 set_comid(dev, dev->comid);
1528
1529 add_token_u8(&err, dev, OPAL_CALL);
1530 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1531 OPAL_UID_LENGTH);
1532 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1533 add_token_u8(&err, dev, OPAL_STARTLIST);
1534 add_token_u8(&err, dev, OPAL_STARTNAME);
1535 add_token_u8(&err, dev, OPAL_VALUES);
1536 add_token_u8(&err, dev, OPAL_STARTLIST);
1537 add_token_u8(&err, dev, OPAL_STARTNAME);
1538 add_token_u8(&err, dev, 1);
Jon Derrickeed64952017-02-22 07:55:13 -07001539 add_token_u8(&err, dev, *mbr_en_dis);
Scott Bauer455a7b22017-02-03 12:50:31 -07001540 add_token_u8(&err, dev, OPAL_ENDNAME);
1541 add_token_u8(&err, dev, OPAL_ENDLIST);
1542 add_token_u8(&err, dev, OPAL_ENDNAME);
1543 add_token_u8(&err, dev, OPAL_ENDLIST);
1544
1545 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001546 pr_debug("Error Building set MBR done command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001547 return err;
1548 }
1549
1550 return finalize_and_send(dev, parse_and_check_status);
1551}
1552
1553static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1554 struct opal_dev *dev)
1555{
1556 int err = 0;
1557
1558 clear_opal_cmd(dev);
1559 set_comid(dev, dev->comid);
1560
1561 add_token_u8(&err, dev, OPAL_CALL);
1562 add_token_bytestring(&err, dev, cpin_uid, OPAL_UID_LENGTH);
1563 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1564 OPAL_UID_LENGTH);
1565 add_token_u8(&err, dev, OPAL_STARTLIST);
1566 add_token_u8(&err, dev, OPAL_STARTNAME);
1567 add_token_u8(&err, dev, OPAL_VALUES);
1568 add_token_u8(&err, dev, OPAL_STARTLIST);
1569 add_token_u8(&err, dev, OPAL_STARTNAME);
1570 add_token_u8(&err, dev, 3); /* PIN */
1571 add_token_bytestring(&err, dev, key, key_len);
1572 add_token_u8(&err, dev, OPAL_ENDNAME);
1573 add_token_u8(&err, dev, OPAL_ENDLIST);
1574 add_token_u8(&err, dev, OPAL_ENDNAME);
1575 add_token_u8(&err, dev, OPAL_ENDLIST);
1576
1577 return err;
1578}
1579
Jon Derrickeed64952017-02-22 07:55:13 -07001580static int set_new_pw(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001581{
1582 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001583 struct opal_session_info *usr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001584
1585 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1586
1587 if (usr->who != OPAL_ADMIN1) {
1588 cpin_uid[5] = 0x03;
1589 if (usr->sum)
1590 cpin_uid[7] = usr->opal_key.lr + 1;
1591 else
1592 cpin_uid[7] = usr->who;
1593 }
1594
1595 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1596 cpin_uid, dev)) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001597 pr_debug("Error building set password command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001598 return -ERANGE;
1599 }
1600
1601 return finalize_and_send(dev, parse_and_check_status);
1602}
1603
Jon Derrickeed64952017-02-22 07:55:13 -07001604static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001605{
1606 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001607 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001608
1609 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1610
1611 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001612 pr_debug("Error building Set SID cpin\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001613 return -ERANGE;
1614 }
1615 return finalize_and_send(dev, parse_and_check_status);
1616}
1617
Jon Derrickeed64952017-02-22 07:55:13 -07001618static int add_user_to_lr(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001619{
1620 u8 lr_buffer[OPAL_UID_LENGTH];
1621 u8 user_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001622 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001623 int err = 0;
1624
1625 clear_opal_cmd(dev);
1626 set_comid(dev, dev->comid);
1627
Scott Bauer455a7b22017-02-03 12:50:31 -07001628 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1629 OPAL_UID_LENGTH);
1630
1631 if (lkul->l_state == OPAL_RW)
1632 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1633 OPAL_UID_LENGTH);
1634
1635 lr_buffer[7] = lkul->session.opal_key.lr;
1636
1637 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1638
1639 user_uid[7] = lkul->session.who;
1640
1641 add_token_u8(&err, dev, OPAL_CALL);
1642 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1643 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1644 OPAL_UID_LENGTH);
1645
1646 add_token_u8(&err, dev, OPAL_STARTLIST);
1647 add_token_u8(&err, dev, OPAL_STARTNAME);
1648 add_token_u8(&err, dev, OPAL_VALUES);
1649
1650 add_token_u8(&err, dev, OPAL_STARTLIST);
1651 add_token_u8(&err, dev, OPAL_STARTNAME);
1652 add_token_u8(&err, dev, 3);
1653
1654 add_token_u8(&err, dev, OPAL_STARTLIST);
1655
1656
1657 add_token_u8(&err, dev, OPAL_STARTNAME);
1658 add_token_bytestring(&err, dev,
1659 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1660 OPAL_UID_LENGTH/2);
1661 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1662 add_token_u8(&err, dev, OPAL_ENDNAME);
1663
1664
1665 add_token_u8(&err, dev, OPAL_STARTNAME);
1666 add_token_bytestring(&err, dev,
1667 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1668 OPAL_UID_LENGTH/2);
1669 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1670 add_token_u8(&err, dev, OPAL_ENDNAME);
1671
1672
1673 add_token_u8(&err, dev, OPAL_STARTNAME);
1674 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1675 OPAL_UID_LENGTH/2);
1676 add_token_u8(&err, dev, 1);
1677 add_token_u8(&err, dev, OPAL_ENDNAME);
1678
1679
1680 add_token_u8(&err, dev, OPAL_ENDLIST);
1681 add_token_u8(&err, dev, OPAL_ENDNAME);
1682 add_token_u8(&err, dev, OPAL_ENDLIST);
1683 add_token_u8(&err, dev, OPAL_ENDNAME);
1684 add_token_u8(&err, dev, OPAL_ENDLIST);
1685
1686 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001687 pr_debug("Error building add user to locking range command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001688 return err;
1689 }
1690
1691 return finalize_and_send(dev, parse_and_check_status);
1692}
1693
Jon Derrickeed64952017-02-22 07:55:13 -07001694static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001695{
1696 u8 lr_buffer[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001697 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001698 u8 read_locked = 1, write_locked = 1;
1699 int err = 0;
1700
1701 clear_opal_cmd(dev);
1702 set_comid(dev, dev->comid);
1703
Scott Bauer455a7b22017-02-03 12:50:31 -07001704 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1705 lkul->session.opal_key.lr) < 0)
1706 return -ERANGE;
1707
1708 switch (lkul->l_state) {
1709 case OPAL_RO:
1710 read_locked = 0;
1711 write_locked = 1;
1712 break;
1713 case OPAL_RW:
1714 read_locked = 0;
1715 write_locked = 0;
1716 break;
1717 case OPAL_LK:
David Kozub1e815b32019-02-14 01:15:54 +01001718 /* vars are initialized to locked */
Scott Bauer455a7b22017-02-03 12:50:31 -07001719 break;
1720 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06001721 pr_debug("Tried to set an invalid locking state... returning to uland\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001722 return OPAL_INVAL_PARAM;
1723 }
1724
1725 add_token_u8(&err, dev, OPAL_CALL);
1726 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1727 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1728 add_token_u8(&err, dev, OPAL_STARTLIST);
1729 add_token_u8(&err, dev, OPAL_STARTNAME);
1730 add_token_u8(&err, dev, OPAL_VALUES);
1731 add_token_u8(&err, dev, OPAL_STARTLIST);
1732
1733 add_token_u8(&err, dev, OPAL_STARTNAME);
1734 add_token_u8(&err, dev, OPAL_READLOCKED);
1735 add_token_u8(&err, dev, read_locked);
1736 add_token_u8(&err, dev, OPAL_ENDNAME);
1737
1738 add_token_u8(&err, dev, OPAL_STARTNAME);
1739 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1740 add_token_u8(&err, dev, write_locked);
1741 add_token_u8(&err, dev, OPAL_ENDNAME);
1742
1743 add_token_u8(&err, dev, OPAL_ENDLIST);
1744 add_token_u8(&err, dev, OPAL_ENDNAME);
1745 add_token_u8(&err, dev, OPAL_ENDLIST);
1746
1747 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001748 pr_debug("Error building SET command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001749 return err;
1750 }
1751 return finalize_and_send(dev, parse_and_check_status);
1752}
1753
1754
Jon Derrickeed64952017-02-22 07:55:13 -07001755static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001756{
1757 u8 lr_buffer[OPAL_UID_LENGTH];
1758 u8 read_locked = 1, write_locked = 1;
Jon Derrickeed64952017-02-22 07:55:13 -07001759 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001760 int ret;
1761
1762 clear_opal_cmd(dev);
1763 set_comid(dev, dev->comid);
1764
Scott Bauer455a7b22017-02-03 12:50:31 -07001765 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1766 lkul->session.opal_key.lr) < 0)
1767 return -ERANGE;
1768
1769 switch (lkul->l_state) {
1770 case OPAL_RO:
1771 read_locked = 0;
1772 write_locked = 1;
1773 break;
1774 case OPAL_RW:
1775 read_locked = 0;
1776 write_locked = 0;
1777 break;
1778 case OPAL_LK:
David Kozub1e815b32019-02-14 01:15:54 +01001779 /* vars are initialized to locked */
Scott Bauer455a7b22017-02-03 12:50:31 -07001780 break;
1781 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06001782 pr_debug("Tried to set an invalid locking state.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001783 return OPAL_INVAL_PARAM;
1784 }
1785 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1786 read_locked, write_locked);
1787
1788 if (ret < 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001789 pr_debug("Error building SET command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001790 return ret;
1791 }
1792 return finalize_and_send(dev, parse_and_check_status);
1793}
1794
Jon Derrickeed64952017-02-22 07:55:13 -07001795static int activate_lsp(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001796{
Jon Derrickeed64952017-02-22 07:55:13 -07001797 struct opal_lr_act *opal_act = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001798 u8 user_lr[OPAL_UID_LENGTH];
1799 u8 uint_3 = 0x83;
1800 int err = 0, i;
1801
1802 clear_opal_cmd(dev);
1803 set_comid(dev, dev->comid);
1804
Scott Bauer455a7b22017-02-03 12:50:31 -07001805 add_token_u8(&err, dev, OPAL_CALL);
1806 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1807 OPAL_UID_LENGTH);
1808 add_token_bytestring(&err, dev, opalmethod[OPAL_ACTIVATE],
1809 OPAL_UID_LENGTH);
1810
1811
1812 if (opal_act->sum) {
1813 err = build_locking_range(user_lr, sizeof(user_lr),
1814 opal_act->lr[0]);
1815 if (err)
1816 return err;
1817
1818 add_token_u8(&err, dev, OPAL_STARTLIST);
1819 add_token_u8(&err, dev, OPAL_STARTNAME);
1820 add_token_u8(&err, dev, uint_3);
1821 add_token_u8(&err, dev, 6);
1822 add_token_u8(&err, dev, 0);
1823 add_token_u8(&err, dev, 0);
1824
1825 add_token_u8(&err, dev, OPAL_STARTLIST);
1826 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1827 for (i = 1; i < opal_act->num_lrs; i++) {
1828 user_lr[7] = opal_act->lr[i];
1829 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1830 }
1831 add_token_u8(&err, dev, OPAL_ENDLIST);
1832 add_token_u8(&err, dev, OPAL_ENDNAME);
1833 add_token_u8(&err, dev, OPAL_ENDLIST);
1834
1835 } else {
1836 add_token_u8(&err, dev, OPAL_STARTLIST);
1837 add_token_u8(&err, dev, OPAL_ENDLIST);
1838 }
1839
1840 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001841 pr_debug("Error building Activate LockingSP command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001842 return err;
1843 }
1844
1845 return finalize_and_send(dev, parse_and_check_status);
1846}
1847
1848static int get_lsp_lifecycle_cont(struct opal_dev *dev)
1849{
1850 u8 lc_status;
1851 int error = 0;
1852
1853 error = parse_and_check_status(dev);
1854 if (error)
1855 return error;
1856
1857 lc_status = response_get_u64(&dev->parsed, 4);
David Kozub1e815b32019-02-14 01:15:54 +01001858 /* 0x08 is Manufactured Inactive */
Scott Bauer455a7b22017-02-03 12:50:31 -07001859 /* 0x09 is Manufactured */
1860 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001861 pr_debug("Couldn't determine the status of the Lifecycle state\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001862 return -ENODEV;
1863 }
1864
1865 return 0;
1866}
1867
1868/* Determine if we're in the Manufactured Inactive or Active state */
Jon Derrickeed64952017-02-22 07:55:13 -07001869static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001870{
1871 int err = 0;
1872
1873 clear_opal_cmd(dev);
1874 set_comid(dev, dev->comid);
1875
1876 add_token_u8(&err, dev, OPAL_CALL);
1877 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1878 OPAL_UID_LENGTH);
1879 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1880
1881 add_token_u8(&err, dev, OPAL_STARTLIST);
1882 add_token_u8(&err, dev, OPAL_STARTLIST);
1883
1884 add_token_u8(&err, dev, OPAL_STARTNAME);
1885 add_token_u8(&err, dev, 3); /* Start Column */
1886 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1887 add_token_u8(&err, dev, OPAL_ENDNAME);
1888
1889 add_token_u8(&err, dev, OPAL_STARTNAME);
1890 add_token_u8(&err, dev, 4); /* End Column */
1891 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1892 add_token_u8(&err, dev, OPAL_ENDNAME);
1893
1894 add_token_u8(&err, dev, OPAL_ENDLIST);
1895 add_token_u8(&err, dev, OPAL_ENDLIST);
1896
1897 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001898 pr_debug("Error Building GET Lifecycle Status command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001899 return err;
1900 }
1901
1902 return finalize_and_send(dev, get_lsp_lifecycle_cont);
1903}
1904
1905static int get_msid_cpin_pin_cont(struct opal_dev *dev)
1906{
1907 const char *msid_pin;
1908 size_t strlen;
1909 int error = 0;
1910
1911 error = parse_and_check_status(dev);
1912 if (error)
1913 return error;
1914
1915 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1916 if (!msid_pin) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001917 pr_debug("%s: Couldn't extract PIN from response\n", __func__);
Scott Bauer455a7b22017-02-03 12:50:31 -07001918 return OPAL_INVAL_PARAM;
1919 }
1920
1921 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1922 if (!dev->prev_data)
1923 return -ENOMEM;
1924
1925 dev->prev_d_len = strlen;
1926
1927 return 0;
1928}
1929
Jon Derrickeed64952017-02-22 07:55:13 -07001930static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001931{
1932 int err = 0;
1933
1934 clear_opal_cmd(dev);
1935 set_comid(dev, dev->comid);
1936
Scott Bauer455a7b22017-02-03 12:50:31 -07001937 add_token_u8(&err, dev, OPAL_CALL);
1938 add_token_bytestring(&err, dev, opaluid[OPAL_C_PIN_MSID],
1939 OPAL_UID_LENGTH);
1940 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1941
1942 add_token_u8(&err, dev, OPAL_STARTLIST);
1943 add_token_u8(&err, dev, OPAL_STARTLIST);
1944
1945 add_token_u8(&err, dev, OPAL_STARTNAME);
1946 add_token_u8(&err, dev, 3); /* Start Column */
1947 add_token_u8(&err, dev, 3); /* PIN */
1948 add_token_u8(&err, dev, OPAL_ENDNAME);
1949
1950 add_token_u8(&err, dev, OPAL_STARTNAME);
1951 add_token_u8(&err, dev, 4); /* End Column */
1952 add_token_u8(&err, dev, 3); /* Lifecycle Column */
1953 add_token_u8(&err, dev, OPAL_ENDNAME);
1954
1955 add_token_u8(&err, dev, OPAL_ENDLIST);
1956 add_token_u8(&err, dev, OPAL_ENDLIST);
1957
1958 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001959 pr_debug("Error building Get MSID CPIN PIN command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001960 return err;
1961 }
1962
1963 return finalize_and_send(dev, get_msid_cpin_pin_cont);
1964}
1965
Jon Derrickeed64952017-02-22 07:55:13 -07001966static int end_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001967{
1968 int err = 0;
1969
1970 clear_opal_cmd(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07001971 set_comid(dev, dev->comid);
1972 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
Scott Bauer455a7b22017-02-03 12:50:31 -07001973
Jon Derrickeed64952017-02-22 07:55:13 -07001974 if (err < 0)
1975 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001976 return finalize_and_send(dev, end_session_cont);
1977}
1978
1979static int end_opal_session_error(struct opal_dev *dev)
1980{
Jon Derrickeed64952017-02-22 07:55:13 -07001981 const struct opal_step error_end_session[] = {
1982 { end_opal_session, },
1983 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07001984 };
Jon Derrickeed64952017-02-22 07:55:13 -07001985 dev->steps = error_end_session;
Scott Bauer455a7b22017-02-03 12:50:31 -07001986 return next(dev);
1987}
1988
1989static inline void setup_opal_dev(struct opal_dev *dev,
Jon Derrickeed64952017-02-22 07:55:13 -07001990 const struct opal_step *steps)
Scott Bauer455a7b22017-02-03 12:50:31 -07001991{
Jon Derrickeed64952017-02-22 07:55:13 -07001992 dev->steps = steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07001993 dev->tsn = 0;
1994 dev->hsn = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -07001995 dev->prev_data = NULL;
1996}
1997
1998static int check_opal_support(struct opal_dev *dev)
1999{
Jon Derrickeed64952017-02-22 07:55:13 -07002000 const struct opal_step steps[] = {
2001 { opal_discovery0, },
2002 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002003 };
2004 int ret;
2005
2006 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002007 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002008 ret = next(dev);
2009 dev->supported = !ret;
2010 mutex_unlock(&dev->dev_lock);
2011 return ret;
2012}
2013
Scott Bauer7d6d1572017-02-22 10:15:06 -07002014static void clean_opal_dev(struct opal_dev *dev)
2015{
2016
2017 struct opal_suspend_data *suspend, *next;
2018
2019 mutex_lock(&dev->dev_lock);
2020 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
2021 list_del(&suspend->node);
2022 kfree(suspend);
2023 }
2024 mutex_unlock(&dev->dev_lock);
2025}
2026
2027void free_opal_dev(struct opal_dev *dev)
2028{
2029 if (!dev)
2030 return;
2031 clean_opal_dev(dev);
2032 kfree(dev);
2033}
2034EXPORT_SYMBOL(free_opal_dev);
2035
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002036struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
Scott Bauer455a7b22017-02-03 12:50:31 -07002037{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002038 struct opal_dev *dev;
2039
2040 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
2041 if (!dev)
2042 return NULL;
2043
2044 INIT_LIST_HEAD(&dev->unlk_lst);
2045 mutex_init(&dev->dev_lock);
2046 dev->data = data;
2047 dev->send_recv = send_recv;
2048 if (check_opal_support(dev) != 0) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +01002049 pr_debug("Opal is not supported on this device\n");
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002050 kfree(dev);
2051 return NULL;
2052 }
2053 return dev;
Scott Bauer455a7b22017-02-03 12:50:31 -07002054}
2055EXPORT_SYMBOL(init_opal_dev);
2056
2057static int opal_secure_erase_locking_range(struct opal_dev *dev,
2058 struct opal_session_info *opal_session)
2059{
Jon Derrickeed64952017-02-22 07:55:13 -07002060 const struct opal_step erase_steps[] = {
2061 { opal_discovery0, },
2062 { start_auth_opal_session, opal_session },
2063 { get_active_key, &opal_session->opal_key.lr },
2064 { gen_key, },
2065 { end_opal_session, },
2066 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002067 };
2068 int ret;
2069
2070 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002071 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002072 ret = next(dev);
2073 mutex_unlock(&dev->dev_lock);
2074 return ret;
2075}
2076
2077static int opal_erase_locking_range(struct opal_dev *dev,
2078 struct opal_session_info *opal_session)
2079{
Jon Derrickeed64952017-02-22 07:55:13 -07002080 const struct opal_step erase_steps[] = {
2081 { opal_discovery0, },
2082 { start_auth_opal_session, opal_session },
2083 { erase_locking_range, opal_session },
2084 { end_opal_session, },
2085 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002086 };
2087 int ret;
2088
2089 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002090 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002091 ret = next(dev);
2092 mutex_unlock(&dev->dev_lock);
2093 return ret;
2094}
2095
2096static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
2097 struct opal_mbr_data *opal_mbr)
2098{
David Kozub78bf4732019-02-14 01:15:53 +01002099 u8 enable_disable = opal_mbr->enable_disable == OPAL_MBR_ENABLE ?
2100 OPAL_TRUE : OPAL_FALSE;
2101
Jon Derrickeed64952017-02-22 07:55:13 -07002102 const struct opal_step mbr_steps[] = {
2103 { opal_discovery0, },
2104 { start_admin1LSP_opal_session, &opal_mbr->key },
David Kozub78bf4732019-02-14 01:15:53 +01002105 { set_mbr_done, &enable_disable },
Jon Derrickeed64952017-02-22 07:55:13 -07002106 { end_opal_session, },
2107 { start_admin1LSP_opal_session, &opal_mbr->key },
David Kozub78bf4732019-02-14 01:15:53 +01002108 { set_mbr_enable_disable, &enable_disable },
Jon Derrickeed64952017-02-22 07:55:13 -07002109 { end_opal_session, },
2110 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002111 };
2112 int ret;
2113
2114 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
2115 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
2116 return -EINVAL;
2117
2118 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002119 setup_opal_dev(dev, mbr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002120 ret = next(dev);
2121 mutex_unlock(&dev->dev_lock);
2122 return ret;
2123}
2124
2125static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2126{
2127 struct opal_suspend_data *suspend;
2128
2129 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
2130 if (!suspend)
2131 return -ENOMEM;
2132
2133 suspend->unlk = *lk_unlk;
2134 suspend->lr = lk_unlk->session.opal_key.lr;
2135
2136 mutex_lock(&dev->dev_lock);
2137 setup_opal_dev(dev, NULL);
2138 add_suspend_info(dev, suspend);
2139 mutex_unlock(&dev->dev_lock);
2140 return 0;
2141}
2142
2143static int opal_add_user_to_lr(struct opal_dev *dev,
2144 struct opal_lock_unlock *lk_unlk)
2145{
Jon Derrickeed64952017-02-22 07:55:13 -07002146 const struct opal_step steps[] = {
2147 { opal_discovery0, },
2148 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2149 { add_user_to_lr, lk_unlk },
2150 { end_opal_session, },
2151 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002152 };
2153 int ret;
2154
2155 if (lk_unlk->l_state != OPAL_RO &&
2156 lk_unlk->l_state != OPAL_RW) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002157 pr_debug("Locking state was not RO or RW\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07002158 return -EINVAL;
2159 }
Jon Derrickb0bfdfc2017-03-06 08:41:04 -07002160 if (lk_unlk->session.who < OPAL_USER1 ||
Scott Bauer455a7b22017-02-03 12:50:31 -07002161 lk_unlk->session.who > OPAL_USER9) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002162 pr_debug("Authority was not within the range of users: %d\n",
2163 lk_unlk->session.who);
Scott Bauer455a7b22017-02-03 12:50:31 -07002164 return -EINVAL;
2165 }
2166 if (lk_unlk->session.sum) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002167 pr_debug("%s not supported in sum. Use setup locking range\n",
2168 __func__);
Scott Bauer455a7b22017-02-03 12:50:31 -07002169 return -EINVAL;
2170 }
2171
2172 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002173 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002174 ret = next(dev);
2175 mutex_unlock(&dev->dev_lock);
2176 return ret;
2177}
2178
2179static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal)
2180{
Jon Derrickeed64952017-02-22 07:55:13 -07002181 const struct opal_step revert_steps[] = {
2182 { opal_discovery0, },
2183 { start_SIDASP_opal_session, opal },
2184 { revert_tper, }, /* controller will terminate session */
2185 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002186 };
2187 int ret;
2188
2189 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002190 setup_opal_dev(dev, revert_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002191 ret = next(dev);
2192 mutex_unlock(&dev->dev_lock);
Scott Bauer7d6d1572017-02-22 10:15:06 -07002193
2194 /*
2195 * If we successfully reverted lets clean
2196 * any saved locking ranges.
2197 */
2198 if (!ret)
2199 clean_opal_dev(dev);
2200
Scott Bauer455a7b22017-02-03 12:50:31 -07002201 return ret;
2202}
2203
Jon Derrickeed64952017-02-22 07:55:13 -07002204static int __opal_lock_unlock(struct opal_dev *dev,
2205 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002206{
Jon Derrickeed64952017-02-22 07:55:13 -07002207 const struct opal_step unlock_steps[] = {
2208 { opal_discovery0, },
2209 { start_auth_opal_session, &lk_unlk->session },
2210 { lock_unlock_locking_range, lk_unlk },
2211 { end_opal_session, },
2212 { NULL, }
2213 };
2214 const struct opal_step unlock_sum_steps[] = {
2215 { opal_discovery0, },
2216 { start_auth_opal_session, &lk_unlk->session },
2217 { lock_unlock_locking_range_sum, lk_unlk },
2218 { end_opal_session, },
2219 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002220 };
2221
Jon Derrickeed64952017-02-22 07:55:13 -07002222 dev->steps = lk_unlk->session.sum ? unlock_sum_steps : unlock_steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07002223 return next(dev);
2224}
2225
Scott Bauerdbec491b2017-09-01 08:53:35 -06002226static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
2227{
David Kozub78bf4732019-02-14 01:15:53 +01002228 u8 mbr_done_tf = OPAL_TRUE;
David Kozub1e815b32019-02-14 01:15:54 +01002229 const struct opal_step mbrdone_step[] = {
Scott Bauerdbec491b2017-09-01 08:53:35 -06002230 { opal_discovery0, },
2231 { start_admin1LSP_opal_session, key },
2232 { set_mbr_done, &mbr_done_tf },
2233 { end_opal_session, },
2234 { NULL, }
2235 };
2236
2237 dev->steps = mbrdone_step;
2238 return next(dev);
2239}
2240
Jon Derrickeed64952017-02-22 07:55:13 -07002241static int opal_lock_unlock(struct opal_dev *dev,
2242 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002243{
Scott Bauer455a7b22017-02-03 12:50:31 -07002244 int ret;
2245
2246 if (lk_unlk->session.who < OPAL_ADMIN1 ||
2247 lk_unlk->session.who > OPAL_USER9)
2248 return -EINVAL;
2249
2250 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002251 ret = __opal_lock_unlock(dev, lk_unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002252 mutex_unlock(&dev->dev_lock);
2253 return ret;
2254}
2255
2256static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2257{
Jon Derrickeed64952017-02-22 07:55:13 -07002258 const struct opal_step owner_steps[] = {
2259 { opal_discovery0, },
2260 { start_anybodyASP_opal_session, },
2261 { get_msid_cpin_pin, },
2262 { end_opal_session, },
2263 { start_SIDASP_opal_session, opal },
2264 { set_sid_cpin_pin, opal },
2265 { end_opal_session, },
2266 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002267 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002268 int ret;
2269
2270 if (!dev)
2271 return -ENODEV;
2272
2273 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002274 setup_opal_dev(dev, owner_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002275 ret = next(dev);
2276 mutex_unlock(&dev->dev_lock);
2277 return ret;
2278}
2279
David Kozub1e815b32019-02-14 01:15:54 +01002280static int opal_activate_lsp(struct opal_dev *dev,
2281 struct opal_lr_act *opal_lr_act)
Scott Bauer455a7b22017-02-03 12:50:31 -07002282{
Jon Derrickeed64952017-02-22 07:55:13 -07002283 const struct opal_step active_steps[] = {
2284 { opal_discovery0, },
2285 { start_SIDASP_opal_session, &opal_lr_act->key },
2286 { get_lsp_lifecycle, },
2287 { activate_lsp, opal_lr_act },
2288 { end_opal_session, },
2289 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002290 };
2291 int ret;
2292
2293 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2294 return -EINVAL;
2295
2296 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002297 setup_opal_dev(dev, active_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002298 ret = next(dev);
2299 mutex_unlock(&dev->dev_lock);
2300 return ret;
2301}
2302
2303static int opal_setup_locking_range(struct opal_dev *dev,
2304 struct opal_user_lr_setup *opal_lrs)
2305{
Jon Derrickeed64952017-02-22 07:55:13 -07002306 const struct opal_step lr_steps[] = {
2307 { opal_discovery0, },
2308 { start_auth_opal_session, &opal_lrs->session },
2309 { setup_locking_range, opal_lrs },
2310 { end_opal_session, },
2311 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002312 };
2313 int ret;
2314
2315 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002316 setup_opal_dev(dev, lr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002317 ret = next(dev);
2318 mutex_unlock(&dev->dev_lock);
2319 return ret;
2320}
2321
2322static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2323{
Jon Derrickeed64952017-02-22 07:55:13 -07002324 const struct opal_step pw_steps[] = {
2325 { opal_discovery0, },
2326 { start_auth_opal_session, &opal_pw->session },
2327 { set_new_pw, &opal_pw->new_user_pw },
2328 { end_opal_session, },
2329 { NULL }
Scott Bauer455a7b22017-02-03 12:50:31 -07002330 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002331 int ret;
2332
2333 if (opal_pw->session.who < OPAL_ADMIN1 ||
2334 opal_pw->session.who > OPAL_USER9 ||
2335 opal_pw->new_user_pw.who < OPAL_ADMIN1 ||
2336 opal_pw->new_user_pw.who > OPAL_USER9)
2337 return -EINVAL;
2338
2339 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002340 setup_opal_dev(dev, pw_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002341 ret = next(dev);
2342 mutex_unlock(&dev->dev_lock);
2343 return ret;
2344}
2345
2346static int opal_activate_user(struct opal_dev *dev,
2347 struct opal_session_info *opal_session)
2348{
Jon Derrickeed64952017-02-22 07:55:13 -07002349 const struct opal_step act_steps[] = {
2350 { opal_discovery0, },
2351 { start_admin1LSP_opal_session, &opal_session->opal_key },
2352 { internal_activate_user, opal_session },
2353 { end_opal_session, },
2354 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002355 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002356 int ret;
2357
2358 /* We can't activate Admin1 it's active as manufactured */
Jon Derrickb0bfdfc2017-03-06 08:41:04 -07002359 if (opal_session->who < OPAL_USER1 ||
Scott Bauer455a7b22017-02-03 12:50:31 -07002360 opal_session->who > OPAL_USER9) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002361 pr_debug("Who was not a valid user: %d\n", opal_session->who);
Scott Bauer455a7b22017-02-03 12:50:31 -07002362 return -EINVAL;
2363 }
2364
2365 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002366 setup_opal_dev(dev, act_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002367 ret = next(dev);
2368 mutex_unlock(&dev->dev_lock);
2369 return ret;
2370}
2371
2372bool opal_unlock_from_suspend(struct opal_dev *dev)
2373{
2374 struct opal_suspend_data *suspend;
Scott Bauer455a7b22017-02-03 12:50:31 -07002375 bool was_failure = false;
2376 int ret = 0;
2377
2378 if (!dev)
2379 return false;
2380 if (!dev->supported)
2381 return false;
2382
2383 mutex_lock(&dev->dev_lock);
2384 setup_opal_dev(dev, NULL);
Scott Bauer455a7b22017-02-03 12:50:31 -07002385
2386 list_for_each_entry(suspend, &dev->unlk_lst, node) {
Scott Bauer455a7b22017-02-03 12:50:31 -07002387 dev->tsn = 0;
2388 dev->hsn = 0;
2389
Jon Derrickeed64952017-02-22 07:55:13 -07002390 ret = __opal_lock_unlock(dev, &suspend->unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002391 if (ret) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002392 pr_debug("Failed to unlock LR %hhu with sum %d\n",
2393 suspend->unlk.session.opal_key.lr,
2394 suspend->unlk.session.sum);
Scott Bauer455a7b22017-02-03 12:50:31 -07002395 was_failure = true;
2396 }
Scott Bauerdbec491b2017-09-01 08:53:35 -06002397 if (dev->mbr_enabled) {
2398 ret = __opal_set_mbr_done(dev, &suspend->unlk.session.opal_key);
2399 if (ret)
2400 pr_debug("Failed to set MBR Done in S3 resume\n");
2401 }
Scott Bauer455a7b22017-02-03 12:50:31 -07002402 }
2403 mutex_unlock(&dev->dev_lock);
2404 return was_failure;
2405}
2406EXPORT_SYMBOL(opal_unlock_from_suspend);
2407
Scott Bauere225c202017-02-14 17:29:36 -07002408int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
Scott Bauer455a7b22017-02-03 12:50:31 -07002409{
Scott Bauere225c202017-02-14 17:29:36 -07002410 void *p;
2411 int ret = -ENOTTY;
Scott Bauer455a7b22017-02-03 12:50:31 -07002412
2413 if (!capable(CAP_SYS_ADMIN))
2414 return -EACCES;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002415 if (!dev)
2416 return -ENOTSUPP;
Scott Bauer591c59d2017-04-07 13:58:50 -06002417 if (!dev->supported)
Scott Bauer455a7b22017-02-03 12:50:31 -07002418 return -ENOTSUPP;
Scott Bauer455a7b22017-02-03 12:50:31 -07002419
Jon Derrickeed64952017-02-22 07:55:13 -07002420 p = memdup_user(arg, _IOC_SIZE(cmd));
Scott Bauere225c202017-02-14 17:29:36 -07002421 if (IS_ERR(p))
2422 return PTR_ERR(p);
2423
Scott Bauer455a7b22017-02-03 12:50:31 -07002424 switch (cmd) {
Scott Bauere225c202017-02-14 17:29:36 -07002425 case IOC_OPAL_SAVE:
2426 ret = opal_save(dev, p);
2427 break;
2428 case IOC_OPAL_LOCK_UNLOCK:
2429 ret = opal_lock_unlock(dev, p);
2430 break;
2431 case IOC_OPAL_TAKE_OWNERSHIP:
2432 ret = opal_take_ownership(dev, p);
2433 break;
2434 case IOC_OPAL_ACTIVATE_LSP:
2435 ret = opal_activate_lsp(dev, p);
2436 break;
2437 case IOC_OPAL_SET_PW:
2438 ret = opal_set_new_pw(dev, p);
2439 break;
2440 case IOC_OPAL_ACTIVATE_USR:
2441 ret = opal_activate_user(dev, p);
2442 break;
2443 case IOC_OPAL_REVERT_TPR:
2444 ret = opal_reverttper(dev, p);
2445 break;
2446 case IOC_OPAL_LR_SETUP:
2447 ret = opal_setup_locking_range(dev, p);
2448 break;
2449 case IOC_OPAL_ADD_USR_TO_LR:
2450 ret = opal_add_user_to_lr(dev, p);
2451 break;
2452 case IOC_OPAL_ENABLE_DISABLE_MBR:
2453 ret = opal_enable_disable_shadow_mbr(dev, p);
2454 break;
2455 case IOC_OPAL_ERASE_LR:
2456 ret = opal_erase_locking_range(dev, p);
2457 break;
2458 case IOC_OPAL_SECURE_ERASE_LR:
2459 ret = opal_secure_erase_locking_range(dev, p);
2460 break;
Scott Bauer455a7b22017-02-03 12:50:31 -07002461 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06002462 break;
Scott Bauer455a7b22017-02-03 12:50:31 -07002463 }
Scott Bauere225c202017-02-14 17:29:36 -07002464
2465 kfree(p);
2466 return ret;
Scott Bauer455a7b22017-02-03 12:50:31 -07002467}
2468EXPORT_SYMBOL_GPL(sed_ioctl);