]> git.ipfire.org Git - thirdparty/linux.git/blame - block/sed-opal.c
block: sed-opal: unify retrieval of table columns
[thirdparty/linux.git] / block / sed-opal.c
CommitLineData
455a7b23
SB
1/*
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
4f1244c8
CH
34#define IO_BUFFER_LENGTH 2048
35#define MAX_TOKS 64
36
eed64951
JD
37struct opal_step {
38 int (*fn)(struct opal_dev *dev, void *data);
39 void *data;
40};
41typedef int (cont_fn)(struct opal_dev *dev);
4f1244c8
CH
42
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;
dbec491b 83 bool mbr_enabled;
4f1244c8
CH
84
85 void *data;
86 sec_send_recv *send_recv;
87
eed64951 88 const struct opal_step *steps;
4f1244c8
CH
89 struct mutex dev_lock;
90 u16 comid;
91 u32 hsn;
92 u32 tsn;
93 u64 align;
94 u64 lowest_lba;
95
96 size_t pos;
97 u8 cmd[IO_BUFFER_LENGTH];
98 u8 resp[IO_BUFFER_LENGTH];
99
100 struct parsed_resp parsed;
101 size_t prev_d_len;
102 void *prev_data;
103
104 struct list_head unlk_lst;
105};
106
107
455a7b23
SB
108static const u8 opaluid[][OPAL_UID_LENGTH] = {
109 /* users */
110 [OPAL_SMUID_UID] =
111 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
112 [OPAL_THISSP_UID] =
113 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
114 [OPAL_ADMINSP_UID] =
115 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },
116 [OPAL_LOCKINGSP_UID] =
117 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },
118 [OPAL_ENTERPRISE_LOCKINGSP_UID] =
119 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 },
120 [OPAL_ANYBODY_UID] =
121 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },
122 [OPAL_SID_UID] =
123 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },
124 [OPAL_ADMIN1_UID] =
125 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },
126 [OPAL_USER1_UID] =
127 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },
128 [OPAL_USER2_UID] =
129 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },
130 [OPAL_PSID_UID] =
131 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },
132 [OPAL_ENTERPRISE_BANDMASTER0_UID] =
133 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 },
134 [OPAL_ENTERPRISE_ERASEMASTER_UID] =
135 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 },
136
137 /* tables */
138
139 [OPAL_LOCKINGRANGE_GLOBAL] =
140 { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 },
141 [OPAL_LOCKINGRANGE_ACE_RDLOCKED] =
142 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 },
143 [OPAL_LOCKINGRANGE_ACE_WRLOCKED] =
144 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 },
145 [OPAL_MBRCONTROL] =
146 { 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 },
147 [OPAL_MBR] =
148 { 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 },
149 [OPAL_AUTHORITY_TABLE] =
150 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00},
151 [OPAL_C_PIN_TABLE] =
152 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00},
153 [OPAL_LOCKING_INFO_TABLE] =
154 { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 },
155 [OPAL_ENTERPRISE_LOCKING_INFO_TABLE] =
156 { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
157
158 /* C_PIN_TABLE object ID's */
159
1e815b33 160 [OPAL_C_PIN_MSID] =
455a7b23
SB
161 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02},
162 [OPAL_C_PIN_SID] =
163 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01},
164 [OPAL_C_PIN_ADMIN1] =
165 { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01},
166
167 /* half UID's (only first 4 bytes used) */
168
169 [OPAL_HALF_UID_AUTHORITY_OBJ_REF] =
170 { 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff },
171 [OPAL_HALF_UID_BOOLEAN_ACE] =
172 { 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff },
173
174 /* special value for omitted optional parameter */
175 [OPAL_UID_HEXFF] =
176 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
177};
178
179/*
180 * TCG Storage SSC Methods.
181 * Derived from: TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
182 * Section: 6.3 Assigned UIDs
183 */
1b6b75b0 184static const u8 opalmethod[][OPAL_METHOD_LENGTH] = {
455a7b23
SB
185 [OPAL_PROPERTIES] =
186 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 },
187 [OPAL_STARTSESSION] =
188 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 },
189 [OPAL_REVERT] =
190 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 },
191 [OPAL_ACTIVATE] =
192 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 },
193 [OPAL_EGET] =
194 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 },
195 [OPAL_ESET] =
196 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 },
197 [OPAL_NEXT] =
198 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 },
199 [OPAL_EAUTHENTICATE] =
200 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c },
201 [OPAL_GETACL] =
202 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d },
203 [OPAL_GENKEY] =
204 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 },
205 [OPAL_REVERTSP] =
206 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 },
207 [OPAL_GET] =
208 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 },
209 [OPAL_SET] =
210 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 },
211 [OPAL_AUTHENTICATE] =
212 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c },
213 [OPAL_RANDOM] =
214 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },
215 [OPAL_ERASE] =
216 { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 },
217};
218
455a7b23
SB
219static int end_opal_session_error(struct opal_dev *dev);
220
221struct opal_suspend_data {
222 struct opal_lock_unlock unlk;
223 u8 lr;
224 struct list_head node;
225};
226
227/*
228 * Derived from:
229 * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
230 * Section: 5.1.5 Method Status Codes
231 */
232static const char * const opal_errors[] = {
233 "Success",
234 "Not Authorized",
235 "Unknown Error",
236 "SP Busy",
237 "SP Failed",
238 "SP Disabled",
239 "SP Frozen",
240 "No Sessions Available",
241 "Uniqueness Conflict",
242 "Insufficient Space",
243 "Insufficient Rows",
244 "Invalid Function",
245 "Invalid Parameter",
246 "Invalid Reference",
247 "Unknown Error",
248 "TPER Malfunction",
249 "Transaction Failure",
250 "Response Overflow",
251 "Authority Locked Out",
252};
253
254static const char *opal_error_to_human(int error)
255{
256 if (error == 0x3f)
257 return "Failed";
258
259 if (error >= ARRAY_SIZE(opal_errors) || error < 0)
260 return "Unknown Error";
261
262 return opal_errors[error];
263}
264
265static void print_buffer(const u8 *ptr, u32 length)
266{
267#ifdef DEBUG
268 print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length);
269 pr_debug("\n");
270#endif
271}
272
273static bool check_tper(const void *data)
274{
275 const struct d0_tper_features *tper = data;
276 u8 flags = tper->supported_features;
277
278 if (!(flags & TPER_SYNC_SUPPORTED)) {
591c59d1
SB
279 pr_debug("TPer sync not supported. flags = %d\n",
280 tper->supported_features);
455a7b23
SB
281 return false;
282 }
283
284 return true;
285}
286
dbec491b
SB
287static bool check_mbrenabled(const void *data)
288{
289 const struct d0_locking_features *lfeat = data;
290 u8 sup_feat = lfeat->supported_features;
291
292 return !!(sup_feat & MBR_ENABLED_MASK);
293}
294
455a7b23
SB
295static bool check_sum(const void *data)
296{
297 const struct d0_single_user_mode *sum = data;
298 u32 nlo = be32_to_cpu(sum->num_locking_objects);
299
300 if (nlo == 0) {
591c59d1 301 pr_debug("Need at least one locking object.\n");
455a7b23
SB
302 return false;
303 }
304
305 pr_debug("Number of locking objects: %d\n", nlo);
306
307 return true;
308}
309
310static u16 get_comid_v100(const void *data)
311{
312 const struct d0_opal_v100 *v100 = data;
313
314 return be16_to_cpu(v100->baseComID);
315}
316
317static u16 get_comid_v200(const void *data)
318{
319 const struct d0_opal_v200 *v200 = data;
320
321 return be16_to_cpu(v200->baseComID);
322}
323
324static int opal_send_cmd(struct opal_dev *dev)
325{
4f1244c8 326 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
455a7b23
SB
327 dev->cmd, IO_BUFFER_LENGTH,
328 true);
329}
330
331static int opal_recv_cmd(struct opal_dev *dev)
332{
4f1244c8 333 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
455a7b23
SB
334 dev->resp, IO_BUFFER_LENGTH,
335 false);
336}
337
338static int opal_recv_check(struct opal_dev *dev)
339{
340 size_t buflen = IO_BUFFER_LENGTH;
341 void *buffer = dev->resp;
342 struct opal_header *hdr = buffer;
343 int ret;
344
345 do {
346 pr_debug("Sent OPAL command: outstanding=%d, minTransfer=%d\n",
347 hdr->cp.outstandingData,
348 hdr->cp.minTransfer);
349
350 if (hdr->cp.outstandingData == 0 ||
351 hdr->cp.minTransfer != 0)
352 return 0;
353
354 memset(buffer, 0, buflen);
355 ret = opal_recv_cmd(dev);
356 } while (!ret);
357
358 return ret;
359}
360
361static int opal_send_recv(struct opal_dev *dev, cont_fn *cont)
362{
363 int ret;
364
365 ret = opal_send_cmd(dev);
366 if (ret)
367 return ret;
368 ret = opal_recv_cmd(dev);
369 if (ret)
370 return ret;
371 ret = opal_recv_check(dev);
372 if (ret)
373 return ret;
374 return cont(dev);
375}
376
377static void check_geometry(struct opal_dev *dev, const void *data)
378{
379 const struct d0_geometry_features *geo = data;
380
381 dev->align = geo->alignment_granularity;
382 dev->lowest_lba = geo->lowest_aligned_lba;
383}
384
385static int next(struct opal_dev *dev)
386{
eed64951
JD
387 const struct opal_step *step;
388 int state = 0, error = 0;
455a7b23
SB
389
390 do {
eed64951
JD
391 step = &dev->steps[state];
392 if (!step->fn)
455a7b23
SB
393 break;
394
eed64951 395 error = step->fn(dev, step->data);
455a7b23 396 if (error) {
b2f9c6eb
JR
397 pr_debug("Step %d (%pS) failed with error %d: %s\n",
398 state, step->fn, error,
591c59d1 399 opal_error_to_human(error));
455a7b23
SB
400
401 /* For each OPAL command we do a discovery0 then we
402 * start some sort of session.
403 * If we haven't passed state 1 then there was an error
404 * on discovery0 or during the attempt to start a
405 * session. Therefore we shouldn't attempt to terminate
406 * a session, as one has not yet been created.
407 */
2d19020b
SB
408 if (state > 1) {
409 end_opal_session_error(dev);
410 return error;
411 }
412
455a7b23 413 }
eed64951 414 state++;
455a7b23
SB
415 } while (!error);
416
417 return error;
418}
419
420static int opal_discovery0_end(struct opal_dev *dev)
421{
422 bool found_com_id = false, supported = true, single_user = false;
423 const struct d0_header *hdr = (struct d0_header *)dev->resp;
424 const u8 *epos = dev->resp, *cpos = dev->resp;
425 u16 comid = 0;
77039b96 426 u32 hlen = be32_to_cpu(hdr->length);
455a7b23 427
77039b96 428 print_buffer(dev->resp, hlen);
dbec491b 429 dev->mbr_enabled = false;
455a7b23 430
77039b96 431 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
591c59d1
SB
432 pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n",
433 sizeof(*hdr), hlen, IO_BUFFER_LENGTH);
77039b96
JD
434 return -EFAULT;
435 }
436
437 epos += hlen; /* end of buffer */
455a7b23
SB
438 cpos += sizeof(*hdr); /* current position on buffer */
439
440 while (cpos < epos && supported) {
441 const struct d0_features *body =
442 (const struct d0_features *)cpos;
443
444 switch (be16_to_cpu(body->code)) {
445 case FC_TPER:
446 supported = check_tper(body->features);
447 break;
448 case FC_SINGLEUSER:
449 single_user = check_sum(body->features);
450 break;
451 case FC_GEOMETRY:
452 check_geometry(dev, body);
453 break;
454 case FC_LOCKING:
dbec491b
SB
455 dev->mbr_enabled = check_mbrenabled(body->features);
456 break;
455a7b23
SB
457 case FC_ENTERPRISE:
458 case FC_DATASTORE:
459 /* some ignored properties */
460 pr_debug("Found OPAL feature description: %d\n",
461 be16_to_cpu(body->code));
462 break;
463 case FC_OPALV100:
464 comid = get_comid_v100(body->features);
465 found_com_id = true;
466 break;
467 case FC_OPALV200:
468 comid = get_comid_v200(body->features);
469 found_com_id = true;
470 break;
471 case 0xbfff ... 0xffff:
472 /* vendor specific, just ignore */
473 break;
474 default:
475 pr_debug("OPAL Unknown feature: %d\n",
476 be16_to_cpu(body->code));
477
478 }
479 cpos += body->length + 4;
480 }
481
482 if (!supported) {
f5b37b7c 483 pr_debug("This device is not Opal enabled. Not Supported!\n");
455a7b23
SB
484 return -EOPNOTSUPP;
485 }
486
487 if (!single_user)
f5b37b7c 488 pr_debug("Device doesn't support single user mode\n");
455a7b23
SB
489
490
491 if (!found_com_id) {
f5b37b7c 492 pr_debug("Could not find OPAL comid for device. Returning early\n");
ed7158ba 493 return -EOPNOTSUPP;
455a7b23
SB
494 }
495
496 dev->comid = comid;
497
498 return 0;
499}
500
eed64951 501static int opal_discovery0(struct opal_dev *dev, void *data)
455a7b23
SB
502{
503 int ret;
504
505 memset(dev->resp, 0, IO_BUFFER_LENGTH);
506 dev->comid = OPAL_DISCOVERY_COMID;
507 ret = opal_recv_cmd(dev);
508 if (ret)
509 return ret;
510 return opal_discovery0_end(dev);
511}
512
e2821a50 513static bool can_add(int *err, struct opal_dev *cmd, size_t len)
455a7b23
SB
514{
515 if (*err)
e2821a50
JR
516 return false;
517
518 if (len > IO_BUFFER_LENGTH || cmd->pos > IO_BUFFER_LENGTH - len) {
519 pr_debug("Error adding %zu bytes: end of buffer.\n", len);
455a7b23 520 *err = -ERANGE;
e2821a50 521 return false;
455a7b23 522 }
e2821a50
JR
523
524 return true;
525}
526
527static void add_token_u8(int *err, struct opal_dev *cmd, u8 tok)
528{
529 if (!can_add(err, cmd, 1))
530 return;
455a7b23
SB
531 cmd->cmd[cmd->pos++] = tok;
532}
533
534static void add_short_atom_header(struct opal_dev *cmd, bool bytestring,
535 bool has_sign, int len)
536{
537 u8 atom;
538 int err = 0;
539
540 atom = SHORT_ATOM_ID;
541 atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;
542 atom |= has_sign ? SHORT_ATOM_SIGNED : 0;
543 atom |= len & SHORT_ATOM_LEN_MASK;
544
545 add_token_u8(&err, cmd, atom);
546}
547
548static void add_medium_atom_header(struct opal_dev *cmd, bool bytestring,
549 bool has_sign, int len)
550{
551 u8 header0;
552
553 header0 = MEDIUM_ATOM_ID;
554 header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;
555 header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;
556 header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;
557 cmd->cmd[cmd->pos++] = header0;
558 cmd->cmd[cmd->pos++] = len;
559}
560
561static void add_token_u64(int *err, struct opal_dev *cmd, u64 number)
562{
455a7b23
SB
563 size_t len;
564 int msb;
455a7b23
SB
565
566 if (!(number & ~TINY_ATOM_DATA_MASK)) {
567 add_token_u8(err, cmd, number);
568 return;
569 }
570
5f990d31
JR
571 msb = fls64(number);
572 len = DIV_ROUND_UP(msb, 8);
455a7b23 573
e2821a50 574 if (!can_add(err, cmd, len + 1)) {
591c59d1 575 pr_debug("Error adding u64: end of buffer.\n");
455a7b23
SB
576 return;
577 }
578 add_short_atom_header(cmd, false, false, len);
5f990d31
JR
579 while (len--)
580 add_token_u8(err, cmd, number >> (len * 8));
455a7b23
SB
581}
582
28559959 583static u8 *add_bytestring_header(int *err, struct opal_dev *cmd, size_t len)
455a7b23
SB
584{
585 size_t header_len = 1;
586 bool is_short_atom = true;
587
455a7b23
SB
588 if (len & ~SHORT_ATOM_LEN_MASK) {
589 header_len = 2;
590 is_short_atom = false;
591 }
592
e2821a50 593 if (!can_add(err, cmd, header_len + len)) {
591c59d1 594 pr_debug("Error adding bytestring: end of buffer.\n");
28559959 595 return NULL;
455a7b23
SB
596 }
597
598 if (is_short_atom)
599 add_short_atom_header(cmd, true, false, len);
600 else
601 add_medium_atom_header(cmd, true, false, len);
602
28559959
JR
603 return &cmd->cmd[cmd->pos];
604}
455a7b23 605
28559959
JR
606static void add_token_bytestring(int *err, struct opal_dev *cmd,
607 const u8 *bytestring, size_t len)
608{
609 u8 *start;
610
611 start = add_bytestring_header(err, cmd, len);
612 if (!start)
613 return;
614 memcpy(start, bytestring, len);
615 cmd->pos += len;
455a7b23
SB
616}
617
618static int build_locking_range(u8 *buffer, size_t length, u8 lr)
619{
620 if (length > OPAL_UID_LENGTH) {
591c59d1 621 pr_debug("Can't build locking range. Length OOB\n");
455a7b23
SB
622 return -ERANGE;
623 }
624
625 memcpy(buffer, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
626
627 if (lr == 0)
628 return 0;
629 buffer[5] = LOCKING_RANGE_NON_GLOBAL;
630 buffer[7] = lr;
631
632 return 0;
633}
634
635static int build_locking_user(u8 *buffer, size_t length, u8 lr)
636{
637 if (length > OPAL_UID_LENGTH) {
1e815b33 638 pr_debug("Can't build locking range user. Length OOB\n");
455a7b23
SB
639 return -ERANGE;
640 }
641
642 memcpy(buffer, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
643
644 buffer[7] = lr + 1;
645
646 return 0;
647}
648
649static void set_comid(struct opal_dev *cmd, u16 comid)
650{
651 struct opal_header *hdr = (struct opal_header *)cmd->cmd;
652
653 hdr->cp.extendedComID[0] = comid >> 8;
654 hdr->cp.extendedComID[1] = comid;
655 hdr->cp.extendedComID[2] = 0;
656 hdr->cp.extendedComID[3] = 0;
657}
658
659static int cmd_finalize(struct opal_dev *cmd, u32 hsn, u32 tsn)
660{
661 struct opal_header *hdr;
662 int err = 0;
663
e8b29224 664 /* close the parameter list opened from cmd_start */
78d584ca
DK
665 add_token_u8(&err, cmd, OPAL_ENDLIST);
666
455a7b23
SB
667 add_token_u8(&err, cmd, OPAL_ENDOFDATA);
668 add_token_u8(&err, cmd, OPAL_STARTLIST);
669 add_token_u8(&err, cmd, 0);
670 add_token_u8(&err, cmd, 0);
671 add_token_u8(&err, cmd, 0);
672 add_token_u8(&err, cmd, OPAL_ENDLIST);
673
674 if (err) {
591c59d1 675 pr_debug("Error finalizing command.\n");
455a7b23
SB
676 return -EFAULT;
677 }
678
679 hdr = (struct opal_header *) cmd->cmd;
680
681 hdr->pkt.tsn = cpu_to_be32(tsn);
682 hdr->pkt.hsn = cpu_to_be32(hsn);
683
684 hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
685 while (cmd->pos % 4) {
686 if (cmd->pos >= IO_BUFFER_LENGTH) {
591c59d1 687 pr_debug("Error: Buffer overrun\n");
455a7b23
SB
688 return -ERANGE;
689 }
690 cmd->cmd[cmd->pos++] = 0;
691 }
692 hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
693 sizeof(hdr->pkt));
694 hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
695
696 return 0;
697}
698
cccb9241
JD
699static const struct opal_resp_tok *response_get_token(
700 const struct parsed_resp *resp,
701 int n)
455a7b23
SB
702{
703 const struct opal_resp_tok *tok;
704
7d9b62ae
DK
705 if (!resp) {
706 pr_debug("Response is NULL\n");
707 return ERR_PTR(-EINVAL);
708 }
709
455a7b23 710 if (n >= resp->num) {
591c59d1
SB
711 pr_debug("Token number doesn't exist: %d, resp: %d\n",
712 n, resp->num);
cccb9241 713 return ERR_PTR(-EINVAL);
455a7b23
SB
714 }
715
716 tok = &resp->toks[n];
717 if (tok->len == 0) {
591c59d1 718 pr_debug("Token length must be non-zero\n");
cccb9241 719 return ERR_PTR(-EINVAL);
455a7b23
SB
720 }
721
cccb9241 722 return tok;
455a7b23
SB
723}
724
aedb6e24
JD
725static ssize_t response_parse_tiny(struct opal_resp_tok *tok,
726 const u8 *pos)
455a7b23
SB
727{
728 tok->pos = pos;
729 tok->len = 1;
730 tok->width = OPAL_WIDTH_TINY;
731
732 if (pos[0] & TINY_ATOM_SIGNED) {
733 tok->type = OPAL_DTA_TOKENID_SINT;
734 } else {
735 tok->type = OPAL_DTA_TOKENID_UINT;
736 tok->stored.u = pos[0] & 0x3f;
737 }
738
739 return tok->len;
740}
741
aedb6e24
JD
742static ssize_t response_parse_short(struct opal_resp_tok *tok,
743 const u8 *pos)
455a7b23
SB
744{
745 tok->pos = pos;
746 tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
747 tok->width = OPAL_WIDTH_SHORT;
748
749 if (pos[0] & SHORT_ATOM_BYTESTRING) {
750 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
751 } else if (pos[0] & SHORT_ATOM_SIGNED) {
752 tok->type = OPAL_DTA_TOKENID_SINT;
753 } else {
754 u64 u_integer = 0;
aedb6e24 755 ssize_t i, b = 0;
455a7b23
SB
756
757 tok->type = OPAL_DTA_TOKENID_UINT;
758 if (tok->len > 9) {
591c59d1 759 pr_debug("uint64 with more than 8 bytes\n");
455a7b23
SB
760 return -EINVAL;
761 }
762 for (i = tok->len - 1; i > 0; i--) {
763 u_integer |= ((u64)pos[i] << (8 * b));
764 b++;
765 }
766 tok->stored.u = u_integer;
767 }
768
769 return tok->len;
770}
771
aedb6e24
JD
772static ssize_t response_parse_medium(struct opal_resp_tok *tok,
773 const u8 *pos)
455a7b23
SB
774{
775 tok->pos = pos;
776 tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
777 tok->width = OPAL_WIDTH_MEDIUM;
778
779 if (pos[0] & MEDIUM_ATOM_BYTESTRING)
780 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
781 else if (pos[0] & MEDIUM_ATOM_SIGNED)
782 tok->type = OPAL_DTA_TOKENID_SINT;
783 else
784 tok->type = OPAL_DTA_TOKENID_UINT;
785
786 return tok->len;
787}
788
aedb6e24
JD
789static ssize_t response_parse_long(struct opal_resp_tok *tok,
790 const u8 *pos)
455a7b23
SB
791{
792 tok->pos = pos;
793 tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
794 tok->width = OPAL_WIDTH_LONG;
795
796 if (pos[0] & LONG_ATOM_BYTESTRING)
797 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
798 else if (pos[0] & LONG_ATOM_SIGNED)
799 tok->type = OPAL_DTA_TOKENID_SINT;
800 else
801 tok->type = OPAL_DTA_TOKENID_UINT;
802
803 return tok->len;
804}
805
aedb6e24
JD
806static ssize_t response_parse_token(struct opal_resp_tok *tok,
807 const u8 *pos)
455a7b23
SB
808{
809 tok->pos = pos;
810 tok->len = 1;
811 tok->type = OPAL_DTA_TOKENID_TOKEN;
812 tok->width = OPAL_WIDTH_TOKEN;
813
814 return tok->len;
815}
816
817static int response_parse(const u8 *buf, size_t length,
818 struct parsed_resp *resp)
819{
820 const struct opal_header *hdr;
821 struct opal_resp_tok *iter;
822 int num_entries = 0;
823 int total;
aedb6e24 824 ssize_t token_length;
455a7b23 825 const u8 *pos;
77039b96 826 u32 clen, plen, slen;
455a7b23
SB
827
828 if (!buf)
829 return -EFAULT;
830
831 if (!resp)
832 return -EFAULT;
833
834 hdr = (struct opal_header *)buf;
835 pos = buf;
836 pos += sizeof(*hdr);
837
77039b96
JD
838 clen = be32_to_cpu(hdr->cp.length);
839 plen = be32_to_cpu(hdr->pkt.length);
840 slen = be32_to_cpu(hdr->subpkt.length);
841 pr_debug("Response size: cp: %u, pkt: %u, subpkt: %u\n",
842 clen, plen, slen);
843
844 if (clen == 0 || plen == 0 || slen == 0 ||
845 slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
591c59d1
SB
846 pr_debug("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
847 clen, plen, slen);
455a7b23
SB
848 print_buffer(pos, sizeof(*hdr));
849 return -EINVAL;
850 }
851
852 if (pos > buf + length)
853 return -EFAULT;
854
855 iter = resp->toks;
77039b96 856 total = slen;
455a7b23
SB
857 print_buffer(pos, total);
858 while (total > 0) {
859 if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */
860 token_length = response_parse_tiny(iter, pos);
861 else if (pos[0] <= SHORT_ATOM_BYTE) /* short atom */
862 token_length = response_parse_short(iter, pos);
863 else if (pos[0] <= MEDIUM_ATOM_BYTE) /* medium atom */
864 token_length = response_parse_medium(iter, pos);
865 else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
866 token_length = response_parse_long(iter, pos);
867 else /* TOKEN */
868 token_length = response_parse_token(iter, pos);
869
aedb6e24
JD
870 if (token_length < 0)
871 return token_length;
455a7b23
SB
872
873 pos += token_length;
874 total -= token_length;
875 iter++;
876 num_entries++;
877 }
878
879 if (num_entries == 0) {
591c59d1 880 pr_debug("Couldn't parse response.\n");
455a7b23
SB
881 return -EINVAL;
882 }
883 resp->num = num_entries;
884
885 return 0;
886}
887
888static size_t response_get_string(const struct parsed_resp *resp, int n,
889 const char **store)
890{
d15e1175 891 u8 skip;
b68f09ec 892 const struct opal_resp_tok *tok;
d15e1175 893
455a7b23 894 *store = NULL;
b68f09ec
DK
895 tok = response_get_token(resp, n);
896 if (IS_ERR(tok))
455a7b23 897 return 0;
455a7b23 898
b68f09ec 899 if (tok->type != OPAL_DTA_TOKENID_BYTESTRING) {
591c59d1 900 pr_debug("Token is not a byte string!\n");
455a7b23
SB
901 return 0;
902 }
903
b68f09ec 904 switch (tok->width) {
d15e1175
JR
905 case OPAL_WIDTH_TINY:
906 case OPAL_WIDTH_SHORT:
907 skip = 1;
908 break;
909 case OPAL_WIDTH_MEDIUM:
910 skip = 2;
911 break;
912 case OPAL_WIDTH_LONG:
913 skip = 4;
914 break;
915 default:
916 pr_debug("Token has invalid width!\n");
917 return 0;
918 }
919
b68f09ec
DK
920 *store = tok->pos + skip;
921 return tok->len - skip;
455a7b23
SB
922}
923
924static u64 response_get_u64(const struct parsed_resp *resp, int n)
925{
b68f09ec 926 const struct opal_resp_tok *tok;
455a7b23 927
b68f09ec
DK
928 tok = response_get_token(resp, n);
929 if (IS_ERR(tok))
455a7b23 930 return 0;
455a7b23 931
b68f09ec
DK
932 if (tok->type != OPAL_DTA_TOKENID_UINT) {
933 pr_debug("Token is not unsigned int: %d\n", tok->type);
455a7b23
SB
934 return 0;
935 }
936
b68f09ec
DK
937 if (tok->width != OPAL_WIDTH_TINY && tok->width != OPAL_WIDTH_SHORT) {
938 pr_debug("Atom is not short or tiny: %d\n", tok->width);
455a7b23
SB
939 return 0;
940 }
941
b68f09ec 942 return tok->stored.u;
455a7b23
SB
943}
944
cccb9241
JD
945static bool response_token_matches(const struct opal_resp_tok *token, u8 match)
946{
947 if (IS_ERR(token) ||
948 token->type != OPAL_DTA_TOKENID_TOKEN ||
949 token->pos[0] != match)
950 return false;
951 return true;
952}
953
455a7b23
SB
954static u8 response_status(const struct parsed_resp *resp)
955{
cccb9241
JD
956 const struct opal_resp_tok *tok;
957
958 tok = response_get_token(resp, 0);
959 if (response_token_matches(tok, OPAL_ENDOFSESSION))
455a7b23 960 return 0;
455a7b23
SB
961
962 if (resp->num < 5)
963 return DTAERROR_NO_METHOD_STATUS;
964
cccb9241
JD
965 tok = response_get_token(resp, resp->num - 5);
966 if (!response_token_matches(tok, OPAL_STARTLIST))
967 return DTAERROR_NO_METHOD_STATUS;
968
969 tok = response_get_token(resp, resp->num - 1);
970 if (!response_token_matches(tok, OPAL_ENDLIST))
455a7b23
SB
971 return DTAERROR_NO_METHOD_STATUS;
972
973 return response_get_u64(resp, resp->num - 4);
974}
975
976/* Parses and checks for errors */
977static int parse_and_check_status(struct opal_dev *dev)
978{
979 int error;
980
981 print_buffer(dev->cmd, dev->pos);
982
983 error = response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed);
984 if (error) {
591c59d1 985 pr_debug("Couldn't parse response.\n");
455a7b23
SB
986 return error;
987 }
988
989 return response_status(&dev->parsed);
990}
991
992static void clear_opal_cmd(struct opal_dev *dev)
993{
994 dev->pos = sizeof(struct opal_header);
995 memset(dev->cmd, 0, IO_BUFFER_LENGTH);
996}
997
e8b29224
DK
998static int cmd_start(struct opal_dev *dev, const u8 *uid, const u8 *method)
999{
1000 int err = 0;
1001
1002 clear_opal_cmd(dev);
1003 set_comid(dev, dev->comid);
1004
1005 add_token_u8(&err, dev, OPAL_CALL);
1006 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1007 add_token_bytestring(&err, dev, method, OPAL_METHOD_LENGTH);
1008
1009 /*
1010 * Every method call is followed by its parameters enclosed within
1011 * OPAL_STARTLIST and OPAL_ENDLIST tokens. We automatically open the
1012 * parameter list here and close it later in cmd_finalize.
1013 */
1014 add_token_u8(&err, dev, OPAL_STARTLIST);
1015
1016 return err;
1017}
1018
455a7b23
SB
1019static int start_opal_session_cont(struct opal_dev *dev)
1020{
1021 u32 hsn, tsn;
1022 int error = 0;
1023
1024 error = parse_and_check_status(dev);
1025 if (error)
1026 return error;
1027
1028 hsn = response_get_u64(&dev->parsed, 4);
1029 tsn = response_get_u64(&dev->parsed, 5);
1030
1031 if (hsn == 0 && tsn == 0) {
591c59d1 1032 pr_debug("Couldn't authenticate session\n");
455a7b23
SB
1033 return -EPERM;
1034 }
1035
1036 dev->hsn = hsn;
1037 dev->tsn = tsn;
1038 return 0;
1039}
1040
1041static void add_suspend_info(struct opal_dev *dev,
1042 struct opal_suspend_data *sus)
1043{
1044 struct opal_suspend_data *iter;
1045
1046 list_for_each_entry(iter, &dev->unlk_lst, node) {
1047 if (iter->lr == sus->lr) {
1048 list_del(&iter->node);
1049 kfree(iter);
1050 break;
1051 }
1052 }
1053 list_add_tail(&sus->node, &dev->unlk_lst);
1054}
1055
1056static int end_session_cont(struct opal_dev *dev)
1057{
1058 dev->hsn = 0;
1059 dev->tsn = 0;
1060 return parse_and_check_status(dev);
1061}
1062
1063static int finalize_and_send(struct opal_dev *dev, cont_fn cont)
1064{
1065 int ret;
1066
1067 ret = cmd_finalize(dev, dev->hsn, dev->tsn);
1068 if (ret) {
591c59d1 1069 pr_debug("Error finalizing command buffer: %d\n", ret);
455a7b23
SB
1070 return ret;
1071 }
1072
1073 print_buffer(dev->cmd, dev->pos);
1074
1075 return opal_send_recv(dev, cont);
1076}
1077
3fff234b
DK
1078/*
1079 * request @column from table @table on device @dev. On success, the column
1080 * data will be available in dev->resp->tok[4]
1081 */
1082static int generic_get_column(struct opal_dev *dev, const u8 *table,
1083 u64 column)
1084{
1085 int err;
1086
1087 err = cmd_start(dev, table, opalmethod[OPAL_GET]);
1088
1089 add_token_u8(&err, dev, OPAL_STARTLIST);
1090
1091 add_token_u8(&err, dev, OPAL_STARTNAME);
1092 add_token_u8(&err, dev, OPAL_STARTCOLUMN);
1093 add_token_u64(&err, dev, column);
1094 add_token_u8(&err, dev, OPAL_ENDNAME);
1095
1096 add_token_u8(&err, dev, OPAL_STARTNAME);
1097 add_token_u8(&err, dev, OPAL_ENDCOLUMN);
1098 add_token_u64(&err, dev, column);
1099 add_token_u8(&err, dev, OPAL_ENDNAME);
1100
1101 add_token_u8(&err, dev, OPAL_ENDLIST);
1102
1103 if (err)
1104 return err;
1105
1106 return finalize_and_send(dev, parse_and_check_status);
1107}
1108
eed64951 1109static int gen_key(struct opal_dev *dev, void *data)
455a7b23 1110{
455a7b23 1111 u8 uid[OPAL_UID_LENGTH];
e8b29224 1112 int err;
455a7b23
SB
1113
1114 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
455a7b23
SB
1115 kfree(dev->prev_data);
1116 dev->prev_data = NULL;
1117
e8b29224 1118 err = cmd_start(dev, uid, opalmethod[OPAL_GENKEY]);
455a7b23
SB
1119
1120 if (err) {
591c59d1 1121 pr_debug("Error building gen key command\n");
455a7b23
SB
1122 return err;
1123
1124 }
1125 return finalize_and_send(dev, parse_and_check_status);
1126}
1127
1128static int get_active_key_cont(struct opal_dev *dev)
1129{
1130 const char *activekey;
1131 size_t keylen;
1132 int error = 0;
1133
1134 error = parse_and_check_status(dev);
1135 if (error)
1136 return error;
1137 keylen = response_get_string(&dev->parsed, 4, &activekey);
1138 if (!activekey) {
591c59d1
SB
1139 pr_debug("%s: Couldn't extract the Activekey from the response\n",
1140 __func__);
455a7b23
SB
1141 return OPAL_INVAL_PARAM;
1142 }
1143 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1144
1145 if (!dev->prev_data)
1146 return -ENOMEM;
1147
1148 dev->prev_d_len = keylen;
1149
1150 return 0;
1151}
1152
eed64951 1153static int get_active_key(struct opal_dev *dev, void *data)
455a7b23
SB
1154{
1155 u8 uid[OPAL_UID_LENGTH];
e8b29224 1156 int err;
eed64951 1157 u8 *lr = data;
455a7b23 1158
455a7b23
SB
1159 err = build_locking_range(uid, sizeof(uid), *lr);
1160 if (err)
1161 return err;
1162
3fff234b
DK
1163 err = generic_get_column(dev, uid, OPAL_ACTIVEKEY);
1164 if (err)
455a7b23 1165 return err;
455a7b23 1166
3fff234b 1167 return get_active_key_cont(dev);
455a7b23
SB
1168}
1169
1170static int generic_lr_enable_disable(struct opal_dev *dev,
1171 u8 *uid, bool rle, bool wle,
1172 bool rl, bool wl)
1173{
e8b29224 1174 int err;
455a7b23 1175
e8b29224 1176 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23 1177
455a7b23
SB
1178 add_token_u8(&err, dev, OPAL_STARTNAME);
1179 add_token_u8(&err, dev, OPAL_VALUES);
1180 add_token_u8(&err, dev, OPAL_STARTLIST);
1181
1182 add_token_u8(&err, dev, OPAL_STARTNAME);
1183 add_token_u8(&err, dev, 5); /* ReadLockEnabled */
1184 add_token_u8(&err, dev, rle);
1185 add_token_u8(&err, dev, OPAL_ENDNAME);
1186
1187 add_token_u8(&err, dev, OPAL_STARTNAME);
1188 add_token_u8(&err, dev, 6); /* WriteLockEnabled */
1189 add_token_u8(&err, dev, wle);
1190 add_token_u8(&err, dev, OPAL_ENDNAME);
1191
1192 add_token_u8(&err, dev, OPAL_STARTNAME);
1193 add_token_u8(&err, dev, OPAL_READLOCKED);
1194 add_token_u8(&err, dev, rl);
1195 add_token_u8(&err, dev, OPAL_ENDNAME);
1196
1197 add_token_u8(&err, dev, OPAL_STARTNAME);
1198 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1199 add_token_u8(&err, dev, wl);
1200 add_token_u8(&err, dev, OPAL_ENDNAME);
1201
1202 add_token_u8(&err, dev, OPAL_ENDLIST);
1203 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1204 return err;
1205}
1206
1207static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1208 struct opal_user_lr_setup *setup)
1209{
1210 int err;
1211
1212 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1213 0, 0);
1214 if (err)
591c59d1 1215 pr_debug("Failed to create enable global lr command\n");
455a7b23
SB
1216 return err;
1217}
1218
eed64951 1219static int setup_locking_range(struct opal_dev *dev, void *data)
455a7b23
SB
1220{
1221 u8 uid[OPAL_UID_LENGTH];
eed64951 1222 struct opal_user_lr_setup *setup = data;
455a7b23 1223 u8 lr;
e8b29224 1224 int err;
455a7b23 1225
455a7b23
SB
1226 lr = setup->session.opal_key.lr;
1227 err = build_locking_range(uid, sizeof(uid), lr);
1228 if (err)
1229 return err;
1230
1231 if (lr == 0)
1232 err = enable_global_lr(dev, uid, setup);
1233 else {
e8b29224 1234 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23 1235
455a7b23
SB
1236 add_token_u8(&err, dev, OPAL_STARTNAME);
1237 add_token_u8(&err, dev, OPAL_VALUES);
1238 add_token_u8(&err, dev, OPAL_STARTLIST);
1239
1240 add_token_u8(&err, dev, OPAL_STARTNAME);
1241 add_token_u8(&err, dev, 3); /* Ranges Start */
1242 add_token_u64(&err, dev, setup->range_start);
1243 add_token_u8(&err, dev, OPAL_ENDNAME);
1244
1245 add_token_u8(&err, dev, OPAL_STARTNAME);
1246 add_token_u8(&err, dev, 4); /* Ranges length */
1247 add_token_u64(&err, dev, setup->range_length);
1248 add_token_u8(&err, dev, OPAL_ENDNAME);
1249
1250 add_token_u8(&err, dev, OPAL_STARTNAME);
1251 add_token_u8(&err, dev, 5); /*ReadLockEnabled */
1252 add_token_u64(&err, dev, !!setup->RLE);
1253 add_token_u8(&err, dev, OPAL_ENDNAME);
1254
1255 add_token_u8(&err, dev, OPAL_STARTNAME);
1256 add_token_u8(&err, dev, 6); /*WriteLockEnabled*/
1257 add_token_u64(&err, dev, !!setup->WLE);
1258 add_token_u8(&err, dev, OPAL_ENDNAME);
1259
1260 add_token_u8(&err, dev, OPAL_ENDLIST);
1261 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1262 }
1263 if (err) {
591c59d1 1264 pr_debug("Error building Setup Locking range command.\n");
455a7b23
SB
1265 return err;
1266
1267 }
1268
1269 return finalize_and_send(dev, parse_and_check_status);
1270}
1271
1272static int start_generic_opal_session(struct opal_dev *dev,
1273 enum opal_uid auth,
1274 enum opal_uid sp_type,
1275 const char *key,
1276 u8 key_len)
1277{
1278 u32 hsn;
e8b29224 1279 int err;
455a7b23 1280
591c59d1 1281 if (key == NULL && auth != OPAL_ANYBODY_UID)
455a7b23 1282 return OPAL_INVAL_PARAM;
455a7b23 1283
455a7b23 1284 hsn = GENERIC_HOST_SESSION_NUM;
e8b29224
DK
1285 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1286 opalmethod[OPAL_STARTSESSION]);
455a7b23 1287
455a7b23
SB
1288 add_token_u64(&err, dev, hsn);
1289 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1290 add_token_u8(&err, dev, 1);
1291
1292 switch (auth) {
1293 case OPAL_ANYBODY_UID:
455a7b23
SB
1294 break;
1295 case OPAL_ADMIN1_UID:
1296 case OPAL_SID_UID:
1297 add_token_u8(&err, dev, OPAL_STARTNAME);
1298 add_token_u8(&err, dev, 0); /* HostChallenge */
1299 add_token_bytestring(&err, dev, key, key_len);
1300 add_token_u8(&err, dev, OPAL_ENDNAME);
1301 add_token_u8(&err, dev, OPAL_STARTNAME);
1302 add_token_u8(&err, dev, 3); /* HostSignAuth */
1303 add_token_bytestring(&err, dev, opaluid[auth],
1304 OPAL_UID_LENGTH);
1305 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1306 break;
1307 default:
591c59d1 1308 pr_debug("Cannot start Admin SP session with auth %d\n", auth);
455a7b23
SB
1309 return OPAL_INVAL_PARAM;
1310 }
1311
1312 if (err) {
591c59d1 1313 pr_debug("Error building start adminsp session command.\n");
455a7b23
SB
1314 return err;
1315 }
1316
1317 return finalize_and_send(dev, start_opal_session_cont);
1318}
1319
eed64951 1320static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1321{
1322 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1323 OPAL_ADMINSP_UID, NULL, 0);
1324}
1325
eed64951 1326static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1327{
1328 int ret;
1329 const u8 *key = dev->prev_data;
455a7b23
SB
1330
1331 if (!key) {
eed64951 1332 const struct opal_key *okey = data;
1e815b33 1333
455a7b23
SB
1334 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1335 OPAL_ADMINSP_UID,
1336 okey->key,
1337 okey->key_len);
1338 } else {
1339 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1340 OPAL_ADMINSP_UID,
1341 key, dev->prev_d_len);
1342 kfree(key);
1343 dev->prev_data = NULL;
1344 }
1345 return ret;
1346}
1347
eed64951 1348static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
455a7b23 1349{
eed64951 1350 struct opal_key *key = data;
1e815b33 1351
455a7b23
SB
1352 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1353 OPAL_LOCKINGSP_UID,
1354 key->key, key->key_len);
1355}
1356
eed64951 1357static int start_auth_opal_session(struct opal_dev *dev, void *data)
455a7b23 1358{
eed64951 1359 struct opal_session_info *session = data;
455a7b23 1360 u8 lk_ul_user[OPAL_UID_LENGTH];
eed64951 1361 size_t keylen = session->opal_key.key_len;
455a7b23
SB
1362 int err = 0;
1363
455a7b23
SB
1364 u8 *key = session->opal_key.key;
1365 u32 hsn = GENERIC_HOST_SESSION_NUM;
1366
e8b29224 1367 if (session->sum)
455a7b23
SB
1368 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1369 session->opal_key.lr);
e8b29224 1370 else if (session->who != OPAL_ADMIN1 && !session->sum)
455a7b23
SB
1371 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1372 session->who - 1);
e8b29224 1373 else
455a7b23
SB
1374 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1375
e8b29224
DK
1376 if (err)
1377 return err;
1378
1379 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1380 opalmethod[OPAL_STARTSESSION]);
455a7b23 1381
455a7b23
SB
1382 add_token_u64(&err, dev, hsn);
1383 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1384 OPAL_UID_LENGTH);
1385 add_token_u8(&err, dev, 1);
1386 add_token_u8(&err, dev, OPAL_STARTNAME);
1387 add_token_u8(&err, dev, 0);
1388 add_token_bytestring(&err, dev, key, keylen);
1389 add_token_u8(&err, dev, OPAL_ENDNAME);
1390 add_token_u8(&err, dev, OPAL_STARTNAME);
1391 add_token_u8(&err, dev, 3);
1392 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1393 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1394
1395 if (err) {
591c59d1 1396 pr_debug("Error building STARTSESSION command.\n");
455a7b23
SB
1397 return err;
1398 }
1399
1400 return finalize_and_send(dev, start_opal_session_cont);
1401}
1402
eed64951 1403static int revert_tper(struct opal_dev *dev, void *data)
455a7b23 1404{
e8b29224 1405 int err;
455a7b23 1406
e8b29224
DK
1407 err = cmd_start(dev, opaluid[OPAL_ADMINSP_UID],
1408 opalmethod[OPAL_REVERT]);
455a7b23 1409 if (err) {
591c59d1 1410 pr_debug("Error building REVERT TPER command.\n");
455a7b23
SB
1411 return err;
1412 }
1413
1414 return finalize_and_send(dev, parse_and_check_status);
1415}
1416
eed64951 1417static int internal_activate_user(struct opal_dev *dev, void *data)
455a7b23 1418{
eed64951 1419 struct opal_session_info *session = data;
455a7b23 1420 u8 uid[OPAL_UID_LENGTH];
e8b29224 1421 int err;
455a7b23
SB
1422
1423 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1424 uid[7] = session->who;
1425
e8b29224 1426 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23
SB
1427 add_token_u8(&err, dev, OPAL_STARTNAME);
1428 add_token_u8(&err, dev, OPAL_VALUES);
1429 add_token_u8(&err, dev, OPAL_STARTLIST);
1430 add_token_u8(&err, dev, OPAL_STARTNAME);
1431 add_token_u8(&err, dev, 5); /* Enabled */
1432 add_token_u8(&err, dev, OPAL_TRUE);
1433 add_token_u8(&err, dev, OPAL_ENDNAME);
1434 add_token_u8(&err, dev, OPAL_ENDLIST);
1435 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1436
1437 if (err) {
591c59d1 1438 pr_debug("Error building Activate UserN command.\n");
455a7b23
SB
1439 return err;
1440 }
1441
1442 return finalize_and_send(dev, parse_and_check_status);
1443}
1444
eed64951 1445static int erase_locking_range(struct opal_dev *dev, void *data)
455a7b23 1446{
eed64951 1447 struct opal_session_info *session = data;
455a7b23 1448 u8 uid[OPAL_UID_LENGTH];
e8b29224 1449 int err;
455a7b23
SB
1450
1451 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1452 return -ERANGE;
1453
e8b29224 1454 err = cmd_start(dev, uid, opalmethod[OPAL_ERASE]);
455a7b23
SB
1455
1456 if (err) {
591c59d1 1457 pr_debug("Error building Erase Locking Range Command.\n");
455a7b23
SB
1458 return err;
1459 }
1460 return finalize_and_send(dev, parse_and_check_status);
1461}
1462
eed64951 1463static int set_mbr_done(struct opal_dev *dev, void *data)
455a7b23 1464{
eed64951 1465 u8 *mbr_done_tf = data;
e8b29224 1466 int err;
455a7b23 1467
e8b29224
DK
1468 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1469 opalmethod[OPAL_SET]);
455a7b23 1470
455a7b23
SB
1471 add_token_u8(&err, dev, OPAL_STARTNAME);
1472 add_token_u8(&err, dev, OPAL_VALUES);
1473 add_token_u8(&err, dev, OPAL_STARTLIST);
1474 add_token_u8(&err, dev, OPAL_STARTNAME);
1475 add_token_u8(&err, dev, 2); /* Done */
eed64951 1476 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
455a7b23
SB
1477 add_token_u8(&err, dev, OPAL_ENDNAME);
1478 add_token_u8(&err, dev, OPAL_ENDLIST);
1479 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1480
1481 if (err) {
591c59d1 1482 pr_debug("Error Building set MBR Done command\n");
455a7b23
SB
1483 return err;
1484 }
1485
1486 return finalize_and_send(dev, parse_and_check_status);
1487}
1488
eed64951 1489static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
455a7b23 1490{
eed64951 1491 u8 *mbr_en_dis = data;
e8b29224 1492 int err;
455a7b23 1493
e8b29224
DK
1494 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1495 opalmethod[OPAL_SET]);
455a7b23 1496
455a7b23
SB
1497 add_token_u8(&err, dev, OPAL_STARTNAME);
1498 add_token_u8(&err, dev, OPAL_VALUES);
1499 add_token_u8(&err, dev, OPAL_STARTLIST);
1500 add_token_u8(&err, dev, OPAL_STARTNAME);
1501 add_token_u8(&err, dev, 1);
eed64951 1502 add_token_u8(&err, dev, *mbr_en_dis);
455a7b23
SB
1503 add_token_u8(&err, dev, OPAL_ENDNAME);
1504 add_token_u8(&err, dev, OPAL_ENDLIST);
1505 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1506
1507 if (err) {
591c59d1 1508 pr_debug("Error Building set MBR done command\n");
455a7b23
SB
1509 return err;
1510 }
1511
1512 return finalize_and_send(dev, parse_and_check_status);
1513}
1514
1515static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1516 struct opal_dev *dev)
1517{
e8b29224 1518 int err;
455a7b23 1519
e8b29224 1520 err = cmd_start(dev, cpin_uid, opalmethod[OPAL_SET]);
455a7b23 1521
455a7b23
SB
1522 add_token_u8(&err, dev, OPAL_STARTNAME);
1523 add_token_u8(&err, dev, OPAL_VALUES);
1524 add_token_u8(&err, dev, OPAL_STARTLIST);
1525 add_token_u8(&err, dev, OPAL_STARTNAME);
1526 add_token_u8(&err, dev, 3); /* PIN */
1527 add_token_bytestring(&err, dev, key, key_len);
1528 add_token_u8(&err, dev, OPAL_ENDNAME);
1529 add_token_u8(&err, dev, OPAL_ENDLIST);
1530 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1531
1532 return err;
1533}
1534
eed64951 1535static int set_new_pw(struct opal_dev *dev, void *data)
455a7b23
SB
1536{
1537 u8 cpin_uid[OPAL_UID_LENGTH];
eed64951 1538 struct opal_session_info *usr = data;
455a7b23
SB
1539
1540 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1541
1542 if (usr->who != OPAL_ADMIN1) {
1543 cpin_uid[5] = 0x03;
1544 if (usr->sum)
1545 cpin_uid[7] = usr->opal_key.lr + 1;
1546 else
1547 cpin_uid[7] = usr->who;
1548 }
1549
1550 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1551 cpin_uid, dev)) {
591c59d1 1552 pr_debug("Error building set password command.\n");
455a7b23
SB
1553 return -ERANGE;
1554 }
1555
1556 return finalize_and_send(dev, parse_and_check_status);
1557}
1558
eed64951 1559static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
455a7b23
SB
1560{
1561 u8 cpin_uid[OPAL_UID_LENGTH];
eed64951 1562 struct opal_key *key = data;
455a7b23
SB
1563
1564 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1565
1566 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
591c59d1 1567 pr_debug("Error building Set SID cpin\n");
455a7b23
SB
1568 return -ERANGE;
1569 }
1570 return finalize_and_send(dev, parse_and_check_status);
1571}
1572
eed64951 1573static int add_user_to_lr(struct opal_dev *dev, void *data)
455a7b23
SB
1574{
1575 u8 lr_buffer[OPAL_UID_LENGTH];
1576 u8 user_uid[OPAL_UID_LENGTH];
eed64951 1577 struct opal_lock_unlock *lkul = data;
e8b29224 1578 int err;
455a7b23 1579
455a7b23
SB
1580 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1581 OPAL_UID_LENGTH);
1582
1583 if (lkul->l_state == OPAL_RW)
1584 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1585 OPAL_UID_LENGTH);
1586
1587 lr_buffer[7] = lkul->session.opal_key.lr;
1588
1589 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1590
1591 user_uid[7] = lkul->session.who;
1592
e8b29224 1593 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
455a7b23 1594
455a7b23
SB
1595 add_token_u8(&err, dev, OPAL_STARTNAME);
1596 add_token_u8(&err, dev, OPAL_VALUES);
1597
1598 add_token_u8(&err, dev, OPAL_STARTLIST);
1599 add_token_u8(&err, dev, OPAL_STARTNAME);
1600 add_token_u8(&err, dev, 3);
1601
1602 add_token_u8(&err, dev, OPAL_STARTLIST);
1603
1604
1605 add_token_u8(&err, dev, OPAL_STARTNAME);
1606 add_token_bytestring(&err, dev,
1607 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1608 OPAL_UID_LENGTH/2);
1609 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1610 add_token_u8(&err, dev, OPAL_ENDNAME);
1611
1612
1613 add_token_u8(&err, dev, OPAL_STARTNAME);
1614 add_token_bytestring(&err, dev,
1615 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1616 OPAL_UID_LENGTH/2);
1617 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1618 add_token_u8(&err, dev, OPAL_ENDNAME);
1619
1620
1621 add_token_u8(&err, dev, OPAL_STARTNAME);
1622 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1623 OPAL_UID_LENGTH/2);
1624 add_token_u8(&err, dev, 1);
1625 add_token_u8(&err, dev, OPAL_ENDNAME);
1626
1627
1628 add_token_u8(&err, dev, OPAL_ENDLIST);
1629 add_token_u8(&err, dev, OPAL_ENDNAME);
1630 add_token_u8(&err, dev, OPAL_ENDLIST);
1631 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1632
1633 if (err) {
591c59d1 1634 pr_debug("Error building add user to locking range command.\n");
455a7b23
SB
1635 return err;
1636 }
1637
1638 return finalize_and_send(dev, parse_and_check_status);
1639}
1640
eed64951 1641static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
455a7b23
SB
1642{
1643 u8 lr_buffer[OPAL_UID_LENGTH];
eed64951 1644 struct opal_lock_unlock *lkul = data;
455a7b23
SB
1645 u8 read_locked = 1, write_locked = 1;
1646 int err = 0;
1647
455a7b23
SB
1648 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1649 lkul->session.opal_key.lr) < 0)
1650 return -ERANGE;
1651
1652 switch (lkul->l_state) {
1653 case OPAL_RO:
1654 read_locked = 0;
1655 write_locked = 1;
1656 break;
1657 case OPAL_RW:
1658 read_locked = 0;
1659 write_locked = 0;
1660 break;
1661 case OPAL_LK:
1e815b33 1662 /* vars are initialized to locked */
455a7b23
SB
1663 break;
1664 default:
591c59d1 1665 pr_debug("Tried to set an invalid locking state... returning to uland\n");
455a7b23
SB
1666 return OPAL_INVAL_PARAM;
1667 }
1668
e8b29224
DK
1669 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
1670
455a7b23
SB
1671 add_token_u8(&err, dev, OPAL_STARTNAME);
1672 add_token_u8(&err, dev, OPAL_VALUES);
1673 add_token_u8(&err, dev, OPAL_STARTLIST);
1674
1675 add_token_u8(&err, dev, OPAL_STARTNAME);
1676 add_token_u8(&err, dev, OPAL_READLOCKED);
1677 add_token_u8(&err, dev, read_locked);
1678 add_token_u8(&err, dev, OPAL_ENDNAME);
1679
1680 add_token_u8(&err, dev, OPAL_STARTNAME);
1681 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1682 add_token_u8(&err, dev, write_locked);
1683 add_token_u8(&err, dev, OPAL_ENDNAME);
1684
1685 add_token_u8(&err, dev, OPAL_ENDLIST);
1686 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1687
1688 if (err) {
591c59d1 1689 pr_debug("Error building SET command.\n");
455a7b23
SB
1690 return err;
1691 }
1692 return finalize_and_send(dev, parse_and_check_status);
1693}
1694
1695
eed64951 1696static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
455a7b23
SB
1697{
1698 u8 lr_buffer[OPAL_UID_LENGTH];
1699 u8 read_locked = 1, write_locked = 1;
eed64951 1700 struct opal_lock_unlock *lkul = data;
455a7b23
SB
1701 int ret;
1702
1703 clear_opal_cmd(dev);
1704 set_comid(dev, dev->comid);
1705
455a7b23
SB
1706 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1707 lkul->session.opal_key.lr) < 0)
1708 return -ERANGE;
1709
1710 switch (lkul->l_state) {
1711 case OPAL_RO:
1712 read_locked = 0;
1713 write_locked = 1;
1714 break;
1715 case OPAL_RW:
1716 read_locked = 0;
1717 write_locked = 0;
1718 break;
1719 case OPAL_LK:
1e815b33 1720 /* vars are initialized to locked */
455a7b23
SB
1721 break;
1722 default:
591c59d1 1723 pr_debug("Tried to set an invalid locking state.\n");
455a7b23
SB
1724 return OPAL_INVAL_PARAM;
1725 }
1726 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1727 read_locked, write_locked);
1728
1729 if (ret < 0) {
591c59d1 1730 pr_debug("Error building SET command.\n");
455a7b23
SB
1731 return ret;
1732 }
1733 return finalize_and_send(dev, parse_and_check_status);
1734}
1735
eed64951 1736static int activate_lsp(struct opal_dev *dev, void *data)
455a7b23 1737{
eed64951 1738 struct opal_lr_act *opal_act = data;
455a7b23
SB
1739 u8 user_lr[OPAL_UID_LENGTH];
1740 u8 uint_3 = 0x83;
e8b29224 1741 int err, i;
455a7b23 1742
e8b29224
DK
1743 err = cmd_start(dev, opaluid[OPAL_LOCKINGSP_UID],
1744 opalmethod[OPAL_ACTIVATE]);
455a7b23
SB
1745
1746 if (opal_act->sum) {
1747 err = build_locking_range(user_lr, sizeof(user_lr),
1748 opal_act->lr[0]);
1749 if (err)
1750 return err;
1751
455a7b23
SB
1752 add_token_u8(&err, dev, OPAL_STARTNAME);
1753 add_token_u8(&err, dev, uint_3);
1754 add_token_u8(&err, dev, 6);
1755 add_token_u8(&err, dev, 0);
1756 add_token_u8(&err, dev, 0);
1757
1758 add_token_u8(&err, dev, OPAL_STARTLIST);
1759 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1760 for (i = 1; i < opal_act->num_lrs; i++) {
1761 user_lr[7] = opal_act->lr[i];
1762 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1763 }
1764 add_token_u8(&err, dev, OPAL_ENDLIST);
1765 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1766 }
1767
1768 if (err) {
591c59d1 1769 pr_debug("Error building Activate LockingSP command.\n");
455a7b23
SB
1770 return err;
1771 }
1772
1773 return finalize_and_send(dev, parse_and_check_status);
1774}
1775
3fff234b
DK
1776/* Determine if we're in the Manufactured Inactive or Active state */
1777static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
455a7b23
SB
1778{
1779 u8 lc_status;
3fff234b 1780 int err;
455a7b23 1781
3fff234b
DK
1782 err = generic_get_column(dev, opaluid[OPAL_LOCKINGSP_UID],
1783 OPAL_LIFECYCLE);
1784 if (err)
1785 return err;
455a7b23
SB
1786
1787 lc_status = response_get_u64(&dev->parsed, 4);
1e815b33 1788 /* 0x08 is Manufactured Inactive */
455a7b23
SB
1789 /* 0x09 is Manufactured */
1790 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
591c59d1 1791 pr_debug("Couldn't determine the status of the Lifecycle state\n");
455a7b23
SB
1792 return -ENODEV;
1793 }
1794
1795 return 0;
1796}
1797
3fff234b 1798static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
455a7b23
SB
1799{
1800 const char *msid_pin;
1801 size_t strlen;
3fff234b 1802 int err;
455a7b23 1803
3fff234b
DK
1804 err = generic_get_column(dev, opaluid[OPAL_C_PIN_MSID], OPAL_PIN);
1805 if (err)
1806 return err;
455a7b23
SB
1807
1808 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1809 if (!msid_pin) {
3fff234b 1810 pr_debug("Couldn't extract MSID_CPIN from response\n");
455a7b23
SB
1811 return OPAL_INVAL_PARAM;
1812 }
1813
1814 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1815 if (!dev->prev_data)
1816 return -ENOMEM;
1817
1818 dev->prev_d_len = strlen;
1819
1820 return 0;
1821}
1822
eed64951 1823static int end_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1824{
1825 int err = 0;
1826
1827 clear_opal_cmd(dev);
455a7b23
SB
1828 set_comid(dev, dev->comid);
1829 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
455a7b23 1830
eed64951
JD
1831 if (err < 0)
1832 return err;
455a7b23
SB
1833 return finalize_and_send(dev, end_session_cont);
1834}
1835
1836static int end_opal_session_error(struct opal_dev *dev)
1837{
eed64951
JD
1838 const struct opal_step error_end_session[] = {
1839 { end_opal_session, },
1840 { NULL, }
455a7b23 1841 };
eed64951 1842 dev->steps = error_end_session;
455a7b23
SB
1843 return next(dev);
1844}
1845
1846static inline void setup_opal_dev(struct opal_dev *dev,
eed64951 1847 const struct opal_step *steps)
455a7b23 1848{
eed64951 1849 dev->steps = steps;
455a7b23
SB
1850 dev->tsn = 0;
1851 dev->hsn = 0;
455a7b23
SB
1852 dev->prev_data = NULL;
1853}
1854
1855static int check_opal_support(struct opal_dev *dev)
1856{
eed64951
JD
1857 const struct opal_step steps[] = {
1858 { opal_discovery0, },
1859 { NULL, }
455a7b23
SB
1860 };
1861 int ret;
1862
1863 mutex_lock(&dev->dev_lock);
eed64951 1864 setup_opal_dev(dev, steps);
455a7b23
SB
1865 ret = next(dev);
1866 dev->supported = !ret;
1867 mutex_unlock(&dev->dev_lock);
1868 return ret;
1869}
1870
7d6d1578
SB
1871static void clean_opal_dev(struct opal_dev *dev)
1872{
1873
1874 struct opal_suspend_data *suspend, *next;
1875
1876 mutex_lock(&dev->dev_lock);
1877 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
1878 list_del(&suspend->node);
1879 kfree(suspend);
1880 }
1881 mutex_unlock(&dev->dev_lock);
1882}
1883
1884void free_opal_dev(struct opal_dev *dev)
1885{
1886 if (!dev)
1887 return;
1888 clean_opal_dev(dev);
1889 kfree(dev);
1890}
1891EXPORT_SYMBOL(free_opal_dev);
1892
4f1244c8 1893struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
455a7b23 1894{
4f1244c8
CH
1895 struct opal_dev *dev;
1896
1897 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
1898 if (!dev)
1899 return NULL;
1900
1901 INIT_LIST_HEAD(&dev->unlk_lst);
1902 mutex_init(&dev->dev_lock);
1903 dev->data = data;
1904 dev->send_recv = send_recv;
1905 if (check_opal_support(dev) != 0) {
f5b37b7c 1906 pr_debug("Opal is not supported on this device\n");
4f1244c8
CH
1907 kfree(dev);
1908 return NULL;
1909 }
1910 return dev;
455a7b23
SB
1911}
1912EXPORT_SYMBOL(init_opal_dev);
1913
1914static int opal_secure_erase_locking_range(struct opal_dev *dev,
1915 struct opal_session_info *opal_session)
1916{
eed64951
JD
1917 const struct opal_step erase_steps[] = {
1918 { opal_discovery0, },
1919 { start_auth_opal_session, opal_session },
1920 { get_active_key, &opal_session->opal_key.lr },
1921 { gen_key, },
1922 { end_opal_session, },
1923 { NULL, }
455a7b23
SB
1924 };
1925 int ret;
1926
1927 mutex_lock(&dev->dev_lock);
eed64951 1928 setup_opal_dev(dev, erase_steps);
455a7b23
SB
1929 ret = next(dev);
1930 mutex_unlock(&dev->dev_lock);
1931 return ret;
1932}
1933
1934static int opal_erase_locking_range(struct opal_dev *dev,
1935 struct opal_session_info *opal_session)
1936{
eed64951
JD
1937 const struct opal_step erase_steps[] = {
1938 { opal_discovery0, },
1939 { start_auth_opal_session, opal_session },
1940 { erase_locking_range, opal_session },
1941 { end_opal_session, },
1942 { NULL, }
455a7b23
SB
1943 };
1944 int ret;
1945
1946 mutex_lock(&dev->dev_lock);
eed64951 1947 setup_opal_dev(dev, erase_steps);
455a7b23
SB
1948 ret = next(dev);
1949 mutex_unlock(&dev->dev_lock);
1950 return ret;
1951}
1952
1953static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
1954 struct opal_mbr_data *opal_mbr)
1955{
78bf4735
DK
1956 u8 enable_disable = opal_mbr->enable_disable == OPAL_MBR_ENABLE ?
1957 OPAL_TRUE : OPAL_FALSE;
1958
eed64951
JD
1959 const struct opal_step mbr_steps[] = {
1960 { opal_discovery0, },
1961 { start_admin1LSP_opal_session, &opal_mbr->key },
78bf4735 1962 { set_mbr_done, &enable_disable },
eed64951
JD
1963 { end_opal_session, },
1964 { start_admin1LSP_opal_session, &opal_mbr->key },
78bf4735 1965 { set_mbr_enable_disable, &enable_disable },
eed64951
JD
1966 { end_opal_session, },
1967 { NULL, }
455a7b23
SB
1968 };
1969 int ret;
1970
1971 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
1972 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
1973 return -EINVAL;
1974
1975 mutex_lock(&dev->dev_lock);
eed64951 1976 setup_opal_dev(dev, mbr_steps);
455a7b23
SB
1977 ret = next(dev);
1978 mutex_unlock(&dev->dev_lock);
1979 return ret;
1980}
1981
1982static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
1983{
1984 struct opal_suspend_data *suspend;
1985
1986 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
1987 if (!suspend)
1988 return -ENOMEM;
1989
1990 suspend->unlk = *lk_unlk;
1991 suspend->lr = lk_unlk->session.opal_key.lr;
1992
1993 mutex_lock(&dev->dev_lock);
1994 setup_opal_dev(dev, NULL);
1995 add_suspend_info(dev, suspend);
1996 mutex_unlock(&dev->dev_lock);
1997 return 0;
1998}
1999
2000static int opal_add_user_to_lr(struct opal_dev *dev,
2001 struct opal_lock_unlock *lk_unlk)
2002{
eed64951
JD
2003 const struct opal_step steps[] = {
2004 { opal_discovery0, },
2005 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2006 { add_user_to_lr, lk_unlk },
2007 { end_opal_session, },
2008 { NULL, }
455a7b23
SB
2009 };
2010 int ret;
2011
2012 if (lk_unlk->l_state != OPAL_RO &&
2013 lk_unlk->l_state != OPAL_RW) {
591c59d1 2014 pr_debug("Locking state was not RO or RW\n");
455a7b23
SB
2015 return -EINVAL;
2016 }
b0bfdfc2 2017 if (lk_unlk->session.who < OPAL_USER1 ||
455a7b23 2018 lk_unlk->session.who > OPAL_USER9) {
591c59d1
SB
2019 pr_debug("Authority was not within the range of users: %d\n",
2020 lk_unlk->session.who);
455a7b23
SB
2021 return -EINVAL;
2022 }
2023 if (lk_unlk->session.sum) {
591c59d1
SB
2024 pr_debug("%s not supported in sum. Use setup locking range\n",
2025 __func__);
455a7b23
SB
2026 return -EINVAL;
2027 }
2028
2029 mutex_lock(&dev->dev_lock);
eed64951 2030 setup_opal_dev(dev, steps);
455a7b23
SB
2031 ret = next(dev);
2032 mutex_unlock(&dev->dev_lock);
2033 return ret;
2034}
2035
2036static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal)
2037{
eed64951
JD
2038 const struct opal_step revert_steps[] = {
2039 { opal_discovery0, },
2040 { start_SIDASP_opal_session, opal },
2041 { revert_tper, }, /* controller will terminate session */
2042 { NULL, }
455a7b23
SB
2043 };
2044 int ret;
2045
2046 mutex_lock(&dev->dev_lock);
eed64951 2047 setup_opal_dev(dev, revert_steps);
455a7b23
SB
2048 ret = next(dev);
2049 mutex_unlock(&dev->dev_lock);
7d6d1578
SB
2050
2051 /*
2052 * If we successfully reverted lets clean
2053 * any saved locking ranges.
2054 */
2055 if (!ret)
2056 clean_opal_dev(dev);
2057
455a7b23
SB
2058 return ret;
2059}
2060
eed64951
JD
2061static int __opal_lock_unlock(struct opal_dev *dev,
2062 struct opal_lock_unlock *lk_unlk)
455a7b23 2063{
eed64951
JD
2064 const struct opal_step unlock_steps[] = {
2065 { opal_discovery0, },
2066 { start_auth_opal_session, &lk_unlk->session },
2067 { lock_unlock_locking_range, lk_unlk },
2068 { end_opal_session, },
2069 { NULL, }
455a7b23 2070 };
eed64951
JD
2071 const struct opal_step unlock_sum_steps[] = {
2072 { opal_discovery0, },
2073 { start_auth_opal_session, &lk_unlk->session },
2074 { lock_unlock_locking_range_sum, lk_unlk },
2075 { end_opal_session, },
2076 { NULL, }
455a7b23
SB
2077 };
2078
eed64951 2079 dev->steps = lk_unlk->session.sum ? unlock_sum_steps : unlock_steps;
455a7b23
SB
2080 return next(dev);
2081}
2082
dbec491b
SB
2083static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
2084{
78bf4735 2085 u8 mbr_done_tf = OPAL_TRUE;
1e815b33 2086 const struct opal_step mbrdone_step[] = {
dbec491b
SB
2087 { opal_discovery0, },
2088 { start_admin1LSP_opal_session, key },
2089 { set_mbr_done, &mbr_done_tf },
2090 { end_opal_session, },
2091 { NULL, }
2092 };
2093
2094 dev->steps = mbrdone_step;
2095 return next(dev);
2096}
2097
eed64951
JD
2098static int opal_lock_unlock(struct opal_dev *dev,
2099 struct opal_lock_unlock *lk_unlk)
455a7b23 2100{
455a7b23
SB
2101 int ret;
2102
2103 if (lk_unlk->session.who < OPAL_ADMIN1 ||
2104 lk_unlk->session.who > OPAL_USER9)
2105 return -EINVAL;
2106
2107 mutex_lock(&dev->dev_lock);
eed64951 2108 ret = __opal_lock_unlock(dev, lk_unlk);
455a7b23
SB
2109 mutex_unlock(&dev->dev_lock);
2110 return ret;
2111}
2112
2113static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2114{
eed64951
JD
2115 const struct opal_step owner_steps[] = {
2116 { opal_discovery0, },
2117 { start_anybodyASP_opal_session, },
2118 { get_msid_cpin_pin, },
2119 { end_opal_session, },
2120 { start_SIDASP_opal_session, opal },
2121 { set_sid_cpin_pin, opal },
2122 { end_opal_session, },
2123 { NULL, }
455a7b23 2124 };
455a7b23
SB
2125 int ret;
2126
2127 if (!dev)
2128 return -ENODEV;
2129
2130 mutex_lock(&dev->dev_lock);
eed64951 2131 setup_opal_dev(dev, owner_steps);
455a7b23
SB
2132 ret = next(dev);
2133 mutex_unlock(&dev->dev_lock);
2134 return ret;
2135}
2136
1e815b33
DK
2137static int opal_activate_lsp(struct opal_dev *dev,
2138 struct opal_lr_act *opal_lr_act)
455a7b23 2139{
eed64951
JD
2140 const struct opal_step active_steps[] = {
2141 { opal_discovery0, },
2142 { start_SIDASP_opal_session, &opal_lr_act->key },
2143 { get_lsp_lifecycle, },
2144 { activate_lsp, opal_lr_act },
2145 { end_opal_session, },
2146 { NULL, }
455a7b23
SB
2147 };
2148 int ret;
2149
2150 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2151 return -EINVAL;
2152
2153 mutex_lock(&dev->dev_lock);
eed64951 2154 setup_opal_dev(dev, active_steps);
455a7b23
SB
2155 ret = next(dev);
2156 mutex_unlock(&dev->dev_lock);
2157 return ret;
2158}
2159
2160static int opal_setup_locking_range(struct opal_dev *dev,
2161 struct opal_user_lr_setup *opal_lrs)
2162{
eed64951
JD
2163 const struct opal_step lr_steps[] = {
2164 { opal_discovery0, },
2165 { start_auth_opal_session, &opal_lrs->session },
2166 { setup_locking_range, opal_lrs },
2167 { end_opal_session, },
2168 { NULL, }
455a7b23
SB
2169 };
2170 int ret;
2171
2172 mutex_lock(&dev->dev_lock);
eed64951 2173 setup_opal_dev(dev, lr_steps);
455a7b23
SB
2174 ret = next(dev);
2175 mutex_unlock(&dev->dev_lock);
2176 return ret;
2177}
2178
2179static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2180{
eed64951
JD
2181 const struct opal_step pw_steps[] = {
2182 { opal_discovery0, },
2183 { start_auth_opal_session, &opal_pw->session },
2184 { set_new_pw, &opal_pw->new_user_pw },
2185 { end_opal_session, },
2186 { NULL }
455a7b23 2187 };
455a7b23
SB
2188 int ret;
2189
2190 if (opal_pw->session.who < OPAL_ADMIN1 ||
2191 opal_pw->session.who > OPAL_USER9 ||
2192 opal_pw->new_user_pw.who < OPAL_ADMIN1 ||
2193 opal_pw->new_user_pw.who > OPAL_USER9)
2194 return -EINVAL;
2195
2196 mutex_lock(&dev->dev_lock);
eed64951 2197 setup_opal_dev(dev, pw_steps);
455a7b23
SB
2198 ret = next(dev);
2199 mutex_unlock(&dev->dev_lock);
2200 return ret;
2201}
2202
2203static int opal_activate_user(struct opal_dev *dev,
2204 struct opal_session_info *opal_session)
2205{
eed64951
JD
2206 const struct opal_step act_steps[] = {
2207 { opal_discovery0, },
2208 { start_admin1LSP_opal_session, &opal_session->opal_key },
2209 { internal_activate_user, opal_session },
2210 { end_opal_session, },
2211 { NULL, }
455a7b23 2212 };
455a7b23
SB
2213 int ret;
2214
2215 /* We can't activate Admin1 it's active as manufactured */
b0bfdfc2 2216 if (opal_session->who < OPAL_USER1 ||
455a7b23 2217 opal_session->who > OPAL_USER9) {
591c59d1 2218 pr_debug("Who was not a valid user: %d\n", opal_session->who);
455a7b23
SB
2219 return -EINVAL;
2220 }
2221
2222 mutex_lock(&dev->dev_lock);
eed64951 2223 setup_opal_dev(dev, act_steps);
455a7b23
SB
2224 ret = next(dev);
2225 mutex_unlock(&dev->dev_lock);
2226 return ret;
2227}
2228
2229bool opal_unlock_from_suspend(struct opal_dev *dev)
2230{
2231 struct opal_suspend_data *suspend;
455a7b23
SB
2232 bool was_failure = false;
2233 int ret = 0;
2234
2235 if (!dev)
2236 return false;
2237 if (!dev->supported)
2238 return false;
2239
2240 mutex_lock(&dev->dev_lock);
2241 setup_opal_dev(dev, NULL);
455a7b23
SB
2242
2243 list_for_each_entry(suspend, &dev->unlk_lst, node) {
455a7b23
SB
2244 dev->tsn = 0;
2245 dev->hsn = 0;
2246
eed64951 2247 ret = __opal_lock_unlock(dev, &suspend->unlk);
455a7b23 2248 if (ret) {
591c59d1
SB
2249 pr_debug("Failed to unlock LR %hhu with sum %d\n",
2250 suspend->unlk.session.opal_key.lr,
2251 suspend->unlk.session.sum);
455a7b23
SB
2252 was_failure = true;
2253 }
dbec491b
SB
2254 if (dev->mbr_enabled) {
2255 ret = __opal_set_mbr_done(dev, &suspend->unlk.session.opal_key);
2256 if (ret)
2257 pr_debug("Failed to set MBR Done in S3 resume\n");
2258 }
455a7b23
SB
2259 }
2260 mutex_unlock(&dev->dev_lock);
2261 return was_failure;
2262}
2263EXPORT_SYMBOL(opal_unlock_from_suspend);
2264
e225c20e 2265int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
455a7b23 2266{
e225c20e
SB
2267 void *p;
2268 int ret = -ENOTTY;
455a7b23
SB
2269
2270 if (!capable(CAP_SYS_ADMIN))
2271 return -EACCES;
4f1244c8
CH
2272 if (!dev)
2273 return -ENOTSUPP;
591c59d1 2274 if (!dev->supported)
455a7b23 2275 return -ENOTSUPP;
455a7b23 2276
eed64951 2277 p = memdup_user(arg, _IOC_SIZE(cmd));
e225c20e
SB
2278 if (IS_ERR(p))
2279 return PTR_ERR(p);
455a7b23 2280
e225c20e
SB
2281 switch (cmd) {
2282 case IOC_OPAL_SAVE:
2283 ret = opal_save(dev, p);
2284 break;
2285 case IOC_OPAL_LOCK_UNLOCK:
2286 ret = opal_lock_unlock(dev, p);
2287 break;
2288 case IOC_OPAL_TAKE_OWNERSHIP:
2289 ret = opal_take_ownership(dev, p);
2290 break;
2291 case IOC_OPAL_ACTIVATE_LSP:
2292 ret = opal_activate_lsp(dev, p);
2293 break;
2294 case IOC_OPAL_SET_PW:
2295 ret = opal_set_new_pw(dev, p);
2296 break;
2297 case IOC_OPAL_ACTIVATE_USR:
2298 ret = opal_activate_user(dev, p);
2299 break;
2300 case IOC_OPAL_REVERT_TPR:
2301 ret = opal_reverttper(dev, p);
2302 break;
2303 case IOC_OPAL_LR_SETUP:
2304 ret = opal_setup_locking_range(dev, p);
2305 break;
2306 case IOC_OPAL_ADD_USR_TO_LR:
2307 ret = opal_add_user_to_lr(dev, p);
2308 break;
2309 case IOC_OPAL_ENABLE_DISABLE_MBR:
2310 ret = opal_enable_disable_shadow_mbr(dev, p);
2311 break;
2312 case IOC_OPAL_ERASE_LR:
2313 ret = opal_erase_locking_range(dev, p);
2314 break;
2315 case IOC_OPAL_SECURE_ERASE_LR:
2316 ret = opal_secure_erase_locking_range(dev, p);
2317 break;
455a7b23 2318 default:
591c59d1 2319 break;
455a7b23 2320 }
e225c20e
SB
2321
2322 kfree(p);
2323 return ret;
455a7b23
SB
2324}
2325EXPORT_SYMBOL_GPL(sed_ioctl);