blob: 1e18dca360fc501033762d4c505c2e32c4674ee6 [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;
83
84 void *data;
85 sec_send_recv *send_recv;
86
Jon Derrickeed64952017-02-22 07:55:13 -070087 const struct opal_step *steps;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010088 struct mutex dev_lock;
89 u16 comid;
90 u32 hsn;
91 u32 tsn;
92 u64 align;
93 u64 lowest_lba;
94
95 size_t pos;
96 u8 cmd[IO_BUFFER_LENGTH];
97 u8 resp[IO_BUFFER_LENGTH];
98
99 struct parsed_resp parsed;
100 size_t prev_d_len;
101 void *prev_data;
102
103 struct list_head unlk_lst;
104};
105
106
Scott Bauer455a7b22017-02-03 12:50:31 -0700107static const u8 opaluid[][OPAL_UID_LENGTH] = {
108 /* users */
109 [OPAL_SMUID_UID] =
110 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
111 [OPAL_THISSP_UID] =
112 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
113 [OPAL_ADMINSP_UID] =
114 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },
115 [OPAL_LOCKINGSP_UID] =
116 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },
117 [OPAL_ENTERPRISE_LOCKINGSP_UID] =
118 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 },
119 [OPAL_ANYBODY_UID] =
120 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },
121 [OPAL_SID_UID] =
122 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },
123 [OPAL_ADMIN1_UID] =
124 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },
125 [OPAL_USER1_UID] =
126 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },
127 [OPAL_USER2_UID] =
128 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },
129 [OPAL_PSID_UID] =
130 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },
131 [OPAL_ENTERPRISE_BANDMASTER0_UID] =
132 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 },
133 [OPAL_ENTERPRISE_ERASEMASTER_UID] =
134 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 },
135
136 /* tables */
137
138 [OPAL_LOCKINGRANGE_GLOBAL] =
139 { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 },
140 [OPAL_LOCKINGRANGE_ACE_RDLOCKED] =
141 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 },
142 [OPAL_LOCKINGRANGE_ACE_WRLOCKED] =
143 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 },
144 [OPAL_MBRCONTROL] =
145 { 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 },
146 [OPAL_MBR] =
147 { 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 },
148 [OPAL_AUTHORITY_TABLE] =
149 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00},
150 [OPAL_C_PIN_TABLE] =
151 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00},
152 [OPAL_LOCKING_INFO_TABLE] =
153 { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 },
154 [OPAL_ENTERPRISE_LOCKING_INFO_TABLE] =
155 { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
156
157 /* C_PIN_TABLE object ID's */
158
159 [OPAL_C_PIN_MSID] =
160 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02},
161 [OPAL_C_PIN_SID] =
162 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01},
163 [OPAL_C_PIN_ADMIN1] =
164 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01},
165
166 /* half UID's (only first 4 bytes used) */
167
168 [OPAL_HALF_UID_AUTHORITY_OBJ_REF] =
169 { 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff },
170 [OPAL_HALF_UID_BOOLEAN_ACE] =
171 { 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff },
172
173 /* special value for omitted optional parameter */
174 [OPAL_UID_HEXFF] =
175 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
176};
177
178/*
179 * TCG Storage SSC Methods.
180 * Derived from: TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
181 * Section: 6.3 Assigned UIDs
182 */
183static const u8 opalmethod[][OPAL_UID_LENGTH] = {
184 [OPAL_PROPERTIES] =
185 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 },
186 [OPAL_STARTSESSION] =
187 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 },
188 [OPAL_REVERT] =
189 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 },
190 [OPAL_ACTIVATE] =
191 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 },
192 [OPAL_EGET] =
193 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 },
194 [OPAL_ESET] =
195 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 },
196 [OPAL_NEXT] =
197 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 },
198 [OPAL_EAUTHENTICATE] =
199 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c },
200 [OPAL_GETACL] =
201 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d },
202 [OPAL_GENKEY] =
203 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 },
204 [OPAL_REVERTSP] =
205 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 },
206 [OPAL_GET] =
207 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 },
208 [OPAL_SET] =
209 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 },
210 [OPAL_AUTHENTICATE] =
211 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c },
212 [OPAL_RANDOM] =
213 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },
214 [OPAL_ERASE] =
215 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 },
216};
217
Scott Bauer455a7b22017-02-03 12:50:31 -0700218static int end_opal_session_error(struct opal_dev *dev);
219
220struct opal_suspend_data {
221 struct opal_lock_unlock unlk;
222 u8 lr;
223 struct list_head node;
224};
225
226/*
227 * Derived from:
228 * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
229 * Section: 5.1.5 Method Status Codes
230 */
231static const char * const opal_errors[] = {
232 "Success",
233 "Not Authorized",
234 "Unknown Error",
235 "SP Busy",
236 "SP Failed",
237 "SP Disabled",
238 "SP Frozen",
239 "No Sessions Available",
240 "Uniqueness Conflict",
241 "Insufficient Space",
242 "Insufficient Rows",
243 "Invalid Function",
244 "Invalid Parameter",
245 "Invalid Reference",
246 "Unknown Error",
247 "TPER Malfunction",
248 "Transaction Failure",
249 "Response Overflow",
250 "Authority Locked Out",
251};
252
253static const char *opal_error_to_human(int error)
254{
255 if (error == 0x3f)
256 return "Failed";
257
258 if (error >= ARRAY_SIZE(opal_errors) || error < 0)
259 return "Unknown Error";
260
261 return opal_errors[error];
262}
263
264static void print_buffer(const u8 *ptr, u32 length)
265{
266#ifdef DEBUG
267 print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length);
268 pr_debug("\n");
269#endif
270}
271
272static bool check_tper(const void *data)
273{
274 const struct d0_tper_features *tper = data;
275 u8 flags = tper->supported_features;
276
277 if (!(flags & TPER_SYNC_SUPPORTED)) {
278 pr_err("TPer sync not supported. flags = %d\n",
279 tper->supported_features);
280 return false;
281 }
282
283 return true;
284}
285
286static bool check_sum(const void *data)
287{
288 const struct d0_single_user_mode *sum = data;
289 u32 nlo = be32_to_cpu(sum->num_locking_objects);
290
291 if (nlo == 0) {
292 pr_err("Need at least one locking object.\n");
293 return false;
294 }
295
296 pr_debug("Number of locking objects: %d\n", nlo);
297
298 return true;
299}
300
301static u16 get_comid_v100(const void *data)
302{
303 const struct d0_opal_v100 *v100 = data;
304
305 return be16_to_cpu(v100->baseComID);
306}
307
308static u16 get_comid_v200(const void *data)
309{
310 const struct d0_opal_v200 *v200 = data;
311
312 return be16_to_cpu(v200->baseComID);
313}
314
315static int opal_send_cmd(struct opal_dev *dev)
316{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +0100317 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
Scott Bauer455a7b22017-02-03 12:50:31 -0700318 dev->cmd, IO_BUFFER_LENGTH,
319 true);
320}
321
322static int opal_recv_cmd(struct opal_dev *dev)
323{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +0100324 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
Scott Bauer455a7b22017-02-03 12:50:31 -0700325 dev->resp, IO_BUFFER_LENGTH,
326 false);
327}
328
329static int opal_recv_check(struct opal_dev *dev)
330{
331 size_t buflen = IO_BUFFER_LENGTH;
332 void *buffer = dev->resp;
333 struct opal_header *hdr = buffer;
334 int ret;
335
336 do {
337 pr_debug("Sent OPAL command: outstanding=%d, minTransfer=%d\n",
338 hdr->cp.outstandingData,
339 hdr->cp.minTransfer);
340
341 if (hdr->cp.outstandingData == 0 ||
342 hdr->cp.minTransfer != 0)
343 return 0;
344
345 memset(buffer, 0, buflen);
346 ret = opal_recv_cmd(dev);
347 } while (!ret);
348
349 return ret;
350}
351
352static int opal_send_recv(struct opal_dev *dev, cont_fn *cont)
353{
354 int ret;
355
356 ret = opal_send_cmd(dev);
357 if (ret)
358 return ret;
359 ret = opal_recv_cmd(dev);
360 if (ret)
361 return ret;
362 ret = opal_recv_check(dev);
363 if (ret)
364 return ret;
365 return cont(dev);
366}
367
368static void check_geometry(struct opal_dev *dev, const void *data)
369{
370 const struct d0_geometry_features *geo = data;
371
372 dev->align = geo->alignment_granularity;
373 dev->lowest_lba = geo->lowest_aligned_lba;
374}
375
376static int next(struct opal_dev *dev)
377{
Jon Derrickeed64952017-02-22 07:55:13 -0700378 const struct opal_step *step;
379 int state = 0, error = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700380
381 do {
Jon Derrickeed64952017-02-22 07:55:13 -0700382 step = &dev->steps[state];
383 if (!step->fn)
Scott Bauer455a7b22017-02-03 12:50:31 -0700384 break;
385
Jon Derrickeed64952017-02-22 07:55:13 -0700386 error = step->fn(dev, step->data);
Scott Bauer455a7b22017-02-03 12:50:31 -0700387 if (error) {
388 pr_err("Error on step function: %d with error %d: %s\n",
Jon Derrickeed64952017-02-22 07:55:13 -0700389 state, error,
Scott Bauer455a7b22017-02-03 12:50:31 -0700390 opal_error_to_human(error));
391
392 /* For each OPAL command we do a discovery0 then we
393 * start some sort of session.
394 * If we haven't passed state 1 then there was an error
395 * on discovery0 or during the attempt to start a
396 * session. Therefore we shouldn't attempt to terminate
397 * a session, as one has not yet been created.
398 */
Scott Bauer2d190202017-02-22 10:15:08 -0700399 if (state > 1) {
400 end_opal_session_error(dev);
401 return error;
402 }
403
Scott Bauer455a7b22017-02-03 12:50:31 -0700404 }
Jon Derrickeed64952017-02-22 07:55:13 -0700405 state++;
Scott Bauer455a7b22017-02-03 12:50:31 -0700406 } while (!error);
407
408 return error;
409}
410
411static int opal_discovery0_end(struct opal_dev *dev)
412{
413 bool found_com_id = false, supported = true, single_user = false;
414 const struct d0_header *hdr = (struct d0_header *)dev->resp;
415 const u8 *epos = dev->resp, *cpos = dev->resp;
416 u16 comid = 0;
Jon Derrick77039b92017-02-21 11:59:15 -0700417 u32 hlen = be32_to_cpu(hdr->length);
Scott Bauer455a7b22017-02-03 12:50:31 -0700418
Jon Derrick77039b92017-02-21 11:59:15 -0700419 print_buffer(dev->resp, hlen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700420
Jon Derrick77039b92017-02-21 11:59:15 -0700421 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
422 pr_warn("Discovery length overflows buffer (%zu+%u)/%u\n",
423 sizeof(*hdr), hlen, IO_BUFFER_LENGTH);
424 return -EFAULT;
425 }
426
427 epos += hlen; /* end of buffer */
Scott Bauer455a7b22017-02-03 12:50:31 -0700428 cpos += sizeof(*hdr); /* current position on buffer */
429
430 while (cpos < epos && supported) {
431 const struct d0_features *body =
432 (const struct d0_features *)cpos;
433
434 switch (be16_to_cpu(body->code)) {
435 case FC_TPER:
436 supported = check_tper(body->features);
437 break;
438 case FC_SINGLEUSER:
439 single_user = check_sum(body->features);
440 break;
441 case FC_GEOMETRY:
442 check_geometry(dev, body);
443 break;
444 case FC_LOCKING:
445 case FC_ENTERPRISE:
446 case FC_DATASTORE:
447 /* some ignored properties */
448 pr_debug("Found OPAL feature description: %d\n",
449 be16_to_cpu(body->code));
450 break;
451 case FC_OPALV100:
452 comid = get_comid_v100(body->features);
453 found_com_id = true;
454 break;
455 case FC_OPALV200:
456 comid = get_comid_v200(body->features);
457 found_com_id = true;
458 break;
459 case 0xbfff ... 0xffff:
460 /* vendor specific, just ignore */
461 break;
462 default:
463 pr_debug("OPAL Unknown feature: %d\n",
464 be16_to_cpu(body->code));
465
466 }
467 cpos += body->length + 4;
468 }
469
470 if (!supported) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100471 pr_debug("This device is not Opal enabled. Not Supported!\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700472 return -EOPNOTSUPP;
473 }
474
475 if (!single_user)
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100476 pr_debug("Device doesn't support single user mode\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700477
478
479 if (!found_com_id) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100480 pr_debug("Could not find OPAL comid for device. Returning early\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700481 return -EOPNOTSUPP;;
482 }
483
484 dev->comid = comid;
485
486 return 0;
487}
488
Jon Derrickeed64952017-02-22 07:55:13 -0700489static int opal_discovery0(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -0700490{
491 int ret;
492
493 memset(dev->resp, 0, IO_BUFFER_LENGTH);
494 dev->comid = OPAL_DISCOVERY_COMID;
495 ret = opal_recv_cmd(dev);
496 if (ret)
497 return ret;
498 return opal_discovery0_end(dev);
499}
500
501static void add_token_u8(int *err, struct opal_dev *cmd, u8 tok)
502{
503 if (*err)
504 return;
505 if (cmd->pos >= IO_BUFFER_LENGTH - 1) {
506 pr_err("Error adding u8: end of buffer.\n");
507 *err = -ERANGE;
508 return;
509 }
510 cmd->cmd[cmd->pos++] = tok;
511}
512
513static void add_short_atom_header(struct opal_dev *cmd, bool bytestring,
514 bool has_sign, int len)
515{
516 u8 atom;
517 int err = 0;
518
519 atom = SHORT_ATOM_ID;
520 atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;
521 atom |= has_sign ? SHORT_ATOM_SIGNED : 0;
522 atom |= len & SHORT_ATOM_LEN_MASK;
523
524 add_token_u8(&err, cmd, atom);
525}
526
527static void add_medium_atom_header(struct opal_dev *cmd, bool bytestring,
528 bool has_sign, int len)
529{
530 u8 header0;
531
532 header0 = MEDIUM_ATOM_ID;
533 header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;
534 header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;
535 header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;
536 cmd->cmd[cmd->pos++] = header0;
537 cmd->cmd[cmd->pos++] = len;
538}
539
540static void add_token_u64(int *err, struct opal_dev *cmd, u64 number)
541{
542
543 size_t len;
544 int msb;
545 u8 n;
546
547 if (!(number & ~TINY_ATOM_DATA_MASK)) {
548 add_token_u8(err, cmd, number);
549 return;
550 }
551
552 msb = fls(number);
553 len = DIV_ROUND_UP(msb, 4);
554
555 if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) {
556 pr_err("Error adding u64: end of buffer.\n");
557 *err = -ERANGE;
558 return;
559 }
560 add_short_atom_header(cmd, false, false, len);
561 while (len--) {
562 n = number >> (len * 8);
563 add_token_u8(err, cmd, n);
564 }
565}
566
567static void add_token_bytestring(int *err, struct opal_dev *cmd,
568 const u8 *bytestring, size_t len)
569{
570 size_t header_len = 1;
571 bool is_short_atom = true;
572
573 if (*err)
574 return;
575
576 if (len & ~SHORT_ATOM_LEN_MASK) {
577 header_len = 2;
578 is_short_atom = false;
579 }
580
581 if (len >= IO_BUFFER_LENGTH - cmd->pos - header_len) {
582 pr_err("Error adding bytestring: end of buffer.\n");
583 *err = -ERANGE;
584 return;
585 }
586
587 if (is_short_atom)
588 add_short_atom_header(cmd, true, false, len);
589 else
590 add_medium_atom_header(cmd, true, false, len);
591
592 memcpy(&cmd->cmd[cmd->pos], bytestring, len);
593 cmd->pos += len;
594
595}
596
597static int build_locking_range(u8 *buffer, size_t length, u8 lr)
598{
599 if (length > OPAL_UID_LENGTH) {
600 pr_err("Can't build locking range. Length OOB\n");
601 return -ERANGE;
602 }
603
604 memcpy(buffer, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
605
606 if (lr == 0)
607 return 0;
608 buffer[5] = LOCKING_RANGE_NON_GLOBAL;
609 buffer[7] = lr;
610
611 return 0;
612}
613
614static int build_locking_user(u8 *buffer, size_t length, u8 lr)
615{
616 if (length > OPAL_UID_LENGTH) {
617 pr_err("Can't build locking range user, Length OOB\n");
618 return -ERANGE;
619 }
620
621 memcpy(buffer, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
622
623 buffer[7] = lr + 1;
624
625 return 0;
626}
627
628static void set_comid(struct opal_dev *cmd, u16 comid)
629{
630 struct opal_header *hdr = (struct opal_header *)cmd->cmd;
631
632 hdr->cp.extendedComID[0] = comid >> 8;
633 hdr->cp.extendedComID[1] = comid;
634 hdr->cp.extendedComID[2] = 0;
635 hdr->cp.extendedComID[3] = 0;
636}
637
638static int cmd_finalize(struct opal_dev *cmd, u32 hsn, u32 tsn)
639{
640 struct opal_header *hdr;
641 int err = 0;
642
643 add_token_u8(&err, cmd, OPAL_ENDOFDATA);
644 add_token_u8(&err, cmd, OPAL_STARTLIST);
645 add_token_u8(&err, cmd, 0);
646 add_token_u8(&err, cmd, 0);
647 add_token_u8(&err, cmd, 0);
648 add_token_u8(&err, cmd, OPAL_ENDLIST);
649
650 if (err) {
651 pr_err("Error finalizing command.\n");
652 return -EFAULT;
653 }
654
655 hdr = (struct opal_header *) cmd->cmd;
656
657 hdr->pkt.tsn = cpu_to_be32(tsn);
658 hdr->pkt.hsn = cpu_to_be32(hsn);
659
660 hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
661 while (cmd->pos % 4) {
662 if (cmd->pos >= IO_BUFFER_LENGTH) {
663 pr_err("Error: Buffer overrun\n");
664 return -ERANGE;
665 }
666 cmd->cmd[cmd->pos++] = 0;
667 }
668 hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
669 sizeof(hdr->pkt));
670 hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
671
672 return 0;
673}
674
Jon Derrickcccb9242017-02-21 11:59:14 -0700675static const struct opal_resp_tok *response_get_token(
676 const struct parsed_resp *resp,
677 int n)
Scott Bauer455a7b22017-02-03 12:50:31 -0700678{
679 const struct opal_resp_tok *tok;
680
681 if (n >= resp->num) {
682 pr_err("Token number doesn't exist: %d, resp: %d\n",
683 n, resp->num);
Jon Derrickcccb9242017-02-21 11:59:14 -0700684 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700685 }
686
687 tok = &resp->toks[n];
688 if (tok->len == 0) {
689 pr_err("Token length must be non-zero\n");
Jon Derrickcccb9242017-02-21 11:59:14 -0700690 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700691 }
692
Jon Derrickcccb9242017-02-21 11:59:14 -0700693 return tok;
Scott Bauer455a7b22017-02-03 12:50:31 -0700694}
695
Jon Derrickaedb6e22017-02-21 11:59:13 -0700696static ssize_t response_parse_tiny(struct opal_resp_tok *tok,
697 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700698{
699 tok->pos = pos;
700 tok->len = 1;
701 tok->width = OPAL_WIDTH_TINY;
702
703 if (pos[0] & TINY_ATOM_SIGNED) {
704 tok->type = OPAL_DTA_TOKENID_SINT;
705 } else {
706 tok->type = OPAL_DTA_TOKENID_UINT;
707 tok->stored.u = pos[0] & 0x3f;
708 }
709
710 return tok->len;
711}
712
Jon Derrickaedb6e22017-02-21 11:59:13 -0700713static ssize_t response_parse_short(struct opal_resp_tok *tok,
714 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700715{
716 tok->pos = pos;
717 tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
718 tok->width = OPAL_WIDTH_SHORT;
719
720 if (pos[0] & SHORT_ATOM_BYTESTRING) {
721 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
722 } else if (pos[0] & SHORT_ATOM_SIGNED) {
723 tok->type = OPAL_DTA_TOKENID_SINT;
724 } else {
725 u64 u_integer = 0;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700726 ssize_t i, b = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700727
728 tok->type = OPAL_DTA_TOKENID_UINT;
729 if (tok->len > 9) {
730 pr_warn("uint64 with more than 8 bytes\n");
731 return -EINVAL;
732 }
733 for (i = tok->len - 1; i > 0; i--) {
734 u_integer |= ((u64)pos[i] << (8 * b));
735 b++;
736 }
737 tok->stored.u = u_integer;
738 }
739
740 return tok->len;
741}
742
Jon Derrickaedb6e22017-02-21 11:59:13 -0700743static ssize_t response_parse_medium(struct opal_resp_tok *tok,
744 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700745{
746 tok->pos = pos;
747 tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
748 tok->width = OPAL_WIDTH_MEDIUM;
749
750 if (pos[0] & MEDIUM_ATOM_BYTESTRING)
751 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
752 else if (pos[0] & MEDIUM_ATOM_SIGNED)
753 tok->type = OPAL_DTA_TOKENID_SINT;
754 else
755 tok->type = OPAL_DTA_TOKENID_UINT;
756
757 return tok->len;
758}
759
Jon Derrickaedb6e22017-02-21 11:59:13 -0700760static ssize_t response_parse_long(struct opal_resp_tok *tok,
761 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700762{
763 tok->pos = pos;
764 tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
765 tok->width = OPAL_WIDTH_LONG;
766
767 if (pos[0] & LONG_ATOM_BYTESTRING)
768 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
769 else if (pos[0] & LONG_ATOM_SIGNED)
770 tok->type = OPAL_DTA_TOKENID_SINT;
771 else
772 tok->type = OPAL_DTA_TOKENID_UINT;
773
774 return tok->len;
775}
776
Jon Derrickaedb6e22017-02-21 11:59:13 -0700777static ssize_t response_parse_token(struct opal_resp_tok *tok,
778 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700779{
780 tok->pos = pos;
781 tok->len = 1;
782 tok->type = OPAL_DTA_TOKENID_TOKEN;
783 tok->width = OPAL_WIDTH_TOKEN;
784
785 return tok->len;
786}
787
788static int response_parse(const u8 *buf, size_t length,
789 struct parsed_resp *resp)
790{
791 const struct opal_header *hdr;
792 struct opal_resp_tok *iter;
793 int num_entries = 0;
794 int total;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700795 ssize_t token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700796 const u8 *pos;
Jon Derrick77039b92017-02-21 11:59:15 -0700797 u32 clen, plen, slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700798
799 if (!buf)
800 return -EFAULT;
801
802 if (!resp)
803 return -EFAULT;
804
805 hdr = (struct opal_header *)buf;
806 pos = buf;
807 pos += sizeof(*hdr);
808
Jon Derrick77039b92017-02-21 11:59:15 -0700809 clen = be32_to_cpu(hdr->cp.length);
810 plen = be32_to_cpu(hdr->pkt.length);
811 slen = be32_to_cpu(hdr->subpkt.length);
812 pr_debug("Response size: cp: %u, pkt: %u, subpkt: %u\n",
813 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700814
Jon Derrick77039b92017-02-21 11:59:15 -0700815 if (clen == 0 || plen == 0 || slen == 0 ||
816 slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
817 pr_err("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
818 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700819 print_buffer(pos, sizeof(*hdr));
820 return -EINVAL;
821 }
822
823 if (pos > buf + length)
824 return -EFAULT;
825
826 iter = resp->toks;
Jon Derrick77039b92017-02-21 11:59:15 -0700827 total = slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700828 print_buffer(pos, total);
829 while (total > 0) {
830 if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */
831 token_length = response_parse_tiny(iter, pos);
832 else if (pos[0] <= SHORT_ATOM_BYTE) /* short atom */
833 token_length = response_parse_short(iter, pos);
834 else if (pos[0] <= MEDIUM_ATOM_BYTE) /* medium atom */
835 token_length = response_parse_medium(iter, pos);
836 else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
837 token_length = response_parse_long(iter, pos);
838 else /* TOKEN */
839 token_length = response_parse_token(iter, pos);
840
Jon Derrickaedb6e22017-02-21 11:59:13 -0700841 if (token_length < 0)
842 return token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700843
844 pos += token_length;
845 total -= token_length;
846 iter++;
847 num_entries++;
848 }
849
850 if (num_entries == 0) {
851 pr_err("Couldn't parse response.\n");
852 return -EINVAL;
853 }
854 resp->num = num_entries;
855
856 return 0;
857}
858
859static size_t response_get_string(const struct parsed_resp *resp, int n,
860 const char **store)
861{
862 *store = NULL;
863 if (!resp) {
864 pr_err("Response is NULL\n");
865 return 0;
866 }
867
868 if (n > resp->num) {
869 pr_err("Response has %d tokens. Can't access %d\n",
870 resp->num, n);
871 return 0;
872 }
873
874 if (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) {
875 pr_err("Token is not a byte string!\n");
876 return 0;
877 }
878
879 *store = resp->toks[n].pos + 1;
880 return resp->toks[n].len - 1;
881}
882
883static u64 response_get_u64(const struct parsed_resp *resp, int n)
884{
885 if (!resp) {
886 pr_err("Response is NULL\n");
887 return 0;
888 }
889
890 if (n > resp->num) {
891 pr_err("Response has %d tokens. Can't access %d\n",
892 resp->num, n);
893 return 0;
894 }
895
896 if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) {
897 pr_err("Token is not unsigned it: %d\n",
898 resp->toks[n].type);
899 return 0;
900 }
901
902 if (!(resp->toks[n].width == OPAL_WIDTH_TINY ||
903 resp->toks[n].width == OPAL_WIDTH_SHORT)) {
904 pr_err("Atom is not short or tiny: %d\n",
905 resp->toks[n].width);
906 return 0;
907 }
908
909 return resp->toks[n].stored.u;
910}
911
Jon Derrickcccb9242017-02-21 11:59:14 -0700912static bool response_token_matches(const struct opal_resp_tok *token, u8 match)
913{
914 if (IS_ERR(token) ||
915 token->type != OPAL_DTA_TOKENID_TOKEN ||
916 token->pos[0] != match)
917 return false;
918 return true;
919}
920
Scott Bauer455a7b22017-02-03 12:50:31 -0700921static u8 response_status(const struct parsed_resp *resp)
922{
Jon Derrickcccb9242017-02-21 11:59:14 -0700923 const struct opal_resp_tok *tok;
924
925 tok = response_get_token(resp, 0);
926 if (response_token_matches(tok, OPAL_ENDOFSESSION))
Scott Bauer455a7b22017-02-03 12:50:31 -0700927 return 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700928
929 if (resp->num < 5)
930 return DTAERROR_NO_METHOD_STATUS;
931
Jon Derrickcccb9242017-02-21 11:59:14 -0700932 tok = response_get_token(resp, resp->num - 5);
933 if (!response_token_matches(tok, OPAL_STARTLIST))
934 return DTAERROR_NO_METHOD_STATUS;
935
936 tok = response_get_token(resp, resp->num - 1);
937 if (!response_token_matches(tok, OPAL_ENDLIST))
Scott Bauer455a7b22017-02-03 12:50:31 -0700938 return DTAERROR_NO_METHOD_STATUS;
939
940 return response_get_u64(resp, resp->num - 4);
941}
942
943/* Parses and checks for errors */
944static int parse_and_check_status(struct opal_dev *dev)
945{
946 int error;
947
948 print_buffer(dev->cmd, dev->pos);
949
950 error = response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed);
951 if (error) {
952 pr_err("Couldn't parse response.\n");
953 return error;
954 }
955
956 return response_status(&dev->parsed);
957}
958
959static void clear_opal_cmd(struct opal_dev *dev)
960{
961 dev->pos = sizeof(struct opal_header);
962 memset(dev->cmd, 0, IO_BUFFER_LENGTH);
963}
964
965static int start_opal_session_cont(struct opal_dev *dev)
966{
967 u32 hsn, tsn;
968 int error = 0;
969
970 error = parse_and_check_status(dev);
971 if (error)
972 return error;
973
974 hsn = response_get_u64(&dev->parsed, 4);
975 tsn = response_get_u64(&dev->parsed, 5);
976
977 if (hsn == 0 && tsn == 0) {
978 pr_err("Couldn't authenticate session\n");
979 return -EPERM;
980 }
981
982 dev->hsn = hsn;
983 dev->tsn = tsn;
984 return 0;
985}
986
987static void add_suspend_info(struct opal_dev *dev,
988 struct opal_suspend_data *sus)
989{
990 struct opal_suspend_data *iter;
991
992 list_for_each_entry(iter, &dev->unlk_lst, node) {
993 if (iter->lr == sus->lr) {
994 list_del(&iter->node);
995 kfree(iter);
996 break;
997 }
998 }
999 list_add_tail(&sus->node, &dev->unlk_lst);
1000}
1001
1002static int end_session_cont(struct opal_dev *dev)
1003{
1004 dev->hsn = 0;
1005 dev->tsn = 0;
1006 return parse_and_check_status(dev);
1007}
1008
1009static int finalize_and_send(struct opal_dev *dev, cont_fn cont)
1010{
1011 int ret;
1012
1013 ret = cmd_finalize(dev, dev->hsn, dev->tsn);
1014 if (ret) {
1015 pr_err("Error finalizing command buffer: %d\n", ret);
1016 return ret;
1017 }
1018
1019 print_buffer(dev->cmd, dev->pos);
1020
1021 return opal_send_recv(dev, cont);
1022}
1023
Jon Derrickeed64952017-02-22 07:55:13 -07001024static int gen_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001025{
1026 const u8 *method;
1027 u8 uid[OPAL_UID_LENGTH];
1028 int err = 0;
1029
1030 clear_opal_cmd(dev);
1031 set_comid(dev, dev->comid);
1032
1033 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
1034 method = opalmethod[OPAL_GENKEY];
1035 kfree(dev->prev_data);
1036 dev->prev_data = NULL;
1037
1038 add_token_u8(&err, dev, OPAL_CALL);
1039 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1040 add_token_bytestring(&err, dev, opalmethod[OPAL_GENKEY],
1041 OPAL_UID_LENGTH);
1042 add_token_u8(&err, dev, OPAL_STARTLIST);
1043 add_token_u8(&err, dev, OPAL_ENDLIST);
1044
1045 if (err) {
1046 pr_err("Error building gen key command\n");
1047 return err;
1048
1049 }
1050 return finalize_and_send(dev, parse_and_check_status);
1051}
1052
1053static int get_active_key_cont(struct opal_dev *dev)
1054{
1055 const char *activekey;
1056 size_t keylen;
1057 int error = 0;
1058
1059 error = parse_and_check_status(dev);
1060 if (error)
1061 return error;
1062 keylen = response_get_string(&dev->parsed, 4, &activekey);
1063 if (!activekey) {
1064 pr_err("%s: Couldn't extract the Activekey from the response\n",
1065 __func__);
1066 return OPAL_INVAL_PARAM;
1067 }
1068 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1069
1070 if (!dev->prev_data)
1071 return -ENOMEM;
1072
1073 dev->prev_d_len = keylen;
1074
1075 return 0;
1076}
1077
Jon Derrickeed64952017-02-22 07:55:13 -07001078static int get_active_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001079{
1080 u8 uid[OPAL_UID_LENGTH];
1081 int err = 0;
Jon Derrickeed64952017-02-22 07:55:13 -07001082 u8 *lr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001083
1084 clear_opal_cmd(dev);
1085 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001086
1087 err = build_locking_range(uid, sizeof(uid), *lr);
1088 if (err)
1089 return err;
1090
1091 err = 0;
1092 add_token_u8(&err, dev, OPAL_CALL);
1093 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1094 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1095 add_token_u8(&err, dev, OPAL_STARTLIST);
1096 add_token_u8(&err, dev, OPAL_STARTLIST);
1097 add_token_u8(&err, dev, OPAL_STARTNAME);
1098 add_token_u8(&err, dev, 3); /* startCloumn */
1099 add_token_u8(&err, dev, 10); /* ActiveKey */
1100 add_token_u8(&err, dev, OPAL_ENDNAME);
1101 add_token_u8(&err, dev, OPAL_STARTNAME);
1102 add_token_u8(&err, dev, 4); /* endColumn */
1103 add_token_u8(&err, dev, 10); /* ActiveKey */
1104 add_token_u8(&err, dev, OPAL_ENDNAME);
1105 add_token_u8(&err, dev, OPAL_ENDLIST);
1106 add_token_u8(&err, dev, OPAL_ENDLIST);
1107 if (err) {
1108 pr_err("Error building get active key command\n");
1109 return err;
1110 }
1111
1112 return finalize_and_send(dev, get_active_key_cont);
1113}
1114
1115static int generic_lr_enable_disable(struct opal_dev *dev,
1116 u8 *uid, bool rle, bool wle,
1117 bool rl, bool wl)
1118{
1119 int err = 0;
1120
1121 add_token_u8(&err, dev, OPAL_CALL);
1122 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1123 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1124
1125 add_token_u8(&err, dev, OPAL_STARTLIST);
1126 add_token_u8(&err, dev, OPAL_STARTNAME);
1127 add_token_u8(&err, dev, OPAL_VALUES);
1128 add_token_u8(&err, dev, OPAL_STARTLIST);
1129
1130 add_token_u8(&err, dev, OPAL_STARTNAME);
1131 add_token_u8(&err, dev, 5); /* ReadLockEnabled */
1132 add_token_u8(&err, dev, rle);
1133 add_token_u8(&err, dev, OPAL_ENDNAME);
1134
1135 add_token_u8(&err, dev, OPAL_STARTNAME);
1136 add_token_u8(&err, dev, 6); /* WriteLockEnabled */
1137 add_token_u8(&err, dev, wle);
1138 add_token_u8(&err, dev, OPAL_ENDNAME);
1139
1140 add_token_u8(&err, dev, OPAL_STARTNAME);
1141 add_token_u8(&err, dev, OPAL_READLOCKED);
1142 add_token_u8(&err, dev, rl);
1143 add_token_u8(&err, dev, OPAL_ENDNAME);
1144
1145 add_token_u8(&err, dev, OPAL_STARTNAME);
1146 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1147 add_token_u8(&err, dev, wl);
1148 add_token_u8(&err, dev, OPAL_ENDNAME);
1149
1150 add_token_u8(&err, dev, OPAL_ENDLIST);
1151 add_token_u8(&err, dev, OPAL_ENDNAME);
1152 add_token_u8(&err, dev, OPAL_ENDLIST);
1153 return err;
1154}
1155
1156static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1157 struct opal_user_lr_setup *setup)
1158{
1159 int err;
1160
1161 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1162 0, 0);
1163 if (err)
1164 pr_err("Failed to create enable global lr command\n");
1165 return err;
1166}
1167
Jon Derrickeed64952017-02-22 07:55:13 -07001168static int setup_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001169{
1170 u8 uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001171 struct opal_user_lr_setup *setup = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001172 u8 lr;
1173 int err = 0;
1174
1175 clear_opal_cmd(dev);
1176 set_comid(dev, dev->comid);
1177
Scott Bauer455a7b22017-02-03 12:50:31 -07001178 lr = setup->session.opal_key.lr;
1179 err = build_locking_range(uid, sizeof(uid), lr);
1180 if (err)
1181 return err;
1182
1183 if (lr == 0)
1184 err = enable_global_lr(dev, uid, setup);
1185 else {
1186 add_token_u8(&err, dev, OPAL_CALL);
1187 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1188 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1189 OPAL_UID_LENGTH);
1190
1191 add_token_u8(&err, dev, OPAL_STARTLIST);
1192 add_token_u8(&err, dev, OPAL_STARTNAME);
1193 add_token_u8(&err, dev, OPAL_VALUES);
1194 add_token_u8(&err, dev, OPAL_STARTLIST);
1195
1196 add_token_u8(&err, dev, OPAL_STARTNAME);
1197 add_token_u8(&err, dev, 3); /* Ranges Start */
1198 add_token_u64(&err, dev, setup->range_start);
1199 add_token_u8(&err, dev, OPAL_ENDNAME);
1200
1201 add_token_u8(&err, dev, OPAL_STARTNAME);
1202 add_token_u8(&err, dev, 4); /* Ranges length */
1203 add_token_u64(&err, dev, setup->range_length);
1204 add_token_u8(&err, dev, OPAL_ENDNAME);
1205
1206 add_token_u8(&err, dev, OPAL_STARTNAME);
1207 add_token_u8(&err, dev, 5); /*ReadLockEnabled */
1208 add_token_u64(&err, dev, !!setup->RLE);
1209 add_token_u8(&err, dev, OPAL_ENDNAME);
1210
1211 add_token_u8(&err, dev, OPAL_STARTNAME);
1212 add_token_u8(&err, dev, 6); /*WriteLockEnabled*/
1213 add_token_u64(&err, dev, !!setup->WLE);
1214 add_token_u8(&err, dev, OPAL_ENDNAME);
1215
1216 add_token_u8(&err, dev, OPAL_ENDLIST);
1217 add_token_u8(&err, dev, OPAL_ENDNAME);
1218 add_token_u8(&err, dev, OPAL_ENDLIST);
1219
1220 }
1221 if (err) {
1222 pr_err("Error building Setup Locking range command.\n");
1223 return err;
1224
1225 }
1226
1227 return finalize_and_send(dev, parse_and_check_status);
1228}
1229
1230static int start_generic_opal_session(struct opal_dev *dev,
1231 enum opal_uid auth,
1232 enum opal_uid sp_type,
1233 const char *key,
1234 u8 key_len)
1235{
1236 u32 hsn;
1237 int err = 0;
1238
1239 if (key == NULL && auth != OPAL_ANYBODY_UID) {
1240 pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \
1241 "Challenge, and not as the Anybody UID\n", __func__);
1242 return OPAL_INVAL_PARAM;
1243 }
1244
1245 clear_opal_cmd(dev);
1246
1247 set_comid(dev, dev->comid);
1248 hsn = GENERIC_HOST_SESSION_NUM;
1249
1250 add_token_u8(&err, dev, OPAL_CALL);
1251 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1252 OPAL_UID_LENGTH);
1253 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1254 OPAL_UID_LENGTH);
1255 add_token_u8(&err, dev, OPAL_STARTLIST);
1256 add_token_u64(&err, dev, hsn);
1257 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1258 add_token_u8(&err, dev, 1);
1259
1260 switch (auth) {
1261 case OPAL_ANYBODY_UID:
1262 add_token_u8(&err, dev, OPAL_ENDLIST);
1263 break;
1264 case OPAL_ADMIN1_UID:
1265 case OPAL_SID_UID:
1266 add_token_u8(&err, dev, OPAL_STARTNAME);
1267 add_token_u8(&err, dev, 0); /* HostChallenge */
1268 add_token_bytestring(&err, dev, key, key_len);
1269 add_token_u8(&err, dev, OPAL_ENDNAME);
1270 add_token_u8(&err, dev, OPAL_STARTNAME);
1271 add_token_u8(&err, dev, 3); /* HostSignAuth */
1272 add_token_bytestring(&err, dev, opaluid[auth],
1273 OPAL_UID_LENGTH);
1274 add_token_u8(&err, dev, OPAL_ENDNAME);
1275 add_token_u8(&err, dev, OPAL_ENDLIST);
1276 break;
1277 default:
1278 pr_err("Cannot start Admin SP session with auth %d\n", auth);
1279 return OPAL_INVAL_PARAM;
1280 }
1281
1282 if (err) {
1283 pr_err("Error building start adminsp session command.\n");
1284 return err;
1285 }
1286
1287 return finalize_and_send(dev, start_opal_session_cont);
1288}
1289
Jon Derrickeed64952017-02-22 07:55:13 -07001290static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001291{
1292 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1293 OPAL_ADMINSP_UID, NULL, 0);
1294}
1295
Jon Derrickeed64952017-02-22 07:55:13 -07001296static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001297{
1298 int ret;
1299 const u8 *key = dev->prev_data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001300
1301 if (!key) {
Jon Derrickeed64952017-02-22 07:55:13 -07001302 const struct opal_key *okey = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001303 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1304 OPAL_ADMINSP_UID,
1305 okey->key,
1306 okey->key_len);
1307 } else {
1308 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1309 OPAL_ADMINSP_UID,
1310 key, dev->prev_d_len);
1311 kfree(key);
1312 dev->prev_data = NULL;
1313 }
1314 return ret;
1315}
1316
Jon Derrickeed64952017-02-22 07:55:13 -07001317static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001318{
Jon Derrickeed64952017-02-22 07:55:13 -07001319 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001320 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1321 OPAL_LOCKINGSP_UID,
1322 key->key, key->key_len);
1323}
1324
Jon Derrickeed64952017-02-22 07:55:13 -07001325static int start_auth_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001326{
Jon Derrickeed64952017-02-22 07:55:13 -07001327 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001328 u8 lk_ul_user[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001329 size_t keylen = session->opal_key.key_len;
Scott Bauer455a7b22017-02-03 12:50:31 -07001330 int err = 0;
1331
Scott Bauer455a7b22017-02-03 12:50:31 -07001332 u8 *key = session->opal_key.key;
1333 u32 hsn = GENERIC_HOST_SESSION_NUM;
1334
1335 clear_opal_cmd(dev);
1336 set_comid(dev, dev->comid);
1337
1338 if (session->sum) {
1339 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1340 session->opal_key.lr);
1341 if (err)
1342 return err;
1343
1344 } else if (session->who != OPAL_ADMIN1 && !session->sum) {
1345 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1346 session->who - 1);
1347 if (err)
1348 return err;
1349 } else
1350 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1351
1352 add_token_u8(&err, dev, OPAL_CALL);
1353 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1354 OPAL_UID_LENGTH);
1355 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1356 OPAL_UID_LENGTH);
1357
1358 add_token_u8(&err, dev, OPAL_STARTLIST);
1359 add_token_u64(&err, dev, hsn);
1360 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1361 OPAL_UID_LENGTH);
1362 add_token_u8(&err, dev, 1);
1363 add_token_u8(&err, dev, OPAL_STARTNAME);
1364 add_token_u8(&err, dev, 0);
1365 add_token_bytestring(&err, dev, key, keylen);
1366 add_token_u8(&err, dev, OPAL_ENDNAME);
1367 add_token_u8(&err, dev, OPAL_STARTNAME);
1368 add_token_u8(&err, dev, 3);
1369 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1370 add_token_u8(&err, dev, OPAL_ENDNAME);
1371 add_token_u8(&err, dev, OPAL_ENDLIST);
1372
1373 if (err) {
1374 pr_err("Error building STARTSESSION command.\n");
1375 return err;
1376 }
1377
1378 return finalize_and_send(dev, start_opal_session_cont);
1379}
1380
Jon Derrickeed64952017-02-22 07:55:13 -07001381static int revert_tper(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001382{
1383 int err = 0;
1384
1385 clear_opal_cmd(dev);
1386 set_comid(dev, dev->comid);
1387
1388 add_token_u8(&err, dev, OPAL_CALL);
1389 add_token_bytestring(&err, dev, opaluid[OPAL_ADMINSP_UID],
1390 OPAL_UID_LENGTH);
1391 add_token_bytestring(&err, dev, opalmethod[OPAL_REVERT],
1392 OPAL_UID_LENGTH);
1393 add_token_u8(&err, dev, OPAL_STARTLIST);
1394 add_token_u8(&err, dev, OPAL_ENDLIST);
1395 if (err) {
1396 pr_err("Error building REVERT TPER command.\n");
1397 return err;
1398 }
1399
1400 return finalize_and_send(dev, parse_and_check_status);
1401}
1402
Jon Derrickeed64952017-02-22 07:55:13 -07001403static int internal_activate_user(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001404{
Jon Derrickeed64952017-02-22 07:55:13 -07001405 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001406 u8 uid[OPAL_UID_LENGTH];
1407 int err = 0;
1408
1409 clear_opal_cmd(dev);
1410 set_comid(dev, dev->comid);
1411
1412 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1413 uid[7] = session->who;
1414
1415 add_token_u8(&err, dev, OPAL_CALL);
1416 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1417 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1418 add_token_u8(&err, dev, OPAL_STARTLIST);
1419 add_token_u8(&err, dev, OPAL_STARTNAME);
1420 add_token_u8(&err, dev, OPAL_VALUES);
1421 add_token_u8(&err, dev, OPAL_STARTLIST);
1422 add_token_u8(&err, dev, OPAL_STARTNAME);
1423 add_token_u8(&err, dev, 5); /* Enabled */
1424 add_token_u8(&err, dev, OPAL_TRUE);
1425 add_token_u8(&err, dev, OPAL_ENDNAME);
1426 add_token_u8(&err, dev, OPAL_ENDLIST);
1427 add_token_u8(&err, dev, OPAL_ENDNAME);
1428 add_token_u8(&err, dev, OPAL_ENDLIST);
1429
1430 if (err) {
1431 pr_err("Error building Activate UserN command.\n");
1432 return err;
1433 }
1434
1435 return finalize_and_send(dev, parse_and_check_status);
1436}
1437
Jon Derrickeed64952017-02-22 07:55:13 -07001438static int erase_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001439{
Jon Derrickeed64952017-02-22 07:55:13 -07001440 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001441 u8 uid[OPAL_UID_LENGTH];
1442 int err = 0;
1443
1444 clear_opal_cmd(dev);
1445 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001446
1447 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1448 return -ERANGE;
1449
1450 add_token_u8(&err, dev, OPAL_CALL);
1451 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1452 add_token_bytestring(&err, dev, opalmethod[OPAL_ERASE],
1453 OPAL_UID_LENGTH);
1454 add_token_u8(&err, dev, OPAL_STARTLIST);
1455 add_token_u8(&err, dev, OPAL_ENDLIST);
1456
1457 if (err) {
1458 pr_err("Error building Erase Locking Range Command.\n");
1459 return err;
1460 }
1461 return finalize_and_send(dev, parse_and_check_status);
1462}
1463
Jon Derrickeed64952017-02-22 07:55:13 -07001464static int set_mbr_done(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001465{
Jon Derrickeed64952017-02-22 07:55:13 -07001466 u8 *mbr_done_tf = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001467 int err = 0;
1468
1469 clear_opal_cmd(dev);
1470 set_comid(dev, dev->comid);
1471
1472 add_token_u8(&err, dev, OPAL_CALL);
1473 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1474 OPAL_UID_LENGTH);
1475 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1476 add_token_u8(&err, dev, OPAL_STARTLIST);
1477 add_token_u8(&err, dev, OPAL_STARTNAME);
1478 add_token_u8(&err, dev, OPAL_VALUES);
1479 add_token_u8(&err, dev, OPAL_STARTLIST);
1480 add_token_u8(&err, dev, OPAL_STARTNAME);
1481 add_token_u8(&err, dev, 2); /* Done */
Jon Derrickeed64952017-02-22 07:55:13 -07001482 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
Scott Bauer455a7b22017-02-03 12:50:31 -07001483 add_token_u8(&err, dev, OPAL_ENDNAME);
1484 add_token_u8(&err, dev, OPAL_ENDLIST);
1485 add_token_u8(&err, dev, OPAL_ENDNAME);
1486 add_token_u8(&err, dev, OPAL_ENDLIST);
1487
1488 if (err) {
1489 pr_err("Error Building set MBR Done command\n");
1490 return err;
1491 }
1492
1493 return finalize_and_send(dev, parse_and_check_status);
1494}
1495
Jon Derrickeed64952017-02-22 07:55:13 -07001496static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001497{
Jon Derrickeed64952017-02-22 07:55:13 -07001498 u8 *mbr_en_dis = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001499 int err = 0;
1500
1501 clear_opal_cmd(dev);
1502 set_comid(dev, dev->comid);
1503
1504 add_token_u8(&err, dev, OPAL_CALL);
1505 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1506 OPAL_UID_LENGTH);
1507 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1508 add_token_u8(&err, dev, OPAL_STARTLIST);
1509 add_token_u8(&err, dev, OPAL_STARTNAME);
1510 add_token_u8(&err, dev, OPAL_VALUES);
1511 add_token_u8(&err, dev, OPAL_STARTLIST);
1512 add_token_u8(&err, dev, OPAL_STARTNAME);
1513 add_token_u8(&err, dev, 1);
Jon Derrickeed64952017-02-22 07:55:13 -07001514 add_token_u8(&err, dev, *mbr_en_dis);
Scott Bauer455a7b22017-02-03 12:50:31 -07001515 add_token_u8(&err, dev, OPAL_ENDNAME);
1516 add_token_u8(&err, dev, OPAL_ENDLIST);
1517 add_token_u8(&err, dev, OPAL_ENDNAME);
1518 add_token_u8(&err, dev, OPAL_ENDLIST);
1519
1520 if (err) {
1521 pr_err("Error Building set MBR done command\n");
1522 return err;
1523 }
1524
1525 return finalize_and_send(dev, parse_and_check_status);
1526}
1527
1528static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1529 struct opal_dev *dev)
1530{
1531 int err = 0;
1532
1533 clear_opal_cmd(dev);
1534 set_comid(dev, dev->comid);
1535
1536 add_token_u8(&err, dev, OPAL_CALL);
1537 add_token_bytestring(&err, dev, cpin_uid, OPAL_UID_LENGTH);
1538 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1539 OPAL_UID_LENGTH);
1540 add_token_u8(&err, dev, OPAL_STARTLIST);
1541 add_token_u8(&err, dev, OPAL_STARTNAME);
1542 add_token_u8(&err, dev, OPAL_VALUES);
1543 add_token_u8(&err, dev, OPAL_STARTLIST);
1544 add_token_u8(&err, dev, OPAL_STARTNAME);
1545 add_token_u8(&err, dev, 3); /* PIN */
1546 add_token_bytestring(&err, dev, key, key_len);
1547 add_token_u8(&err, dev, OPAL_ENDNAME);
1548 add_token_u8(&err, dev, OPAL_ENDLIST);
1549 add_token_u8(&err, dev, OPAL_ENDNAME);
1550 add_token_u8(&err, dev, OPAL_ENDLIST);
1551
1552 return err;
1553}
1554
Jon Derrickeed64952017-02-22 07:55:13 -07001555static int set_new_pw(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001556{
1557 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001558 struct opal_session_info *usr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001559
1560 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1561
1562 if (usr->who != OPAL_ADMIN1) {
1563 cpin_uid[5] = 0x03;
1564 if (usr->sum)
1565 cpin_uid[7] = usr->opal_key.lr + 1;
1566 else
1567 cpin_uid[7] = usr->who;
1568 }
1569
1570 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1571 cpin_uid, dev)) {
1572 pr_err("Error building set password command.\n");
1573 return -ERANGE;
1574 }
1575
1576 return finalize_and_send(dev, parse_and_check_status);
1577}
1578
Jon Derrickeed64952017-02-22 07:55:13 -07001579static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001580{
1581 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001582 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001583
1584 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1585
1586 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
1587 pr_err("Error building Set SID cpin\n");
1588 return -ERANGE;
1589 }
1590 return finalize_and_send(dev, parse_and_check_status);
1591}
1592
Jon Derrickeed64952017-02-22 07:55:13 -07001593static int add_user_to_lr(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001594{
1595 u8 lr_buffer[OPAL_UID_LENGTH];
1596 u8 user_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001597 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001598 int err = 0;
1599
1600 clear_opal_cmd(dev);
1601 set_comid(dev, dev->comid);
1602
Scott Bauer455a7b22017-02-03 12:50:31 -07001603 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1604 OPAL_UID_LENGTH);
1605
1606 if (lkul->l_state == OPAL_RW)
1607 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1608 OPAL_UID_LENGTH);
1609
1610 lr_buffer[7] = lkul->session.opal_key.lr;
1611
1612 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1613
1614 user_uid[7] = lkul->session.who;
1615
1616 add_token_u8(&err, dev, OPAL_CALL);
1617 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1618 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1619 OPAL_UID_LENGTH);
1620
1621 add_token_u8(&err, dev, OPAL_STARTLIST);
1622 add_token_u8(&err, dev, OPAL_STARTNAME);
1623 add_token_u8(&err, dev, OPAL_VALUES);
1624
1625 add_token_u8(&err, dev, OPAL_STARTLIST);
1626 add_token_u8(&err, dev, OPAL_STARTNAME);
1627 add_token_u8(&err, dev, 3);
1628
1629 add_token_u8(&err, dev, OPAL_STARTLIST);
1630
1631
1632 add_token_u8(&err, dev, OPAL_STARTNAME);
1633 add_token_bytestring(&err, dev,
1634 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1635 OPAL_UID_LENGTH/2);
1636 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1637 add_token_u8(&err, dev, OPAL_ENDNAME);
1638
1639
1640 add_token_u8(&err, dev, OPAL_STARTNAME);
1641 add_token_bytestring(&err, dev,
1642 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1643 OPAL_UID_LENGTH/2);
1644 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1645 add_token_u8(&err, dev, OPAL_ENDNAME);
1646
1647
1648 add_token_u8(&err, dev, OPAL_STARTNAME);
1649 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1650 OPAL_UID_LENGTH/2);
1651 add_token_u8(&err, dev, 1);
1652 add_token_u8(&err, dev, OPAL_ENDNAME);
1653
1654
1655 add_token_u8(&err, dev, OPAL_ENDLIST);
1656 add_token_u8(&err, dev, OPAL_ENDNAME);
1657 add_token_u8(&err, dev, OPAL_ENDLIST);
1658 add_token_u8(&err, dev, OPAL_ENDNAME);
1659 add_token_u8(&err, dev, OPAL_ENDLIST);
1660
1661 if (err) {
1662 pr_err("Error building add user to locking range command.\n");
1663 return err;
1664 }
1665
1666 return finalize_and_send(dev, parse_and_check_status);
1667}
1668
Jon Derrickeed64952017-02-22 07:55:13 -07001669static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001670{
1671 u8 lr_buffer[OPAL_UID_LENGTH];
1672 const u8 *method;
Jon Derrickeed64952017-02-22 07:55:13 -07001673 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001674 u8 read_locked = 1, write_locked = 1;
1675 int err = 0;
1676
1677 clear_opal_cmd(dev);
1678 set_comid(dev, dev->comid);
1679
1680 method = opalmethod[OPAL_SET];
Scott Bauer455a7b22017-02-03 12:50:31 -07001681 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1682 lkul->session.opal_key.lr) < 0)
1683 return -ERANGE;
1684
1685 switch (lkul->l_state) {
1686 case OPAL_RO:
1687 read_locked = 0;
1688 write_locked = 1;
1689 break;
1690 case OPAL_RW:
1691 read_locked = 0;
1692 write_locked = 0;
1693 break;
1694 case OPAL_LK:
1695 /* vars are initalized to locked */
1696 break;
1697 default:
1698 pr_err("Tried to set an invalid locking state... returning to uland\n");
1699 return OPAL_INVAL_PARAM;
1700 }
1701
1702 add_token_u8(&err, dev, OPAL_CALL);
1703 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1704 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1705 add_token_u8(&err, dev, OPAL_STARTLIST);
1706 add_token_u8(&err, dev, OPAL_STARTNAME);
1707 add_token_u8(&err, dev, OPAL_VALUES);
1708 add_token_u8(&err, dev, OPAL_STARTLIST);
1709
1710 add_token_u8(&err, dev, OPAL_STARTNAME);
1711 add_token_u8(&err, dev, OPAL_READLOCKED);
1712 add_token_u8(&err, dev, read_locked);
1713 add_token_u8(&err, dev, OPAL_ENDNAME);
1714
1715 add_token_u8(&err, dev, OPAL_STARTNAME);
1716 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1717 add_token_u8(&err, dev, write_locked);
1718 add_token_u8(&err, dev, OPAL_ENDNAME);
1719
1720 add_token_u8(&err, dev, OPAL_ENDLIST);
1721 add_token_u8(&err, dev, OPAL_ENDNAME);
1722 add_token_u8(&err, dev, OPAL_ENDLIST);
1723
1724 if (err) {
1725 pr_err("Error building SET command.\n");
1726 return err;
1727 }
1728 return finalize_and_send(dev, parse_and_check_status);
1729}
1730
1731
Jon Derrickeed64952017-02-22 07:55:13 -07001732static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001733{
1734 u8 lr_buffer[OPAL_UID_LENGTH];
1735 u8 read_locked = 1, write_locked = 1;
1736 const u8 *method;
Jon Derrickeed64952017-02-22 07:55:13 -07001737 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001738 int ret;
1739
1740 clear_opal_cmd(dev);
1741 set_comid(dev, dev->comid);
1742
1743 method = opalmethod[OPAL_SET];
Scott Bauer455a7b22017-02-03 12:50:31 -07001744 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1745 lkul->session.opal_key.lr) < 0)
1746 return -ERANGE;
1747
1748 switch (lkul->l_state) {
1749 case OPAL_RO:
1750 read_locked = 0;
1751 write_locked = 1;
1752 break;
1753 case OPAL_RW:
1754 read_locked = 0;
1755 write_locked = 0;
1756 break;
1757 case OPAL_LK:
1758 /* vars are initalized to locked */
1759 break;
1760 default:
1761 pr_err("Tried to set an invalid locking state.\n");
1762 return OPAL_INVAL_PARAM;
1763 }
1764 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1765 read_locked, write_locked);
1766
1767 if (ret < 0) {
1768 pr_err("Error building SET command.\n");
1769 return ret;
1770 }
1771 return finalize_and_send(dev, parse_and_check_status);
1772}
1773
Jon Derrickeed64952017-02-22 07:55:13 -07001774static int activate_lsp(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001775{
Jon Derrickeed64952017-02-22 07:55:13 -07001776 struct opal_lr_act *opal_act = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001777 u8 user_lr[OPAL_UID_LENGTH];
1778 u8 uint_3 = 0x83;
1779 int err = 0, i;
1780
1781 clear_opal_cmd(dev);
1782 set_comid(dev, dev->comid);
1783
Scott Bauer455a7b22017-02-03 12:50:31 -07001784 add_token_u8(&err, dev, OPAL_CALL);
1785 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1786 OPAL_UID_LENGTH);
1787 add_token_bytestring(&err, dev, opalmethod[OPAL_ACTIVATE],
1788 OPAL_UID_LENGTH);
1789
1790
1791 if (opal_act->sum) {
1792 err = build_locking_range(user_lr, sizeof(user_lr),
1793 opal_act->lr[0]);
1794 if (err)
1795 return err;
1796
1797 add_token_u8(&err, dev, OPAL_STARTLIST);
1798 add_token_u8(&err, dev, OPAL_STARTNAME);
1799 add_token_u8(&err, dev, uint_3);
1800 add_token_u8(&err, dev, 6);
1801 add_token_u8(&err, dev, 0);
1802 add_token_u8(&err, dev, 0);
1803
1804 add_token_u8(&err, dev, OPAL_STARTLIST);
1805 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1806 for (i = 1; i < opal_act->num_lrs; i++) {
1807 user_lr[7] = opal_act->lr[i];
1808 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1809 }
1810 add_token_u8(&err, dev, OPAL_ENDLIST);
1811 add_token_u8(&err, dev, OPAL_ENDNAME);
1812 add_token_u8(&err, dev, OPAL_ENDLIST);
1813
1814 } else {
1815 add_token_u8(&err, dev, OPAL_STARTLIST);
1816 add_token_u8(&err, dev, OPAL_ENDLIST);
1817 }
1818
1819 if (err) {
1820 pr_err("Error building Activate LockingSP command.\n");
1821 return err;
1822 }
1823
1824 return finalize_and_send(dev, parse_and_check_status);
1825}
1826
1827static int get_lsp_lifecycle_cont(struct opal_dev *dev)
1828{
1829 u8 lc_status;
1830 int error = 0;
1831
1832 error = parse_and_check_status(dev);
1833 if (error)
1834 return error;
1835
1836 lc_status = response_get_u64(&dev->parsed, 4);
1837 /* 0x08 is Manufacured Inactive */
1838 /* 0x09 is Manufactured */
1839 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
1840 pr_err("Couldn't determine the status of the Lifcycle state\n");
1841 return -ENODEV;
1842 }
1843
1844 return 0;
1845}
1846
1847/* Determine if we're in the Manufactured Inactive or Active state */
Jon Derrickeed64952017-02-22 07:55:13 -07001848static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001849{
1850 int err = 0;
1851
1852 clear_opal_cmd(dev);
1853 set_comid(dev, dev->comid);
1854
1855 add_token_u8(&err, dev, OPAL_CALL);
1856 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1857 OPAL_UID_LENGTH);
1858 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1859
1860 add_token_u8(&err, dev, OPAL_STARTLIST);
1861 add_token_u8(&err, dev, OPAL_STARTLIST);
1862
1863 add_token_u8(&err, dev, OPAL_STARTNAME);
1864 add_token_u8(&err, dev, 3); /* Start Column */
1865 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1866 add_token_u8(&err, dev, OPAL_ENDNAME);
1867
1868 add_token_u8(&err, dev, OPAL_STARTNAME);
1869 add_token_u8(&err, dev, 4); /* End Column */
1870 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1871 add_token_u8(&err, dev, OPAL_ENDNAME);
1872
1873 add_token_u8(&err, dev, OPAL_ENDLIST);
1874 add_token_u8(&err, dev, OPAL_ENDLIST);
1875
1876 if (err) {
1877 pr_err("Error Building GET Lifecycle Status command\n");
1878 return err;
1879 }
1880
1881 return finalize_and_send(dev, get_lsp_lifecycle_cont);
1882}
1883
1884static int get_msid_cpin_pin_cont(struct opal_dev *dev)
1885{
1886 const char *msid_pin;
1887 size_t strlen;
1888 int error = 0;
1889
1890 error = parse_and_check_status(dev);
1891 if (error)
1892 return error;
1893
1894 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1895 if (!msid_pin) {
1896 pr_err("%s: Couldn't extract PIN from response\n", __func__);
1897 return OPAL_INVAL_PARAM;
1898 }
1899
1900 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1901 if (!dev->prev_data)
1902 return -ENOMEM;
1903
1904 dev->prev_d_len = strlen;
1905
1906 return 0;
1907}
1908
Jon Derrickeed64952017-02-22 07:55:13 -07001909static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001910{
1911 int err = 0;
1912
1913 clear_opal_cmd(dev);
1914 set_comid(dev, dev->comid);
1915
Scott Bauer455a7b22017-02-03 12:50:31 -07001916 add_token_u8(&err, dev, OPAL_CALL);
1917 add_token_bytestring(&err, dev, opaluid[OPAL_C_PIN_MSID],
1918 OPAL_UID_LENGTH);
1919 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1920
1921 add_token_u8(&err, dev, OPAL_STARTLIST);
1922 add_token_u8(&err, dev, OPAL_STARTLIST);
1923
1924 add_token_u8(&err, dev, OPAL_STARTNAME);
1925 add_token_u8(&err, dev, 3); /* Start Column */
1926 add_token_u8(&err, dev, 3); /* PIN */
1927 add_token_u8(&err, dev, OPAL_ENDNAME);
1928
1929 add_token_u8(&err, dev, OPAL_STARTNAME);
1930 add_token_u8(&err, dev, 4); /* End Column */
1931 add_token_u8(&err, dev, 3); /* Lifecycle Column */
1932 add_token_u8(&err, dev, OPAL_ENDNAME);
1933
1934 add_token_u8(&err, dev, OPAL_ENDLIST);
1935 add_token_u8(&err, dev, OPAL_ENDLIST);
1936
1937 if (err) {
1938 pr_err("Error building Get MSID CPIN PIN command.\n");
1939 return err;
1940 }
1941
1942 return finalize_and_send(dev, get_msid_cpin_pin_cont);
1943}
1944
Jon Derrickeed64952017-02-22 07:55:13 -07001945static int end_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001946{
1947 int err = 0;
1948
1949 clear_opal_cmd(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07001950 set_comid(dev, dev->comid);
1951 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
Scott Bauer455a7b22017-02-03 12:50:31 -07001952
Jon Derrickeed64952017-02-22 07:55:13 -07001953 if (err < 0)
1954 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001955 return finalize_and_send(dev, end_session_cont);
1956}
1957
1958static int end_opal_session_error(struct opal_dev *dev)
1959{
Jon Derrickeed64952017-02-22 07:55:13 -07001960 const struct opal_step error_end_session[] = {
1961 { end_opal_session, },
1962 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07001963 };
Jon Derrickeed64952017-02-22 07:55:13 -07001964 dev->steps = error_end_session;
Scott Bauer455a7b22017-02-03 12:50:31 -07001965 return next(dev);
1966}
1967
1968static inline void setup_opal_dev(struct opal_dev *dev,
Jon Derrickeed64952017-02-22 07:55:13 -07001969 const struct opal_step *steps)
Scott Bauer455a7b22017-02-03 12:50:31 -07001970{
Jon Derrickeed64952017-02-22 07:55:13 -07001971 dev->steps = steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07001972 dev->tsn = 0;
1973 dev->hsn = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -07001974 dev->prev_data = NULL;
1975}
1976
1977static int check_opal_support(struct opal_dev *dev)
1978{
Jon Derrickeed64952017-02-22 07:55:13 -07001979 const struct opal_step steps[] = {
1980 { opal_discovery0, },
1981 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07001982 };
1983 int ret;
1984
1985 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07001986 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07001987 ret = next(dev);
1988 dev->supported = !ret;
1989 mutex_unlock(&dev->dev_lock);
1990 return ret;
1991}
1992
Scott Bauer7d6d1572017-02-22 10:15:06 -07001993static void clean_opal_dev(struct opal_dev *dev)
1994{
1995
1996 struct opal_suspend_data *suspend, *next;
1997
1998 mutex_lock(&dev->dev_lock);
1999 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
2000 list_del(&suspend->node);
2001 kfree(suspend);
2002 }
2003 mutex_unlock(&dev->dev_lock);
2004}
2005
2006void free_opal_dev(struct opal_dev *dev)
2007{
2008 if (!dev)
2009 return;
2010 clean_opal_dev(dev);
2011 kfree(dev);
2012}
2013EXPORT_SYMBOL(free_opal_dev);
2014
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002015struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
Scott Bauer455a7b22017-02-03 12:50:31 -07002016{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002017 struct opal_dev *dev;
2018
2019 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
2020 if (!dev)
2021 return NULL;
2022
2023 INIT_LIST_HEAD(&dev->unlk_lst);
2024 mutex_init(&dev->dev_lock);
2025 dev->data = data;
2026 dev->send_recv = send_recv;
2027 if (check_opal_support(dev) != 0) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +01002028 pr_debug("Opal is not supported on this device\n");
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002029 kfree(dev);
2030 return NULL;
2031 }
2032 return dev;
Scott Bauer455a7b22017-02-03 12:50:31 -07002033}
2034EXPORT_SYMBOL(init_opal_dev);
2035
2036static int opal_secure_erase_locking_range(struct opal_dev *dev,
2037 struct opal_session_info *opal_session)
2038{
Jon Derrickeed64952017-02-22 07:55:13 -07002039 const struct opal_step erase_steps[] = {
2040 { opal_discovery0, },
2041 { start_auth_opal_session, opal_session },
2042 { get_active_key, &opal_session->opal_key.lr },
2043 { gen_key, },
2044 { end_opal_session, },
2045 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002046 };
2047 int ret;
2048
2049 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002050 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002051 ret = next(dev);
2052 mutex_unlock(&dev->dev_lock);
2053 return ret;
2054}
2055
2056static int opal_erase_locking_range(struct opal_dev *dev,
2057 struct opal_session_info *opal_session)
2058{
Jon Derrickeed64952017-02-22 07:55:13 -07002059 const struct opal_step erase_steps[] = {
2060 { opal_discovery0, },
2061 { start_auth_opal_session, opal_session },
2062 { erase_locking_range, opal_session },
2063 { end_opal_session, },
2064 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002065 };
2066 int ret;
2067
2068 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002069 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002070 ret = next(dev);
2071 mutex_unlock(&dev->dev_lock);
2072 return ret;
2073}
2074
2075static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
2076 struct opal_mbr_data *opal_mbr)
2077{
Jon Derrickeed64952017-02-22 07:55:13 -07002078 const struct opal_step mbr_steps[] = {
2079 { opal_discovery0, },
2080 { start_admin1LSP_opal_session, &opal_mbr->key },
2081 { set_mbr_done, &opal_mbr->enable_disable },
2082 { end_opal_session, },
2083 { start_admin1LSP_opal_session, &opal_mbr->key },
2084 { set_mbr_enable_disable, &opal_mbr->enable_disable },
2085 { end_opal_session, },
2086 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002087 };
2088 int ret;
2089
2090 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
2091 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
2092 return -EINVAL;
2093
2094 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002095 setup_opal_dev(dev, mbr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002096 ret = next(dev);
2097 mutex_unlock(&dev->dev_lock);
2098 return ret;
2099}
2100
2101static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2102{
2103 struct opal_suspend_data *suspend;
2104
2105 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
2106 if (!suspend)
2107 return -ENOMEM;
2108
2109 suspend->unlk = *lk_unlk;
2110 suspend->lr = lk_unlk->session.opal_key.lr;
2111
2112 mutex_lock(&dev->dev_lock);
2113 setup_opal_dev(dev, NULL);
2114 add_suspend_info(dev, suspend);
2115 mutex_unlock(&dev->dev_lock);
2116 return 0;
2117}
2118
2119static int opal_add_user_to_lr(struct opal_dev *dev,
2120 struct opal_lock_unlock *lk_unlk)
2121{
Jon Derrickeed64952017-02-22 07:55:13 -07002122 const struct opal_step steps[] = {
2123 { opal_discovery0, },
2124 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2125 { add_user_to_lr, lk_unlk },
2126 { end_opal_session, },
2127 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002128 };
2129 int ret;
2130
2131 if (lk_unlk->l_state != OPAL_RO &&
2132 lk_unlk->l_state != OPAL_RW) {
2133 pr_err("Locking state was not RO or RW\n");
2134 return -EINVAL;
2135 }
2136 if (lk_unlk->session.who < OPAL_USER1 &&
2137 lk_unlk->session.who > OPAL_USER9) {
2138 pr_err("Authority was not within the range of users: %d\n",
2139 lk_unlk->session.who);
2140 return -EINVAL;
2141 }
2142 if (lk_unlk->session.sum) {
2143 pr_err("%s not supported in sum. Use setup locking range\n",
2144 __func__);
2145 return -EINVAL;
2146 }
2147
2148 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002149 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002150 ret = next(dev);
2151 mutex_unlock(&dev->dev_lock);
2152 return ret;
2153}
2154
2155static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal)
2156{
Jon Derrickeed64952017-02-22 07:55:13 -07002157 const struct opal_step revert_steps[] = {
2158 { opal_discovery0, },
2159 { start_SIDASP_opal_session, opal },
2160 { revert_tper, }, /* controller will terminate session */
2161 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002162 };
2163 int ret;
2164
2165 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002166 setup_opal_dev(dev, revert_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002167 ret = next(dev);
2168 mutex_unlock(&dev->dev_lock);
Scott Bauer7d6d1572017-02-22 10:15:06 -07002169
2170 /*
2171 * If we successfully reverted lets clean
2172 * any saved locking ranges.
2173 */
2174 if (!ret)
2175 clean_opal_dev(dev);
2176
Scott Bauer455a7b22017-02-03 12:50:31 -07002177 return ret;
2178}
2179
Jon Derrickeed64952017-02-22 07:55:13 -07002180static int __opal_lock_unlock(struct opal_dev *dev,
2181 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002182{
Jon Derrickeed64952017-02-22 07:55:13 -07002183 const struct opal_step unlock_steps[] = {
2184 { opal_discovery0, },
2185 { start_auth_opal_session, &lk_unlk->session },
2186 { lock_unlock_locking_range, lk_unlk },
2187 { end_opal_session, },
2188 { NULL, }
2189 };
2190 const struct opal_step unlock_sum_steps[] = {
2191 { opal_discovery0, },
2192 { start_auth_opal_session, &lk_unlk->session },
2193 { lock_unlock_locking_range_sum, lk_unlk },
2194 { end_opal_session, },
2195 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002196 };
2197
Jon Derrickeed64952017-02-22 07:55:13 -07002198 dev->steps = lk_unlk->session.sum ? unlock_sum_steps : unlock_steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07002199 return next(dev);
2200}
2201
Jon Derrickeed64952017-02-22 07:55:13 -07002202static int opal_lock_unlock(struct opal_dev *dev,
2203 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002204{
Scott Bauer455a7b22017-02-03 12:50:31 -07002205 int ret;
2206
2207 if (lk_unlk->session.who < OPAL_ADMIN1 ||
2208 lk_unlk->session.who > OPAL_USER9)
2209 return -EINVAL;
2210
2211 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002212 ret = __opal_lock_unlock(dev, lk_unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002213 mutex_unlock(&dev->dev_lock);
2214 return ret;
2215}
2216
2217static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2218{
Jon Derrickeed64952017-02-22 07:55:13 -07002219 const struct opal_step owner_steps[] = {
2220 { opal_discovery0, },
2221 { start_anybodyASP_opal_session, },
2222 { get_msid_cpin_pin, },
2223 { end_opal_session, },
2224 { start_SIDASP_opal_session, opal },
2225 { set_sid_cpin_pin, opal },
2226 { end_opal_session, },
2227 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002228 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002229 int ret;
2230
2231 if (!dev)
2232 return -ENODEV;
2233
2234 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002235 setup_opal_dev(dev, owner_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002236 ret = next(dev);
2237 mutex_unlock(&dev->dev_lock);
2238 return ret;
2239}
2240
2241static int opal_activate_lsp(struct opal_dev *dev, struct opal_lr_act *opal_lr_act)
2242{
Jon Derrickeed64952017-02-22 07:55:13 -07002243 const struct opal_step active_steps[] = {
2244 { opal_discovery0, },
2245 { start_SIDASP_opal_session, &opal_lr_act->key },
2246 { get_lsp_lifecycle, },
2247 { activate_lsp, opal_lr_act },
2248 { end_opal_session, },
2249 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002250 };
2251 int ret;
2252
2253 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2254 return -EINVAL;
2255
2256 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002257 setup_opal_dev(dev, active_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002258 ret = next(dev);
2259 mutex_unlock(&dev->dev_lock);
2260 return ret;
2261}
2262
2263static int opal_setup_locking_range(struct opal_dev *dev,
2264 struct opal_user_lr_setup *opal_lrs)
2265{
Jon Derrickeed64952017-02-22 07:55:13 -07002266 const struct opal_step lr_steps[] = {
2267 { opal_discovery0, },
2268 { start_auth_opal_session, &opal_lrs->session },
2269 { setup_locking_range, opal_lrs },
2270 { end_opal_session, },
2271 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002272 };
2273 int ret;
2274
2275 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002276 setup_opal_dev(dev, lr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002277 ret = next(dev);
2278 mutex_unlock(&dev->dev_lock);
2279 return ret;
2280}
2281
2282static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2283{
Jon Derrickeed64952017-02-22 07:55:13 -07002284 const struct opal_step pw_steps[] = {
2285 { opal_discovery0, },
2286 { start_auth_opal_session, &opal_pw->session },
2287 { set_new_pw, &opal_pw->new_user_pw },
2288 { end_opal_session, },
2289 { NULL }
Scott Bauer455a7b22017-02-03 12:50:31 -07002290 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002291 int ret;
2292
2293 if (opal_pw->session.who < OPAL_ADMIN1 ||
2294 opal_pw->session.who > OPAL_USER9 ||
2295 opal_pw->new_user_pw.who < OPAL_ADMIN1 ||
2296 opal_pw->new_user_pw.who > OPAL_USER9)
2297 return -EINVAL;
2298
2299 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002300 setup_opal_dev(dev, pw_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002301 ret = next(dev);
2302 mutex_unlock(&dev->dev_lock);
2303 return ret;
2304}
2305
2306static int opal_activate_user(struct opal_dev *dev,
2307 struct opal_session_info *opal_session)
2308{
Jon Derrickeed64952017-02-22 07:55:13 -07002309 const struct opal_step act_steps[] = {
2310 { opal_discovery0, },
2311 { start_admin1LSP_opal_session, &opal_session->opal_key },
2312 { internal_activate_user, opal_session },
2313 { end_opal_session, },
2314 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002315 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002316 int ret;
2317
2318 /* We can't activate Admin1 it's active as manufactured */
2319 if (opal_session->who < OPAL_USER1 &&
2320 opal_session->who > OPAL_USER9) {
2321 pr_err("Who was not a valid user: %d\n", opal_session->who);
2322 return -EINVAL;
2323 }
2324
2325 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002326 setup_opal_dev(dev, act_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002327 ret = next(dev);
2328 mutex_unlock(&dev->dev_lock);
2329 return ret;
2330}
2331
2332bool opal_unlock_from_suspend(struct opal_dev *dev)
2333{
2334 struct opal_suspend_data *suspend;
Scott Bauer455a7b22017-02-03 12:50:31 -07002335 bool was_failure = false;
2336 int ret = 0;
2337
2338 if (!dev)
2339 return false;
2340 if (!dev->supported)
2341 return false;
2342
2343 mutex_lock(&dev->dev_lock);
2344 setup_opal_dev(dev, NULL);
Scott Bauer455a7b22017-02-03 12:50:31 -07002345
2346 list_for_each_entry(suspend, &dev->unlk_lst, node) {
Scott Bauer455a7b22017-02-03 12:50:31 -07002347 dev->tsn = 0;
2348 dev->hsn = 0;
2349
Jon Derrickeed64952017-02-22 07:55:13 -07002350 ret = __opal_lock_unlock(dev, &suspend->unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002351 if (ret) {
2352 pr_warn("Failed to unlock LR %hhu with sum %d\n",
2353 suspend->unlk.session.opal_key.lr,
2354 suspend->unlk.session.sum);
2355 was_failure = true;
2356 }
2357 }
2358 mutex_unlock(&dev->dev_lock);
2359 return was_failure;
2360}
2361EXPORT_SYMBOL(opal_unlock_from_suspend);
2362
Scott Bauere225c202017-02-14 17:29:36 -07002363int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
Scott Bauer455a7b22017-02-03 12:50:31 -07002364{
Scott Bauere225c202017-02-14 17:29:36 -07002365 void *p;
2366 int ret = -ENOTTY;
Scott Bauer455a7b22017-02-03 12:50:31 -07002367
2368 if (!capable(CAP_SYS_ADMIN))
2369 return -EACCES;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002370 if (!dev)
2371 return -ENOTSUPP;
Scott Bauer455a7b22017-02-03 12:50:31 -07002372 if (!dev->supported) {
2373 pr_err("Not supported\n");
2374 return -ENOTSUPP;
2375 }
2376
Jon Derrickeed64952017-02-22 07:55:13 -07002377 p = memdup_user(arg, _IOC_SIZE(cmd));
Scott Bauere225c202017-02-14 17:29:36 -07002378 if (IS_ERR(p))
2379 return PTR_ERR(p);
2380
Scott Bauer455a7b22017-02-03 12:50:31 -07002381 switch (cmd) {
Scott Bauere225c202017-02-14 17:29:36 -07002382 case IOC_OPAL_SAVE:
2383 ret = opal_save(dev, p);
2384 break;
2385 case IOC_OPAL_LOCK_UNLOCK:
2386 ret = opal_lock_unlock(dev, p);
2387 break;
2388 case IOC_OPAL_TAKE_OWNERSHIP:
2389 ret = opal_take_ownership(dev, p);
2390 break;
2391 case IOC_OPAL_ACTIVATE_LSP:
2392 ret = opal_activate_lsp(dev, p);
2393 break;
2394 case IOC_OPAL_SET_PW:
2395 ret = opal_set_new_pw(dev, p);
2396 break;
2397 case IOC_OPAL_ACTIVATE_USR:
2398 ret = opal_activate_user(dev, p);
2399 break;
2400 case IOC_OPAL_REVERT_TPR:
2401 ret = opal_reverttper(dev, p);
2402 break;
2403 case IOC_OPAL_LR_SETUP:
2404 ret = opal_setup_locking_range(dev, p);
2405 break;
2406 case IOC_OPAL_ADD_USR_TO_LR:
2407 ret = opal_add_user_to_lr(dev, p);
2408 break;
2409 case IOC_OPAL_ENABLE_DISABLE_MBR:
2410 ret = opal_enable_disable_shadow_mbr(dev, p);
2411 break;
2412 case IOC_OPAL_ERASE_LR:
2413 ret = opal_erase_locking_range(dev, p);
2414 break;
2415 case IOC_OPAL_SECURE_ERASE_LR:
2416 ret = opal_secure_erase_locking_range(dev, p);
2417 break;
Scott Bauer455a7b22017-02-03 12:50:31 -07002418 default:
2419 pr_warn("No such Opal Ioctl %u\n", cmd);
2420 }
Scott Bauere225c202017-02-14 17:29:36 -07002421
2422 kfree(p);
2423 return ret;
Scott Bauer455a7b22017-02-03 12:50:31 -07002424}
2425EXPORT_SYMBOL_GPL(sed_ioctl);