block: sed-opal: add token for OPAL_LIFECYCLE
[linux-2.6-block.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
eed64951 1078static int gen_key(struct opal_dev *dev, void *data)
455a7b23 1079{
455a7b23 1080 u8 uid[OPAL_UID_LENGTH];
e8b29224 1081 int err;
455a7b23
SB
1082
1083 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
455a7b23
SB
1084 kfree(dev->prev_data);
1085 dev->prev_data = NULL;
1086
e8b29224 1087 err = cmd_start(dev, uid, opalmethod[OPAL_GENKEY]);
455a7b23
SB
1088
1089 if (err) {
591c59d1 1090 pr_debug("Error building gen key command\n");
455a7b23
SB
1091 return err;
1092
1093 }
1094 return finalize_and_send(dev, parse_and_check_status);
1095}
1096
1097static int get_active_key_cont(struct opal_dev *dev)
1098{
1099 const char *activekey;
1100 size_t keylen;
1101 int error = 0;
1102
1103 error = parse_and_check_status(dev);
1104 if (error)
1105 return error;
1106 keylen = response_get_string(&dev->parsed, 4, &activekey);
1107 if (!activekey) {
591c59d1
SB
1108 pr_debug("%s: Couldn't extract the Activekey from the response\n",
1109 __func__);
455a7b23
SB
1110 return OPAL_INVAL_PARAM;
1111 }
1112 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1113
1114 if (!dev->prev_data)
1115 return -ENOMEM;
1116
1117 dev->prev_d_len = keylen;
1118
1119 return 0;
1120}
1121
eed64951 1122static int get_active_key(struct opal_dev *dev, void *data)
455a7b23
SB
1123{
1124 u8 uid[OPAL_UID_LENGTH];
e8b29224 1125 int err;
eed64951 1126 u8 *lr = data;
455a7b23 1127
455a7b23
SB
1128 err = build_locking_range(uid, sizeof(uid), *lr);
1129 if (err)
1130 return err;
1131
e8b29224 1132 err = cmd_start(dev, uid, opalmethod[OPAL_GET]);
455a7b23
SB
1133 add_token_u8(&err, dev, OPAL_STARTLIST);
1134 add_token_u8(&err, dev, OPAL_STARTNAME);
1135 add_token_u8(&err, dev, 3); /* startCloumn */
1136 add_token_u8(&err, dev, 10); /* ActiveKey */
1137 add_token_u8(&err, dev, OPAL_ENDNAME);
1138 add_token_u8(&err, dev, OPAL_STARTNAME);
1139 add_token_u8(&err, dev, 4); /* endColumn */
1140 add_token_u8(&err, dev, 10); /* ActiveKey */
1141 add_token_u8(&err, dev, OPAL_ENDNAME);
1142 add_token_u8(&err, dev, OPAL_ENDLIST);
455a7b23 1143 if (err) {
591c59d1 1144 pr_debug("Error building get active key command\n");
455a7b23
SB
1145 return err;
1146 }
1147
1148 return finalize_and_send(dev, get_active_key_cont);
1149}
1150
1151static int generic_lr_enable_disable(struct opal_dev *dev,
1152 u8 *uid, bool rle, bool wle,
1153 bool rl, bool wl)
1154{
e8b29224 1155 int err;
455a7b23 1156
e8b29224 1157 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23 1158
455a7b23
SB
1159 add_token_u8(&err, dev, OPAL_STARTNAME);
1160 add_token_u8(&err, dev, OPAL_VALUES);
1161 add_token_u8(&err, dev, OPAL_STARTLIST);
1162
1163 add_token_u8(&err, dev, OPAL_STARTNAME);
1164 add_token_u8(&err, dev, 5); /* ReadLockEnabled */
1165 add_token_u8(&err, dev, rle);
1166 add_token_u8(&err, dev, OPAL_ENDNAME);
1167
1168 add_token_u8(&err, dev, OPAL_STARTNAME);
1169 add_token_u8(&err, dev, 6); /* WriteLockEnabled */
1170 add_token_u8(&err, dev, wle);
1171 add_token_u8(&err, dev, OPAL_ENDNAME);
1172
1173 add_token_u8(&err, dev, OPAL_STARTNAME);
1174 add_token_u8(&err, dev, OPAL_READLOCKED);
1175 add_token_u8(&err, dev, rl);
1176 add_token_u8(&err, dev, OPAL_ENDNAME);
1177
1178 add_token_u8(&err, dev, OPAL_STARTNAME);
1179 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1180 add_token_u8(&err, dev, wl);
1181 add_token_u8(&err, dev, OPAL_ENDNAME);
1182
1183 add_token_u8(&err, dev, OPAL_ENDLIST);
1184 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1185 return err;
1186}
1187
1188static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1189 struct opal_user_lr_setup *setup)
1190{
1191 int err;
1192
1193 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1194 0, 0);
1195 if (err)
591c59d1 1196 pr_debug("Failed to create enable global lr command\n");
455a7b23
SB
1197 return err;
1198}
1199
eed64951 1200static int setup_locking_range(struct opal_dev *dev, void *data)
455a7b23
SB
1201{
1202 u8 uid[OPAL_UID_LENGTH];
eed64951 1203 struct opal_user_lr_setup *setup = data;
455a7b23 1204 u8 lr;
e8b29224 1205 int err;
455a7b23 1206
455a7b23
SB
1207 lr = setup->session.opal_key.lr;
1208 err = build_locking_range(uid, sizeof(uid), lr);
1209 if (err)
1210 return err;
1211
1212 if (lr == 0)
1213 err = enable_global_lr(dev, uid, setup);
1214 else {
e8b29224 1215 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23 1216
455a7b23
SB
1217 add_token_u8(&err, dev, OPAL_STARTNAME);
1218 add_token_u8(&err, dev, OPAL_VALUES);
1219 add_token_u8(&err, dev, OPAL_STARTLIST);
1220
1221 add_token_u8(&err, dev, OPAL_STARTNAME);
1222 add_token_u8(&err, dev, 3); /* Ranges Start */
1223 add_token_u64(&err, dev, setup->range_start);
1224 add_token_u8(&err, dev, OPAL_ENDNAME);
1225
1226 add_token_u8(&err, dev, OPAL_STARTNAME);
1227 add_token_u8(&err, dev, 4); /* Ranges length */
1228 add_token_u64(&err, dev, setup->range_length);
1229 add_token_u8(&err, dev, OPAL_ENDNAME);
1230
1231 add_token_u8(&err, dev, OPAL_STARTNAME);
1232 add_token_u8(&err, dev, 5); /*ReadLockEnabled */
1233 add_token_u64(&err, dev, !!setup->RLE);
1234 add_token_u8(&err, dev, OPAL_ENDNAME);
1235
1236 add_token_u8(&err, dev, OPAL_STARTNAME);
1237 add_token_u8(&err, dev, 6); /*WriteLockEnabled*/
1238 add_token_u64(&err, dev, !!setup->WLE);
1239 add_token_u8(&err, dev, OPAL_ENDNAME);
1240
1241 add_token_u8(&err, dev, OPAL_ENDLIST);
1242 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1243 }
1244 if (err) {
591c59d1 1245 pr_debug("Error building Setup Locking range command.\n");
455a7b23
SB
1246 return err;
1247
1248 }
1249
1250 return finalize_and_send(dev, parse_and_check_status);
1251}
1252
1253static int start_generic_opal_session(struct opal_dev *dev,
1254 enum opal_uid auth,
1255 enum opal_uid sp_type,
1256 const char *key,
1257 u8 key_len)
1258{
1259 u32 hsn;
e8b29224 1260 int err;
455a7b23 1261
591c59d1 1262 if (key == NULL && auth != OPAL_ANYBODY_UID)
455a7b23 1263 return OPAL_INVAL_PARAM;
455a7b23 1264
455a7b23 1265 hsn = GENERIC_HOST_SESSION_NUM;
e8b29224
DK
1266 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1267 opalmethod[OPAL_STARTSESSION]);
455a7b23 1268
455a7b23
SB
1269 add_token_u64(&err, dev, hsn);
1270 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1271 add_token_u8(&err, dev, 1);
1272
1273 switch (auth) {
1274 case OPAL_ANYBODY_UID:
455a7b23
SB
1275 break;
1276 case OPAL_ADMIN1_UID:
1277 case OPAL_SID_UID:
1278 add_token_u8(&err, dev, OPAL_STARTNAME);
1279 add_token_u8(&err, dev, 0); /* HostChallenge */
1280 add_token_bytestring(&err, dev, key, key_len);
1281 add_token_u8(&err, dev, OPAL_ENDNAME);
1282 add_token_u8(&err, dev, OPAL_STARTNAME);
1283 add_token_u8(&err, dev, 3); /* HostSignAuth */
1284 add_token_bytestring(&err, dev, opaluid[auth],
1285 OPAL_UID_LENGTH);
1286 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1287 break;
1288 default:
591c59d1 1289 pr_debug("Cannot start Admin SP session with auth %d\n", auth);
455a7b23
SB
1290 return OPAL_INVAL_PARAM;
1291 }
1292
1293 if (err) {
591c59d1 1294 pr_debug("Error building start adminsp session command.\n");
455a7b23
SB
1295 return err;
1296 }
1297
1298 return finalize_and_send(dev, start_opal_session_cont);
1299}
1300
eed64951 1301static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1302{
1303 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1304 OPAL_ADMINSP_UID, NULL, 0);
1305}
1306
eed64951 1307static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1308{
1309 int ret;
1310 const u8 *key = dev->prev_data;
455a7b23
SB
1311
1312 if (!key) {
eed64951 1313 const struct opal_key *okey = data;
1e815b33 1314
455a7b23
SB
1315 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1316 OPAL_ADMINSP_UID,
1317 okey->key,
1318 okey->key_len);
1319 } else {
1320 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1321 OPAL_ADMINSP_UID,
1322 key, dev->prev_d_len);
1323 kfree(key);
1324 dev->prev_data = NULL;
1325 }
1326 return ret;
1327}
1328
eed64951 1329static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
455a7b23 1330{
eed64951 1331 struct opal_key *key = data;
1e815b33 1332
455a7b23
SB
1333 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1334 OPAL_LOCKINGSP_UID,
1335 key->key, key->key_len);
1336}
1337
eed64951 1338static int start_auth_opal_session(struct opal_dev *dev, void *data)
455a7b23 1339{
eed64951 1340 struct opal_session_info *session = data;
455a7b23 1341 u8 lk_ul_user[OPAL_UID_LENGTH];
eed64951 1342 size_t keylen = session->opal_key.key_len;
455a7b23
SB
1343 int err = 0;
1344
455a7b23
SB
1345 u8 *key = session->opal_key.key;
1346 u32 hsn = GENERIC_HOST_SESSION_NUM;
1347
e8b29224 1348 if (session->sum)
455a7b23
SB
1349 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1350 session->opal_key.lr);
e8b29224 1351 else if (session->who != OPAL_ADMIN1 && !session->sum)
455a7b23
SB
1352 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1353 session->who - 1);
e8b29224 1354 else
455a7b23
SB
1355 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1356
e8b29224
DK
1357 if (err)
1358 return err;
1359
1360 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1361 opalmethod[OPAL_STARTSESSION]);
455a7b23 1362
455a7b23
SB
1363 add_token_u64(&err, dev, hsn);
1364 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1365 OPAL_UID_LENGTH);
1366 add_token_u8(&err, dev, 1);
1367 add_token_u8(&err, dev, OPAL_STARTNAME);
1368 add_token_u8(&err, dev, 0);
1369 add_token_bytestring(&err, dev, key, keylen);
1370 add_token_u8(&err, dev, OPAL_ENDNAME);
1371 add_token_u8(&err, dev, OPAL_STARTNAME);
1372 add_token_u8(&err, dev, 3);
1373 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1374 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1375
1376 if (err) {
591c59d1 1377 pr_debug("Error building STARTSESSION command.\n");
455a7b23
SB
1378 return err;
1379 }
1380
1381 return finalize_and_send(dev, start_opal_session_cont);
1382}
1383
eed64951 1384static int revert_tper(struct opal_dev *dev, void *data)
455a7b23 1385{
e8b29224 1386 int err;
455a7b23 1387
e8b29224
DK
1388 err = cmd_start(dev, opaluid[OPAL_ADMINSP_UID],
1389 opalmethod[OPAL_REVERT]);
455a7b23 1390 if (err) {
591c59d1 1391 pr_debug("Error building REVERT TPER command.\n");
455a7b23
SB
1392 return err;
1393 }
1394
1395 return finalize_and_send(dev, parse_and_check_status);
1396}
1397
eed64951 1398static int internal_activate_user(struct opal_dev *dev, void *data)
455a7b23 1399{
eed64951 1400 struct opal_session_info *session = data;
455a7b23 1401 u8 uid[OPAL_UID_LENGTH];
e8b29224 1402 int err;
455a7b23
SB
1403
1404 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1405 uid[7] = session->who;
1406
e8b29224 1407 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23
SB
1408 add_token_u8(&err, dev, OPAL_STARTNAME);
1409 add_token_u8(&err, dev, OPAL_VALUES);
1410 add_token_u8(&err, dev, OPAL_STARTLIST);
1411 add_token_u8(&err, dev, OPAL_STARTNAME);
1412 add_token_u8(&err, dev, 5); /* Enabled */
1413 add_token_u8(&err, dev, OPAL_TRUE);
1414 add_token_u8(&err, dev, OPAL_ENDNAME);
1415 add_token_u8(&err, dev, OPAL_ENDLIST);
1416 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1417
1418 if (err) {
591c59d1 1419 pr_debug("Error building Activate UserN command.\n");
455a7b23
SB
1420 return err;
1421 }
1422
1423 return finalize_and_send(dev, parse_and_check_status);
1424}
1425
eed64951 1426static int erase_locking_range(struct opal_dev *dev, void *data)
455a7b23 1427{
eed64951 1428 struct opal_session_info *session = data;
455a7b23 1429 u8 uid[OPAL_UID_LENGTH];
e8b29224 1430 int err;
455a7b23
SB
1431
1432 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1433 return -ERANGE;
1434
e8b29224 1435 err = cmd_start(dev, uid, opalmethod[OPAL_ERASE]);
455a7b23
SB
1436
1437 if (err) {
591c59d1 1438 pr_debug("Error building Erase Locking Range Command.\n");
455a7b23
SB
1439 return err;
1440 }
1441 return finalize_and_send(dev, parse_and_check_status);
1442}
1443
eed64951 1444static int set_mbr_done(struct opal_dev *dev, void *data)
455a7b23 1445{
eed64951 1446 u8 *mbr_done_tf = data;
e8b29224 1447 int err;
455a7b23 1448
e8b29224
DK
1449 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1450 opalmethod[OPAL_SET]);
455a7b23 1451
455a7b23
SB
1452 add_token_u8(&err, dev, OPAL_STARTNAME);
1453 add_token_u8(&err, dev, OPAL_VALUES);
1454 add_token_u8(&err, dev, OPAL_STARTLIST);
1455 add_token_u8(&err, dev, OPAL_STARTNAME);
1456 add_token_u8(&err, dev, 2); /* Done */
eed64951 1457 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
455a7b23
SB
1458 add_token_u8(&err, dev, OPAL_ENDNAME);
1459 add_token_u8(&err, dev, OPAL_ENDLIST);
1460 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1461
1462 if (err) {
591c59d1 1463 pr_debug("Error Building set MBR Done command\n");
455a7b23
SB
1464 return err;
1465 }
1466
1467 return finalize_and_send(dev, parse_and_check_status);
1468}
1469
eed64951 1470static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
455a7b23 1471{
eed64951 1472 u8 *mbr_en_dis = data;
e8b29224 1473 int err;
455a7b23 1474
e8b29224
DK
1475 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1476 opalmethod[OPAL_SET]);
455a7b23 1477
455a7b23
SB
1478 add_token_u8(&err, dev, OPAL_STARTNAME);
1479 add_token_u8(&err, dev, OPAL_VALUES);
1480 add_token_u8(&err, dev, OPAL_STARTLIST);
1481 add_token_u8(&err, dev, OPAL_STARTNAME);
1482 add_token_u8(&err, dev, 1);
eed64951 1483 add_token_u8(&err, dev, *mbr_en_dis);
455a7b23
SB
1484 add_token_u8(&err, dev, OPAL_ENDNAME);
1485 add_token_u8(&err, dev, OPAL_ENDLIST);
1486 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1487
1488 if (err) {
591c59d1 1489 pr_debug("Error Building set MBR done command\n");
455a7b23
SB
1490 return err;
1491 }
1492
1493 return finalize_and_send(dev, parse_and_check_status);
1494}
1495
1496static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1497 struct opal_dev *dev)
1498{
e8b29224 1499 int err;
455a7b23 1500
e8b29224 1501 err = cmd_start(dev, cpin_uid, opalmethod[OPAL_SET]);
455a7b23 1502
455a7b23
SB
1503 add_token_u8(&err, dev, OPAL_STARTNAME);
1504 add_token_u8(&err, dev, OPAL_VALUES);
1505 add_token_u8(&err, dev, OPAL_STARTLIST);
1506 add_token_u8(&err, dev, OPAL_STARTNAME);
1507 add_token_u8(&err, dev, 3); /* PIN */
1508 add_token_bytestring(&err, dev, key, key_len);
1509 add_token_u8(&err, dev, OPAL_ENDNAME);
1510 add_token_u8(&err, dev, OPAL_ENDLIST);
1511 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1512
1513 return err;
1514}
1515
eed64951 1516static int set_new_pw(struct opal_dev *dev, void *data)
455a7b23
SB
1517{
1518 u8 cpin_uid[OPAL_UID_LENGTH];
eed64951 1519 struct opal_session_info *usr = data;
455a7b23
SB
1520
1521 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1522
1523 if (usr->who != OPAL_ADMIN1) {
1524 cpin_uid[5] = 0x03;
1525 if (usr->sum)
1526 cpin_uid[7] = usr->opal_key.lr + 1;
1527 else
1528 cpin_uid[7] = usr->who;
1529 }
1530
1531 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1532 cpin_uid, dev)) {
591c59d1 1533 pr_debug("Error building set password command.\n");
455a7b23
SB
1534 return -ERANGE;
1535 }
1536
1537 return finalize_and_send(dev, parse_and_check_status);
1538}
1539
eed64951 1540static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
455a7b23
SB
1541{
1542 u8 cpin_uid[OPAL_UID_LENGTH];
eed64951 1543 struct opal_key *key = data;
455a7b23
SB
1544
1545 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1546
1547 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
591c59d1 1548 pr_debug("Error building Set SID cpin\n");
455a7b23
SB
1549 return -ERANGE;
1550 }
1551 return finalize_and_send(dev, parse_and_check_status);
1552}
1553
eed64951 1554static int add_user_to_lr(struct opal_dev *dev, void *data)
455a7b23
SB
1555{
1556 u8 lr_buffer[OPAL_UID_LENGTH];
1557 u8 user_uid[OPAL_UID_LENGTH];
eed64951 1558 struct opal_lock_unlock *lkul = data;
e8b29224 1559 int err;
455a7b23 1560
455a7b23
SB
1561 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1562 OPAL_UID_LENGTH);
1563
1564 if (lkul->l_state == OPAL_RW)
1565 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1566 OPAL_UID_LENGTH);
1567
1568 lr_buffer[7] = lkul->session.opal_key.lr;
1569
1570 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1571
1572 user_uid[7] = lkul->session.who;
1573
e8b29224 1574 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
455a7b23 1575
455a7b23
SB
1576 add_token_u8(&err, dev, OPAL_STARTNAME);
1577 add_token_u8(&err, dev, OPAL_VALUES);
1578
1579 add_token_u8(&err, dev, OPAL_STARTLIST);
1580 add_token_u8(&err, dev, OPAL_STARTNAME);
1581 add_token_u8(&err, dev, 3);
1582
1583 add_token_u8(&err, dev, OPAL_STARTLIST);
1584
1585
1586 add_token_u8(&err, dev, OPAL_STARTNAME);
1587 add_token_bytestring(&err, dev,
1588 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1589 OPAL_UID_LENGTH/2);
1590 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1591 add_token_u8(&err, dev, OPAL_ENDNAME);
1592
1593
1594 add_token_u8(&err, dev, OPAL_STARTNAME);
1595 add_token_bytestring(&err, dev,
1596 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1597 OPAL_UID_LENGTH/2);
1598 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1599 add_token_u8(&err, dev, OPAL_ENDNAME);
1600
1601
1602 add_token_u8(&err, dev, OPAL_STARTNAME);
1603 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1604 OPAL_UID_LENGTH/2);
1605 add_token_u8(&err, dev, 1);
1606 add_token_u8(&err, dev, OPAL_ENDNAME);
1607
1608
1609 add_token_u8(&err, dev, OPAL_ENDLIST);
1610 add_token_u8(&err, dev, OPAL_ENDNAME);
1611 add_token_u8(&err, dev, OPAL_ENDLIST);
1612 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1613
1614 if (err) {
591c59d1 1615 pr_debug("Error building add user to locking range command.\n");
455a7b23
SB
1616 return err;
1617 }
1618
1619 return finalize_and_send(dev, parse_and_check_status);
1620}
1621
eed64951 1622static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
455a7b23
SB
1623{
1624 u8 lr_buffer[OPAL_UID_LENGTH];
eed64951 1625 struct opal_lock_unlock *lkul = data;
455a7b23
SB
1626 u8 read_locked = 1, write_locked = 1;
1627 int err = 0;
1628
455a7b23
SB
1629 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1630 lkul->session.opal_key.lr) < 0)
1631 return -ERANGE;
1632
1633 switch (lkul->l_state) {
1634 case OPAL_RO:
1635 read_locked = 0;
1636 write_locked = 1;
1637 break;
1638 case OPAL_RW:
1639 read_locked = 0;
1640 write_locked = 0;
1641 break;
1642 case OPAL_LK:
1e815b33 1643 /* vars are initialized to locked */
455a7b23
SB
1644 break;
1645 default:
591c59d1 1646 pr_debug("Tried to set an invalid locking state... returning to uland\n");
455a7b23
SB
1647 return OPAL_INVAL_PARAM;
1648 }
1649
e8b29224
DK
1650 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
1651
455a7b23
SB
1652 add_token_u8(&err, dev, OPAL_STARTNAME);
1653 add_token_u8(&err, dev, OPAL_VALUES);
1654 add_token_u8(&err, dev, OPAL_STARTLIST);
1655
1656 add_token_u8(&err, dev, OPAL_STARTNAME);
1657 add_token_u8(&err, dev, OPAL_READLOCKED);
1658 add_token_u8(&err, dev, read_locked);
1659 add_token_u8(&err, dev, OPAL_ENDNAME);
1660
1661 add_token_u8(&err, dev, OPAL_STARTNAME);
1662 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1663 add_token_u8(&err, dev, write_locked);
1664 add_token_u8(&err, dev, OPAL_ENDNAME);
1665
1666 add_token_u8(&err, dev, OPAL_ENDLIST);
1667 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1668
1669 if (err) {
591c59d1 1670 pr_debug("Error building SET command.\n");
455a7b23
SB
1671 return err;
1672 }
1673 return finalize_and_send(dev, parse_and_check_status);
1674}
1675
1676
eed64951 1677static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
455a7b23
SB
1678{
1679 u8 lr_buffer[OPAL_UID_LENGTH];
1680 u8 read_locked = 1, write_locked = 1;
eed64951 1681 struct opal_lock_unlock *lkul = data;
455a7b23
SB
1682 int ret;
1683
1684 clear_opal_cmd(dev);
1685 set_comid(dev, dev->comid);
1686
455a7b23
SB
1687 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1688 lkul->session.opal_key.lr) < 0)
1689 return -ERANGE;
1690
1691 switch (lkul->l_state) {
1692 case OPAL_RO:
1693 read_locked = 0;
1694 write_locked = 1;
1695 break;
1696 case OPAL_RW:
1697 read_locked = 0;
1698 write_locked = 0;
1699 break;
1700 case OPAL_LK:
1e815b33 1701 /* vars are initialized to locked */
455a7b23
SB
1702 break;
1703 default:
591c59d1 1704 pr_debug("Tried to set an invalid locking state.\n");
455a7b23
SB
1705 return OPAL_INVAL_PARAM;
1706 }
1707 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1708 read_locked, write_locked);
1709
1710 if (ret < 0) {
591c59d1 1711 pr_debug("Error building SET command.\n");
455a7b23
SB
1712 return ret;
1713 }
1714 return finalize_and_send(dev, parse_and_check_status);
1715}
1716
eed64951 1717static int activate_lsp(struct opal_dev *dev, void *data)
455a7b23 1718{
eed64951 1719 struct opal_lr_act *opal_act = data;
455a7b23
SB
1720 u8 user_lr[OPAL_UID_LENGTH];
1721 u8 uint_3 = 0x83;
e8b29224 1722 int err, i;
455a7b23 1723
e8b29224
DK
1724 err = cmd_start(dev, opaluid[OPAL_LOCKINGSP_UID],
1725 opalmethod[OPAL_ACTIVATE]);
455a7b23
SB
1726
1727 if (opal_act->sum) {
1728 err = build_locking_range(user_lr, sizeof(user_lr),
1729 opal_act->lr[0]);
1730 if (err)
1731 return err;
1732
455a7b23
SB
1733 add_token_u8(&err, dev, OPAL_STARTNAME);
1734 add_token_u8(&err, dev, uint_3);
1735 add_token_u8(&err, dev, 6);
1736 add_token_u8(&err, dev, 0);
1737 add_token_u8(&err, dev, 0);
1738
1739 add_token_u8(&err, dev, OPAL_STARTLIST);
1740 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1741 for (i = 1; i < opal_act->num_lrs; i++) {
1742 user_lr[7] = opal_act->lr[i];
1743 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1744 }
1745 add_token_u8(&err, dev, OPAL_ENDLIST);
1746 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1747 }
1748
1749 if (err) {
591c59d1 1750 pr_debug("Error building Activate LockingSP command.\n");
455a7b23
SB
1751 return err;
1752 }
1753
1754 return finalize_and_send(dev, parse_and_check_status);
1755}
1756
1757static int get_lsp_lifecycle_cont(struct opal_dev *dev)
1758{
1759 u8 lc_status;
1760 int error = 0;
1761
1762 error = parse_and_check_status(dev);
1763 if (error)
1764 return error;
1765
1766 lc_status = response_get_u64(&dev->parsed, 4);
1e815b33 1767 /* 0x08 is Manufactured Inactive */
455a7b23
SB
1768 /* 0x09 is Manufactured */
1769 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
591c59d1 1770 pr_debug("Couldn't determine the status of the Lifecycle state\n");
455a7b23
SB
1771 return -ENODEV;
1772 }
1773
1774 return 0;
1775}
1776
1777/* Determine if we're in the Manufactured Inactive or Active state */
eed64951 1778static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
455a7b23 1779{
e8b29224 1780 int err;
455a7b23 1781
e8b29224
DK
1782 err = cmd_start(dev, opaluid[OPAL_LOCKINGSP_UID],
1783 opalmethod[OPAL_GET]);
455a7b23 1784
455a7b23
SB
1785 add_token_u8(&err, dev, OPAL_STARTLIST);
1786
1787 add_token_u8(&err, dev, OPAL_STARTNAME);
1788 add_token_u8(&err, dev, 3); /* Start Column */
a4ddbd1b 1789 add_token_u8(&err, dev, OPAL_LIFECYCLE);
455a7b23
SB
1790 add_token_u8(&err, dev, OPAL_ENDNAME);
1791
1792 add_token_u8(&err, dev, OPAL_STARTNAME);
1793 add_token_u8(&err, dev, 4); /* End Column */
a4ddbd1b 1794 add_token_u8(&err, dev, OPAL_LIFECYCLE);
455a7b23
SB
1795 add_token_u8(&err, dev, OPAL_ENDNAME);
1796
455a7b23
SB
1797 add_token_u8(&err, dev, OPAL_ENDLIST);
1798
1799 if (err) {
591c59d1 1800 pr_debug("Error Building GET Lifecycle Status command\n");
455a7b23
SB
1801 return err;
1802 }
1803
1804 return finalize_and_send(dev, get_lsp_lifecycle_cont);
1805}
1806
1807static int get_msid_cpin_pin_cont(struct opal_dev *dev)
1808{
1809 const char *msid_pin;
1810 size_t strlen;
1811 int error = 0;
1812
1813 error = parse_and_check_status(dev);
1814 if (error)
1815 return error;
1816
1817 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1818 if (!msid_pin) {
591c59d1 1819 pr_debug("%s: Couldn't extract PIN from response\n", __func__);
455a7b23
SB
1820 return OPAL_INVAL_PARAM;
1821 }
1822
1823 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1824 if (!dev->prev_data)
1825 return -ENOMEM;
1826
1827 dev->prev_d_len = strlen;
1828
1829 return 0;
1830}
1831
eed64951 1832static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
455a7b23 1833{
e8b29224 1834 int err;
455a7b23 1835
e8b29224
DK
1836 err = cmd_start(dev, opaluid[OPAL_C_PIN_MSID],
1837 opalmethod[OPAL_GET]);
455a7b23
SB
1838
1839 add_token_u8(&err, dev, OPAL_STARTLIST);
455a7b23
SB
1840 add_token_u8(&err, dev, OPAL_STARTNAME);
1841 add_token_u8(&err, dev, 3); /* Start Column */
1842 add_token_u8(&err, dev, 3); /* PIN */
1843 add_token_u8(&err, dev, OPAL_ENDNAME);
1844
1845 add_token_u8(&err, dev, OPAL_STARTNAME);
1846 add_token_u8(&err, dev, 4); /* End Column */
1847 add_token_u8(&err, dev, 3); /* Lifecycle Column */
1848 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1849 add_token_u8(&err, dev, OPAL_ENDLIST);
1850
1851 if (err) {
591c59d1 1852 pr_debug("Error building Get MSID CPIN PIN command.\n");
455a7b23
SB
1853 return err;
1854 }
1855
1856 return finalize_and_send(dev, get_msid_cpin_pin_cont);
1857}
1858
eed64951 1859static int end_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1860{
1861 int err = 0;
1862
1863 clear_opal_cmd(dev);
455a7b23
SB
1864 set_comid(dev, dev->comid);
1865 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
455a7b23 1866
eed64951
JD
1867 if (err < 0)
1868 return err;
455a7b23
SB
1869 return finalize_and_send(dev, end_session_cont);
1870}
1871
1872static int end_opal_session_error(struct opal_dev *dev)
1873{
eed64951
JD
1874 const struct opal_step error_end_session[] = {
1875 { end_opal_session, },
1876 { NULL, }
455a7b23 1877 };
eed64951 1878 dev->steps = error_end_session;
455a7b23
SB
1879 return next(dev);
1880}
1881
1882static inline void setup_opal_dev(struct opal_dev *dev,
eed64951 1883 const struct opal_step *steps)
455a7b23 1884{
eed64951 1885 dev->steps = steps;
455a7b23
SB
1886 dev->tsn = 0;
1887 dev->hsn = 0;
455a7b23
SB
1888 dev->prev_data = NULL;
1889}
1890
1891static int check_opal_support(struct opal_dev *dev)
1892{
eed64951
JD
1893 const struct opal_step steps[] = {
1894 { opal_discovery0, },
1895 { NULL, }
455a7b23
SB
1896 };
1897 int ret;
1898
1899 mutex_lock(&dev->dev_lock);
eed64951 1900 setup_opal_dev(dev, steps);
455a7b23
SB
1901 ret = next(dev);
1902 dev->supported = !ret;
1903 mutex_unlock(&dev->dev_lock);
1904 return ret;
1905}
1906
7d6d1578
SB
1907static void clean_opal_dev(struct opal_dev *dev)
1908{
1909
1910 struct opal_suspend_data *suspend, *next;
1911
1912 mutex_lock(&dev->dev_lock);
1913 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
1914 list_del(&suspend->node);
1915 kfree(suspend);
1916 }
1917 mutex_unlock(&dev->dev_lock);
1918}
1919
1920void free_opal_dev(struct opal_dev *dev)
1921{
1922 if (!dev)
1923 return;
1924 clean_opal_dev(dev);
1925 kfree(dev);
1926}
1927EXPORT_SYMBOL(free_opal_dev);
1928
4f1244c8 1929struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
455a7b23 1930{
4f1244c8
CH
1931 struct opal_dev *dev;
1932
1933 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
1934 if (!dev)
1935 return NULL;
1936
1937 INIT_LIST_HEAD(&dev->unlk_lst);
1938 mutex_init(&dev->dev_lock);
1939 dev->data = data;
1940 dev->send_recv = send_recv;
1941 if (check_opal_support(dev) != 0) {
f5b37b7c 1942 pr_debug("Opal is not supported on this device\n");
4f1244c8
CH
1943 kfree(dev);
1944 return NULL;
1945 }
1946 return dev;
455a7b23
SB
1947}
1948EXPORT_SYMBOL(init_opal_dev);
1949
1950static int opal_secure_erase_locking_range(struct opal_dev *dev,
1951 struct opal_session_info *opal_session)
1952{
eed64951
JD
1953 const struct opal_step erase_steps[] = {
1954 { opal_discovery0, },
1955 { start_auth_opal_session, opal_session },
1956 { get_active_key, &opal_session->opal_key.lr },
1957 { gen_key, },
1958 { end_opal_session, },
1959 { NULL, }
455a7b23
SB
1960 };
1961 int ret;
1962
1963 mutex_lock(&dev->dev_lock);
eed64951 1964 setup_opal_dev(dev, erase_steps);
455a7b23
SB
1965 ret = next(dev);
1966 mutex_unlock(&dev->dev_lock);
1967 return ret;
1968}
1969
1970static int opal_erase_locking_range(struct opal_dev *dev,
1971 struct opal_session_info *opal_session)
1972{
eed64951
JD
1973 const struct opal_step erase_steps[] = {
1974 { opal_discovery0, },
1975 { start_auth_opal_session, opal_session },
1976 { erase_locking_range, opal_session },
1977 { end_opal_session, },
1978 { NULL, }
455a7b23
SB
1979 };
1980 int ret;
1981
1982 mutex_lock(&dev->dev_lock);
eed64951 1983 setup_opal_dev(dev, erase_steps);
455a7b23
SB
1984 ret = next(dev);
1985 mutex_unlock(&dev->dev_lock);
1986 return ret;
1987}
1988
1989static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
1990 struct opal_mbr_data *opal_mbr)
1991{
78bf4735
DK
1992 u8 enable_disable = opal_mbr->enable_disable == OPAL_MBR_ENABLE ?
1993 OPAL_TRUE : OPAL_FALSE;
1994
eed64951
JD
1995 const struct opal_step mbr_steps[] = {
1996 { opal_discovery0, },
1997 { start_admin1LSP_opal_session, &opal_mbr->key },
78bf4735 1998 { set_mbr_done, &enable_disable },
eed64951
JD
1999 { end_opal_session, },
2000 { start_admin1LSP_opal_session, &opal_mbr->key },
78bf4735 2001 { set_mbr_enable_disable, &enable_disable },
eed64951
JD
2002 { end_opal_session, },
2003 { NULL, }
455a7b23
SB
2004 };
2005 int ret;
2006
2007 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
2008 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
2009 return -EINVAL;
2010
2011 mutex_lock(&dev->dev_lock);
eed64951 2012 setup_opal_dev(dev, mbr_steps);
455a7b23
SB
2013 ret = next(dev);
2014 mutex_unlock(&dev->dev_lock);
2015 return ret;
2016}
2017
2018static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2019{
2020 struct opal_suspend_data *suspend;
2021
2022 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
2023 if (!suspend)
2024 return -ENOMEM;
2025
2026 suspend->unlk = *lk_unlk;
2027 suspend->lr = lk_unlk->session.opal_key.lr;
2028
2029 mutex_lock(&dev->dev_lock);
2030 setup_opal_dev(dev, NULL);
2031 add_suspend_info(dev, suspend);
2032 mutex_unlock(&dev->dev_lock);
2033 return 0;
2034}
2035
2036static int opal_add_user_to_lr(struct opal_dev *dev,
2037 struct opal_lock_unlock *lk_unlk)
2038{
eed64951
JD
2039 const struct opal_step steps[] = {
2040 { opal_discovery0, },
2041 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2042 { add_user_to_lr, lk_unlk },
2043 { end_opal_session, },
2044 { NULL, }
455a7b23
SB
2045 };
2046 int ret;
2047
2048 if (lk_unlk->l_state != OPAL_RO &&
2049 lk_unlk->l_state != OPAL_RW) {
591c59d1 2050 pr_debug("Locking state was not RO or RW\n");
455a7b23
SB
2051 return -EINVAL;
2052 }
b0bfdfc2 2053 if (lk_unlk->session.who < OPAL_USER1 ||
455a7b23 2054 lk_unlk->session.who > OPAL_USER9) {
591c59d1
SB
2055 pr_debug("Authority was not within the range of users: %d\n",
2056 lk_unlk->session.who);
455a7b23
SB
2057 return -EINVAL;
2058 }
2059 if (lk_unlk->session.sum) {
591c59d1
SB
2060 pr_debug("%s not supported in sum. Use setup locking range\n",
2061 __func__);
455a7b23
SB
2062 return -EINVAL;
2063 }
2064
2065 mutex_lock(&dev->dev_lock);
eed64951 2066 setup_opal_dev(dev, steps);
455a7b23
SB
2067 ret = next(dev);
2068 mutex_unlock(&dev->dev_lock);
2069 return ret;
2070}
2071
2072static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal)
2073{
eed64951
JD
2074 const struct opal_step revert_steps[] = {
2075 { opal_discovery0, },
2076 { start_SIDASP_opal_session, opal },
2077 { revert_tper, }, /* controller will terminate session */
2078 { NULL, }
455a7b23
SB
2079 };
2080 int ret;
2081
2082 mutex_lock(&dev->dev_lock);
eed64951 2083 setup_opal_dev(dev, revert_steps);
455a7b23
SB
2084 ret = next(dev);
2085 mutex_unlock(&dev->dev_lock);
7d6d1578
SB
2086
2087 /*
2088 * If we successfully reverted lets clean
2089 * any saved locking ranges.
2090 */
2091 if (!ret)
2092 clean_opal_dev(dev);
2093
455a7b23
SB
2094 return ret;
2095}
2096
eed64951
JD
2097static int __opal_lock_unlock(struct opal_dev *dev,
2098 struct opal_lock_unlock *lk_unlk)
455a7b23 2099{
eed64951
JD
2100 const struct opal_step unlock_steps[] = {
2101 { opal_discovery0, },
2102 { start_auth_opal_session, &lk_unlk->session },
2103 { lock_unlock_locking_range, lk_unlk },
2104 { end_opal_session, },
2105 { NULL, }
455a7b23 2106 };
eed64951
JD
2107 const struct opal_step unlock_sum_steps[] = {
2108 { opal_discovery0, },
2109 { start_auth_opal_session, &lk_unlk->session },
2110 { lock_unlock_locking_range_sum, lk_unlk },
2111 { end_opal_session, },
2112 { NULL, }
455a7b23
SB
2113 };
2114
eed64951 2115 dev->steps = lk_unlk->session.sum ? unlock_sum_steps : unlock_steps;
455a7b23
SB
2116 return next(dev);
2117}
2118
dbec491b
SB
2119static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
2120{
78bf4735 2121 u8 mbr_done_tf = OPAL_TRUE;
1e815b33 2122 const struct opal_step mbrdone_step[] = {
dbec491b
SB
2123 { opal_discovery0, },
2124 { start_admin1LSP_opal_session, key },
2125 { set_mbr_done, &mbr_done_tf },
2126 { end_opal_session, },
2127 { NULL, }
2128 };
2129
2130 dev->steps = mbrdone_step;
2131 return next(dev);
2132}
2133
eed64951
JD
2134static int opal_lock_unlock(struct opal_dev *dev,
2135 struct opal_lock_unlock *lk_unlk)
455a7b23 2136{
455a7b23
SB
2137 int ret;
2138
2139 if (lk_unlk->session.who < OPAL_ADMIN1 ||
2140 lk_unlk->session.who > OPAL_USER9)
2141 return -EINVAL;
2142
2143 mutex_lock(&dev->dev_lock);
eed64951 2144 ret = __opal_lock_unlock(dev, lk_unlk);
455a7b23
SB
2145 mutex_unlock(&dev->dev_lock);
2146 return ret;
2147}
2148
2149static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2150{
eed64951
JD
2151 const struct opal_step owner_steps[] = {
2152 { opal_discovery0, },
2153 { start_anybodyASP_opal_session, },
2154 { get_msid_cpin_pin, },
2155 { end_opal_session, },
2156 { start_SIDASP_opal_session, opal },
2157 { set_sid_cpin_pin, opal },
2158 { end_opal_session, },
2159 { NULL, }
455a7b23 2160 };
455a7b23
SB
2161 int ret;
2162
2163 if (!dev)
2164 return -ENODEV;
2165
2166 mutex_lock(&dev->dev_lock);
eed64951 2167 setup_opal_dev(dev, owner_steps);
455a7b23
SB
2168 ret = next(dev);
2169 mutex_unlock(&dev->dev_lock);
2170 return ret;
2171}
2172
1e815b33
DK
2173static int opal_activate_lsp(struct opal_dev *dev,
2174 struct opal_lr_act *opal_lr_act)
455a7b23 2175{
eed64951
JD
2176 const struct opal_step active_steps[] = {
2177 { opal_discovery0, },
2178 { start_SIDASP_opal_session, &opal_lr_act->key },
2179 { get_lsp_lifecycle, },
2180 { activate_lsp, opal_lr_act },
2181 { end_opal_session, },
2182 { NULL, }
455a7b23
SB
2183 };
2184 int ret;
2185
2186 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2187 return -EINVAL;
2188
2189 mutex_lock(&dev->dev_lock);
eed64951 2190 setup_opal_dev(dev, active_steps);
455a7b23
SB
2191 ret = next(dev);
2192 mutex_unlock(&dev->dev_lock);
2193 return ret;
2194}
2195
2196static int opal_setup_locking_range(struct opal_dev *dev,
2197 struct opal_user_lr_setup *opal_lrs)
2198{
eed64951
JD
2199 const struct opal_step lr_steps[] = {
2200 { opal_discovery0, },
2201 { start_auth_opal_session, &opal_lrs->session },
2202 { setup_locking_range, opal_lrs },
2203 { end_opal_session, },
2204 { NULL, }
455a7b23
SB
2205 };
2206 int ret;
2207
2208 mutex_lock(&dev->dev_lock);
eed64951 2209 setup_opal_dev(dev, lr_steps);
455a7b23
SB
2210 ret = next(dev);
2211 mutex_unlock(&dev->dev_lock);
2212 return ret;
2213}
2214
2215static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2216{
eed64951
JD
2217 const struct opal_step pw_steps[] = {
2218 { opal_discovery0, },
2219 { start_auth_opal_session, &opal_pw->session },
2220 { set_new_pw, &opal_pw->new_user_pw },
2221 { end_opal_session, },
2222 { NULL }
455a7b23 2223 };
455a7b23
SB
2224 int ret;
2225
2226 if (opal_pw->session.who < OPAL_ADMIN1 ||
2227 opal_pw->session.who > OPAL_USER9 ||
2228 opal_pw->new_user_pw.who < OPAL_ADMIN1 ||
2229 opal_pw->new_user_pw.who > OPAL_USER9)
2230 return -EINVAL;
2231
2232 mutex_lock(&dev->dev_lock);
eed64951 2233 setup_opal_dev(dev, pw_steps);
455a7b23
SB
2234 ret = next(dev);
2235 mutex_unlock(&dev->dev_lock);
2236 return ret;
2237}
2238
2239static int opal_activate_user(struct opal_dev *dev,
2240 struct opal_session_info *opal_session)
2241{
eed64951
JD
2242 const struct opal_step act_steps[] = {
2243 { opal_discovery0, },
2244 { start_admin1LSP_opal_session, &opal_session->opal_key },
2245 { internal_activate_user, opal_session },
2246 { end_opal_session, },
2247 { NULL, }
455a7b23 2248 };
455a7b23
SB
2249 int ret;
2250
2251 /* We can't activate Admin1 it's active as manufactured */
b0bfdfc2 2252 if (opal_session->who < OPAL_USER1 ||
455a7b23 2253 opal_session->who > OPAL_USER9) {
591c59d1 2254 pr_debug("Who was not a valid user: %d\n", opal_session->who);
455a7b23
SB
2255 return -EINVAL;
2256 }
2257
2258 mutex_lock(&dev->dev_lock);
eed64951 2259 setup_opal_dev(dev, act_steps);
455a7b23
SB
2260 ret = next(dev);
2261 mutex_unlock(&dev->dev_lock);
2262 return ret;
2263}
2264
2265bool opal_unlock_from_suspend(struct opal_dev *dev)
2266{
2267 struct opal_suspend_data *suspend;
455a7b23
SB
2268 bool was_failure = false;
2269 int ret = 0;
2270
2271 if (!dev)
2272 return false;
2273 if (!dev->supported)
2274 return false;
2275
2276 mutex_lock(&dev->dev_lock);
2277 setup_opal_dev(dev, NULL);
455a7b23
SB
2278
2279 list_for_each_entry(suspend, &dev->unlk_lst, node) {
455a7b23
SB
2280 dev->tsn = 0;
2281 dev->hsn = 0;
2282
eed64951 2283 ret = __opal_lock_unlock(dev, &suspend->unlk);
455a7b23 2284 if (ret) {
591c59d1
SB
2285 pr_debug("Failed to unlock LR %hhu with sum %d\n",
2286 suspend->unlk.session.opal_key.lr,
2287 suspend->unlk.session.sum);
455a7b23
SB
2288 was_failure = true;
2289 }
dbec491b
SB
2290 if (dev->mbr_enabled) {
2291 ret = __opal_set_mbr_done(dev, &suspend->unlk.session.opal_key);
2292 if (ret)
2293 pr_debug("Failed to set MBR Done in S3 resume\n");
2294 }
455a7b23
SB
2295 }
2296 mutex_unlock(&dev->dev_lock);
2297 return was_failure;
2298}
2299EXPORT_SYMBOL(opal_unlock_from_suspend);
2300
e225c20e 2301int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
455a7b23 2302{
e225c20e
SB
2303 void *p;
2304 int ret = -ENOTTY;
455a7b23
SB
2305
2306 if (!capable(CAP_SYS_ADMIN))
2307 return -EACCES;
4f1244c8
CH
2308 if (!dev)
2309 return -ENOTSUPP;
591c59d1 2310 if (!dev->supported)
455a7b23 2311 return -ENOTSUPP;
455a7b23 2312
eed64951 2313 p = memdup_user(arg, _IOC_SIZE(cmd));
e225c20e
SB
2314 if (IS_ERR(p))
2315 return PTR_ERR(p);
455a7b23 2316
e225c20e
SB
2317 switch (cmd) {
2318 case IOC_OPAL_SAVE:
2319 ret = opal_save(dev, p);
2320 break;
2321 case IOC_OPAL_LOCK_UNLOCK:
2322 ret = opal_lock_unlock(dev, p);
2323 break;
2324 case IOC_OPAL_TAKE_OWNERSHIP:
2325 ret = opal_take_ownership(dev, p);
2326 break;
2327 case IOC_OPAL_ACTIVATE_LSP:
2328 ret = opal_activate_lsp(dev, p);
2329 break;
2330 case IOC_OPAL_SET_PW:
2331 ret = opal_set_new_pw(dev, p);
2332 break;
2333 case IOC_OPAL_ACTIVATE_USR:
2334 ret = opal_activate_user(dev, p);
2335 break;
2336 case IOC_OPAL_REVERT_TPR:
2337 ret = opal_reverttper(dev, p);
2338 break;
2339 case IOC_OPAL_LR_SETUP:
2340 ret = opal_setup_locking_range(dev, p);
2341 break;
2342 case IOC_OPAL_ADD_USR_TO_LR:
2343 ret = opal_add_user_to_lr(dev, p);
2344 break;
2345 case IOC_OPAL_ENABLE_DISABLE_MBR:
2346 ret = opal_enable_disable_shadow_mbr(dev, p);
2347 break;
2348 case IOC_OPAL_ERASE_LR:
2349 ret = opal_erase_locking_range(dev, p);
2350 break;
2351 case IOC_OPAL_SECURE_ERASE_LR:
2352 ret = opal_secure_erase_locking_range(dev, p);
2353 break;
455a7b23 2354 default:
591c59d1 2355 break;
455a7b23 2356 }
e225c20e
SB
2357
2358 kfree(p);
2359 return ret;
455a7b23
SB
2360}
2361EXPORT_SYMBOL_GPL(sed_ioctl);