blob: 020bf3e28e38db1869d29b72ed012aebda00530e [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 */
Jon Derrickeed64952017-02-22 07:55:13 -0700399 if (state > 1)
Scott Bauer455a7b22017-02-03 12:50:31 -0700400 return end_opal_session_error(dev);
401 }
Jon Derrickeed64952017-02-22 07:55:13 -0700402 state++;
Scott Bauer455a7b22017-02-03 12:50:31 -0700403 } while (!error);
404
405 return error;
406}
407
408static int opal_discovery0_end(struct opal_dev *dev)
409{
410 bool found_com_id = false, supported = true, single_user = false;
411 const struct d0_header *hdr = (struct d0_header *)dev->resp;
412 const u8 *epos = dev->resp, *cpos = dev->resp;
413 u16 comid = 0;
Jon Derrick77039b92017-02-21 11:59:15 -0700414 u32 hlen = be32_to_cpu(hdr->length);
Scott Bauer455a7b22017-02-03 12:50:31 -0700415
Jon Derrick77039b92017-02-21 11:59:15 -0700416 print_buffer(dev->resp, hlen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700417
Jon Derrick77039b92017-02-21 11:59:15 -0700418 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
419 pr_warn("Discovery length overflows buffer (%zu+%u)/%u\n",
420 sizeof(*hdr), hlen, IO_BUFFER_LENGTH);
421 return -EFAULT;
422 }
423
424 epos += hlen; /* end of buffer */
Scott Bauer455a7b22017-02-03 12:50:31 -0700425 cpos += sizeof(*hdr); /* current position on buffer */
426
427 while (cpos < epos && supported) {
428 const struct d0_features *body =
429 (const struct d0_features *)cpos;
430
431 switch (be16_to_cpu(body->code)) {
432 case FC_TPER:
433 supported = check_tper(body->features);
434 break;
435 case FC_SINGLEUSER:
436 single_user = check_sum(body->features);
437 break;
438 case FC_GEOMETRY:
439 check_geometry(dev, body);
440 break;
441 case FC_LOCKING:
442 case FC_ENTERPRISE:
443 case FC_DATASTORE:
444 /* some ignored properties */
445 pr_debug("Found OPAL feature description: %d\n",
446 be16_to_cpu(body->code));
447 break;
448 case FC_OPALV100:
449 comid = get_comid_v100(body->features);
450 found_com_id = true;
451 break;
452 case FC_OPALV200:
453 comid = get_comid_v200(body->features);
454 found_com_id = true;
455 break;
456 case 0xbfff ... 0xffff:
457 /* vendor specific, just ignore */
458 break;
459 default:
460 pr_debug("OPAL Unknown feature: %d\n",
461 be16_to_cpu(body->code));
462
463 }
464 cpos += body->length + 4;
465 }
466
467 if (!supported) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100468 pr_debug("This device is not Opal enabled. Not Supported!\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700469 return -EOPNOTSUPP;
470 }
471
472 if (!single_user)
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100473 pr_debug("Device doesn't support single user mode\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700474
475
476 if (!found_com_id) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100477 pr_debug("Could not find OPAL comid for device. Returning early\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700478 return -EOPNOTSUPP;;
479 }
480
481 dev->comid = comid;
482
483 return 0;
484}
485
Jon Derrickeed64952017-02-22 07:55:13 -0700486static int opal_discovery0(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -0700487{
488 int ret;
489
490 memset(dev->resp, 0, IO_BUFFER_LENGTH);
491 dev->comid = OPAL_DISCOVERY_COMID;
492 ret = opal_recv_cmd(dev);
493 if (ret)
494 return ret;
495 return opal_discovery0_end(dev);
496}
497
498static void add_token_u8(int *err, struct opal_dev *cmd, u8 tok)
499{
500 if (*err)
501 return;
502 if (cmd->pos >= IO_BUFFER_LENGTH - 1) {
503 pr_err("Error adding u8: end of buffer.\n");
504 *err = -ERANGE;
505 return;
506 }
507 cmd->cmd[cmd->pos++] = tok;
508}
509
510static void add_short_atom_header(struct opal_dev *cmd, bool bytestring,
511 bool has_sign, int len)
512{
513 u8 atom;
514 int err = 0;
515
516 atom = SHORT_ATOM_ID;
517 atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;
518 atom |= has_sign ? SHORT_ATOM_SIGNED : 0;
519 atom |= len & SHORT_ATOM_LEN_MASK;
520
521 add_token_u8(&err, cmd, atom);
522}
523
524static void add_medium_atom_header(struct opal_dev *cmd, bool bytestring,
525 bool has_sign, int len)
526{
527 u8 header0;
528
529 header0 = MEDIUM_ATOM_ID;
530 header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;
531 header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;
532 header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;
533 cmd->cmd[cmd->pos++] = header0;
534 cmd->cmd[cmd->pos++] = len;
535}
536
537static void add_token_u64(int *err, struct opal_dev *cmd, u64 number)
538{
539
540 size_t len;
541 int msb;
542 u8 n;
543
544 if (!(number & ~TINY_ATOM_DATA_MASK)) {
545 add_token_u8(err, cmd, number);
546 return;
547 }
548
549 msb = fls(number);
550 len = DIV_ROUND_UP(msb, 4);
551
552 if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) {
553 pr_err("Error adding u64: end of buffer.\n");
554 *err = -ERANGE;
555 return;
556 }
557 add_short_atom_header(cmd, false, false, len);
558 while (len--) {
559 n = number >> (len * 8);
560 add_token_u8(err, cmd, n);
561 }
562}
563
564static void add_token_bytestring(int *err, struct opal_dev *cmd,
565 const u8 *bytestring, size_t len)
566{
567 size_t header_len = 1;
568 bool is_short_atom = true;
569
570 if (*err)
571 return;
572
573 if (len & ~SHORT_ATOM_LEN_MASK) {
574 header_len = 2;
575 is_short_atom = false;
576 }
577
578 if (len >= IO_BUFFER_LENGTH - cmd->pos - header_len) {
579 pr_err("Error adding bytestring: end of buffer.\n");
580 *err = -ERANGE;
581 return;
582 }
583
584 if (is_short_atom)
585 add_short_atom_header(cmd, true, false, len);
586 else
587 add_medium_atom_header(cmd, true, false, len);
588
589 memcpy(&cmd->cmd[cmd->pos], bytestring, len);
590 cmd->pos += len;
591
592}
593
594static int build_locking_range(u8 *buffer, size_t length, u8 lr)
595{
596 if (length > OPAL_UID_LENGTH) {
597 pr_err("Can't build locking range. Length OOB\n");
598 return -ERANGE;
599 }
600
601 memcpy(buffer, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
602
603 if (lr == 0)
604 return 0;
605 buffer[5] = LOCKING_RANGE_NON_GLOBAL;
606 buffer[7] = lr;
607
608 return 0;
609}
610
611static int build_locking_user(u8 *buffer, size_t length, u8 lr)
612{
613 if (length > OPAL_UID_LENGTH) {
614 pr_err("Can't build locking range user, Length OOB\n");
615 return -ERANGE;
616 }
617
618 memcpy(buffer, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
619
620 buffer[7] = lr + 1;
621
622 return 0;
623}
624
625static void set_comid(struct opal_dev *cmd, u16 comid)
626{
627 struct opal_header *hdr = (struct opal_header *)cmd->cmd;
628
629 hdr->cp.extendedComID[0] = comid >> 8;
630 hdr->cp.extendedComID[1] = comid;
631 hdr->cp.extendedComID[2] = 0;
632 hdr->cp.extendedComID[3] = 0;
633}
634
635static int cmd_finalize(struct opal_dev *cmd, u32 hsn, u32 tsn)
636{
637 struct opal_header *hdr;
638 int err = 0;
639
640 add_token_u8(&err, cmd, OPAL_ENDOFDATA);
641 add_token_u8(&err, cmd, OPAL_STARTLIST);
642 add_token_u8(&err, cmd, 0);
643 add_token_u8(&err, cmd, 0);
644 add_token_u8(&err, cmd, 0);
645 add_token_u8(&err, cmd, OPAL_ENDLIST);
646
647 if (err) {
648 pr_err("Error finalizing command.\n");
649 return -EFAULT;
650 }
651
652 hdr = (struct opal_header *) cmd->cmd;
653
654 hdr->pkt.tsn = cpu_to_be32(tsn);
655 hdr->pkt.hsn = cpu_to_be32(hsn);
656
657 hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
658 while (cmd->pos % 4) {
659 if (cmd->pos >= IO_BUFFER_LENGTH) {
660 pr_err("Error: Buffer overrun\n");
661 return -ERANGE;
662 }
663 cmd->cmd[cmd->pos++] = 0;
664 }
665 hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
666 sizeof(hdr->pkt));
667 hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
668
669 return 0;
670}
671
Jon Derrickcccb9242017-02-21 11:59:14 -0700672static const struct opal_resp_tok *response_get_token(
673 const struct parsed_resp *resp,
674 int n)
Scott Bauer455a7b22017-02-03 12:50:31 -0700675{
676 const struct opal_resp_tok *tok;
677
678 if (n >= resp->num) {
679 pr_err("Token number doesn't exist: %d, resp: %d\n",
680 n, resp->num);
Jon Derrickcccb9242017-02-21 11:59:14 -0700681 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700682 }
683
684 tok = &resp->toks[n];
685 if (tok->len == 0) {
686 pr_err("Token length must be non-zero\n");
Jon Derrickcccb9242017-02-21 11:59:14 -0700687 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700688 }
689
Jon Derrickcccb9242017-02-21 11:59:14 -0700690 return tok;
Scott Bauer455a7b22017-02-03 12:50:31 -0700691}
692
Jon Derrickaedb6e22017-02-21 11:59:13 -0700693static ssize_t response_parse_tiny(struct opal_resp_tok *tok,
694 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700695{
696 tok->pos = pos;
697 tok->len = 1;
698 tok->width = OPAL_WIDTH_TINY;
699
700 if (pos[0] & TINY_ATOM_SIGNED) {
701 tok->type = OPAL_DTA_TOKENID_SINT;
702 } else {
703 tok->type = OPAL_DTA_TOKENID_UINT;
704 tok->stored.u = pos[0] & 0x3f;
705 }
706
707 return tok->len;
708}
709
Jon Derrickaedb6e22017-02-21 11:59:13 -0700710static ssize_t response_parse_short(struct opal_resp_tok *tok,
711 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700712{
713 tok->pos = pos;
714 tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
715 tok->width = OPAL_WIDTH_SHORT;
716
717 if (pos[0] & SHORT_ATOM_BYTESTRING) {
718 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
719 } else if (pos[0] & SHORT_ATOM_SIGNED) {
720 tok->type = OPAL_DTA_TOKENID_SINT;
721 } else {
722 u64 u_integer = 0;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700723 ssize_t i, b = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700724
725 tok->type = OPAL_DTA_TOKENID_UINT;
726 if (tok->len > 9) {
727 pr_warn("uint64 with more than 8 bytes\n");
728 return -EINVAL;
729 }
730 for (i = tok->len - 1; i > 0; i--) {
731 u_integer |= ((u64)pos[i] << (8 * b));
732 b++;
733 }
734 tok->stored.u = u_integer;
735 }
736
737 return tok->len;
738}
739
Jon Derrickaedb6e22017-02-21 11:59:13 -0700740static ssize_t response_parse_medium(struct opal_resp_tok *tok,
741 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700742{
743 tok->pos = pos;
744 tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
745 tok->width = OPAL_WIDTH_MEDIUM;
746
747 if (pos[0] & MEDIUM_ATOM_BYTESTRING)
748 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
749 else if (pos[0] & MEDIUM_ATOM_SIGNED)
750 tok->type = OPAL_DTA_TOKENID_SINT;
751 else
752 tok->type = OPAL_DTA_TOKENID_UINT;
753
754 return tok->len;
755}
756
Jon Derrickaedb6e22017-02-21 11:59:13 -0700757static ssize_t response_parse_long(struct opal_resp_tok *tok,
758 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700759{
760 tok->pos = pos;
761 tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
762 tok->width = OPAL_WIDTH_LONG;
763
764 if (pos[0] & LONG_ATOM_BYTESTRING)
765 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
766 else if (pos[0] & LONG_ATOM_SIGNED)
767 tok->type = OPAL_DTA_TOKENID_SINT;
768 else
769 tok->type = OPAL_DTA_TOKENID_UINT;
770
771 return tok->len;
772}
773
Jon Derrickaedb6e22017-02-21 11:59:13 -0700774static ssize_t response_parse_token(struct opal_resp_tok *tok,
775 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700776{
777 tok->pos = pos;
778 tok->len = 1;
779 tok->type = OPAL_DTA_TOKENID_TOKEN;
780 tok->width = OPAL_WIDTH_TOKEN;
781
782 return tok->len;
783}
784
785static int response_parse(const u8 *buf, size_t length,
786 struct parsed_resp *resp)
787{
788 const struct opal_header *hdr;
789 struct opal_resp_tok *iter;
790 int num_entries = 0;
791 int total;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700792 ssize_t token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700793 const u8 *pos;
Jon Derrick77039b92017-02-21 11:59:15 -0700794 u32 clen, plen, slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700795
796 if (!buf)
797 return -EFAULT;
798
799 if (!resp)
800 return -EFAULT;
801
802 hdr = (struct opal_header *)buf;
803 pos = buf;
804 pos += sizeof(*hdr);
805
Jon Derrick77039b92017-02-21 11:59:15 -0700806 clen = be32_to_cpu(hdr->cp.length);
807 plen = be32_to_cpu(hdr->pkt.length);
808 slen = be32_to_cpu(hdr->subpkt.length);
809 pr_debug("Response size: cp: %u, pkt: %u, subpkt: %u\n",
810 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700811
Jon Derrick77039b92017-02-21 11:59:15 -0700812 if (clen == 0 || plen == 0 || slen == 0 ||
813 slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
814 pr_err("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
815 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700816 print_buffer(pos, sizeof(*hdr));
817 return -EINVAL;
818 }
819
820 if (pos > buf + length)
821 return -EFAULT;
822
823 iter = resp->toks;
Jon Derrick77039b92017-02-21 11:59:15 -0700824 total = slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700825 print_buffer(pos, total);
826 while (total > 0) {
827 if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */
828 token_length = response_parse_tiny(iter, pos);
829 else if (pos[0] <= SHORT_ATOM_BYTE) /* short atom */
830 token_length = response_parse_short(iter, pos);
831 else if (pos[0] <= MEDIUM_ATOM_BYTE) /* medium atom */
832 token_length = response_parse_medium(iter, pos);
833 else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
834 token_length = response_parse_long(iter, pos);
835 else /* TOKEN */
836 token_length = response_parse_token(iter, pos);
837
Jon Derrickaedb6e22017-02-21 11:59:13 -0700838 if (token_length < 0)
839 return token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700840
841 pos += token_length;
842 total -= token_length;
843 iter++;
844 num_entries++;
845 }
846
847 if (num_entries == 0) {
848 pr_err("Couldn't parse response.\n");
849 return -EINVAL;
850 }
851 resp->num = num_entries;
852
853 return 0;
854}
855
856static size_t response_get_string(const struct parsed_resp *resp, int n,
857 const char **store)
858{
859 *store = NULL;
860 if (!resp) {
861 pr_err("Response is NULL\n");
862 return 0;
863 }
864
865 if (n > resp->num) {
866 pr_err("Response has %d tokens. Can't access %d\n",
867 resp->num, n);
868 return 0;
869 }
870
871 if (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) {
872 pr_err("Token is not a byte string!\n");
873 return 0;
874 }
875
876 *store = resp->toks[n].pos + 1;
877 return resp->toks[n].len - 1;
878}
879
880static u64 response_get_u64(const struct parsed_resp *resp, int n)
881{
882 if (!resp) {
883 pr_err("Response is NULL\n");
884 return 0;
885 }
886
887 if (n > resp->num) {
888 pr_err("Response has %d tokens. Can't access %d\n",
889 resp->num, n);
890 return 0;
891 }
892
893 if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) {
894 pr_err("Token is not unsigned it: %d\n",
895 resp->toks[n].type);
896 return 0;
897 }
898
899 if (!(resp->toks[n].width == OPAL_WIDTH_TINY ||
900 resp->toks[n].width == OPAL_WIDTH_SHORT)) {
901 pr_err("Atom is not short or tiny: %d\n",
902 resp->toks[n].width);
903 return 0;
904 }
905
906 return resp->toks[n].stored.u;
907}
908
Jon Derrickcccb9242017-02-21 11:59:14 -0700909static bool response_token_matches(const struct opal_resp_tok *token, u8 match)
910{
911 if (IS_ERR(token) ||
912 token->type != OPAL_DTA_TOKENID_TOKEN ||
913 token->pos[0] != match)
914 return false;
915 return true;
916}
917
Scott Bauer455a7b22017-02-03 12:50:31 -0700918static u8 response_status(const struct parsed_resp *resp)
919{
Jon Derrickcccb9242017-02-21 11:59:14 -0700920 const struct opal_resp_tok *tok;
921
922 tok = response_get_token(resp, 0);
923 if (response_token_matches(tok, OPAL_ENDOFSESSION))
Scott Bauer455a7b22017-02-03 12:50:31 -0700924 return 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700925
926 if (resp->num < 5)
927 return DTAERROR_NO_METHOD_STATUS;
928
Jon Derrickcccb9242017-02-21 11:59:14 -0700929 tok = response_get_token(resp, resp->num - 5);
930 if (!response_token_matches(tok, OPAL_STARTLIST))
931 return DTAERROR_NO_METHOD_STATUS;
932
933 tok = response_get_token(resp, resp->num - 1);
934 if (!response_token_matches(tok, OPAL_ENDLIST))
Scott Bauer455a7b22017-02-03 12:50:31 -0700935 return DTAERROR_NO_METHOD_STATUS;
936
937 return response_get_u64(resp, resp->num - 4);
938}
939
940/* Parses and checks for errors */
941static int parse_and_check_status(struct opal_dev *dev)
942{
943 int error;
944
945 print_buffer(dev->cmd, dev->pos);
946
947 error = response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed);
948 if (error) {
949 pr_err("Couldn't parse response.\n");
950 return error;
951 }
952
953 return response_status(&dev->parsed);
954}
955
956static void clear_opal_cmd(struct opal_dev *dev)
957{
958 dev->pos = sizeof(struct opal_header);
959 memset(dev->cmd, 0, IO_BUFFER_LENGTH);
960}
961
962static int start_opal_session_cont(struct opal_dev *dev)
963{
964 u32 hsn, tsn;
965 int error = 0;
966
967 error = parse_and_check_status(dev);
968 if (error)
969 return error;
970
971 hsn = response_get_u64(&dev->parsed, 4);
972 tsn = response_get_u64(&dev->parsed, 5);
973
974 if (hsn == 0 && tsn == 0) {
975 pr_err("Couldn't authenticate session\n");
976 return -EPERM;
977 }
978
979 dev->hsn = hsn;
980 dev->tsn = tsn;
981 return 0;
982}
983
984static void add_suspend_info(struct opal_dev *dev,
985 struct opal_suspend_data *sus)
986{
987 struct opal_suspend_data *iter;
988
989 list_for_each_entry(iter, &dev->unlk_lst, node) {
990 if (iter->lr == sus->lr) {
991 list_del(&iter->node);
992 kfree(iter);
993 break;
994 }
995 }
996 list_add_tail(&sus->node, &dev->unlk_lst);
997}
998
999static int end_session_cont(struct opal_dev *dev)
1000{
1001 dev->hsn = 0;
1002 dev->tsn = 0;
1003 return parse_and_check_status(dev);
1004}
1005
1006static int finalize_and_send(struct opal_dev *dev, cont_fn cont)
1007{
1008 int ret;
1009
1010 ret = cmd_finalize(dev, dev->hsn, dev->tsn);
1011 if (ret) {
1012 pr_err("Error finalizing command buffer: %d\n", ret);
1013 return ret;
1014 }
1015
1016 print_buffer(dev->cmd, dev->pos);
1017
1018 return opal_send_recv(dev, cont);
1019}
1020
Jon Derrickeed64952017-02-22 07:55:13 -07001021static int gen_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001022{
1023 const u8 *method;
1024 u8 uid[OPAL_UID_LENGTH];
1025 int err = 0;
1026
1027 clear_opal_cmd(dev);
1028 set_comid(dev, dev->comid);
1029
1030 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
1031 method = opalmethod[OPAL_GENKEY];
1032 kfree(dev->prev_data);
1033 dev->prev_data = NULL;
1034
1035 add_token_u8(&err, dev, OPAL_CALL);
1036 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1037 add_token_bytestring(&err, dev, opalmethod[OPAL_GENKEY],
1038 OPAL_UID_LENGTH);
1039 add_token_u8(&err, dev, OPAL_STARTLIST);
1040 add_token_u8(&err, dev, OPAL_ENDLIST);
1041
1042 if (err) {
1043 pr_err("Error building gen key command\n");
1044 return err;
1045
1046 }
1047 return finalize_and_send(dev, parse_and_check_status);
1048}
1049
1050static int get_active_key_cont(struct opal_dev *dev)
1051{
1052 const char *activekey;
1053 size_t keylen;
1054 int error = 0;
1055
1056 error = parse_and_check_status(dev);
1057 if (error)
1058 return error;
1059 keylen = response_get_string(&dev->parsed, 4, &activekey);
1060 if (!activekey) {
1061 pr_err("%s: Couldn't extract the Activekey from the response\n",
1062 __func__);
1063 return OPAL_INVAL_PARAM;
1064 }
1065 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1066
1067 if (!dev->prev_data)
1068 return -ENOMEM;
1069
1070 dev->prev_d_len = keylen;
1071
1072 return 0;
1073}
1074
Jon Derrickeed64952017-02-22 07:55:13 -07001075static int get_active_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001076{
1077 u8 uid[OPAL_UID_LENGTH];
1078 int err = 0;
Jon Derrickeed64952017-02-22 07:55:13 -07001079 u8 *lr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001080
1081 clear_opal_cmd(dev);
1082 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001083
1084 err = build_locking_range(uid, sizeof(uid), *lr);
1085 if (err)
1086 return err;
1087
1088 err = 0;
1089 add_token_u8(&err, dev, OPAL_CALL);
1090 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1091 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1092 add_token_u8(&err, dev, OPAL_STARTLIST);
1093 add_token_u8(&err, dev, OPAL_STARTLIST);
1094 add_token_u8(&err, dev, OPAL_STARTNAME);
1095 add_token_u8(&err, dev, 3); /* startCloumn */
1096 add_token_u8(&err, dev, 10); /* ActiveKey */
1097 add_token_u8(&err, dev, OPAL_ENDNAME);
1098 add_token_u8(&err, dev, OPAL_STARTNAME);
1099 add_token_u8(&err, dev, 4); /* endColumn */
1100 add_token_u8(&err, dev, 10); /* ActiveKey */
1101 add_token_u8(&err, dev, OPAL_ENDNAME);
1102 add_token_u8(&err, dev, OPAL_ENDLIST);
1103 add_token_u8(&err, dev, OPAL_ENDLIST);
1104 if (err) {
1105 pr_err("Error building get active key command\n");
1106 return err;
1107 }
1108
1109 return finalize_and_send(dev, get_active_key_cont);
1110}
1111
1112static int generic_lr_enable_disable(struct opal_dev *dev,
1113 u8 *uid, bool rle, bool wle,
1114 bool rl, bool wl)
1115{
1116 int err = 0;
1117
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_SET], OPAL_UID_LENGTH);
1121
1122 add_token_u8(&err, dev, OPAL_STARTLIST);
1123 add_token_u8(&err, dev, OPAL_STARTNAME);
1124 add_token_u8(&err, dev, OPAL_VALUES);
1125 add_token_u8(&err, dev, OPAL_STARTLIST);
1126
1127 add_token_u8(&err, dev, OPAL_STARTNAME);
1128 add_token_u8(&err, dev, 5); /* ReadLockEnabled */
1129 add_token_u8(&err, dev, rle);
1130 add_token_u8(&err, dev, OPAL_ENDNAME);
1131
1132 add_token_u8(&err, dev, OPAL_STARTNAME);
1133 add_token_u8(&err, dev, 6); /* WriteLockEnabled */
1134 add_token_u8(&err, dev, wle);
1135 add_token_u8(&err, dev, OPAL_ENDNAME);
1136
1137 add_token_u8(&err, dev, OPAL_STARTNAME);
1138 add_token_u8(&err, dev, OPAL_READLOCKED);
1139 add_token_u8(&err, dev, rl);
1140 add_token_u8(&err, dev, OPAL_ENDNAME);
1141
1142 add_token_u8(&err, dev, OPAL_STARTNAME);
1143 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1144 add_token_u8(&err, dev, wl);
1145 add_token_u8(&err, dev, OPAL_ENDNAME);
1146
1147 add_token_u8(&err, dev, OPAL_ENDLIST);
1148 add_token_u8(&err, dev, OPAL_ENDNAME);
1149 add_token_u8(&err, dev, OPAL_ENDLIST);
1150 return err;
1151}
1152
1153static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1154 struct opal_user_lr_setup *setup)
1155{
1156 int err;
1157
1158 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1159 0, 0);
1160 if (err)
1161 pr_err("Failed to create enable global lr command\n");
1162 return err;
1163}
1164
Jon Derrickeed64952017-02-22 07:55:13 -07001165static int setup_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001166{
1167 u8 uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001168 struct opal_user_lr_setup *setup = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001169 u8 lr;
1170 int err = 0;
1171
1172 clear_opal_cmd(dev);
1173 set_comid(dev, dev->comid);
1174
Scott Bauer455a7b22017-02-03 12:50:31 -07001175 lr = setup->session.opal_key.lr;
1176 err = build_locking_range(uid, sizeof(uid), lr);
1177 if (err)
1178 return err;
1179
1180 if (lr == 0)
1181 err = enable_global_lr(dev, uid, setup);
1182 else {
1183 add_token_u8(&err, dev, OPAL_CALL);
1184 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1185 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1186 OPAL_UID_LENGTH);
1187
1188 add_token_u8(&err, dev, OPAL_STARTLIST);
1189 add_token_u8(&err, dev, OPAL_STARTNAME);
1190 add_token_u8(&err, dev, OPAL_VALUES);
1191 add_token_u8(&err, dev, OPAL_STARTLIST);
1192
1193 add_token_u8(&err, dev, OPAL_STARTNAME);
1194 add_token_u8(&err, dev, 3); /* Ranges Start */
1195 add_token_u64(&err, dev, setup->range_start);
1196 add_token_u8(&err, dev, OPAL_ENDNAME);
1197
1198 add_token_u8(&err, dev, OPAL_STARTNAME);
1199 add_token_u8(&err, dev, 4); /* Ranges length */
1200 add_token_u64(&err, dev, setup->range_length);
1201 add_token_u8(&err, dev, OPAL_ENDNAME);
1202
1203 add_token_u8(&err, dev, OPAL_STARTNAME);
1204 add_token_u8(&err, dev, 5); /*ReadLockEnabled */
1205 add_token_u64(&err, dev, !!setup->RLE);
1206 add_token_u8(&err, dev, OPAL_ENDNAME);
1207
1208 add_token_u8(&err, dev, OPAL_STARTNAME);
1209 add_token_u8(&err, dev, 6); /*WriteLockEnabled*/
1210 add_token_u64(&err, dev, !!setup->WLE);
1211 add_token_u8(&err, dev, OPAL_ENDNAME);
1212
1213 add_token_u8(&err, dev, OPAL_ENDLIST);
1214 add_token_u8(&err, dev, OPAL_ENDNAME);
1215 add_token_u8(&err, dev, OPAL_ENDLIST);
1216
1217 }
1218 if (err) {
1219 pr_err("Error building Setup Locking range command.\n");
1220 return err;
1221
1222 }
1223
1224 return finalize_and_send(dev, parse_and_check_status);
1225}
1226
1227static int start_generic_opal_session(struct opal_dev *dev,
1228 enum opal_uid auth,
1229 enum opal_uid sp_type,
1230 const char *key,
1231 u8 key_len)
1232{
1233 u32 hsn;
1234 int err = 0;
1235
1236 if (key == NULL && auth != OPAL_ANYBODY_UID) {
1237 pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \
1238 "Challenge, and not as the Anybody UID\n", __func__);
1239 return OPAL_INVAL_PARAM;
1240 }
1241
1242 clear_opal_cmd(dev);
1243
1244 set_comid(dev, dev->comid);
1245 hsn = GENERIC_HOST_SESSION_NUM;
1246
1247 add_token_u8(&err, dev, OPAL_CALL);
1248 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1249 OPAL_UID_LENGTH);
1250 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1251 OPAL_UID_LENGTH);
1252 add_token_u8(&err, dev, OPAL_STARTLIST);
1253 add_token_u64(&err, dev, hsn);
1254 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1255 add_token_u8(&err, dev, 1);
1256
1257 switch (auth) {
1258 case OPAL_ANYBODY_UID:
1259 add_token_u8(&err, dev, OPAL_ENDLIST);
1260 break;
1261 case OPAL_ADMIN1_UID:
1262 case OPAL_SID_UID:
1263 add_token_u8(&err, dev, OPAL_STARTNAME);
1264 add_token_u8(&err, dev, 0); /* HostChallenge */
1265 add_token_bytestring(&err, dev, key, key_len);
1266 add_token_u8(&err, dev, OPAL_ENDNAME);
1267 add_token_u8(&err, dev, OPAL_STARTNAME);
1268 add_token_u8(&err, dev, 3); /* HostSignAuth */
1269 add_token_bytestring(&err, dev, opaluid[auth],
1270 OPAL_UID_LENGTH);
1271 add_token_u8(&err, dev, OPAL_ENDNAME);
1272 add_token_u8(&err, dev, OPAL_ENDLIST);
1273 break;
1274 default:
1275 pr_err("Cannot start Admin SP session with auth %d\n", auth);
1276 return OPAL_INVAL_PARAM;
1277 }
1278
1279 if (err) {
1280 pr_err("Error building start adminsp session command.\n");
1281 return err;
1282 }
1283
1284 return finalize_and_send(dev, start_opal_session_cont);
1285}
1286
Jon Derrickeed64952017-02-22 07:55:13 -07001287static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001288{
1289 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1290 OPAL_ADMINSP_UID, NULL, 0);
1291}
1292
Jon Derrickeed64952017-02-22 07:55:13 -07001293static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001294{
1295 int ret;
1296 const u8 *key = dev->prev_data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001297
1298 if (!key) {
Jon Derrickeed64952017-02-22 07:55:13 -07001299 const struct opal_key *okey = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001300 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1301 OPAL_ADMINSP_UID,
1302 okey->key,
1303 okey->key_len);
1304 } else {
1305 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1306 OPAL_ADMINSP_UID,
1307 key, dev->prev_d_len);
1308 kfree(key);
1309 dev->prev_data = NULL;
1310 }
1311 return ret;
1312}
1313
Jon Derrickeed64952017-02-22 07:55:13 -07001314static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001315{
Jon Derrickeed64952017-02-22 07:55:13 -07001316 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001317 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1318 OPAL_LOCKINGSP_UID,
1319 key->key, key->key_len);
1320}
1321
Jon Derrickeed64952017-02-22 07:55:13 -07001322static int start_auth_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001323{
Jon Derrickeed64952017-02-22 07:55:13 -07001324 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001325 u8 lk_ul_user[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001326 size_t keylen = session->opal_key.key_len;
Scott Bauer455a7b22017-02-03 12:50:31 -07001327 int err = 0;
1328
Scott Bauer455a7b22017-02-03 12:50:31 -07001329 u8 *key = session->opal_key.key;
1330 u32 hsn = GENERIC_HOST_SESSION_NUM;
1331
1332 clear_opal_cmd(dev);
1333 set_comid(dev, dev->comid);
1334
1335 if (session->sum) {
1336 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1337 session->opal_key.lr);
1338 if (err)
1339 return err;
1340
1341 } else if (session->who != OPAL_ADMIN1 && !session->sum) {
1342 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1343 session->who - 1);
1344 if (err)
1345 return err;
1346 } else
1347 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1348
1349 add_token_u8(&err, dev, OPAL_CALL);
1350 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1351 OPAL_UID_LENGTH);
1352 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1353 OPAL_UID_LENGTH);
1354
1355 add_token_u8(&err, dev, OPAL_STARTLIST);
1356 add_token_u64(&err, dev, hsn);
1357 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1358 OPAL_UID_LENGTH);
1359 add_token_u8(&err, dev, 1);
1360 add_token_u8(&err, dev, OPAL_STARTNAME);
1361 add_token_u8(&err, dev, 0);
1362 add_token_bytestring(&err, dev, key, keylen);
1363 add_token_u8(&err, dev, OPAL_ENDNAME);
1364 add_token_u8(&err, dev, OPAL_STARTNAME);
1365 add_token_u8(&err, dev, 3);
1366 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1367 add_token_u8(&err, dev, OPAL_ENDNAME);
1368 add_token_u8(&err, dev, OPAL_ENDLIST);
1369
1370 if (err) {
1371 pr_err("Error building STARTSESSION command.\n");
1372 return err;
1373 }
1374
1375 return finalize_and_send(dev, start_opal_session_cont);
1376}
1377
Jon Derrickeed64952017-02-22 07:55:13 -07001378static int revert_tper(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001379{
1380 int err = 0;
1381
1382 clear_opal_cmd(dev);
1383 set_comid(dev, dev->comid);
1384
1385 add_token_u8(&err, dev, OPAL_CALL);
1386 add_token_bytestring(&err, dev, opaluid[OPAL_ADMINSP_UID],
1387 OPAL_UID_LENGTH);
1388 add_token_bytestring(&err, dev, opalmethod[OPAL_REVERT],
1389 OPAL_UID_LENGTH);
1390 add_token_u8(&err, dev, OPAL_STARTLIST);
1391 add_token_u8(&err, dev, OPAL_ENDLIST);
1392 if (err) {
1393 pr_err("Error building REVERT TPER command.\n");
1394 return err;
1395 }
1396
1397 return finalize_and_send(dev, parse_and_check_status);
1398}
1399
Jon Derrickeed64952017-02-22 07:55:13 -07001400static int internal_activate_user(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001401{
Jon Derrickeed64952017-02-22 07:55:13 -07001402 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001403 u8 uid[OPAL_UID_LENGTH];
1404 int err = 0;
1405
1406 clear_opal_cmd(dev);
1407 set_comid(dev, dev->comid);
1408
1409 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1410 uid[7] = session->who;
1411
1412 add_token_u8(&err, dev, OPAL_CALL);
1413 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1414 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1415 add_token_u8(&err, dev, OPAL_STARTLIST);
1416 add_token_u8(&err, dev, OPAL_STARTNAME);
1417 add_token_u8(&err, dev, OPAL_VALUES);
1418 add_token_u8(&err, dev, OPAL_STARTLIST);
1419 add_token_u8(&err, dev, OPAL_STARTNAME);
1420 add_token_u8(&err, dev, 5); /* Enabled */
1421 add_token_u8(&err, dev, OPAL_TRUE);
1422 add_token_u8(&err, dev, OPAL_ENDNAME);
1423 add_token_u8(&err, dev, OPAL_ENDLIST);
1424 add_token_u8(&err, dev, OPAL_ENDNAME);
1425 add_token_u8(&err, dev, OPAL_ENDLIST);
1426
1427 if (err) {
1428 pr_err("Error building Activate UserN command.\n");
1429 return err;
1430 }
1431
1432 return finalize_and_send(dev, parse_and_check_status);
1433}
1434
Jon Derrickeed64952017-02-22 07:55:13 -07001435static int erase_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001436{
Jon Derrickeed64952017-02-22 07:55:13 -07001437 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001438 u8 uid[OPAL_UID_LENGTH];
1439 int err = 0;
1440
1441 clear_opal_cmd(dev);
1442 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001443
1444 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1445 return -ERANGE;
1446
1447 add_token_u8(&err, dev, OPAL_CALL);
1448 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1449 add_token_bytestring(&err, dev, opalmethod[OPAL_ERASE],
1450 OPAL_UID_LENGTH);
1451 add_token_u8(&err, dev, OPAL_STARTLIST);
1452 add_token_u8(&err, dev, OPAL_ENDLIST);
1453
1454 if (err) {
1455 pr_err("Error building Erase Locking Range Command.\n");
1456 return err;
1457 }
1458 return finalize_and_send(dev, parse_and_check_status);
1459}
1460
Jon Derrickeed64952017-02-22 07:55:13 -07001461static int set_mbr_done(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001462{
Jon Derrickeed64952017-02-22 07:55:13 -07001463 u8 *mbr_done_tf = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001464 int err = 0;
1465
1466 clear_opal_cmd(dev);
1467 set_comid(dev, dev->comid);
1468
1469 add_token_u8(&err, dev, OPAL_CALL);
1470 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1471 OPAL_UID_LENGTH);
1472 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1473 add_token_u8(&err, dev, OPAL_STARTLIST);
1474 add_token_u8(&err, dev, OPAL_STARTNAME);
1475 add_token_u8(&err, dev, OPAL_VALUES);
1476 add_token_u8(&err, dev, OPAL_STARTLIST);
1477 add_token_u8(&err, dev, OPAL_STARTNAME);
1478 add_token_u8(&err, dev, 2); /* Done */
Jon Derrickeed64952017-02-22 07:55:13 -07001479 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
Scott Bauer455a7b22017-02-03 12:50:31 -07001480 add_token_u8(&err, dev, OPAL_ENDNAME);
1481 add_token_u8(&err, dev, OPAL_ENDLIST);
1482 add_token_u8(&err, dev, OPAL_ENDNAME);
1483 add_token_u8(&err, dev, OPAL_ENDLIST);
1484
1485 if (err) {
1486 pr_err("Error Building set MBR Done command\n");
1487 return err;
1488 }
1489
1490 return finalize_and_send(dev, parse_and_check_status);
1491}
1492
Jon Derrickeed64952017-02-22 07:55:13 -07001493static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001494{
Jon Derrickeed64952017-02-22 07:55:13 -07001495 u8 *mbr_en_dis = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001496 int err = 0;
1497
1498 clear_opal_cmd(dev);
1499 set_comid(dev, dev->comid);
1500
1501 add_token_u8(&err, dev, OPAL_CALL);
1502 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1503 OPAL_UID_LENGTH);
1504 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1505 add_token_u8(&err, dev, OPAL_STARTLIST);
1506 add_token_u8(&err, dev, OPAL_STARTNAME);
1507 add_token_u8(&err, dev, OPAL_VALUES);
1508 add_token_u8(&err, dev, OPAL_STARTLIST);
1509 add_token_u8(&err, dev, OPAL_STARTNAME);
1510 add_token_u8(&err, dev, 1);
Jon Derrickeed64952017-02-22 07:55:13 -07001511 add_token_u8(&err, dev, *mbr_en_dis);
Scott Bauer455a7b22017-02-03 12:50:31 -07001512 add_token_u8(&err, dev, OPAL_ENDNAME);
1513 add_token_u8(&err, dev, OPAL_ENDLIST);
1514 add_token_u8(&err, dev, OPAL_ENDNAME);
1515 add_token_u8(&err, dev, OPAL_ENDLIST);
1516
1517 if (err) {
1518 pr_err("Error Building set MBR done command\n");
1519 return err;
1520 }
1521
1522 return finalize_and_send(dev, parse_and_check_status);
1523}
1524
1525static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1526 struct opal_dev *dev)
1527{
1528 int err = 0;
1529
1530 clear_opal_cmd(dev);
1531 set_comid(dev, dev->comid);
1532
1533 add_token_u8(&err, dev, OPAL_CALL);
1534 add_token_bytestring(&err, dev, cpin_uid, OPAL_UID_LENGTH);
1535 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1536 OPAL_UID_LENGTH);
1537 add_token_u8(&err, dev, OPAL_STARTLIST);
1538 add_token_u8(&err, dev, OPAL_STARTNAME);
1539 add_token_u8(&err, dev, OPAL_VALUES);
1540 add_token_u8(&err, dev, OPAL_STARTLIST);
1541 add_token_u8(&err, dev, OPAL_STARTNAME);
1542 add_token_u8(&err, dev, 3); /* PIN */
1543 add_token_bytestring(&err, dev, key, key_len);
1544 add_token_u8(&err, dev, OPAL_ENDNAME);
1545 add_token_u8(&err, dev, OPAL_ENDLIST);
1546 add_token_u8(&err, dev, OPAL_ENDNAME);
1547 add_token_u8(&err, dev, OPAL_ENDLIST);
1548
1549 return err;
1550}
1551
Jon Derrickeed64952017-02-22 07:55:13 -07001552static int set_new_pw(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001553{
1554 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001555 struct opal_session_info *usr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001556
1557 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1558
1559 if (usr->who != OPAL_ADMIN1) {
1560 cpin_uid[5] = 0x03;
1561 if (usr->sum)
1562 cpin_uid[7] = usr->opal_key.lr + 1;
1563 else
1564 cpin_uid[7] = usr->who;
1565 }
1566
1567 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1568 cpin_uid, dev)) {
1569 pr_err("Error building set password command.\n");
1570 return -ERANGE;
1571 }
1572
1573 return finalize_and_send(dev, parse_and_check_status);
1574}
1575
Jon Derrickeed64952017-02-22 07:55:13 -07001576static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001577{
1578 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001579 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001580
1581 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1582
1583 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
1584 pr_err("Error building Set SID cpin\n");
1585 return -ERANGE;
1586 }
1587 return finalize_and_send(dev, parse_and_check_status);
1588}
1589
Jon Derrickeed64952017-02-22 07:55:13 -07001590static int add_user_to_lr(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001591{
1592 u8 lr_buffer[OPAL_UID_LENGTH];
1593 u8 user_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001594 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001595 int err = 0;
1596
1597 clear_opal_cmd(dev);
1598 set_comid(dev, dev->comid);
1599
Scott Bauer455a7b22017-02-03 12:50:31 -07001600 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1601 OPAL_UID_LENGTH);
1602
1603 if (lkul->l_state == OPAL_RW)
1604 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1605 OPAL_UID_LENGTH);
1606
1607 lr_buffer[7] = lkul->session.opal_key.lr;
1608
1609 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1610
1611 user_uid[7] = lkul->session.who;
1612
1613 add_token_u8(&err, dev, OPAL_CALL);
1614 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1615 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1616 OPAL_UID_LENGTH);
1617
1618 add_token_u8(&err, dev, OPAL_STARTLIST);
1619 add_token_u8(&err, dev, OPAL_STARTNAME);
1620 add_token_u8(&err, dev, OPAL_VALUES);
1621
1622 add_token_u8(&err, dev, OPAL_STARTLIST);
1623 add_token_u8(&err, dev, OPAL_STARTNAME);
1624 add_token_u8(&err, dev, 3);
1625
1626 add_token_u8(&err, dev, OPAL_STARTLIST);
1627
1628
1629 add_token_u8(&err, dev, OPAL_STARTNAME);
1630 add_token_bytestring(&err, dev,
1631 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1632 OPAL_UID_LENGTH/2);
1633 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1634 add_token_u8(&err, dev, OPAL_ENDNAME);
1635
1636
1637 add_token_u8(&err, dev, OPAL_STARTNAME);
1638 add_token_bytestring(&err, dev,
1639 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1640 OPAL_UID_LENGTH/2);
1641 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1642 add_token_u8(&err, dev, OPAL_ENDNAME);
1643
1644
1645 add_token_u8(&err, dev, OPAL_STARTNAME);
1646 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1647 OPAL_UID_LENGTH/2);
1648 add_token_u8(&err, dev, 1);
1649 add_token_u8(&err, dev, OPAL_ENDNAME);
1650
1651
1652 add_token_u8(&err, dev, OPAL_ENDLIST);
1653 add_token_u8(&err, dev, OPAL_ENDNAME);
1654 add_token_u8(&err, dev, OPAL_ENDLIST);
1655 add_token_u8(&err, dev, OPAL_ENDNAME);
1656 add_token_u8(&err, dev, OPAL_ENDLIST);
1657
1658 if (err) {
1659 pr_err("Error building add user to locking range command.\n");
1660 return err;
1661 }
1662
1663 return finalize_and_send(dev, parse_and_check_status);
1664}
1665
Jon Derrickeed64952017-02-22 07:55:13 -07001666static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001667{
1668 u8 lr_buffer[OPAL_UID_LENGTH];
1669 const u8 *method;
Jon Derrickeed64952017-02-22 07:55:13 -07001670 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001671 u8 read_locked = 1, write_locked = 1;
1672 int err = 0;
1673
1674 clear_opal_cmd(dev);
1675 set_comid(dev, dev->comid);
1676
1677 method = opalmethod[OPAL_SET];
Scott Bauer455a7b22017-02-03 12:50:31 -07001678 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1679 lkul->session.opal_key.lr) < 0)
1680 return -ERANGE;
1681
1682 switch (lkul->l_state) {
1683 case OPAL_RO:
1684 read_locked = 0;
1685 write_locked = 1;
1686 break;
1687 case OPAL_RW:
1688 read_locked = 0;
1689 write_locked = 0;
1690 break;
1691 case OPAL_LK:
1692 /* vars are initalized to locked */
1693 break;
1694 default:
1695 pr_err("Tried to set an invalid locking state... returning to uland\n");
1696 return OPAL_INVAL_PARAM;
1697 }
1698
1699 add_token_u8(&err, dev, OPAL_CALL);
1700 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1701 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1702 add_token_u8(&err, dev, OPAL_STARTLIST);
1703 add_token_u8(&err, dev, OPAL_STARTNAME);
1704 add_token_u8(&err, dev, OPAL_VALUES);
1705 add_token_u8(&err, dev, OPAL_STARTLIST);
1706
1707 add_token_u8(&err, dev, OPAL_STARTNAME);
1708 add_token_u8(&err, dev, OPAL_READLOCKED);
1709 add_token_u8(&err, dev, read_locked);
1710 add_token_u8(&err, dev, OPAL_ENDNAME);
1711
1712 add_token_u8(&err, dev, OPAL_STARTNAME);
1713 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1714 add_token_u8(&err, dev, write_locked);
1715 add_token_u8(&err, dev, OPAL_ENDNAME);
1716
1717 add_token_u8(&err, dev, OPAL_ENDLIST);
1718 add_token_u8(&err, dev, OPAL_ENDNAME);
1719 add_token_u8(&err, dev, OPAL_ENDLIST);
1720
1721 if (err) {
1722 pr_err("Error building SET command.\n");
1723 return err;
1724 }
1725 return finalize_and_send(dev, parse_and_check_status);
1726}
1727
1728
Jon Derrickeed64952017-02-22 07:55:13 -07001729static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001730{
1731 u8 lr_buffer[OPAL_UID_LENGTH];
1732 u8 read_locked = 1, write_locked = 1;
1733 const u8 *method;
Jon Derrickeed64952017-02-22 07:55:13 -07001734 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001735 int ret;
1736
1737 clear_opal_cmd(dev);
1738 set_comid(dev, dev->comid);
1739
1740 method = opalmethod[OPAL_SET];
Scott Bauer455a7b22017-02-03 12:50:31 -07001741 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1742 lkul->session.opal_key.lr) < 0)
1743 return -ERANGE;
1744
1745 switch (lkul->l_state) {
1746 case OPAL_RO:
1747 read_locked = 0;
1748 write_locked = 1;
1749 break;
1750 case OPAL_RW:
1751 read_locked = 0;
1752 write_locked = 0;
1753 break;
1754 case OPAL_LK:
1755 /* vars are initalized to locked */
1756 break;
1757 default:
1758 pr_err("Tried to set an invalid locking state.\n");
1759 return OPAL_INVAL_PARAM;
1760 }
1761 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1762 read_locked, write_locked);
1763
1764 if (ret < 0) {
1765 pr_err("Error building SET command.\n");
1766 return ret;
1767 }
1768 return finalize_and_send(dev, parse_and_check_status);
1769}
1770
Jon Derrickeed64952017-02-22 07:55:13 -07001771static int activate_lsp(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001772{
Jon Derrickeed64952017-02-22 07:55:13 -07001773 struct opal_lr_act *opal_act = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001774 u8 user_lr[OPAL_UID_LENGTH];
1775 u8 uint_3 = 0x83;
1776 int err = 0, i;
1777
1778 clear_opal_cmd(dev);
1779 set_comid(dev, dev->comid);
1780
Scott Bauer455a7b22017-02-03 12:50:31 -07001781 add_token_u8(&err, dev, OPAL_CALL);
1782 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1783 OPAL_UID_LENGTH);
1784 add_token_bytestring(&err, dev, opalmethod[OPAL_ACTIVATE],
1785 OPAL_UID_LENGTH);
1786
1787
1788 if (opal_act->sum) {
1789 err = build_locking_range(user_lr, sizeof(user_lr),
1790 opal_act->lr[0]);
1791 if (err)
1792 return err;
1793
1794 add_token_u8(&err, dev, OPAL_STARTLIST);
1795 add_token_u8(&err, dev, OPAL_STARTNAME);
1796 add_token_u8(&err, dev, uint_3);
1797 add_token_u8(&err, dev, 6);
1798 add_token_u8(&err, dev, 0);
1799 add_token_u8(&err, dev, 0);
1800
1801 add_token_u8(&err, dev, OPAL_STARTLIST);
1802 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1803 for (i = 1; i < opal_act->num_lrs; i++) {
1804 user_lr[7] = opal_act->lr[i];
1805 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1806 }
1807 add_token_u8(&err, dev, OPAL_ENDLIST);
1808 add_token_u8(&err, dev, OPAL_ENDNAME);
1809 add_token_u8(&err, dev, OPAL_ENDLIST);
1810
1811 } else {
1812 add_token_u8(&err, dev, OPAL_STARTLIST);
1813 add_token_u8(&err, dev, OPAL_ENDLIST);
1814 }
1815
1816 if (err) {
1817 pr_err("Error building Activate LockingSP command.\n");
1818 return err;
1819 }
1820
1821 return finalize_and_send(dev, parse_and_check_status);
1822}
1823
1824static int get_lsp_lifecycle_cont(struct opal_dev *dev)
1825{
1826 u8 lc_status;
1827 int error = 0;
1828
1829 error = parse_and_check_status(dev);
1830 if (error)
1831 return error;
1832
1833 lc_status = response_get_u64(&dev->parsed, 4);
1834 /* 0x08 is Manufacured Inactive */
1835 /* 0x09 is Manufactured */
1836 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
1837 pr_err("Couldn't determine the status of the Lifcycle state\n");
1838 return -ENODEV;
1839 }
1840
1841 return 0;
1842}
1843
1844/* Determine if we're in the Manufactured Inactive or Active state */
Jon Derrickeed64952017-02-22 07:55:13 -07001845static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001846{
1847 int err = 0;
1848
1849 clear_opal_cmd(dev);
1850 set_comid(dev, dev->comid);
1851
1852 add_token_u8(&err, dev, OPAL_CALL);
1853 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1854 OPAL_UID_LENGTH);
1855 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1856
1857 add_token_u8(&err, dev, OPAL_STARTLIST);
1858 add_token_u8(&err, dev, OPAL_STARTLIST);
1859
1860 add_token_u8(&err, dev, OPAL_STARTNAME);
1861 add_token_u8(&err, dev, 3); /* Start Column */
1862 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1863 add_token_u8(&err, dev, OPAL_ENDNAME);
1864
1865 add_token_u8(&err, dev, OPAL_STARTNAME);
1866 add_token_u8(&err, dev, 4); /* End Column */
1867 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1868 add_token_u8(&err, dev, OPAL_ENDNAME);
1869
1870 add_token_u8(&err, dev, OPAL_ENDLIST);
1871 add_token_u8(&err, dev, OPAL_ENDLIST);
1872
1873 if (err) {
1874 pr_err("Error Building GET Lifecycle Status command\n");
1875 return err;
1876 }
1877
1878 return finalize_and_send(dev, get_lsp_lifecycle_cont);
1879}
1880
1881static int get_msid_cpin_pin_cont(struct opal_dev *dev)
1882{
1883 const char *msid_pin;
1884 size_t strlen;
1885 int error = 0;
1886
1887 error = parse_and_check_status(dev);
1888 if (error)
1889 return error;
1890
1891 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1892 if (!msid_pin) {
1893 pr_err("%s: Couldn't extract PIN from response\n", __func__);
1894 return OPAL_INVAL_PARAM;
1895 }
1896
1897 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1898 if (!dev->prev_data)
1899 return -ENOMEM;
1900
1901 dev->prev_d_len = strlen;
1902
1903 return 0;
1904}
1905
Jon Derrickeed64952017-02-22 07:55:13 -07001906static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001907{
1908 int err = 0;
1909
1910 clear_opal_cmd(dev);
1911 set_comid(dev, dev->comid);
1912
Scott Bauer455a7b22017-02-03 12:50:31 -07001913 add_token_u8(&err, dev, OPAL_CALL);
1914 add_token_bytestring(&err, dev, opaluid[OPAL_C_PIN_MSID],
1915 OPAL_UID_LENGTH);
1916 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1917
1918 add_token_u8(&err, dev, OPAL_STARTLIST);
1919 add_token_u8(&err, dev, OPAL_STARTLIST);
1920
1921 add_token_u8(&err, dev, OPAL_STARTNAME);
1922 add_token_u8(&err, dev, 3); /* Start Column */
1923 add_token_u8(&err, dev, 3); /* PIN */
1924 add_token_u8(&err, dev, OPAL_ENDNAME);
1925
1926 add_token_u8(&err, dev, OPAL_STARTNAME);
1927 add_token_u8(&err, dev, 4); /* End Column */
1928 add_token_u8(&err, dev, 3); /* Lifecycle Column */
1929 add_token_u8(&err, dev, OPAL_ENDNAME);
1930
1931 add_token_u8(&err, dev, OPAL_ENDLIST);
1932 add_token_u8(&err, dev, OPAL_ENDLIST);
1933
1934 if (err) {
1935 pr_err("Error building Get MSID CPIN PIN command.\n");
1936 return err;
1937 }
1938
1939 return finalize_and_send(dev, get_msid_cpin_pin_cont);
1940}
1941
Jon Derrickeed64952017-02-22 07:55:13 -07001942static int end_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001943{
1944 int err = 0;
1945
1946 clear_opal_cmd(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07001947 set_comid(dev, dev->comid);
1948 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
Scott Bauer455a7b22017-02-03 12:50:31 -07001949
Jon Derrickeed64952017-02-22 07:55:13 -07001950 if (err < 0)
1951 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001952 return finalize_and_send(dev, end_session_cont);
1953}
1954
1955static int end_opal_session_error(struct opal_dev *dev)
1956{
Jon Derrickeed64952017-02-22 07:55:13 -07001957 const struct opal_step error_end_session[] = {
1958 { end_opal_session, },
1959 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07001960 };
Jon Derrickeed64952017-02-22 07:55:13 -07001961 dev->steps = error_end_session;
Scott Bauer455a7b22017-02-03 12:50:31 -07001962 return next(dev);
1963}
1964
1965static inline void setup_opal_dev(struct opal_dev *dev,
Jon Derrickeed64952017-02-22 07:55:13 -07001966 const struct opal_step *steps)
Scott Bauer455a7b22017-02-03 12:50:31 -07001967{
Jon Derrickeed64952017-02-22 07:55:13 -07001968 dev->steps = steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07001969 dev->tsn = 0;
1970 dev->hsn = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -07001971 dev->prev_data = NULL;
1972}
1973
1974static int check_opal_support(struct opal_dev *dev)
1975{
Jon Derrickeed64952017-02-22 07:55:13 -07001976 const struct opal_step steps[] = {
1977 { opal_discovery0, },
1978 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07001979 };
1980 int ret;
1981
1982 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07001983 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07001984 ret = next(dev);
1985 dev->supported = !ret;
1986 mutex_unlock(&dev->dev_lock);
1987 return ret;
1988}
1989
Scott Bauer7d6d1572017-02-22 10:15:06 -07001990static void clean_opal_dev(struct opal_dev *dev)
1991{
1992
1993 struct opal_suspend_data *suspend, *next;
1994
1995 mutex_lock(&dev->dev_lock);
1996 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
1997 list_del(&suspend->node);
1998 kfree(suspend);
1999 }
2000 mutex_unlock(&dev->dev_lock);
2001}
2002
2003void free_opal_dev(struct opal_dev *dev)
2004{
2005 if (!dev)
2006 return;
2007 clean_opal_dev(dev);
2008 kfree(dev);
2009}
2010EXPORT_SYMBOL(free_opal_dev);
2011
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002012struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
Scott Bauer455a7b22017-02-03 12:50:31 -07002013{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002014 struct opal_dev *dev;
2015
2016 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
2017 if (!dev)
2018 return NULL;
2019
2020 INIT_LIST_HEAD(&dev->unlk_lst);
2021 mutex_init(&dev->dev_lock);
2022 dev->data = data;
2023 dev->send_recv = send_recv;
2024 if (check_opal_support(dev) != 0) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +01002025 pr_debug("Opal is not supported on this device\n");
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002026 kfree(dev);
2027 return NULL;
2028 }
2029 return dev;
Scott Bauer455a7b22017-02-03 12:50:31 -07002030}
2031EXPORT_SYMBOL(init_opal_dev);
2032
2033static int opal_secure_erase_locking_range(struct opal_dev *dev,
2034 struct opal_session_info *opal_session)
2035{
Jon Derrickeed64952017-02-22 07:55:13 -07002036 const struct opal_step erase_steps[] = {
2037 { opal_discovery0, },
2038 { start_auth_opal_session, opal_session },
2039 { get_active_key, &opal_session->opal_key.lr },
2040 { gen_key, },
2041 { end_opal_session, },
2042 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002043 };
2044 int ret;
2045
2046 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002047 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002048 ret = next(dev);
2049 mutex_unlock(&dev->dev_lock);
2050 return ret;
2051}
2052
2053static int opal_erase_locking_range(struct opal_dev *dev,
2054 struct opal_session_info *opal_session)
2055{
Jon Derrickeed64952017-02-22 07:55:13 -07002056 const struct opal_step erase_steps[] = {
2057 { opal_discovery0, },
2058 { start_auth_opal_session, opal_session },
2059 { erase_locking_range, opal_session },
2060 { end_opal_session, },
2061 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002062 };
2063 int ret;
2064
2065 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002066 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002067 ret = next(dev);
2068 mutex_unlock(&dev->dev_lock);
2069 return ret;
2070}
2071
2072static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
2073 struct opal_mbr_data *opal_mbr)
2074{
Jon Derrickeed64952017-02-22 07:55:13 -07002075 const struct opal_step mbr_steps[] = {
2076 { opal_discovery0, },
2077 { start_admin1LSP_opal_session, &opal_mbr->key },
2078 { set_mbr_done, &opal_mbr->enable_disable },
2079 { end_opal_session, },
2080 { start_admin1LSP_opal_session, &opal_mbr->key },
2081 { set_mbr_enable_disable, &opal_mbr->enable_disable },
2082 { end_opal_session, },
2083 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002084 };
2085 int ret;
2086
2087 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
2088 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
2089 return -EINVAL;
2090
2091 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002092 setup_opal_dev(dev, mbr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002093 ret = next(dev);
2094 mutex_unlock(&dev->dev_lock);
2095 return ret;
2096}
2097
2098static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2099{
2100 struct opal_suspend_data *suspend;
2101
2102 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
2103 if (!suspend)
2104 return -ENOMEM;
2105
2106 suspend->unlk = *lk_unlk;
2107 suspend->lr = lk_unlk->session.opal_key.lr;
2108
2109 mutex_lock(&dev->dev_lock);
2110 setup_opal_dev(dev, NULL);
2111 add_suspend_info(dev, suspend);
2112 mutex_unlock(&dev->dev_lock);
2113 return 0;
2114}
2115
2116static int opal_add_user_to_lr(struct opal_dev *dev,
2117 struct opal_lock_unlock *lk_unlk)
2118{
Jon Derrickeed64952017-02-22 07:55:13 -07002119 const struct opal_step steps[] = {
2120 { opal_discovery0, },
2121 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2122 { add_user_to_lr, lk_unlk },
2123 { end_opal_session, },
2124 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002125 };
2126 int ret;
2127
2128 if (lk_unlk->l_state != OPAL_RO &&
2129 lk_unlk->l_state != OPAL_RW) {
2130 pr_err("Locking state was not RO or RW\n");
2131 return -EINVAL;
2132 }
2133 if (lk_unlk->session.who < OPAL_USER1 &&
2134 lk_unlk->session.who > OPAL_USER9) {
2135 pr_err("Authority was not within the range of users: %d\n",
2136 lk_unlk->session.who);
2137 return -EINVAL;
2138 }
2139 if (lk_unlk->session.sum) {
2140 pr_err("%s not supported in sum. Use setup locking range\n",
2141 __func__);
2142 return -EINVAL;
2143 }
2144
2145 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002146 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002147 ret = next(dev);
2148 mutex_unlock(&dev->dev_lock);
2149 return ret;
2150}
2151
2152static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal)
2153{
Jon Derrickeed64952017-02-22 07:55:13 -07002154 const struct opal_step revert_steps[] = {
2155 { opal_discovery0, },
2156 { start_SIDASP_opal_session, opal },
2157 { revert_tper, }, /* controller will terminate session */
2158 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002159 };
2160 int ret;
2161
2162 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002163 setup_opal_dev(dev, revert_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002164 ret = next(dev);
2165 mutex_unlock(&dev->dev_lock);
Scott Bauer7d6d1572017-02-22 10:15:06 -07002166
2167 /*
2168 * If we successfully reverted lets clean
2169 * any saved locking ranges.
2170 */
2171 if (!ret)
2172 clean_opal_dev(dev);
2173
Scott Bauer455a7b22017-02-03 12:50:31 -07002174 return ret;
2175}
2176
Jon Derrickeed64952017-02-22 07:55:13 -07002177static int __opal_lock_unlock(struct opal_dev *dev,
2178 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002179{
Jon Derrickeed64952017-02-22 07:55:13 -07002180 const struct opal_step unlock_steps[] = {
2181 { opal_discovery0, },
2182 { start_auth_opal_session, &lk_unlk->session },
2183 { lock_unlock_locking_range, lk_unlk },
2184 { end_opal_session, },
2185 { NULL, }
2186 };
2187 const struct opal_step unlock_sum_steps[] = {
2188 { opal_discovery0, },
2189 { start_auth_opal_session, &lk_unlk->session },
2190 { lock_unlock_locking_range_sum, lk_unlk },
2191 { end_opal_session, },
2192 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002193 };
2194
Jon Derrickeed64952017-02-22 07:55:13 -07002195 dev->steps = lk_unlk->session.sum ? unlock_sum_steps : unlock_steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07002196 return next(dev);
2197}
2198
Jon Derrickeed64952017-02-22 07:55:13 -07002199static int opal_lock_unlock(struct opal_dev *dev,
2200 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002201{
Scott Bauer455a7b22017-02-03 12:50:31 -07002202 int ret;
2203
2204 if (lk_unlk->session.who < OPAL_ADMIN1 ||
2205 lk_unlk->session.who > OPAL_USER9)
2206 return -EINVAL;
2207
2208 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002209 ret = __opal_lock_unlock(dev, lk_unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002210 mutex_unlock(&dev->dev_lock);
2211 return ret;
2212}
2213
2214static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2215{
Jon Derrickeed64952017-02-22 07:55:13 -07002216 const struct opal_step owner_steps[] = {
2217 { opal_discovery0, },
2218 { start_anybodyASP_opal_session, },
2219 { get_msid_cpin_pin, },
2220 { end_opal_session, },
2221 { start_SIDASP_opal_session, opal },
2222 { set_sid_cpin_pin, opal },
2223 { end_opal_session, },
2224 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002225 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002226 int ret;
2227
2228 if (!dev)
2229 return -ENODEV;
2230
2231 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002232 setup_opal_dev(dev, owner_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002233 ret = next(dev);
2234 mutex_unlock(&dev->dev_lock);
2235 return ret;
2236}
2237
2238static int opal_activate_lsp(struct opal_dev *dev, struct opal_lr_act *opal_lr_act)
2239{
Jon Derrickeed64952017-02-22 07:55:13 -07002240 const struct opal_step active_steps[] = {
2241 { opal_discovery0, },
2242 { start_SIDASP_opal_session, &opal_lr_act->key },
2243 { get_lsp_lifecycle, },
2244 { activate_lsp, opal_lr_act },
2245 { end_opal_session, },
2246 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002247 };
2248 int ret;
2249
2250 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2251 return -EINVAL;
2252
2253 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002254 setup_opal_dev(dev, active_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002255 ret = next(dev);
2256 mutex_unlock(&dev->dev_lock);
2257 return ret;
2258}
2259
2260static int opal_setup_locking_range(struct opal_dev *dev,
2261 struct opal_user_lr_setup *opal_lrs)
2262{
Jon Derrickeed64952017-02-22 07:55:13 -07002263 const struct opal_step lr_steps[] = {
2264 { opal_discovery0, },
2265 { start_auth_opal_session, &opal_lrs->session },
2266 { setup_locking_range, opal_lrs },
2267 { end_opal_session, },
2268 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002269 };
2270 int ret;
2271
2272 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002273 setup_opal_dev(dev, lr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002274 ret = next(dev);
2275 mutex_unlock(&dev->dev_lock);
2276 return ret;
2277}
2278
2279static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2280{
Jon Derrickeed64952017-02-22 07:55:13 -07002281 const struct opal_step pw_steps[] = {
2282 { opal_discovery0, },
2283 { start_auth_opal_session, &opal_pw->session },
2284 { set_new_pw, &opal_pw->new_user_pw },
2285 { end_opal_session, },
2286 { NULL }
Scott Bauer455a7b22017-02-03 12:50:31 -07002287 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002288 int ret;
2289
2290 if (opal_pw->session.who < OPAL_ADMIN1 ||
2291 opal_pw->session.who > OPAL_USER9 ||
2292 opal_pw->new_user_pw.who < OPAL_ADMIN1 ||
2293 opal_pw->new_user_pw.who > OPAL_USER9)
2294 return -EINVAL;
2295
2296 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002297 setup_opal_dev(dev, pw_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_activate_user(struct opal_dev *dev,
2304 struct opal_session_info *opal_session)
2305{
Jon Derrickeed64952017-02-22 07:55:13 -07002306 const struct opal_step act_steps[] = {
2307 { opal_discovery0, },
2308 { start_admin1LSP_opal_session, &opal_session->opal_key },
2309 { internal_activate_user, opal_session },
2310 { end_opal_session, },
2311 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002312 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002313 int ret;
2314
2315 /* We can't activate Admin1 it's active as manufactured */
2316 if (opal_session->who < OPAL_USER1 &&
2317 opal_session->who > OPAL_USER9) {
2318 pr_err("Who was not a valid user: %d\n", opal_session->who);
2319 return -EINVAL;
2320 }
2321
2322 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002323 setup_opal_dev(dev, act_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002324 ret = next(dev);
2325 mutex_unlock(&dev->dev_lock);
2326 return ret;
2327}
2328
2329bool opal_unlock_from_suspend(struct opal_dev *dev)
2330{
2331 struct opal_suspend_data *suspend;
Scott Bauer455a7b22017-02-03 12:50:31 -07002332 bool was_failure = false;
2333 int ret = 0;
2334
2335 if (!dev)
2336 return false;
2337 if (!dev->supported)
2338 return false;
2339
2340 mutex_lock(&dev->dev_lock);
2341 setup_opal_dev(dev, NULL);
Scott Bauer455a7b22017-02-03 12:50:31 -07002342
2343 list_for_each_entry(suspend, &dev->unlk_lst, node) {
Scott Bauer455a7b22017-02-03 12:50:31 -07002344 dev->tsn = 0;
2345 dev->hsn = 0;
2346
Jon Derrickeed64952017-02-22 07:55:13 -07002347 ret = __opal_lock_unlock(dev, &suspend->unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002348 if (ret) {
2349 pr_warn("Failed to unlock LR %hhu with sum %d\n",
2350 suspend->unlk.session.opal_key.lr,
2351 suspend->unlk.session.sum);
2352 was_failure = true;
2353 }
2354 }
2355 mutex_unlock(&dev->dev_lock);
2356 return was_failure;
2357}
2358EXPORT_SYMBOL(opal_unlock_from_suspend);
2359
Scott Bauere225c202017-02-14 17:29:36 -07002360int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
Scott Bauer455a7b22017-02-03 12:50:31 -07002361{
Scott Bauere225c202017-02-14 17:29:36 -07002362 void *p;
2363 int ret = -ENOTTY;
Scott Bauer455a7b22017-02-03 12:50:31 -07002364
2365 if (!capable(CAP_SYS_ADMIN))
2366 return -EACCES;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002367 if (!dev)
2368 return -ENOTSUPP;
Scott Bauer455a7b22017-02-03 12:50:31 -07002369 if (!dev->supported) {
2370 pr_err("Not supported\n");
2371 return -ENOTSUPP;
2372 }
2373
Jon Derrickeed64952017-02-22 07:55:13 -07002374 p = memdup_user(arg, _IOC_SIZE(cmd));
Scott Bauere225c202017-02-14 17:29:36 -07002375 if (IS_ERR(p))
2376 return PTR_ERR(p);
2377
Scott Bauer455a7b22017-02-03 12:50:31 -07002378 switch (cmd) {
Scott Bauere225c202017-02-14 17:29:36 -07002379 case IOC_OPAL_SAVE:
2380 ret = opal_save(dev, p);
2381 break;
2382 case IOC_OPAL_LOCK_UNLOCK:
2383 ret = opal_lock_unlock(dev, p);
2384 break;
2385 case IOC_OPAL_TAKE_OWNERSHIP:
2386 ret = opal_take_ownership(dev, p);
2387 break;
2388 case IOC_OPAL_ACTIVATE_LSP:
2389 ret = opal_activate_lsp(dev, p);
2390 break;
2391 case IOC_OPAL_SET_PW:
2392 ret = opal_set_new_pw(dev, p);
2393 break;
2394 case IOC_OPAL_ACTIVATE_USR:
2395 ret = opal_activate_user(dev, p);
2396 break;
2397 case IOC_OPAL_REVERT_TPR:
2398 ret = opal_reverttper(dev, p);
2399 break;
2400 case IOC_OPAL_LR_SETUP:
2401 ret = opal_setup_locking_range(dev, p);
2402 break;
2403 case IOC_OPAL_ADD_USR_TO_LR:
2404 ret = opal_add_user_to_lr(dev, p);
2405 break;
2406 case IOC_OPAL_ENABLE_DISABLE_MBR:
2407 ret = opal_enable_disable_shadow_mbr(dev, p);
2408 break;
2409 case IOC_OPAL_ERASE_LR:
2410 ret = opal_erase_locking_range(dev, p);
2411 break;
2412 case IOC_OPAL_SECURE_ERASE_LR:
2413 ret = opal_secure_erase_locking_range(dev, p);
2414 break;
Scott Bauer455a7b22017-02-03 12:50:31 -07002415 default:
2416 pr_warn("No such Opal Ioctl %u\n", cmd);
2417 }
Scott Bauere225c202017-02-14 17:29:36 -07002418
2419 kfree(p);
2420 return ret;
Scott Bauer455a7b22017-02-03 12:50:31 -07002421}
2422EXPORT_SYMBOL_GPL(sed_ioctl);