blob: 14035f826b5e350dbec1710d60aca560f2c1066b [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{
Scott Bauer455a7b22017-02-03 12:50:31 -07001026 u8 uid[OPAL_UID_LENGTH];
1027 int err = 0;
1028
1029 clear_opal_cmd(dev);
1030 set_comid(dev, dev->comid);
1031
1032 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
Scott Bauer455a7b22017-02-03 12:50:31 -07001033 kfree(dev->prev_data);
1034 dev->prev_data = NULL;
1035
1036 add_token_u8(&err, dev, OPAL_CALL);
1037 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1038 add_token_bytestring(&err, dev, opalmethod[OPAL_GENKEY],
1039 OPAL_UID_LENGTH);
1040 add_token_u8(&err, dev, OPAL_STARTLIST);
1041 add_token_u8(&err, dev, OPAL_ENDLIST);
1042
1043 if (err) {
1044 pr_err("Error building gen key command\n");
1045 return err;
1046
1047 }
1048 return finalize_and_send(dev, parse_and_check_status);
1049}
1050
1051static int get_active_key_cont(struct opal_dev *dev)
1052{
1053 const char *activekey;
1054 size_t keylen;
1055 int error = 0;
1056
1057 error = parse_and_check_status(dev);
1058 if (error)
1059 return error;
1060 keylen = response_get_string(&dev->parsed, 4, &activekey);
1061 if (!activekey) {
1062 pr_err("%s: Couldn't extract the Activekey from the response\n",
1063 __func__);
1064 return OPAL_INVAL_PARAM;
1065 }
1066 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1067
1068 if (!dev->prev_data)
1069 return -ENOMEM;
1070
1071 dev->prev_d_len = keylen;
1072
1073 return 0;
1074}
1075
Jon Derrickeed64952017-02-22 07:55:13 -07001076static int get_active_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001077{
1078 u8 uid[OPAL_UID_LENGTH];
1079 int err = 0;
Jon Derrickeed64952017-02-22 07:55:13 -07001080 u8 *lr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001081
1082 clear_opal_cmd(dev);
1083 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001084
1085 err = build_locking_range(uid, sizeof(uid), *lr);
1086 if (err)
1087 return err;
1088
1089 err = 0;
1090 add_token_u8(&err, dev, OPAL_CALL);
1091 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1092 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1093 add_token_u8(&err, dev, OPAL_STARTLIST);
1094 add_token_u8(&err, dev, OPAL_STARTLIST);
1095 add_token_u8(&err, dev, OPAL_STARTNAME);
1096 add_token_u8(&err, dev, 3); /* startCloumn */
1097 add_token_u8(&err, dev, 10); /* ActiveKey */
1098 add_token_u8(&err, dev, OPAL_ENDNAME);
1099 add_token_u8(&err, dev, OPAL_STARTNAME);
1100 add_token_u8(&err, dev, 4); /* endColumn */
1101 add_token_u8(&err, dev, 10); /* ActiveKey */
1102 add_token_u8(&err, dev, OPAL_ENDNAME);
1103 add_token_u8(&err, dev, OPAL_ENDLIST);
1104 add_token_u8(&err, dev, OPAL_ENDLIST);
1105 if (err) {
1106 pr_err("Error building get active key command\n");
1107 return err;
1108 }
1109
1110 return finalize_and_send(dev, get_active_key_cont);
1111}
1112
1113static int generic_lr_enable_disable(struct opal_dev *dev,
1114 u8 *uid, bool rle, bool wle,
1115 bool rl, bool wl)
1116{
1117 int err = 0;
1118
1119 add_token_u8(&err, dev, OPAL_CALL);
1120 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1121 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1122
1123 add_token_u8(&err, dev, OPAL_STARTLIST);
1124 add_token_u8(&err, dev, OPAL_STARTNAME);
1125 add_token_u8(&err, dev, OPAL_VALUES);
1126 add_token_u8(&err, dev, OPAL_STARTLIST);
1127
1128 add_token_u8(&err, dev, OPAL_STARTNAME);
1129 add_token_u8(&err, dev, 5); /* ReadLockEnabled */
1130 add_token_u8(&err, dev, rle);
1131 add_token_u8(&err, dev, OPAL_ENDNAME);
1132
1133 add_token_u8(&err, dev, OPAL_STARTNAME);
1134 add_token_u8(&err, dev, 6); /* WriteLockEnabled */
1135 add_token_u8(&err, dev, wle);
1136 add_token_u8(&err, dev, OPAL_ENDNAME);
1137
1138 add_token_u8(&err, dev, OPAL_STARTNAME);
1139 add_token_u8(&err, dev, OPAL_READLOCKED);
1140 add_token_u8(&err, dev, rl);
1141 add_token_u8(&err, dev, OPAL_ENDNAME);
1142
1143 add_token_u8(&err, dev, OPAL_STARTNAME);
1144 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1145 add_token_u8(&err, dev, wl);
1146 add_token_u8(&err, dev, OPAL_ENDNAME);
1147
1148 add_token_u8(&err, dev, OPAL_ENDLIST);
1149 add_token_u8(&err, dev, OPAL_ENDNAME);
1150 add_token_u8(&err, dev, OPAL_ENDLIST);
1151 return err;
1152}
1153
1154static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1155 struct opal_user_lr_setup *setup)
1156{
1157 int err;
1158
1159 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1160 0, 0);
1161 if (err)
1162 pr_err("Failed to create enable global lr command\n");
1163 return err;
1164}
1165
Jon Derrickeed64952017-02-22 07:55:13 -07001166static int setup_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001167{
1168 u8 uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001169 struct opal_user_lr_setup *setup = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001170 u8 lr;
1171 int err = 0;
1172
1173 clear_opal_cmd(dev);
1174 set_comid(dev, dev->comid);
1175
Scott Bauer455a7b22017-02-03 12:50:31 -07001176 lr = setup->session.opal_key.lr;
1177 err = build_locking_range(uid, sizeof(uid), lr);
1178 if (err)
1179 return err;
1180
1181 if (lr == 0)
1182 err = enable_global_lr(dev, uid, setup);
1183 else {
1184 add_token_u8(&err, dev, OPAL_CALL);
1185 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1186 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1187 OPAL_UID_LENGTH);
1188
1189 add_token_u8(&err, dev, OPAL_STARTLIST);
1190 add_token_u8(&err, dev, OPAL_STARTNAME);
1191 add_token_u8(&err, dev, OPAL_VALUES);
1192 add_token_u8(&err, dev, OPAL_STARTLIST);
1193
1194 add_token_u8(&err, dev, OPAL_STARTNAME);
1195 add_token_u8(&err, dev, 3); /* Ranges Start */
1196 add_token_u64(&err, dev, setup->range_start);
1197 add_token_u8(&err, dev, OPAL_ENDNAME);
1198
1199 add_token_u8(&err, dev, OPAL_STARTNAME);
1200 add_token_u8(&err, dev, 4); /* Ranges length */
1201 add_token_u64(&err, dev, setup->range_length);
1202 add_token_u8(&err, dev, OPAL_ENDNAME);
1203
1204 add_token_u8(&err, dev, OPAL_STARTNAME);
1205 add_token_u8(&err, dev, 5); /*ReadLockEnabled */
1206 add_token_u64(&err, dev, !!setup->RLE);
1207 add_token_u8(&err, dev, OPAL_ENDNAME);
1208
1209 add_token_u8(&err, dev, OPAL_STARTNAME);
1210 add_token_u8(&err, dev, 6); /*WriteLockEnabled*/
1211 add_token_u64(&err, dev, !!setup->WLE);
1212 add_token_u8(&err, dev, OPAL_ENDNAME);
1213
1214 add_token_u8(&err, dev, OPAL_ENDLIST);
1215 add_token_u8(&err, dev, OPAL_ENDNAME);
1216 add_token_u8(&err, dev, OPAL_ENDLIST);
1217
1218 }
1219 if (err) {
1220 pr_err("Error building Setup Locking range command.\n");
1221 return err;
1222
1223 }
1224
1225 return finalize_and_send(dev, parse_and_check_status);
1226}
1227
1228static int start_generic_opal_session(struct opal_dev *dev,
1229 enum opal_uid auth,
1230 enum opal_uid sp_type,
1231 const char *key,
1232 u8 key_len)
1233{
1234 u32 hsn;
1235 int err = 0;
1236
1237 if (key == NULL && auth != OPAL_ANYBODY_UID) {
1238 pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \
1239 "Challenge, and not as the Anybody UID\n", __func__);
1240 return OPAL_INVAL_PARAM;
1241 }
1242
1243 clear_opal_cmd(dev);
1244
1245 set_comid(dev, dev->comid);
1246 hsn = GENERIC_HOST_SESSION_NUM;
1247
1248 add_token_u8(&err, dev, OPAL_CALL);
1249 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1250 OPAL_UID_LENGTH);
1251 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1252 OPAL_UID_LENGTH);
1253 add_token_u8(&err, dev, OPAL_STARTLIST);
1254 add_token_u64(&err, dev, hsn);
1255 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1256 add_token_u8(&err, dev, 1);
1257
1258 switch (auth) {
1259 case OPAL_ANYBODY_UID:
1260 add_token_u8(&err, dev, OPAL_ENDLIST);
1261 break;
1262 case OPAL_ADMIN1_UID:
1263 case OPAL_SID_UID:
1264 add_token_u8(&err, dev, OPAL_STARTNAME);
1265 add_token_u8(&err, dev, 0); /* HostChallenge */
1266 add_token_bytestring(&err, dev, key, key_len);
1267 add_token_u8(&err, dev, OPAL_ENDNAME);
1268 add_token_u8(&err, dev, OPAL_STARTNAME);
1269 add_token_u8(&err, dev, 3); /* HostSignAuth */
1270 add_token_bytestring(&err, dev, opaluid[auth],
1271 OPAL_UID_LENGTH);
1272 add_token_u8(&err, dev, OPAL_ENDNAME);
1273 add_token_u8(&err, dev, OPAL_ENDLIST);
1274 break;
1275 default:
1276 pr_err("Cannot start Admin SP session with auth %d\n", auth);
1277 return OPAL_INVAL_PARAM;
1278 }
1279
1280 if (err) {
1281 pr_err("Error building start adminsp session command.\n");
1282 return err;
1283 }
1284
1285 return finalize_and_send(dev, start_opal_session_cont);
1286}
1287
Jon Derrickeed64952017-02-22 07:55:13 -07001288static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001289{
1290 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1291 OPAL_ADMINSP_UID, NULL, 0);
1292}
1293
Jon Derrickeed64952017-02-22 07:55:13 -07001294static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001295{
1296 int ret;
1297 const u8 *key = dev->prev_data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001298
1299 if (!key) {
Jon Derrickeed64952017-02-22 07:55:13 -07001300 const struct opal_key *okey = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001301 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1302 OPAL_ADMINSP_UID,
1303 okey->key,
1304 okey->key_len);
1305 } else {
1306 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1307 OPAL_ADMINSP_UID,
1308 key, dev->prev_d_len);
1309 kfree(key);
1310 dev->prev_data = NULL;
1311 }
1312 return ret;
1313}
1314
Jon Derrickeed64952017-02-22 07:55:13 -07001315static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001316{
Jon Derrickeed64952017-02-22 07:55:13 -07001317 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001318 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1319 OPAL_LOCKINGSP_UID,
1320 key->key, key->key_len);
1321}
1322
Jon Derrickeed64952017-02-22 07:55:13 -07001323static int start_auth_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001324{
Jon Derrickeed64952017-02-22 07:55:13 -07001325 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001326 u8 lk_ul_user[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001327 size_t keylen = session->opal_key.key_len;
Scott Bauer455a7b22017-02-03 12:50:31 -07001328 int err = 0;
1329
Scott Bauer455a7b22017-02-03 12:50:31 -07001330 u8 *key = session->opal_key.key;
1331 u32 hsn = GENERIC_HOST_SESSION_NUM;
1332
1333 clear_opal_cmd(dev);
1334 set_comid(dev, dev->comid);
1335
1336 if (session->sum) {
1337 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1338 session->opal_key.lr);
1339 if (err)
1340 return err;
1341
1342 } else if (session->who != OPAL_ADMIN1 && !session->sum) {
1343 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1344 session->who - 1);
1345 if (err)
1346 return err;
1347 } else
1348 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1349
1350 add_token_u8(&err, dev, OPAL_CALL);
1351 add_token_bytestring(&err, dev, opaluid[OPAL_SMUID_UID],
1352 OPAL_UID_LENGTH);
1353 add_token_bytestring(&err, dev, opalmethod[OPAL_STARTSESSION],
1354 OPAL_UID_LENGTH);
1355
1356 add_token_u8(&err, dev, OPAL_STARTLIST);
1357 add_token_u64(&err, dev, hsn);
1358 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1359 OPAL_UID_LENGTH);
1360 add_token_u8(&err, dev, 1);
1361 add_token_u8(&err, dev, OPAL_STARTNAME);
1362 add_token_u8(&err, dev, 0);
1363 add_token_bytestring(&err, dev, key, keylen);
1364 add_token_u8(&err, dev, OPAL_ENDNAME);
1365 add_token_u8(&err, dev, OPAL_STARTNAME);
1366 add_token_u8(&err, dev, 3);
1367 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1368 add_token_u8(&err, dev, OPAL_ENDNAME);
1369 add_token_u8(&err, dev, OPAL_ENDLIST);
1370
1371 if (err) {
1372 pr_err("Error building STARTSESSION command.\n");
1373 return err;
1374 }
1375
1376 return finalize_and_send(dev, start_opal_session_cont);
1377}
1378
Jon Derrickeed64952017-02-22 07:55:13 -07001379static int revert_tper(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001380{
1381 int err = 0;
1382
1383 clear_opal_cmd(dev);
1384 set_comid(dev, dev->comid);
1385
1386 add_token_u8(&err, dev, OPAL_CALL);
1387 add_token_bytestring(&err, dev, opaluid[OPAL_ADMINSP_UID],
1388 OPAL_UID_LENGTH);
1389 add_token_bytestring(&err, dev, opalmethod[OPAL_REVERT],
1390 OPAL_UID_LENGTH);
1391 add_token_u8(&err, dev, OPAL_STARTLIST);
1392 add_token_u8(&err, dev, OPAL_ENDLIST);
1393 if (err) {
1394 pr_err("Error building REVERT TPER command.\n");
1395 return err;
1396 }
1397
1398 return finalize_and_send(dev, parse_and_check_status);
1399}
1400
Jon Derrickeed64952017-02-22 07:55:13 -07001401static int internal_activate_user(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001402{
Jon Derrickeed64952017-02-22 07:55:13 -07001403 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001404 u8 uid[OPAL_UID_LENGTH];
1405 int err = 0;
1406
1407 clear_opal_cmd(dev);
1408 set_comid(dev, dev->comid);
1409
1410 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1411 uid[7] = session->who;
1412
1413 add_token_u8(&err, dev, OPAL_CALL);
1414 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1415 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1416 add_token_u8(&err, dev, OPAL_STARTLIST);
1417 add_token_u8(&err, dev, OPAL_STARTNAME);
1418 add_token_u8(&err, dev, OPAL_VALUES);
1419 add_token_u8(&err, dev, OPAL_STARTLIST);
1420 add_token_u8(&err, dev, OPAL_STARTNAME);
1421 add_token_u8(&err, dev, 5); /* Enabled */
1422 add_token_u8(&err, dev, OPAL_TRUE);
1423 add_token_u8(&err, dev, OPAL_ENDNAME);
1424 add_token_u8(&err, dev, OPAL_ENDLIST);
1425 add_token_u8(&err, dev, OPAL_ENDNAME);
1426 add_token_u8(&err, dev, OPAL_ENDLIST);
1427
1428 if (err) {
1429 pr_err("Error building Activate UserN command.\n");
1430 return err;
1431 }
1432
1433 return finalize_and_send(dev, parse_and_check_status);
1434}
1435
Jon Derrickeed64952017-02-22 07:55:13 -07001436static int erase_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001437{
Jon Derrickeed64952017-02-22 07:55:13 -07001438 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001439 u8 uid[OPAL_UID_LENGTH];
1440 int err = 0;
1441
1442 clear_opal_cmd(dev);
1443 set_comid(dev, dev->comid);
Scott Bauer455a7b22017-02-03 12:50:31 -07001444
1445 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1446 return -ERANGE;
1447
1448 add_token_u8(&err, dev, OPAL_CALL);
1449 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1450 add_token_bytestring(&err, dev, opalmethod[OPAL_ERASE],
1451 OPAL_UID_LENGTH);
1452 add_token_u8(&err, dev, OPAL_STARTLIST);
1453 add_token_u8(&err, dev, OPAL_ENDLIST);
1454
1455 if (err) {
1456 pr_err("Error building Erase Locking Range Command.\n");
1457 return err;
1458 }
1459 return finalize_and_send(dev, parse_and_check_status);
1460}
1461
Jon Derrickeed64952017-02-22 07:55:13 -07001462static int set_mbr_done(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001463{
Jon Derrickeed64952017-02-22 07:55:13 -07001464 u8 *mbr_done_tf = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001465 int err = 0;
1466
1467 clear_opal_cmd(dev);
1468 set_comid(dev, dev->comid);
1469
1470 add_token_u8(&err, dev, OPAL_CALL);
1471 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1472 OPAL_UID_LENGTH);
1473 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1474 add_token_u8(&err, dev, OPAL_STARTLIST);
1475 add_token_u8(&err, dev, OPAL_STARTNAME);
1476 add_token_u8(&err, dev, OPAL_VALUES);
1477 add_token_u8(&err, dev, OPAL_STARTLIST);
1478 add_token_u8(&err, dev, OPAL_STARTNAME);
1479 add_token_u8(&err, dev, 2); /* Done */
Jon Derrickeed64952017-02-22 07:55:13 -07001480 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
Scott Bauer455a7b22017-02-03 12:50:31 -07001481 add_token_u8(&err, dev, OPAL_ENDNAME);
1482 add_token_u8(&err, dev, OPAL_ENDLIST);
1483 add_token_u8(&err, dev, OPAL_ENDNAME);
1484 add_token_u8(&err, dev, OPAL_ENDLIST);
1485
1486 if (err) {
1487 pr_err("Error Building set MBR Done command\n");
1488 return err;
1489 }
1490
1491 return finalize_and_send(dev, parse_and_check_status);
1492}
1493
Jon Derrickeed64952017-02-22 07:55:13 -07001494static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001495{
Jon Derrickeed64952017-02-22 07:55:13 -07001496 u8 *mbr_en_dis = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001497 int err = 0;
1498
1499 clear_opal_cmd(dev);
1500 set_comid(dev, dev->comid);
1501
1502 add_token_u8(&err, dev, OPAL_CALL);
1503 add_token_bytestring(&err, dev, opaluid[OPAL_MBRCONTROL],
1504 OPAL_UID_LENGTH);
1505 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1506 add_token_u8(&err, dev, OPAL_STARTLIST);
1507 add_token_u8(&err, dev, OPAL_STARTNAME);
1508 add_token_u8(&err, dev, OPAL_VALUES);
1509 add_token_u8(&err, dev, OPAL_STARTLIST);
1510 add_token_u8(&err, dev, OPAL_STARTNAME);
1511 add_token_u8(&err, dev, 1);
Jon Derrickeed64952017-02-22 07:55:13 -07001512 add_token_u8(&err, dev, *mbr_en_dis);
Scott Bauer455a7b22017-02-03 12:50:31 -07001513 add_token_u8(&err, dev, OPAL_ENDNAME);
1514 add_token_u8(&err, dev, OPAL_ENDLIST);
1515 add_token_u8(&err, dev, OPAL_ENDNAME);
1516 add_token_u8(&err, dev, OPAL_ENDLIST);
1517
1518 if (err) {
1519 pr_err("Error Building set MBR done command\n");
1520 return err;
1521 }
1522
1523 return finalize_and_send(dev, parse_and_check_status);
1524}
1525
1526static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1527 struct opal_dev *dev)
1528{
1529 int err = 0;
1530
1531 clear_opal_cmd(dev);
1532 set_comid(dev, dev->comid);
1533
1534 add_token_u8(&err, dev, OPAL_CALL);
1535 add_token_bytestring(&err, dev, cpin_uid, OPAL_UID_LENGTH);
1536 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1537 OPAL_UID_LENGTH);
1538 add_token_u8(&err, dev, OPAL_STARTLIST);
1539 add_token_u8(&err, dev, OPAL_STARTNAME);
1540 add_token_u8(&err, dev, OPAL_VALUES);
1541 add_token_u8(&err, dev, OPAL_STARTLIST);
1542 add_token_u8(&err, dev, OPAL_STARTNAME);
1543 add_token_u8(&err, dev, 3); /* PIN */
1544 add_token_bytestring(&err, dev, key, key_len);
1545 add_token_u8(&err, dev, OPAL_ENDNAME);
1546 add_token_u8(&err, dev, OPAL_ENDLIST);
1547 add_token_u8(&err, dev, OPAL_ENDNAME);
1548 add_token_u8(&err, dev, OPAL_ENDLIST);
1549
1550 return err;
1551}
1552
Jon Derrickeed64952017-02-22 07:55:13 -07001553static int set_new_pw(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001554{
1555 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001556 struct opal_session_info *usr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001557
1558 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1559
1560 if (usr->who != OPAL_ADMIN1) {
1561 cpin_uid[5] = 0x03;
1562 if (usr->sum)
1563 cpin_uid[7] = usr->opal_key.lr + 1;
1564 else
1565 cpin_uid[7] = usr->who;
1566 }
1567
1568 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1569 cpin_uid, dev)) {
1570 pr_err("Error building set password command.\n");
1571 return -ERANGE;
1572 }
1573
1574 return finalize_and_send(dev, parse_and_check_status);
1575}
1576
Jon Derrickeed64952017-02-22 07:55:13 -07001577static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001578{
1579 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001580 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001581
1582 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1583
1584 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
1585 pr_err("Error building Set SID cpin\n");
1586 return -ERANGE;
1587 }
1588 return finalize_and_send(dev, parse_and_check_status);
1589}
1590
Jon Derrickeed64952017-02-22 07:55:13 -07001591static int add_user_to_lr(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001592{
1593 u8 lr_buffer[OPAL_UID_LENGTH];
1594 u8 user_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001595 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001596 int err = 0;
1597
1598 clear_opal_cmd(dev);
1599 set_comid(dev, dev->comid);
1600
Scott Bauer455a7b22017-02-03 12:50:31 -07001601 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1602 OPAL_UID_LENGTH);
1603
1604 if (lkul->l_state == OPAL_RW)
1605 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1606 OPAL_UID_LENGTH);
1607
1608 lr_buffer[7] = lkul->session.opal_key.lr;
1609
1610 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1611
1612 user_uid[7] = lkul->session.who;
1613
1614 add_token_u8(&err, dev, OPAL_CALL);
1615 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1616 add_token_bytestring(&err, dev, opalmethod[OPAL_SET],
1617 OPAL_UID_LENGTH);
1618
1619 add_token_u8(&err, dev, OPAL_STARTLIST);
1620 add_token_u8(&err, dev, OPAL_STARTNAME);
1621 add_token_u8(&err, dev, OPAL_VALUES);
1622
1623 add_token_u8(&err, dev, OPAL_STARTLIST);
1624 add_token_u8(&err, dev, OPAL_STARTNAME);
1625 add_token_u8(&err, dev, 3);
1626
1627 add_token_u8(&err, dev, OPAL_STARTLIST);
1628
1629
1630 add_token_u8(&err, dev, OPAL_STARTNAME);
1631 add_token_bytestring(&err, dev,
1632 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1633 OPAL_UID_LENGTH/2);
1634 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1635 add_token_u8(&err, dev, OPAL_ENDNAME);
1636
1637
1638 add_token_u8(&err, dev, OPAL_STARTNAME);
1639 add_token_bytestring(&err, dev,
1640 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1641 OPAL_UID_LENGTH/2);
1642 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1643 add_token_u8(&err, dev, OPAL_ENDNAME);
1644
1645
1646 add_token_u8(&err, dev, OPAL_STARTNAME);
1647 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1648 OPAL_UID_LENGTH/2);
1649 add_token_u8(&err, dev, 1);
1650 add_token_u8(&err, dev, OPAL_ENDNAME);
1651
1652
1653 add_token_u8(&err, dev, OPAL_ENDLIST);
1654 add_token_u8(&err, dev, OPAL_ENDNAME);
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
1659 if (err) {
1660 pr_err("Error building add user to locking range command.\n");
1661 return err;
1662 }
1663
1664 return finalize_and_send(dev, parse_and_check_status);
1665}
1666
Jon Derrickeed64952017-02-22 07:55:13 -07001667static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001668{
1669 u8 lr_buffer[OPAL_UID_LENGTH];
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
Scott Bauer455a7b22017-02-03 12:50:31 -07001677 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1678 lkul->session.opal_key.lr) < 0)
1679 return -ERANGE;
1680
1681 switch (lkul->l_state) {
1682 case OPAL_RO:
1683 read_locked = 0;
1684 write_locked = 1;
1685 break;
1686 case OPAL_RW:
1687 read_locked = 0;
1688 write_locked = 0;
1689 break;
1690 case OPAL_LK:
1691 /* vars are initalized to locked */
1692 break;
1693 default:
1694 pr_err("Tried to set an invalid locking state... returning to uland\n");
1695 return OPAL_INVAL_PARAM;
1696 }
1697
1698 add_token_u8(&err, dev, OPAL_CALL);
1699 add_token_bytestring(&err, dev, lr_buffer, OPAL_UID_LENGTH);
1700 add_token_bytestring(&err, dev, opalmethod[OPAL_SET], OPAL_UID_LENGTH);
1701 add_token_u8(&err, dev, OPAL_STARTLIST);
1702 add_token_u8(&err, dev, OPAL_STARTNAME);
1703 add_token_u8(&err, dev, OPAL_VALUES);
1704 add_token_u8(&err, dev, OPAL_STARTLIST);
1705
1706 add_token_u8(&err, dev, OPAL_STARTNAME);
1707 add_token_u8(&err, dev, OPAL_READLOCKED);
1708 add_token_u8(&err, dev, read_locked);
1709 add_token_u8(&err, dev, OPAL_ENDNAME);
1710
1711 add_token_u8(&err, dev, OPAL_STARTNAME);
1712 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1713 add_token_u8(&err, dev, write_locked);
1714 add_token_u8(&err, dev, OPAL_ENDNAME);
1715
1716 add_token_u8(&err, dev, OPAL_ENDLIST);
1717 add_token_u8(&err, dev, OPAL_ENDNAME);
1718 add_token_u8(&err, dev, OPAL_ENDLIST);
1719
1720 if (err) {
1721 pr_err("Error building SET command.\n");
1722 return err;
1723 }
1724 return finalize_and_send(dev, parse_and_check_status);
1725}
1726
1727
Jon Derrickeed64952017-02-22 07:55:13 -07001728static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001729{
1730 u8 lr_buffer[OPAL_UID_LENGTH];
1731 u8 read_locked = 1, write_locked = 1;
Jon Derrickeed64952017-02-22 07:55:13 -07001732 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001733 int ret;
1734
1735 clear_opal_cmd(dev);
1736 set_comid(dev, dev->comid);
1737
Scott Bauer455a7b22017-02-03 12:50:31 -07001738 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1739 lkul->session.opal_key.lr) < 0)
1740 return -ERANGE;
1741
1742 switch (lkul->l_state) {
1743 case OPAL_RO:
1744 read_locked = 0;
1745 write_locked = 1;
1746 break;
1747 case OPAL_RW:
1748 read_locked = 0;
1749 write_locked = 0;
1750 break;
1751 case OPAL_LK:
1752 /* vars are initalized to locked */
1753 break;
1754 default:
1755 pr_err("Tried to set an invalid locking state.\n");
1756 return OPAL_INVAL_PARAM;
1757 }
1758 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1759 read_locked, write_locked);
1760
1761 if (ret < 0) {
1762 pr_err("Error building SET command.\n");
1763 return ret;
1764 }
1765 return finalize_and_send(dev, parse_and_check_status);
1766}
1767
Jon Derrickeed64952017-02-22 07:55:13 -07001768static int activate_lsp(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001769{
Jon Derrickeed64952017-02-22 07:55:13 -07001770 struct opal_lr_act *opal_act = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001771 u8 user_lr[OPAL_UID_LENGTH];
1772 u8 uint_3 = 0x83;
1773 int err = 0, i;
1774
1775 clear_opal_cmd(dev);
1776 set_comid(dev, dev->comid);
1777
Scott Bauer455a7b22017-02-03 12:50:31 -07001778 add_token_u8(&err, dev, OPAL_CALL);
1779 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1780 OPAL_UID_LENGTH);
1781 add_token_bytestring(&err, dev, opalmethod[OPAL_ACTIVATE],
1782 OPAL_UID_LENGTH);
1783
1784
1785 if (opal_act->sum) {
1786 err = build_locking_range(user_lr, sizeof(user_lr),
1787 opal_act->lr[0]);
1788 if (err)
1789 return err;
1790
1791 add_token_u8(&err, dev, OPAL_STARTLIST);
1792 add_token_u8(&err, dev, OPAL_STARTNAME);
1793 add_token_u8(&err, dev, uint_3);
1794 add_token_u8(&err, dev, 6);
1795 add_token_u8(&err, dev, 0);
1796 add_token_u8(&err, dev, 0);
1797
1798 add_token_u8(&err, dev, OPAL_STARTLIST);
1799 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1800 for (i = 1; i < opal_act->num_lrs; i++) {
1801 user_lr[7] = opal_act->lr[i];
1802 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1803 }
1804 add_token_u8(&err, dev, OPAL_ENDLIST);
1805 add_token_u8(&err, dev, OPAL_ENDNAME);
1806 add_token_u8(&err, dev, OPAL_ENDLIST);
1807
1808 } else {
1809 add_token_u8(&err, dev, OPAL_STARTLIST);
1810 add_token_u8(&err, dev, OPAL_ENDLIST);
1811 }
1812
1813 if (err) {
1814 pr_err("Error building Activate LockingSP command.\n");
1815 return err;
1816 }
1817
1818 return finalize_and_send(dev, parse_and_check_status);
1819}
1820
1821static int get_lsp_lifecycle_cont(struct opal_dev *dev)
1822{
1823 u8 lc_status;
1824 int error = 0;
1825
1826 error = parse_and_check_status(dev);
1827 if (error)
1828 return error;
1829
1830 lc_status = response_get_u64(&dev->parsed, 4);
1831 /* 0x08 is Manufacured Inactive */
1832 /* 0x09 is Manufactured */
1833 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
1834 pr_err("Couldn't determine the status of the Lifcycle state\n");
1835 return -ENODEV;
1836 }
1837
1838 return 0;
1839}
1840
1841/* Determine if we're in the Manufactured Inactive or Active state */
Jon Derrickeed64952017-02-22 07:55:13 -07001842static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001843{
1844 int err = 0;
1845
1846 clear_opal_cmd(dev);
1847 set_comid(dev, dev->comid);
1848
1849 add_token_u8(&err, dev, OPAL_CALL);
1850 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1851 OPAL_UID_LENGTH);
1852 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1853
1854 add_token_u8(&err, dev, OPAL_STARTLIST);
1855 add_token_u8(&err, dev, OPAL_STARTLIST);
1856
1857 add_token_u8(&err, dev, OPAL_STARTNAME);
1858 add_token_u8(&err, dev, 3); /* Start Column */
1859 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1860 add_token_u8(&err, dev, OPAL_ENDNAME);
1861
1862 add_token_u8(&err, dev, OPAL_STARTNAME);
1863 add_token_u8(&err, dev, 4); /* End Column */
1864 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1865 add_token_u8(&err, dev, OPAL_ENDNAME);
1866
1867 add_token_u8(&err, dev, OPAL_ENDLIST);
1868 add_token_u8(&err, dev, OPAL_ENDLIST);
1869
1870 if (err) {
1871 pr_err("Error Building GET Lifecycle Status command\n");
1872 return err;
1873 }
1874
1875 return finalize_and_send(dev, get_lsp_lifecycle_cont);
1876}
1877
1878static int get_msid_cpin_pin_cont(struct opal_dev *dev)
1879{
1880 const char *msid_pin;
1881 size_t strlen;
1882 int error = 0;
1883
1884 error = parse_and_check_status(dev);
1885 if (error)
1886 return error;
1887
1888 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1889 if (!msid_pin) {
1890 pr_err("%s: Couldn't extract PIN from response\n", __func__);
1891 return OPAL_INVAL_PARAM;
1892 }
1893
1894 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1895 if (!dev->prev_data)
1896 return -ENOMEM;
1897
1898 dev->prev_d_len = strlen;
1899
1900 return 0;
1901}
1902
Jon Derrickeed64952017-02-22 07:55:13 -07001903static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001904{
1905 int err = 0;
1906
1907 clear_opal_cmd(dev);
1908 set_comid(dev, dev->comid);
1909
Scott Bauer455a7b22017-02-03 12:50:31 -07001910 add_token_u8(&err, dev, OPAL_CALL);
1911 add_token_bytestring(&err, dev, opaluid[OPAL_C_PIN_MSID],
1912 OPAL_UID_LENGTH);
1913 add_token_bytestring(&err, dev, opalmethod[OPAL_GET], OPAL_UID_LENGTH);
1914
1915 add_token_u8(&err, dev, OPAL_STARTLIST);
1916 add_token_u8(&err, dev, OPAL_STARTLIST);
1917
1918 add_token_u8(&err, dev, OPAL_STARTNAME);
1919 add_token_u8(&err, dev, 3); /* Start Column */
1920 add_token_u8(&err, dev, 3); /* PIN */
1921 add_token_u8(&err, dev, OPAL_ENDNAME);
1922
1923 add_token_u8(&err, dev, OPAL_STARTNAME);
1924 add_token_u8(&err, dev, 4); /* End Column */
1925 add_token_u8(&err, dev, 3); /* Lifecycle Column */
1926 add_token_u8(&err, dev, OPAL_ENDNAME);
1927
1928 add_token_u8(&err, dev, OPAL_ENDLIST);
1929 add_token_u8(&err, dev, OPAL_ENDLIST);
1930
1931 if (err) {
1932 pr_err("Error building Get MSID CPIN PIN command.\n");
1933 return err;
1934 }
1935
1936 return finalize_and_send(dev, get_msid_cpin_pin_cont);
1937}
1938
Jon Derrickeed64952017-02-22 07:55:13 -07001939static int end_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001940{
1941 int err = 0;
1942
1943 clear_opal_cmd(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07001944 set_comid(dev, dev->comid);
1945 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
Scott Bauer455a7b22017-02-03 12:50:31 -07001946
Jon Derrickeed64952017-02-22 07:55:13 -07001947 if (err < 0)
1948 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001949 return finalize_and_send(dev, end_session_cont);
1950}
1951
1952static int end_opal_session_error(struct opal_dev *dev)
1953{
Jon Derrickeed64952017-02-22 07:55:13 -07001954 const struct opal_step error_end_session[] = {
1955 { end_opal_session, },
1956 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07001957 };
Jon Derrickeed64952017-02-22 07:55:13 -07001958 dev->steps = error_end_session;
Scott Bauer455a7b22017-02-03 12:50:31 -07001959 return next(dev);
1960}
1961
1962static inline void setup_opal_dev(struct opal_dev *dev,
Jon Derrickeed64952017-02-22 07:55:13 -07001963 const struct opal_step *steps)
Scott Bauer455a7b22017-02-03 12:50:31 -07001964{
Jon Derrickeed64952017-02-22 07:55:13 -07001965 dev->steps = steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07001966 dev->tsn = 0;
1967 dev->hsn = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -07001968 dev->prev_data = NULL;
1969}
1970
1971static int check_opal_support(struct opal_dev *dev)
1972{
Jon Derrickeed64952017-02-22 07:55:13 -07001973 const struct opal_step steps[] = {
1974 { opal_discovery0, },
1975 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07001976 };
1977 int ret;
1978
1979 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07001980 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07001981 ret = next(dev);
1982 dev->supported = !ret;
1983 mutex_unlock(&dev->dev_lock);
1984 return ret;
1985}
1986
Scott Bauer7d6d1572017-02-22 10:15:06 -07001987static void clean_opal_dev(struct opal_dev *dev)
1988{
1989
1990 struct opal_suspend_data *suspend, *next;
1991
1992 mutex_lock(&dev->dev_lock);
1993 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
1994 list_del(&suspend->node);
1995 kfree(suspend);
1996 }
1997 mutex_unlock(&dev->dev_lock);
1998}
1999
2000void free_opal_dev(struct opal_dev *dev)
2001{
2002 if (!dev)
2003 return;
2004 clean_opal_dev(dev);
2005 kfree(dev);
2006}
2007EXPORT_SYMBOL(free_opal_dev);
2008
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002009struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
Scott Bauer455a7b22017-02-03 12:50:31 -07002010{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002011 struct opal_dev *dev;
2012
2013 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
2014 if (!dev)
2015 return NULL;
2016
2017 INIT_LIST_HEAD(&dev->unlk_lst);
2018 mutex_init(&dev->dev_lock);
2019 dev->data = data;
2020 dev->send_recv = send_recv;
2021 if (check_opal_support(dev) != 0) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +01002022 pr_debug("Opal is not supported on this device\n");
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002023 kfree(dev);
2024 return NULL;
2025 }
2026 return dev;
Scott Bauer455a7b22017-02-03 12:50:31 -07002027}
2028EXPORT_SYMBOL(init_opal_dev);
2029
2030static int opal_secure_erase_locking_range(struct opal_dev *dev,
2031 struct opal_session_info *opal_session)
2032{
Jon Derrickeed64952017-02-22 07:55:13 -07002033 const struct opal_step erase_steps[] = {
2034 { opal_discovery0, },
2035 { start_auth_opal_session, opal_session },
2036 { get_active_key, &opal_session->opal_key.lr },
2037 { gen_key, },
2038 { end_opal_session, },
2039 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002040 };
2041 int ret;
2042
2043 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002044 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002045 ret = next(dev);
2046 mutex_unlock(&dev->dev_lock);
2047 return ret;
2048}
2049
2050static int opal_erase_locking_range(struct opal_dev *dev,
2051 struct opal_session_info *opal_session)
2052{
Jon Derrickeed64952017-02-22 07:55:13 -07002053 const struct opal_step erase_steps[] = {
2054 { opal_discovery0, },
2055 { start_auth_opal_session, opal_session },
2056 { erase_locking_range, opal_session },
2057 { end_opal_session, },
2058 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002059 };
2060 int ret;
2061
2062 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002063 setup_opal_dev(dev, erase_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002064 ret = next(dev);
2065 mutex_unlock(&dev->dev_lock);
2066 return ret;
2067}
2068
2069static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
2070 struct opal_mbr_data *opal_mbr)
2071{
Jon Derrickeed64952017-02-22 07:55:13 -07002072 const struct opal_step mbr_steps[] = {
2073 { opal_discovery0, },
2074 { start_admin1LSP_opal_session, &opal_mbr->key },
2075 { set_mbr_done, &opal_mbr->enable_disable },
2076 { end_opal_session, },
2077 { start_admin1LSP_opal_session, &opal_mbr->key },
2078 { set_mbr_enable_disable, &opal_mbr->enable_disable },
2079 { end_opal_session, },
2080 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002081 };
2082 int ret;
2083
2084 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
2085 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
2086 return -EINVAL;
2087
2088 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002089 setup_opal_dev(dev, mbr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002090 ret = next(dev);
2091 mutex_unlock(&dev->dev_lock);
2092 return ret;
2093}
2094
2095static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2096{
2097 struct opal_suspend_data *suspend;
2098
2099 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
2100 if (!suspend)
2101 return -ENOMEM;
2102
2103 suspend->unlk = *lk_unlk;
2104 suspend->lr = lk_unlk->session.opal_key.lr;
2105
2106 mutex_lock(&dev->dev_lock);
2107 setup_opal_dev(dev, NULL);
2108 add_suspend_info(dev, suspend);
2109 mutex_unlock(&dev->dev_lock);
2110 return 0;
2111}
2112
2113static int opal_add_user_to_lr(struct opal_dev *dev,
2114 struct opal_lock_unlock *lk_unlk)
2115{
Jon Derrickeed64952017-02-22 07:55:13 -07002116 const struct opal_step steps[] = {
2117 { opal_discovery0, },
2118 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2119 { add_user_to_lr, lk_unlk },
2120 { end_opal_session, },
2121 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002122 };
2123 int ret;
2124
2125 if (lk_unlk->l_state != OPAL_RO &&
2126 lk_unlk->l_state != OPAL_RW) {
2127 pr_err("Locking state was not RO or RW\n");
2128 return -EINVAL;
2129 }
Jon Derrickb0bfdfc2017-03-06 08:41:04 -07002130 if (lk_unlk->session.who < OPAL_USER1 ||
Scott Bauer455a7b22017-02-03 12:50:31 -07002131 lk_unlk->session.who > OPAL_USER9) {
2132 pr_err("Authority was not within the range of users: %d\n",
2133 lk_unlk->session.who);
2134 return -EINVAL;
2135 }
2136 if (lk_unlk->session.sum) {
2137 pr_err("%s not supported in sum. Use setup locking range\n",
2138 __func__);
2139 return -EINVAL;
2140 }
2141
2142 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002143 setup_opal_dev(dev, steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002144 ret = next(dev);
2145 mutex_unlock(&dev->dev_lock);
2146 return ret;
2147}
2148
2149static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal)
2150{
Jon Derrickeed64952017-02-22 07:55:13 -07002151 const struct opal_step revert_steps[] = {
2152 { opal_discovery0, },
2153 { start_SIDASP_opal_session, opal },
2154 { revert_tper, }, /* controller will terminate session */
2155 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002156 };
2157 int ret;
2158
2159 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002160 setup_opal_dev(dev, revert_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002161 ret = next(dev);
2162 mutex_unlock(&dev->dev_lock);
Scott Bauer7d6d1572017-02-22 10:15:06 -07002163
2164 /*
2165 * If we successfully reverted lets clean
2166 * any saved locking ranges.
2167 */
2168 if (!ret)
2169 clean_opal_dev(dev);
2170
Scott Bauer455a7b22017-02-03 12:50:31 -07002171 return ret;
2172}
2173
Jon Derrickeed64952017-02-22 07:55:13 -07002174static int __opal_lock_unlock(struct opal_dev *dev,
2175 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002176{
Jon Derrickeed64952017-02-22 07:55:13 -07002177 const struct opal_step unlock_steps[] = {
2178 { opal_discovery0, },
2179 { start_auth_opal_session, &lk_unlk->session },
2180 { lock_unlock_locking_range, lk_unlk },
2181 { end_opal_session, },
2182 { NULL, }
2183 };
2184 const struct opal_step unlock_sum_steps[] = {
2185 { opal_discovery0, },
2186 { start_auth_opal_session, &lk_unlk->session },
2187 { lock_unlock_locking_range_sum, lk_unlk },
2188 { end_opal_session, },
2189 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002190 };
2191
Jon Derrickeed64952017-02-22 07:55:13 -07002192 dev->steps = lk_unlk->session.sum ? unlock_sum_steps : unlock_steps;
Scott Bauer455a7b22017-02-03 12:50:31 -07002193 return next(dev);
2194}
2195
Jon Derrickeed64952017-02-22 07:55:13 -07002196static int opal_lock_unlock(struct opal_dev *dev,
2197 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002198{
Scott Bauer455a7b22017-02-03 12:50:31 -07002199 int ret;
2200
2201 if (lk_unlk->session.who < OPAL_ADMIN1 ||
2202 lk_unlk->session.who > OPAL_USER9)
2203 return -EINVAL;
2204
2205 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002206 ret = __opal_lock_unlock(dev, lk_unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002207 mutex_unlock(&dev->dev_lock);
2208 return ret;
2209}
2210
2211static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2212{
Jon Derrickeed64952017-02-22 07:55:13 -07002213 const struct opal_step owner_steps[] = {
2214 { opal_discovery0, },
2215 { start_anybodyASP_opal_session, },
2216 { get_msid_cpin_pin, },
2217 { end_opal_session, },
2218 { start_SIDASP_opal_session, opal },
2219 { set_sid_cpin_pin, opal },
2220 { end_opal_session, },
2221 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002222 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002223 int ret;
2224
2225 if (!dev)
2226 return -ENODEV;
2227
2228 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002229 setup_opal_dev(dev, owner_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002230 ret = next(dev);
2231 mutex_unlock(&dev->dev_lock);
2232 return ret;
2233}
2234
2235static int opal_activate_lsp(struct opal_dev *dev, struct opal_lr_act *opal_lr_act)
2236{
Jon Derrickeed64952017-02-22 07:55:13 -07002237 const struct opal_step active_steps[] = {
2238 { opal_discovery0, },
2239 { start_SIDASP_opal_session, &opal_lr_act->key },
2240 { get_lsp_lifecycle, },
2241 { activate_lsp, opal_lr_act },
2242 { end_opal_session, },
2243 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002244 };
2245 int ret;
2246
2247 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2248 return -EINVAL;
2249
2250 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002251 setup_opal_dev(dev, active_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002252 ret = next(dev);
2253 mutex_unlock(&dev->dev_lock);
2254 return ret;
2255}
2256
2257static int opal_setup_locking_range(struct opal_dev *dev,
2258 struct opal_user_lr_setup *opal_lrs)
2259{
Jon Derrickeed64952017-02-22 07:55:13 -07002260 const struct opal_step lr_steps[] = {
2261 { opal_discovery0, },
2262 { start_auth_opal_session, &opal_lrs->session },
2263 { setup_locking_range, opal_lrs },
2264 { end_opal_session, },
2265 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002266 };
2267 int ret;
2268
2269 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002270 setup_opal_dev(dev, lr_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002271 ret = next(dev);
2272 mutex_unlock(&dev->dev_lock);
2273 return ret;
2274}
2275
2276static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2277{
Jon Derrickeed64952017-02-22 07:55:13 -07002278 const struct opal_step pw_steps[] = {
2279 { opal_discovery0, },
2280 { start_auth_opal_session, &opal_pw->session },
2281 { set_new_pw, &opal_pw->new_user_pw },
2282 { end_opal_session, },
2283 { NULL }
Scott Bauer455a7b22017-02-03 12:50:31 -07002284 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002285 int ret;
2286
2287 if (opal_pw->session.who < OPAL_ADMIN1 ||
2288 opal_pw->session.who > OPAL_USER9 ||
2289 opal_pw->new_user_pw.who < OPAL_ADMIN1 ||
2290 opal_pw->new_user_pw.who > OPAL_USER9)
2291 return -EINVAL;
2292
2293 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002294 setup_opal_dev(dev, pw_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002295 ret = next(dev);
2296 mutex_unlock(&dev->dev_lock);
2297 return ret;
2298}
2299
2300static int opal_activate_user(struct opal_dev *dev,
2301 struct opal_session_info *opal_session)
2302{
Jon Derrickeed64952017-02-22 07:55:13 -07002303 const struct opal_step act_steps[] = {
2304 { opal_discovery0, },
2305 { start_admin1LSP_opal_session, &opal_session->opal_key },
2306 { internal_activate_user, opal_session },
2307 { end_opal_session, },
2308 { NULL, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002309 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002310 int ret;
2311
2312 /* We can't activate Admin1 it's active as manufactured */
Jon Derrickb0bfdfc2017-03-06 08:41:04 -07002313 if (opal_session->who < OPAL_USER1 ||
Scott Bauer455a7b22017-02-03 12:50:31 -07002314 opal_session->who > OPAL_USER9) {
2315 pr_err("Who was not a valid user: %d\n", opal_session->who);
2316 return -EINVAL;
2317 }
2318
2319 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002320 setup_opal_dev(dev, act_steps);
Scott Bauer455a7b22017-02-03 12:50:31 -07002321 ret = next(dev);
2322 mutex_unlock(&dev->dev_lock);
2323 return ret;
2324}
2325
2326bool opal_unlock_from_suspend(struct opal_dev *dev)
2327{
2328 struct opal_suspend_data *suspend;
Scott Bauer455a7b22017-02-03 12:50:31 -07002329 bool was_failure = false;
2330 int ret = 0;
2331
2332 if (!dev)
2333 return false;
2334 if (!dev->supported)
2335 return false;
2336
2337 mutex_lock(&dev->dev_lock);
2338 setup_opal_dev(dev, NULL);
Scott Bauer455a7b22017-02-03 12:50:31 -07002339
2340 list_for_each_entry(suspend, &dev->unlk_lst, node) {
Scott Bauer455a7b22017-02-03 12:50:31 -07002341 dev->tsn = 0;
2342 dev->hsn = 0;
2343
Jon Derrickeed64952017-02-22 07:55:13 -07002344 ret = __opal_lock_unlock(dev, &suspend->unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002345 if (ret) {
2346 pr_warn("Failed to unlock LR %hhu with sum %d\n",
2347 suspend->unlk.session.opal_key.lr,
2348 suspend->unlk.session.sum);
2349 was_failure = true;
2350 }
2351 }
2352 mutex_unlock(&dev->dev_lock);
2353 return was_failure;
2354}
2355EXPORT_SYMBOL(opal_unlock_from_suspend);
2356
Scott Bauere225c202017-02-14 17:29:36 -07002357int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
Scott Bauer455a7b22017-02-03 12:50:31 -07002358{
Scott Bauere225c202017-02-14 17:29:36 -07002359 void *p;
2360 int ret = -ENOTTY;
Scott Bauer455a7b22017-02-03 12:50:31 -07002361
2362 if (!capable(CAP_SYS_ADMIN))
2363 return -EACCES;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002364 if (!dev)
2365 return -ENOTSUPP;
Scott Bauer455a7b22017-02-03 12:50:31 -07002366 if (!dev->supported) {
2367 pr_err("Not supported\n");
2368 return -ENOTSUPP;
2369 }
2370
Jon Derrickeed64952017-02-22 07:55:13 -07002371 p = memdup_user(arg, _IOC_SIZE(cmd));
Scott Bauere225c202017-02-14 17:29:36 -07002372 if (IS_ERR(p))
2373 return PTR_ERR(p);
2374
Scott Bauer455a7b22017-02-03 12:50:31 -07002375 switch (cmd) {
Scott Bauere225c202017-02-14 17:29:36 -07002376 case IOC_OPAL_SAVE:
2377 ret = opal_save(dev, p);
2378 break;
2379 case IOC_OPAL_LOCK_UNLOCK:
2380 ret = opal_lock_unlock(dev, p);
2381 break;
2382 case IOC_OPAL_TAKE_OWNERSHIP:
2383 ret = opal_take_ownership(dev, p);
2384 break;
2385 case IOC_OPAL_ACTIVATE_LSP:
2386 ret = opal_activate_lsp(dev, p);
2387 break;
2388 case IOC_OPAL_SET_PW:
2389 ret = opal_set_new_pw(dev, p);
2390 break;
2391 case IOC_OPAL_ACTIVATE_USR:
2392 ret = opal_activate_user(dev, p);
2393 break;
2394 case IOC_OPAL_REVERT_TPR:
2395 ret = opal_reverttper(dev, p);
2396 break;
2397 case IOC_OPAL_LR_SETUP:
2398 ret = opal_setup_locking_range(dev, p);
2399 break;
2400 case IOC_OPAL_ADD_USR_TO_LR:
2401 ret = opal_add_user_to_lr(dev, p);
2402 break;
2403 case IOC_OPAL_ENABLE_DISABLE_MBR:
2404 ret = opal_enable_disable_shadow_mbr(dev, p);
2405 break;
2406 case IOC_OPAL_ERASE_LR:
2407 ret = opal_erase_locking_range(dev, p);
2408 break;
2409 case IOC_OPAL_SECURE_ERASE_LR:
2410 ret = opal_secure_erase_locking_range(dev, p);
2411 break;
Scott Bauer455a7b22017-02-03 12:50:31 -07002412 default:
2413 pr_warn("No such Opal Ioctl %u\n", cmd);
2414 }
Scott Bauere225c202017-02-14 17:29:36 -07002415
2416 kfree(p);
2417 return ret;
Scott Bauer455a7b22017-02-03 12:50:31 -07002418}
2419EXPORT_SYMBOL_GPL(sed_ioctl);