]> git.ipfire.org Git - thirdparty/linux.git/blame - block/sed-opal.c
block: sed-opal: unify error handling of responses
[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) {
591c59d1
SB
397 pr_debug("Error on step function: %d with error %d: %s\n",
398 state, error,
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
583static void add_token_bytestring(int *err, struct opal_dev *cmd,
584 const u8 *bytestring, size_t len)
585{
586 size_t header_len = 1;
587 bool is_short_atom = true;
588
589 if (*err)
590 return;
591
592 if (len & ~SHORT_ATOM_LEN_MASK) {
593 header_len = 2;
594 is_short_atom = false;
595 }
596
e2821a50 597 if (!can_add(err, cmd, header_len + len)) {
591c59d1 598 pr_debug("Error adding bytestring: end of buffer.\n");
455a7b23
SB
599 return;
600 }
601
602 if (is_short_atom)
603 add_short_atom_header(cmd, true, false, len);
604 else
605 add_medium_atom_header(cmd, true, false, len);
606
607 memcpy(&cmd->cmd[cmd->pos], bytestring, len);
608 cmd->pos += len;
609
610}
611
612static int build_locking_range(u8 *buffer, size_t length, u8 lr)
613{
614 if (length > OPAL_UID_LENGTH) {
591c59d1 615 pr_debug("Can't build locking range. Length OOB\n");
455a7b23
SB
616 return -ERANGE;
617 }
618
619 memcpy(buffer, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
620
621 if (lr == 0)
622 return 0;
623 buffer[5] = LOCKING_RANGE_NON_GLOBAL;
624 buffer[7] = lr;
625
626 return 0;
627}
628
629static int build_locking_user(u8 *buffer, size_t length, u8 lr)
630{
631 if (length > OPAL_UID_LENGTH) {
1e815b33 632 pr_debug("Can't build locking range user. Length OOB\n");
455a7b23
SB
633 return -ERANGE;
634 }
635
636 memcpy(buffer, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
637
638 buffer[7] = lr + 1;
639
640 return 0;
641}
642
643static void set_comid(struct opal_dev *cmd, u16 comid)
644{
645 struct opal_header *hdr = (struct opal_header *)cmd->cmd;
646
647 hdr->cp.extendedComID[0] = comid >> 8;
648 hdr->cp.extendedComID[1] = comid;
649 hdr->cp.extendedComID[2] = 0;
650 hdr->cp.extendedComID[3] = 0;
651}
652
653static int cmd_finalize(struct opal_dev *cmd, u32 hsn, u32 tsn)
654{
655 struct opal_header *hdr;
656 int err = 0;
657
e8b29224 658 /* close the parameter list opened from cmd_start */
78d584ca
DK
659 add_token_u8(&err, cmd, OPAL_ENDLIST);
660
455a7b23
SB
661 add_token_u8(&err, cmd, OPAL_ENDOFDATA);
662 add_token_u8(&err, cmd, OPAL_STARTLIST);
663 add_token_u8(&err, cmd, 0);
664 add_token_u8(&err, cmd, 0);
665 add_token_u8(&err, cmd, 0);
666 add_token_u8(&err, cmd, OPAL_ENDLIST);
667
668 if (err) {
591c59d1 669 pr_debug("Error finalizing command.\n");
455a7b23
SB
670 return -EFAULT;
671 }
672
673 hdr = (struct opal_header *) cmd->cmd;
674
675 hdr->pkt.tsn = cpu_to_be32(tsn);
676 hdr->pkt.hsn = cpu_to_be32(hsn);
677
678 hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
679 while (cmd->pos % 4) {
680 if (cmd->pos >= IO_BUFFER_LENGTH) {
591c59d1 681 pr_debug("Error: Buffer overrun\n");
455a7b23
SB
682 return -ERANGE;
683 }
684 cmd->cmd[cmd->pos++] = 0;
685 }
686 hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
687 sizeof(hdr->pkt));
688 hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
689
690 return 0;
691}
692
cccb9241
JD
693static const struct opal_resp_tok *response_get_token(
694 const struct parsed_resp *resp,
695 int n)
455a7b23
SB
696{
697 const struct opal_resp_tok *tok;
698
7d9b62ae
DK
699 if (!resp) {
700 pr_debug("Response is NULL\n");
701 return ERR_PTR(-EINVAL);
702 }
703
455a7b23 704 if (n >= resp->num) {
591c59d1
SB
705 pr_debug("Token number doesn't exist: %d, resp: %d\n",
706 n, resp->num);
cccb9241 707 return ERR_PTR(-EINVAL);
455a7b23
SB
708 }
709
710 tok = &resp->toks[n];
711 if (tok->len == 0) {
591c59d1 712 pr_debug("Token length must be non-zero\n");
cccb9241 713 return ERR_PTR(-EINVAL);
455a7b23
SB
714 }
715
cccb9241 716 return tok;
455a7b23
SB
717}
718
aedb6e24
JD
719static ssize_t response_parse_tiny(struct opal_resp_tok *tok,
720 const u8 *pos)
455a7b23
SB
721{
722 tok->pos = pos;
723 tok->len = 1;
724 tok->width = OPAL_WIDTH_TINY;
725
726 if (pos[0] & TINY_ATOM_SIGNED) {
727 tok->type = OPAL_DTA_TOKENID_SINT;
728 } else {
729 tok->type = OPAL_DTA_TOKENID_UINT;
730 tok->stored.u = pos[0] & 0x3f;
731 }
732
733 return tok->len;
734}
735
aedb6e24
JD
736static ssize_t response_parse_short(struct opal_resp_tok *tok,
737 const u8 *pos)
455a7b23
SB
738{
739 tok->pos = pos;
740 tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
741 tok->width = OPAL_WIDTH_SHORT;
742
743 if (pos[0] & SHORT_ATOM_BYTESTRING) {
744 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
745 } else if (pos[0] & SHORT_ATOM_SIGNED) {
746 tok->type = OPAL_DTA_TOKENID_SINT;
747 } else {
748 u64 u_integer = 0;
aedb6e24 749 ssize_t i, b = 0;
455a7b23
SB
750
751 tok->type = OPAL_DTA_TOKENID_UINT;
752 if (tok->len > 9) {
591c59d1 753 pr_debug("uint64 with more than 8 bytes\n");
455a7b23
SB
754 return -EINVAL;
755 }
756 for (i = tok->len - 1; i > 0; i--) {
757 u_integer |= ((u64)pos[i] << (8 * b));
758 b++;
759 }
760 tok->stored.u = u_integer;
761 }
762
763 return tok->len;
764}
765
aedb6e24
JD
766static ssize_t response_parse_medium(struct opal_resp_tok *tok,
767 const u8 *pos)
455a7b23
SB
768{
769 tok->pos = pos;
770 tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
771 tok->width = OPAL_WIDTH_MEDIUM;
772
773 if (pos[0] & MEDIUM_ATOM_BYTESTRING)
774 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
775 else if (pos[0] & MEDIUM_ATOM_SIGNED)
776 tok->type = OPAL_DTA_TOKENID_SINT;
777 else
778 tok->type = OPAL_DTA_TOKENID_UINT;
779
780 return tok->len;
781}
782
aedb6e24
JD
783static ssize_t response_parse_long(struct opal_resp_tok *tok,
784 const u8 *pos)
455a7b23
SB
785{
786 tok->pos = pos;
787 tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
788 tok->width = OPAL_WIDTH_LONG;
789
790 if (pos[0] & LONG_ATOM_BYTESTRING)
791 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
792 else if (pos[0] & LONG_ATOM_SIGNED)
793 tok->type = OPAL_DTA_TOKENID_SINT;
794 else
795 tok->type = OPAL_DTA_TOKENID_UINT;
796
797 return tok->len;
798}
799
aedb6e24
JD
800static ssize_t response_parse_token(struct opal_resp_tok *tok,
801 const u8 *pos)
455a7b23
SB
802{
803 tok->pos = pos;
804 tok->len = 1;
805 tok->type = OPAL_DTA_TOKENID_TOKEN;
806 tok->width = OPAL_WIDTH_TOKEN;
807
808 return tok->len;
809}
810
811static int response_parse(const u8 *buf, size_t length,
812 struct parsed_resp *resp)
813{
814 const struct opal_header *hdr;
815 struct opal_resp_tok *iter;
816 int num_entries = 0;
817 int total;
aedb6e24 818 ssize_t token_length;
455a7b23 819 const u8 *pos;
77039b96 820 u32 clen, plen, slen;
455a7b23
SB
821
822 if (!buf)
823 return -EFAULT;
824
825 if (!resp)
826 return -EFAULT;
827
828 hdr = (struct opal_header *)buf;
829 pos = buf;
830 pos += sizeof(*hdr);
831
77039b96
JD
832 clen = be32_to_cpu(hdr->cp.length);
833 plen = be32_to_cpu(hdr->pkt.length);
834 slen = be32_to_cpu(hdr->subpkt.length);
835 pr_debug("Response size: cp: %u, pkt: %u, subpkt: %u\n",
836 clen, plen, slen);
837
838 if (clen == 0 || plen == 0 || slen == 0 ||
839 slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
591c59d1
SB
840 pr_debug("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
841 clen, plen, slen);
455a7b23
SB
842 print_buffer(pos, sizeof(*hdr));
843 return -EINVAL;
844 }
845
846 if (pos > buf + length)
847 return -EFAULT;
848
849 iter = resp->toks;
77039b96 850 total = slen;
455a7b23
SB
851 print_buffer(pos, total);
852 while (total > 0) {
853 if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */
854 token_length = response_parse_tiny(iter, pos);
855 else if (pos[0] <= SHORT_ATOM_BYTE) /* short atom */
856 token_length = response_parse_short(iter, pos);
857 else if (pos[0] <= MEDIUM_ATOM_BYTE) /* medium atom */
858 token_length = response_parse_medium(iter, pos);
859 else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
860 token_length = response_parse_long(iter, pos);
861 else /* TOKEN */
862 token_length = response_parse_token(iter, pos);
863
aedb6e24
JD
864 if (token_length < 0)
865 return token_length;
455a7b23
SB
866
867 pos += token_length;
868 total -= token_length;
869 iter++;
870 num_entries++;
871 }
872
873 if (num_entries == 0) {
591c59d1 874 pr_debug("Couldn't parse response.\n");
455a7b23
SB
875 return -EINVAL;
876 }
877 resp->num = num_entries;
878
879 return 0;
880}
881
882static size_t response_get_string(const struct parsed_resp *resp, int n,
883 const char **store)
884{
d15e1175
JR
885 u8 skip;
886 const struct opal_resp_tok *token;
887
455a7b23
SB
888 *store = NULL;
889 if (!resp) {
591c59d1 890 pr_debug("Response is NULL\n");
455a7b23
SB
891 return 0;
892 }
893
ce042c18 894 if (n >= resp->num) {
591c59d1
SB
895 pr_debug("Response has %d tokens. Can't access %d\n",
896 resp->num, n);
455a7b23
SB
897 return 0;
898 }
899
d15e1175
JR
900 token = &resp->toks[n];
901 if (token->type != OPAL_DTA_TOKENID_BYTESTRING) {
591c59d1 902 pr_debug("Token is not a byte string!\n");
455a7b23
SB
903 return 0;
904 }
905
d15e1175
JR
906 switch (token->width) {
907 case OPAL_WIDTH_TINY:
908 case OPAL_WIDTH_SHORT:
909 skip = 1;
910 break;
911 case OPAL_WIDTH_MEDIUM:
912 skip = 2;
913 break;
914 case OPAL_WIDTH_LONG:
915 skip = 4;
916 break;
917 default:
918 pr_debug("Token has invalid width!\n");
919 return 0;
920 }
921
922 *store = token->pos + skip;
923 return token->len - skip;
455a7b23
SB
924}
925
926static u64 response_get_u64(const struct parsed_resp *resp, int n)
927{
928 if (!resp) {
591c59d1 929 pr_debug("Response is NULL\n");
455a7b23
SB
930 return 0;
931 }
932
ce042c18 933 if (n >= resp->num) {
591c59d1
SB
934 pr_debug("Response has %d tokens. Can't access %d\n",
935 resp->num, n);
455a7b23
SB
936 return 0;
937 }
938
939 if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) {
591c59d1
SB
940 pr_debug("Token is not unsigned it: %d\n",
941 resp->toks[n].type);
455a7b23
SB
942 return 0;
943 }
944
945 if (!(resp->toks[n].width == OPAL_WIDTH_TINY ||
946 resp->toks[n].width == OPAL_WIDTH_SHORT)) {
591c59d1
SB
947 pr_debug("Atom is not short or tiny: %d\n",
948 resp->toks[n].width);
455a7b23
SB
949 return 0;
950 }
951
952 return resp->toks[n].stored.u;
953}
954
cccb9241
JD
955static bool response_token_matches(const struct opal_resp_tok *token, u8 match)
956{
957 if (IS_ERR(token) ||
958 token->type != OPAL_DTA_TOKENID_TOKEN ||
959 token->pos[0] != match)
960 return false;
961 return true;
962}
963
455a7b23
SB
964static u8 response_status(const struct parsed_resp *resp)
965{
cccb9241
JD
966 const struct opal_resp_tok *tok;
967
968 tok = response_get_token(resp, 0);
969 if (response_token_matches(tok, OPAL_ENDOFSESSION))
455a7b23 970 return 0;
455a7b23
SB
971
972 if (resp->num < 5)
973 return DTAERROR_NO_METHOD_STATUS;
974
cccb9241
JD
975 tok = response_get_token(resp, resp->num - 5);
976 if (!response_token_matches(tok, OPAL_STARTLIST))
977 return DTAERROR_NO_METHOD_STATUS;
978
979 tok = response_get_token(resp, resp->num - 1);
980 if (!response_token_matches(tok, OPAL_ENDLIST))
455a7b23
SB
981 return DTAERROR_NO_METHOD_STATUS;
982
983 return response_get_u64(resp, resp->num - 4);
984}
985
986/* Parses and checks for errors */
987static int parse_and_check_status(struct opal_dev *dev)
988{
989 int error;
990
991 print_buffer(dev->cmd, dev->pos);
992
993 error = response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed);
994 if (error) {
591c59d1 995 pr_debug("Couldn't parse response.\n");
455a7b23
SB
996 return error;
997 }
998
999 return response_status(&dev->parsed);
1000}
1001
1002static void clear_opal_cmd(struct opal_dev *dev)
1003{
1004 dev->pos = sizeof(struct opal_header);
1005 memset(dev->cmd, 0, IO_BUFFER_LENGTH);
1006}
1007
e8b29224
DK
1008static int cmd_start(struct opal_dev *dev, const u8 *uid, const u8 *method)
1009{
1010 int err = 0;
1011
1012 clear_opal_cmd(dev);
1013 set_comid(dev, dev->comid);
1014
1015 add_token_u8(&err, dev, OPAL_CALL);
1016 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1017 add_token_bytestring(&err, dev, method, OPAL_METHOD_LENGTH);
1018
1019 /*
1020 * Every method call is followed by its parameters enclosed within
1021 * OPAL_STARTLIST and OPAL_ENDLIST tokens. We automatically open the
1022 * parameter list here and close it later in cmd_finalize.
1023 */
1024 add_token_u8(&err, dev, OPAL_STARTLIST);
1025
1026 return err;
1027}
1028
455a7b23
SB
1029static int start_opal_session_cont(struct opal_dev *dev)
1030{
1031 u32 hsn, tsn;
1032 int error = 0;
1033
1034 error = parse_and_check_status(dev);
1035 if (error)
1036 return error;
1037
1038 hsn = response_get_u64(&dev->parsed, 4);
1039 tsn = response_get_u64(&dev->parsed, 5);
1040
1041 if (hsn == 0 && tsn == 0) {
591c59d1 1042 pr_debug("Couldn't authenticate session\n");
455a7b23
SB
1043 return -EPERM;
1044 }
1045
1046 dev->hsn = hsn;
1047 dev->tsn = tsn;
1048 return 0;
1049}
1050
1051static void add_suspend_info(struct opal_dev *dev,
1052 struct opal_suspend_data *sus)
1053{
1054 struct opal_suspend_data *iter;
1055
1056 list_for_each_entry(iter, &dev->unlk_lst, node) {
1057 if (iter->lr == sus->lr) {
1058 list_del(&iter->node);
1059 kfree(iter);
1060 break;
1061 }
1062 }
1063 list_add_tail(&sus->node, &dev->unlk_lst);
1064}
1065
1066static int end_session_cont(struct opal_dev *dev)
1067{
1068 dev->hsn = 0;
1069 dev->tsn = 0;
1070 return parse_and_check_status(dev);
1071}
1072
1073static int finalize_and_send(struct opal_dev *dev, cont_fn cont)
1074{
1075 int ret;
1076
1077 ret = cmd_finalize(dev, dev->hsn, dev->tsn);
1078 if (ret) {
591c59d1 1079 pr_debug("Error finalizing command buffer: %d\n", ret);
455a7b23
SB
1080 return ret;
1081 }
1082
1083 print_buffer(dev->cmd, dev->pos);
1084
1085 return opal_send_recv(dev, cont);
1086}
1087
eed64951 1088static int gen_key(struct opal_dev *dev, void *data)
455a7b23 1089{
455a7b23 1090 u8 uid[OPAL_UID_LENGTH];
e8b29224 1091 int err;
455a7b23
SB
1092
1093 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
455a7b23
SB
1094 kfree(dev->prev_data);
1095 dev->prev_data = NULL;
1096
e8b29224 1097 err = cmd_start(dev, uid, opalmethod[OPAL_GENKEY]);
455a7b23
SB
1098
1099 if (err) {
591c59d1 1100 pr_debug("Error building gen key command\n");
455a7b23
SB
1101 return err;
1102
1103 }
1104 return finalize_and_send(dev, parse_and_check_status);
1105}
1106
1107static int get_active_key_cont(struct opal_dev *dev)
1108{
1109 const char *activekey;
1110 size_t keylen;
1111 int error = 0;
1112
1113 error = parse_and_check_status(dev);
1114 if (error)
1115 return error;
1116 keylen = response_get_string(&dev->parsed, 4, &activekey);
1117 if (!activekey) {
591c59d1
SB
1118 pr_debug("%s: Couldn't extract the Activekey from the response\n",
1119 __func__);
455a7b23
SB
1120 return OPAL_INVAL_PARAM;
1121 }
1122 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1123
1124 if (!dev->prev_data)
1125 return -ENOMEM;
1126
1127 dev->prev_d_len = keylen;
1128
1129 return 0;
1130}
1131
eed64951 1132static int get_active_key(struct opal_dev *dev, void *data)
455a7b23
SB
1133{
1134 u8 uid[OPAL_UID_LENGTH];
e8b29224 1135 int err;
eed64951 1136 u8 *lr = data;
455a7b23 1137
455a7b23
SB
1138 err = build_locking_range(uid, sizeof(uid), *lr);
1139 if (err)
1140 return err;
1141
e8b29224 1142 err = cmd_start(dev, uid, opalmethod[OPAL_GET]);
455a7b23
SB
1143 add_token_u8(&err, dev, OPAL_STARTLIST);
1144 add_token_u8(&err, dev, OPAL_STARTNAME);
1145 add_token_u8(&err, dev, 3); /* startCloumn */
1146 add_token_u8(&err, dev, 10); /* ActiveKey */
1147 add_token_u8(&err, dev, OPAL_ENDNAME);
1148 add_token_u8(&err, dev, OPAL_STARTNAME);
1149 add_token_u8(&err, dev, 4); /* endColumn */
1150 add_token_u8(&err, dev, 10); /* ActiveKey */
1151 add_token_u8(&err, dev, OPAL_ENDNAME);
1152 add_token_u8(&err, dev, OPAL_ENDLIST);
455a7b23 1153 if (err) {
591c59d1 1154 pr_debug("Error building get active key command\n");
455a7b23
SB
1155 return err;
1156 }
1157
1158 return finalize_and_send(dev, get_active_key_cont);
1159}
1160
1161static int generic_lr_enable_disable(struct opal_dev *dev,
1162 u8 *uid, bool rle, bool wle,
1163 bool rl, bool wl)
1164{
e8b29224 1165 int err;
455a7b23 1166
e8b29224 1167 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23 1168
455a7b23
SB
1169 add_token_u8(&err, dev, OPAL_STARTNAME);
1170 add_token_u8(&err, dev, OPAL_VALUES);
1171 add_token_u8(&err, dev, OPAL_STARTLIST);
1172
1173 add_token_u8(&err, dev, OPAL_STARTNAME);
1174 add_token_u8(&err, dev, 5); /* ReadLockEnabled */
1175 add_token_u8(&err, dev, rle);
1176 add_token_u8(&err, dev, OPAL_ENDNAME);
1177
1178 add_token_u8(&err, dev, OPAL_STARTNAME);
1179 add_token_u8(&err, dev, 6); /* WriteLockEnabled */
1180 add_token_u8(&err, dev, wle);
1181 add_token_u8(&err, dev, OPAL_ENDNAME);
1182
1183 add_token_u8(&err, dev, OPAL_STARTNAME);
1184 add_token_u8(&err, dev, OPAL_READLOCKED);
1185 add_token_u8(&err, dev, rl);
1186 add_token_u8(&err, dev, OPAL_ENDNAME);
1187
1188 add_token_u8(&err, dev, OPAL_STARTNAME);
1189 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1190 add_token_u8(&err, dev, wl);
1191 add_token_u8(&err, dev, OPAL_ENDNAME);
1192
1193 add_token_u8(&err, dev, OPAL_ENDLIST);
1194 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1195 return err;
1196}
1197
1198static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1199 struct opal_user_lr_setup *setup)
1200{
1201 int err;
1202
1203 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1204 0, 0);
1205 if (err)
591c59d1 1206 pr_debug("Failed to create enable global lr command\n");
455a7b23
SB
1207 return err;
1208}
1209
eed64951 1210static int setup_locking_range(struct opal_dev *dev, void *data)
455a7b23
SB
1211{
1212 u8 uid[OPAL_UID_LENGTH];
eed64951 1213 struct opal_user_lr_setup *setup = data;
455a7b23 1214 u8 lr;
e8b29224 1215 int err;
455a7b23 1216
455a7b23
SB
1217 lr = setup->session.opal_key.lr;
1218 err = build_locking_range(uid, sizeof(uid), lr);
1219 if (err)
1220 return err;
1221
1222 if (lr == 0)
1223 err = enable_global_lr(dev, uid, setup);
1224 else {
e8b29224 1225 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23 1226
455a7b23
SB
1227 add_token_u8(&err, dev, OPAL_STARTNAME);
1228 add_token_u8(&err, dev, OPAL_VALUES);
1229 add_token_u8(&err, dev, OPAL_STARTLIST);
1230
1231 add_token_u8(&err, dev, OPAL_STARTNAME);
1232 add_token_u8(&err, dev, 3); /* Ranges Start */
1233 add_token_u64(&err, dev, setup->range_start);
1234 add_token_u8(&err, dev, OPAL_ENDNAME);
1235
1236 add_token_u8(&err, dev, OPAL_STARTNAME);
1237 add_token_u8(&err, dev, 4); /* Ranges length */
1238 add_token_u64(&err, dev, setup->range_length);
1239 add_token_u8(&err, dev, OPAL_ENDNAME);
1240
1241 add_token_u8(&err, dev, OPAL_STARTNAME);
1242 add_token_u8(&err, dev, 5); /*ReadLockEnabled */
1243 add_token_u64(&err, dev, !!setup->RLE);
1244 add_token_u8(&err, dev, OPAL_ENDNAME);
1245
1246 add_token_u8(&err, dev, OPAL_STARTNAME);
1247 add_token_u8(&err, dev, 6); /*WriteLockEnabled*/
1248 add_token_u64(&err, dev, !!setup->WLE);
1249 add_token_u8(&err, dev, OPAL_ENDNAME);
1250
1251 add_token_u8(&err, dev, OPAL_ENDLIST);
1252 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1253 }
1254 if (err) {
591c59d1 1255 pr_debug("Error building Setup Locking range command.\n");
455a7b23
SB
1256 return err;
1257
1258 }
1259
1260 return finalize_and_send(dev, parse_and_check_status);
1261}
1262
1263static int start_generic_opal_session(struct opal_dev *dev,
1264 enum opal_uid auth,
1265 enum opal_uid sp_type,
1266 const char *key,
1267 u8 key_len)
1268{
1269 u32 hsn;
e8b29224 1270 int err;
455a7b23 1271
591c59d1 1272 if (key == NULL && auth != OPAL_ANYBODY_UID)
455a7b23 1273 return OPAL_INVAL_PARAM;
455a7b23 1274
455a7b23 1275 hsn = GENERIC_HOST_SESSION_NUM;
e8b29224
DK
1276 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1277 opalmethod[OPAL_STARTSESSION]);
455a7b23 1278
455a7b23
SB
1279 add_token_u64(&err, dev, hsn);
1280 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1281 add_token_u8(&err, dev, 1);
1282
1283 switch (auth) {
1284 case OPAL_ANYBODY_UID:
455a7b23
SB
1285 break;
1286 case OPAL_ADMIN1_UID:
1287 case OPAL_SID_UID:
1288 add_token_u8(&err, dev, OPAL_STARTNAME);
1289 add_token_u8(&err, dev, 0); /* HostChallenge */
1290 add_token_bytestring(&err, dev, key, key_len);
1291 add_token_u8(&err, dev, OPAL_ENDNAME);
1292 add_token_u8(&err, dev, OPAL_STARTNAME);
1293 add_token_u8(&err, dev, 3); /* HostSignAuth */
1294 add_token_bytestring(&err, dev, opaluid[auth],
1295 OPAL_UID_LENGTH);
1296 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1297 break;
1298 default:
591c59d1 1299 pr_debug("Cannot start Admin SP session with auth %d\n", auth);
455a7b23
SB
1300 return OPAL_INVAL_PARAM;
1301 }
1302
1303 if (err) {
591c59d1 1304 pr_debug("Error building start adminsp session command.\n");
455a7b23
SB
1305 return err;
1306 }
1307
1308 return finalize_and_send(dev, start_opal_session_cont);
1309}
1310
eed64951 1311static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1312{
1313 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1314 OPAL_ADMINSP_UID, NULL, 0);
1315}
1316
eed64951 1317static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1318{
1319 int ret;
1320 const u8 *key = dev->prev_data;
455a7b23
SB
1321
1322 if (!key) {
eed64951 1323 const struct opal_key *okey = data;
1e815b33 1324
455a7b23
SB
1325 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1326 OPAL_ADMINSP_UID,
1327 okey->key,
1328 okey->key_len);
1329 } else {
1330 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1331 OPAL_ADMINSP_UID,
1332 key, dev->prev_d_len);
1333 kfree(key);
1334 dev->prev_data = NULL;
1335 }
1336 return ret;
1337}
1338
eed64951 1339static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
455a7b23 1340{
eed64951 1341 struct opal_key *key = data;
1e815b33 1342
455a7b23
SB
1343 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1344 OPAL_LOCKINGSP_UID,
1345 key->key, key->key_len);
1346}
1347
eed64951 1348static int start_auth_opal_session(struct opal_dev *dev, void *data)
455a7b23 1349{
eed64951 1350 struct opal_session_info *session = data;
455a7b23 1351 u8 lk_ul_user[OPAL_UID_LENGTH];
eed64951 1352 size_t keylen = session->opal_key.key_len;
455a7b23
SB
1353 int err = 0;
1354
455a7b23
SB
1355 u8 *key = session->opal_key.key;
1356 u32 hsn = GENERIC_HOST_SESSION_NUM;
1357
e8b29224 1358 if (session->sum)
455a7b23
SB
1359 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1360 session->opal_key.lr);
e8b29224 1361 else if (session->who != OPAL_ADMIN1 && !session->sum)
455a7b23
SB
1362 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1363 session->who - 1);
e8b29224 1364 else
455a7b23
SB
1365 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1366
e8b29224
DK
1367 if (err)
1368 return err;
1369
1370 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1371 opalmethod[OPAL_STARTSESSION]);
455a7b23 1372
455a7b23
SB
1373 add_token_u64(&err, dev, hsn);
1374 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1375 OPAL_UID_LENGTH);
1376 add_token_u8(&err, dev, 1);
1377 add_token_u8(&err, dev, OPAL_STARTNAME);
1378 add_token_u8(&err, dev, 0);
1379 add_token_bytestring(&err, dev, key, keylen);
1380 add_token_u8(&err, dev, OPAL_ENDNAME);
1381 add_token_u8(&err, dev, OPAL_STARTNAME);
1382 add_token_u8(&err, dev, 3);
1383 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1384 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1385
1386 if (err) {
591c59d1 1387 pr_debug("Error building STARTSESSION command.\n");
455a7b23
SB
1388 return err;
1389 }
1390
1391 return finalize_and_send(dev, start_opal_session_cont);
1392}
1393
eed64951 1394static int revert_tper(struct opal_dev *dev, void *data)
455a7b23 1395{
e8b29224 1396 int err;
455a7b23 1397
e8b29224
DK
1398 err = cmd_start(dev, opaluid[OPAL_ADMINSP_UID],
1399 opalmethod[OPAL_REVERT]);
455a7b23 1400 if (err) {
591c59d1 1401 pr_debug("Error building REVERT TPER command.\n");
455a7b23
SB
1402 return err;
1403 }
1404
1405 return finalize_and_send(dev, parse_and_check_status);
1406}
1407
eed64951 1408static int internal_activate_user(struct opal_dev *dev, void *data)
455a7b23 1409{
eed64951 1410 struct opal_session_info *session = data;
455a7b23 1411 u8 uid[OPAL_UID_LENGTH];
e8b29224 1412 int err;
455a7b23
SB
1413
1414 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1415 uid[7] = session->who;
1416
e8b29224 1417 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
455a7b23
SB
1418 add_token_u8(&err, dev, OPAL_STARTNAME);
1419 add_token_u8(&err, dev, OPAL_VALUES);
1420 add_token_u8(&err, dev, OPAL_STARTLIST);
1421 add_token_u8(&err, dev, OPAL_STARTNAME);
1422 add_token_u8(&err, dev, 5); /* Enabled */
1423 add_token_u8(&err, dev, OPAL_TRUE);
1424 add_token_u8(&err, dev, OPAL_ENDNAME);
1425 add_token_u8(&err, dev, OPAL_ENDLIST);
1426 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1427
1428 if (err) {
591c59d1 1429 pr_debug("Error building Activate UserN command.\n");
455a7b23
SB
1430 return err;
1431 }
1432
1433 return finalize_and_send(dev, parse_and_check_status);
1434}
1435
eed64951 1436static int erase_locking_range(struct opal_dev *dev, void *data)
455a7b23 1437{
eed64951 1438 struct opal_session_info *session = data;
455a7b23 1439 u8 uid[OPAL_UID_LENGTH];
e8b29224 1440 int err;
455a7b23
SB
1441
1442 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1443 return -ERANGE;
1444
e8b29224 1445 err = cmd_start(dev, uid, opalmethod[OPAL_ERASE]);
455a7b23
SB
1446
1447 if (err) {
591c59d1 1448 pr_debug("Error building Erase Locking Range Command.\n");
455a7b23
SB
1449 return err;
1450 }
1451 return finalize_and_send(dev, parse_and_check_status);
1452}
1453
eed64951 1454static int set_mbr_done(struct opal_dev *dev, void *data)
455a7b23 1455{
eed64951 1456 u8 *mbr_done_tf = data;
e8b29224 1457 int err;
455a7b23 1458
e8b29224
DK
1459 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1460 opalmethod[OPAL_SET]);
455a7b23 1461
455a7b23
SB
1462 add_token_u8(&err, dev, OPAL_STARTNAME);
1463 add_token_u8(&err, dev, OPAL_VALUES);
1464 add_token_u8(&err, dev, OPAL_STARTLIST);
1465 add_token_u8(&err, dev, OPAL_STARTNAME);
1466 add_token_u8(&err, dev, 2); /* Done */
eed64951 1467 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
455a7b23
SB
1468 add_token_u8(&err, dev, OPAL_ENDNAME);
1469 add_token_u8(&err, dev, OPAL_ENDLIST);
1470 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1471
1472 if (err) {
591c59d1 1473 pr_debug("Error Building set MBR Done command\n");
455a7b23
SB
1474 return err;
1475 }
1476
1477 return finalize_and_send(dev, parse_and_check_status);
1478}
1479
eed64951 1480static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
455a7b23 1481{
eed64951 1482 u8 *mbr_en_dis = data;
e8b29224 1483 int err;
455a7b23 1484
e8b29224
DK
1485 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1486 opalmethod[OPAL_SET]);
455a7b23 1487
455a7b23
SB
1488 add_token_u8(&err, dev, OPAL_STARTNAME);
1489 add_token_u8(&err, dev, OPAL_VALUES);
1490 add_token_u8(&err, dev, OPAL_STARTLIST);
1491 add_token_u8(&err, dev, OPAL_STARTNAME);
1492 add_token_u8(&err, dev, 1);
eed64951 1493 add_token_u8(&err, dev, *mbr_en_dis);
455a7b23
SB
1494 add_token_u8(&err, dev, OPAL_ENDNAME);
1495 add_token_u8(&err, dev, OPAL_ENDLIST);
1496 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1497
1498 if (err) {
591c59d1 1499 pr_debug("Error Building set MBR done command\n");
455a7b23
SB
1500 return err;
1501 }
1502
1503 return finalize_and_send(dev, parse_and_check_status);
1504}
1505
1506static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1507 struct opal_dev *dev)
1508{
e8b29224 1509 int err;
455a7b23 1510
e8b29224 1511 err = cmd_start(dev, cpin_uid, opalmethod[OPAL_SET]);
455a7b23 1512
455a7b23
SB
1513 add_token_u8(&err, dev, OPAL_STARTNAME);
1514 add_token_u8(&err, dev, OPAL_VALUES);
1515 add_token_u8(&err, dev, OPAL_STARTLIST);
1516 add_token_u8(&err, dev, OPAL_STARTNAME);
1517 add_token_u8(&err, dev, 3); /* PIN */
1518 add_token_bytestring(&err, dev, key, key_len);
1519 add_token_u8(&err, dev, OPAL_ENDNAME);
1520 add_token_u8(&err, dev, OPAL_ENDLIST);
1521 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1522
1523 return err;
1524}
1525
eed64951 1526static int set_new_pw(struct opal_dev *dev, void *data)
455a7b23
SB
1527{
1528 u8 cpin_uid[OPAL_UID_LENGTH];
eed64951 1529 struct opal_session_info *usr = data;
455a7b23
SB
1530
1531 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1532
1533 if (usr->who != OPAL_ADMIN1) {
1534 cpin_uid[5] = 0x03;
1535 if (usr->sum)
1536 cpin_uid[7] = usr->opal_key.lr + 1;
1537 else
1538 cpin_uid[7] = usr->who;
1539 }
1540
1541 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1542 cpin_uid, dev)) {
591c59d1 1543 pr_debug("Error building set password command.\n");
455a7b23
SB
1544 return -ERANGE;
1545 }
1546
1547 return finalize_and_send(dev, parse_and_check_status);
1548}
1549
eed64951 1550static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
455a7b23
SB
1551{
1552 u8 cpin_uid[OPAL_UID_LENGTH];
eed64951 1553 struct opal_key *key = data;
455a7b23
SB
1554
1555 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1556
1557 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
591c59d1 1558 pr_debug("Error building Set SID cpin\n");
455a7b23
SB
1559 return -ERANGE;
1560 }
1561 return finalize_and_send(dev, parse_and_check_status);
1562}
1563
eed64951 1564static int add_user_to_lr(struct opal_dev *dev, void *data)
455a7b23
SB
1565{
1566 u8 lr_buffer[OPAL_UID_LENGTH];
1567 u8 user_uid[OPAL_UID_LENGTH];
eed64951 1568 struct opal_lock_unlock *lkul = data;
e8b29224 1569 int err;
455a7b23 1570
455a7b23
SB
1571 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1572 OPAL_UID_LENGTH);
1573
1574 if (lkul->l_state == OPAL_RW)
1575 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1576 OPAL_UID_LENGTH);
1577
1578 lr_buffer[7] = lkul->session.opal_key.lr;
1579
1580 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1581
1582 user_uid[7] = lkul->session.who;
1583
e8b29224 1584 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
455a7b23 1585
455a7b23
SB
1586 add_token_u8(&err, dev, OPAL_STARTNAME);
1587 add_token_u8(&err, dev, OPAL_VALUES);
1588
1589 add_token_u8(&err, dev, OPAL_STARTLIST);
1590 add_token_u8(&err, dev, OPAL_STARTNAME);
1591 add_token_u8(&err, dev, 3);
1592
1593 add_token_u8(&err, dev, OPAL_STARTLIST);
1594
1595
1596 add_token_u8(&err, dev, OPAL_STARTNAME);
1597 add_token_bytestring(&err, dev,
1598 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1599 OPAL_UID_LENGTH/2);
1600 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1601 add_token_u8(&err, dev, OPAL_ENDNAME);
1602
1603
1604 add_token_u8(&err, dev, OPAL_STARTNAME);
1605 add_token_bytestring(&err, dev,
1606 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1607 OPAL_UID_LENGTH/2);
1608 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1609 add_token_u8(&err, dev, OPAL_ENDNAME);
1610
1611
1612 add_token_u8(&err, dev, OPAL_STARTNAME);
1613 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1614 OPAL_UID_LENGTH/2);
1615 add_token_u8(&err, dev, 1);
1616 add_token_u8(&err, dev, OPAL_ENDNAME);
1617
1618
1619 add_token_u8(&err, dev, OPAL_ENDLIST);
1620 add_token_u8(&err, dev, OPAL_ENDNAME);
1621 add_token_u8(&err, dev, OPAL_ENDLIST);
1622 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1623
1624 if (err) {
591c59d1 1625 pr_debug("Error building add user to locking range command.\n");
455a7b23
SB
1626 return err;
1627 }
1628
1629 return finalize_and_send(dev, parse_and_check_status);
1630}
1631
eed64951 1632static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
455a7b23
SB
1633{
1634 u8 lr_buffer[OPAL_UID_LENGTH];
eed64951 1635 struct opal_lock_unlock *lkul = data;
455a7b23
SB
1636 u8 read_locked = 1, write_locked = 1;
1637 int err = 0;
1638
455a7b23
SB
1639 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1640 lkul->session.opal_key.lr) < 0)
1641 return -ERANGE;
1642
1643 switch (lkul->l_state) {
1644 case OPAL_RO:
1645 read_locked = 0;
1646 write_locked = 1;
1647 break;
1648 case OPAL_RW:
1649 read_locked = 0;
1650 write_locked = 0;
1651 break;
1652 case OPAL_LK:
1e815b33 1653 /* vars are initialized to locked */
455a7b23
SB
1654 break;
1655 default:
591c59d1 1656 pr_debug("Tried to set an invalid locking state... returning to uland\n");
455a7b23
SB
1657 return OPAL_INVAL_PARAM;
1658 }
1659
e8b29224
DK
1660 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
1661
455a7b23
SB
1662 add_token_u8(&err, dev, OPAL_STARTNAME);
1663 add_token_u8(&err, dev, OPAL_VALUES);
1664 add_token_u8(&err, dev, OPAL_STARTLIST);
1665
1666 add_token_u8(&err, dev, OPAL_STARTNAME);
1667 add_token_u8(&err, dev, OPAL_READLOCKED);
1668 add_token_u8(&err, dev, read_locked);
1669 add_token_u8(&err, dev, OPAL_ENDNAME);
1670
1671 add_token_u8(&err, dev, OPAL_STARTNAME);
1672 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1673 add_token_u8(&err, dev, write_locked);
1674 add_token_u8(&err, dev, OPAL_ENDNAME);
1675
1676 add_token_u8(&err, dev, OPAL_ENDLIST);
1677 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1678
1679 if (err) {
591c59d1 1680 pr_debug("Error building SET command.\n");
455a7b23
SB
1681 return err;
1682 }
1683 return finalize_and_send(dev, parse_and_check_status);
1684}
1685
1686
eed64951 1687static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
455a7b23
SB
1688{
1689 u8 lr_buffer[OPAL_UID_LENGTH];
1690 u8 read_locked = 1, write_locked = 1;
eed64951 1691 struct opal_lock_unlock *lkul = data;
455a7b23
SB
1692 int ret;
1693
1694 clear_opal_cmd(dev);
1695 set_comid(dev, dev->comid);
1696
455a7b23
SB
1697 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1698 lkul->session.opal_key.lr) < 0)
1699 return -ERANGE;
1700
1701 switch (lkul->l_state) {
1702 case OPAL_RO:
1703 read_locked = 0;
1704 write_locked = 1;
1705 break;
1706 case OPAL_RW:
1707 read_locked = 0;
1708 write_locked = 0;
1709 break;
1710 case OPAL_LK:
1e815b33 1711 /* vars are initialized to locked */
455a7b23
SB
1712 break;
1713 default:
591c59d1 1714 pr_debug("Tried to set an invalid locking state.\n");
455a7b23
SB
1715 return OPAL_INVAL_PARAM;
1716 }
1717 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1718 read_locked, write_locked);
1719
1720 if (ret < 0) {
591c59d1 1721 pr_debug("Error building SET command.\n");
455a7b23
SB
1722 return ret;
1723 }
1724 return finalize_and_send(dev, parse_and_check_status);
1725}
1726
eed64951 1727static int activate_lsp(struct opal_dev *dev, void *data)
455a7b23 1728{
eed64951 1729 struct opal_lr_act *opal_act = data;
455a7b23
SB
1730 u8 user_lr[OPAL_UID_LENGTH];
1731 u8 uint_3 = 0x83;
e8b29224 1732 int err, i;
455a7b23 1733
e8b29224
DK
1734 err = cmd_start(dev, opaluid[OPAL_LOCKINGSP_UID],
1735 opalmethod[OPAL_ACTIVATE]);
455a7b23
SB
1736
1737 if (opal_act->sum) {
1738 err = build_locking_range(user_lr, sizeof(user_lr),
1739 opal_act->lr[0]);
1740 if (err)
1741 return err;
1742
455a7b23
SB
1743 add_token_u8(&err, dev, OPAL_STARTNAME);
1744 add_token_u8(&err, dev, uint_3);
1745 add_token_u8(&err, dev, 6);
1746 add_token_u8(&err, dev, 0);
1747 add_token_u8(&err, dev, 0);
1748
1749 add_token_u8(&err, dev, OPAL_STARTLIST);
1750 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1751 for (i = 1; i < opal_act->num_lrs; i++) {
1752 user_lr[7] = opal_act->lr[i];
1753 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1754 }
1755 add_token_u8(&err, dev, OPAL_ENDLIST);
1756 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1757 }
1758
1759 if (err) {
591c59d1 1760 pr_debug("Error building Activate LockingSP command.\n");
455a7b23
SB
1761 return err;
1762 }
1763
1764 return finalize_and_send(dev, parse_and_check_status);
1765}
1766
1767static int get_lsp_lifecycle_cont(struct opal_dev *dev)
1768{
1769 u8 lc_status;
1770 int error = 0;
1771
1772 error = parse_and_check_status(dev);
1773 if (error)
1774 return error;
1775
1776 lc_status = response_get_u64(&dev->parsed, 4);
1e815b33 1777 /* 0x08 is Manufactured Inactive */
455a7b23
SB
1778 /* 0x09 is Manufactured */
1779 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
591c59d1 1780 pr_debug("Couldn't determine the status of the Lifecycle state\n");
455a7b23
SB
1781 return -ENODEV;
1782 }
1783
1784 return 0;
1785}
1786
1787/* Determine if we're in the Manufactured Inactive or Active state */
eed64951 1788static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
455a7b23 1789{
e8b29224 1790 int err;
455a7b23 1791
e8b29224
DK
1792 err = cmd_start(dev, opaluid[OPAL_LOCKINGSP_UID],
1793 opalmethod[OPAL_GET]);
455a7b23 1794
455a7b23
SB
1795 add_token_u8(&err, dev, OPAL_STARTLIST);
1796
1797 add_token_u8(&err, dev, OPAL_STARTNAME);
1798 add_token_u8(&err, dev, 3); /* Start Column */
1799 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1800 add_token_u8(&err, dev, OPAL_ENDNAME);
1801
1802 add_token_u8(&err, dev, OPAL_STARTNAME);
1803 add_token_u8(&err, dev, 4); /* End Column */
1804 add_token_u8(&err, dev, 6); /* Lifecycle Column */
1805 add_token_u8(&err, dev, OPAL_ENDNAME);
1806
455a7b23
SB
1807 add_token_u8(&err, dev, OPAL_ENDLIST);
1808
1809 if (err) {
591c59d1 1810 pr_debug("Error Building GET Lifecycle Status command\n");
455a7b23
SB
1811 return err;
1812 }
1813
1814 return finalize_and_send(dev, get_lsp_lifecycle_cont);
1815}
1816
1817static int get_msid_cpin_pin_cont(struct opal_dev *dev)
1818{
1819 const char *msid_pin;
1820 size_t strlen;
1821 int error = 0;
1822
1823 error = parse_and_check_status(dev);
1824 if (error)
1825 return error;
1826
1827 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1828 if (!msid_pin) {
591c59d1 1829 pr_debug("%s: Couldn't extract PIN from response\n", __func__);
455a7b23
SB
1830 return OPAL_INVAL_PARAM;
1831 }
1832
1833 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1834 if (!dev->prev_data)
1835 return -ENOMEM;
1836
1837 dev->prev_d_len = strlen;
1838
1839 return 0;
1840}
1841
eed64951 1842static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
455a7b23 1843{
e8b29224 1844 int err;
455a7b23 1845
e8b29224
DK
1846 err = cmd_start(dev, opaluid[OPAL_C_PIN_MSID],
1847 opalmethod[OPAL_GET]);
455a7b23
SB
1848
1849 add_token_u8(&err, dev, OPAL_STARTLIST);
455a7b23
SB
1850 add_token_u8(&err, dev, OPAL_STARTNAME);
1851 add_token_u8(&err, dev, 3); /* Start Column */
1852 add_token_u8(&err, dev, 3); /* PIN */
1853 add_token_u8(&err, dev, OPAL_ENDNAME);
1854
1855 add_token_u8(&err, dev, OPAL_STARTNAME);
1856 add_token_u8(&err, dev, 4); /* End Column */
1857 add_token_u8(&err, dev, 3); /* Lifecycle Column */
1858 add_token_u8(&err, dev, OPAL_ENDNAME);
455a7b23
SB
1859 add_token_u8(&err, dev, OPAL_ENDLIST);
1860
1861 if (err) {
591c59d1 1862 pr_debug("Error building Get MSID CPIN PIN command.\n");
455a7b23
SB
1863 return err;
1864 }
1865
1866 return finalize_and_send(dev, get_msid_cpin_pin_cont);
1867}
1868
eed64951 1869static int end_opal_session(struct opal_dev *dev, void *data)
455a7b23
SB
1870{
1871 int err = 0;
1872
1873 clear_opal_cmd(dev);
455a7b23
SB
1874 set_comid(dev, dev->comid);
1875 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
455a7b23 1876
eed64951
JD
1877 if (err < 0)
1878 return err;
455a7b23
SB
1879 return finalize_and_send(dev, end_session_cont);
1880}
1881
1882static int end_opal_session_error(struct opal_dev *dev)
1883{
eed64951
JD
1884 const struct opal_step error_end_session[] = {
1885 { end_opal_session, },
1886 { NULL, }
455a7b23 1887 };
eed64951 1888 dev->steps = error_end_session;
455a7b23
SB
1889 return next(dev);
1890}
1891
1892static inline void setup_opal_dev(struct opal_dev *dev,
eed64951 1893 const struct opal_step *steps)
455a7b23 1894{
eed64951 1895 dev->steps = steps;
455a7b23
SB
1896 dev->tsn = 0;
1897 dev->hsn = 0;
455a7b23
SB
1898 dev->prev_data = NULL;
1899}
1900
1901static int check_opal_support(struct opal_dev *dev)
1902{
eed64951
JD
1903 const struct opal_step steps[] = {
1904 { opal_discovery0, },
1905 { NULL, }
455a7b23
SB
1906 };
1907 int ret;
1908
1909 mutex_lock(&dev->dev_lock);
eed64951 1910 setup_opal_dev(dev, steps);
455a7b23
SB
1911 ret = next(dev);
1912 dev->supported = !ret;
1913 mutex_unlock(&dev->dev_lock);
1914 return ret;
1915}
1916
7d6d1578
SB
1917static void clean_opal_dev(struct opal_dev *dev)
1918{
1919
1920 struct opal_suspend_data *suspend, *next;
1921
1922 mutex_lock(&dev->dev_lock);
1923 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
1924 list_del(&suspend->node);
1925 kfree(suspend);
1926 }
1927 mutex_unlock(&dev->dev_lock);
1928}
1929
1930void free_opal_dev(struct opal_dev *dev)
1931{
1932 if (!dev)
1933 return;
1934 clean_opal_dev(dev);
1935 kfree(dev);
1936}
1937EXPORT_SYMBOL(free_opal_dev);
1938
4f1244c8 1939struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
455a7b23 1940{
4f1244c8
CH
1941 struct opal_dev *dev;
1942
1943 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
1944 if (!dev)
1945 return NULL;
1946
1947 INIT_LIST_HEAD(&dev->unlk_lst);
1948 mutex_init(&dev->dev_lock);
1949 dev->data = data;
1950 dev->send_recv = send_recv;
1951 if (check_opal_support(dev) != 0) {
f5b37b7c 1952 pr_debug("Opal is not supported on this device\n");
4f1244c8
CH
1953 kfree(dev);
1954 return NULL;
1955 }
1956 return dev;
455a7b23
SB
1957}
1958EXPORT_SYMBOL(init_opal_dev);
1959
1960static int opal_secure_erase_locking_range(struct opal_dev *dev,
1961 struct opal_session_info *opal_session)
1962{
eed64951
JD
1963 const struct opal_step erase_steps[] = {
1964 { opal_discovery0, },
1965 { start_auth_opal_session, opal_session },
1966 { get_active_key, &opal_session->opal_key.lr },
1967 { gen_key, },
1968 { end_opal_session, },
1969 { NULL, }
455a7b23
SB
1970 };
1971 int ret;
1972
1973 mutex_lock(&dev->dev_lock);
eed64951 1974 setup_opal_dev(dev, erase_steps);
455a7b23
SB
1975 ret = next(dev);
1976 mutex_unlock(&dev->dev_lock);
1977 return ret;
1978}
1979
1980static int opal_erase_locking_range(struct opal_dev *dev,
1981 struct opal_session_info *opal_session)
1982{
eed64951
JD
1983 const struct opal_step erase_steps[] = {
1984 { opal_discovery0, },
1985 { start_auth_opal_session, opal_session },
1986 { erase_locking_range, opal_session },
1987 { end_opal_session, },
1988 { NULL, }
455a7b23
SB
1989 };
1990 int ret;
1991
1992 mutex_lock(&dev->dev_lock);
eed64951 1993 setup_opal_dev(dev, erase_steps);
455a7b23
SB
1994 ret = next(dev);
1995 mutex_unlock(&dev->dev_lock);
1996 return ret;
1997}
1998
1999static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
2000 struct opal_mbr_data *opal_mbr)
2001{
78bf4735
DK
2002 u8 enable_disable = opal_mbr->enable_disable == OPAL_MBR_ENABLE ?
2003 OPAL_TRUE : OPAL_FALSE;
2004
eed64951
JD
2005 const struct opal_step mbr_steps[] = {
2006 { opal_discovery0, },
2007 { start_admin1LSP_opal_session, &opal_mbr->key },
78bf4735 2008 { set_mbr_done, &enable_disable },
eed64951
JD
2009 { end_opal_session, },
2010 { start_admin1LSP_opal_session, &opal_mbr->key },
78bf4735 2011 { set_mbr_enable_disable, &enable_disable },
eed64951
JD
2012 { end_opal_session, },
2013 { NULL, }
455a7b23
SB
2014 };
2015 int ret;
2016
2017 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
2018 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
2019 return -EINVAL;
2020
2021 mutex_lock(&dev->dev_lock);
eed64951 2022 setup_opal_dev(dev, mbr_steps);
455a7b23
SB
2023 ret = next(dev);
2024 mutex_unlock(&dev->dev_lock);
2025 return ret;
2026}
2027
2028static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2029{
2030 struct opal_suspend_data *suspend;
2031
2032 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
2033 if (!suspend)
2034 return -ENOMEM;
2035
2036 suspend->unlk = *lk_unlk;
2037 suspend->lr = lk_unlk->session.opal_key.lr;
2038
2039 mutex_lock(&dev->dev_lock);
2040 setup_opal_dev(dev, NULL);
2041 add_suspend_info(dev, suspend);
2042 mutex_unlock(&dev->dev_lock);
2043 return 0;
2044}
2045
2046static int opal_add_user_to_lr(struct opal_dev *dev,
2047 struct opal_lock_unlock *lk_unlk)
2048{
eed64951
JD
2049 const struct opal_step steps[] = {
2050 { opal_discovery0, },
2051 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2052 { add_user_to_lr, lk_unlk },
2053 { end_opal_session, },
2054 { NULL, }
455a7b23
SB
2055 };
2056 int ret;
2057
2058 if (lk_unlk->l_state != OPAL_RO &&
2059 lk_unlk->l_state != OPAL_RW) {
591c59d1 2060 pr_debug("Locking state was not RO or RW\n");
455a7b23
SB
2061 return -EINVAL;
2062 }
b0bfdfc2 2063 if (lk_unlk->session.who < OPAL_USER1 ||
455a7b23 2064 lk_unlk->session.who > OPAL_USER9) {
591c59d1
SB
2065 pr_debug("Authority was not within the range of users: %d\n",
2066 lk_unlk->session.who);
455a7b23
SB
2067 return -EINVAL;
2068 }
2069 if (lk_unlk->session.sum) {
591c59d1
SB
2070 pr_debug("%s not supported in sum. Use setup locking range\n",
2071 __func__);
455a7b23
SB
2072 return -EINVAL;
2073 }
2074
2075 mutex_lock(&dev->dev_lock);
eed64951 2076 setup_opal_dev(dev, steps);
455a7b23
SB
2077 ret = next(dev);
2078 mutex_unlock(&dev->dev_lock);
2079 return ret;
2080}
2081
2082static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal)
2083{
eed64951
JD
2084 const struct opal_step revert_steps[] = {
2085 { opal_discovery0, },
2086 { start_SIDASP_opal_session, opal },
2087 { revert_tper, }, /* controller will terminate session */
2088 { NULL, }
455a7b23
SB
2089 };
2090 int ret;
2091
2092 mutex_lock(&dev->dev_lock);
eed64951 2093 setup_opal_dev(dev, revert_steps);
455a7b23
SB
2094 ret = next(dev);
2095 mutex_unlock(&dev->dev_lock);
7d6d1578
SB
2096
2097 /*
2098 * If we successfully reverted lets clean
2099 * any saved locking ranges.
2100 */
2101 if (!ret)
2102 clean_opal_dev(dev);
2103
455a7b23
SB
2104 return ret;
2105}
2106
eed64951
JD
2107static int __opal_lock_unlock(struct opal_dev *dev,
2108 struct opal_lock_unlock *lk_unlk)
455a7b23 2109{
eed64951
JD
2110 const struct opal_step unlock_steps[] = {
2111 { opal_discovery0, },
2112 { start_auth_opal_session, &lk_unlk->session },
2113 { lock_unlock_locking_range, lk_unlk },
2114 { end_opal_session, },
2115 { NULL, }
455a7b23 2116 };
eed64951
JD
2117 const struct opal_step unlock_sum_steps[] = {
2118 { opal_discovery0, },
2119 { start_auth_opal_session, &lk_unlk->session },
2120 { lock_unlock_locking_range_sum, lk_unlk },
2121 { end_opal_session, },
2122 { NULL, }
455a7b23
SB
2123 };
2124
eed64951 2125 dev->steps = lk_unlk->session.sum ? unlock_sum_steps : unlock_steps;
455a7b23
SB
2126 return next(dev);
2127}
2128
dbec491b
SB
2129static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
2130{
78bf4735 2131 u8 mbr_done_tf = OPAL_TRUE;
1e815b33 2132 const struct opal_step mbrdone_step[] = {
dbec491b
SB
2133 { opal_discovery0, },
2134 { start_admin1LSP_opal_session, key },
2135 { set_mbr_done, &mbr_done_tf },
2136 { end_opal_session, },
2137 { NULL, }
2138 };
2139
2140 dev->steps = mbrdone_step;
2141 return next(dev);
2142}
2143
eed64951
JD
2144static int opal_lock_unlock(struct opal_dev *dev,
2145 struct opal_lock_unlock *lk_unlk)
455a7b23 2146{
455a7b23
SB
2147 int ret;
2148
2149 if (lk_unlk->session.who < OPAL_ADMIN1 ||
2150 lk_unlk->session.who > OPAL_USER9)
2151 return -EINVAL;
2152
2153 mutex_lock(&dev->dev_lock);
eed64951 2154 ret = __opal_lock_unlock(dev, lk_unlk);
455a7b23
SB
2155 mutex_unlock(&dev->dev_lock);
2156 return ret;
2157}
2158
2159static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2160{
eed64951
JD
2161 const struct opal_step owner_steps[] = {
2162 { opal_discovery0, },
2163 { start_anybodyASP_opal_session, },
2164 { get_msid_cpin_pin, },
2165 { end_opal_session, },
2166 { start_SIDASP_opal_session, opal },
2167 { set_sid_cpin_pin, opal },
2168 { end_opal_session, },
2169 { NULL, }
455a7b23 2170 };
455a7b23
SB
2171 int ret;
2172
2173 if (!dev)
2174 return -ENODEV;
2175
2176 mutex_lock(&dev->dev_lock);
eed64951 2177 setup_opal_dev(dev, owner_steps);
455a7b23
SB
2178 ret = next(dev);
2179 mutex_unlock(&dev->dev_lock);
2180 return ret;
2181}
2182
1e815b33
DK
2183static int opal_activate_lsp(struct opal_dev *dev,
2184 struct opal_lr_act *opal_lr_act)
455a7b23 2185{
eed64951
JD
2186 const struct opal_step active_steps[] = {
2187 { opal_discovery0, },
2188 { start_SIDASP_opal_session, &opal_lr_act->key },
2189 { get_lsp_lifecycle, },
2190 { activate_lsp, opal_lr_act },
2191 { end_opal_session, },
2192 { NULL, }
455a7b23
SB
2193 };
2194 int ret;
2195
2196 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2197 return -EINVAL;
2198
2199 mutex_lock(&dev->dev_lock);
eed64951 2200 setup_opal_dev(dev, active_steps);
455a7b23
SB
2201 ret = next(dev);
2202 mutex_unlock(&dev->dev_lock);
2203 return ret;
2204}
2205
2206static int opal_setup_locking_range(struct opal_dev *dev,
2207 struct opal_user_lr_setup *opal_lrs)
2208{
eed64951
JD
2209 const struct opal_step lr_steps[] = {
2210 { opal_discovery0, },
2211 { start_auth_opal_session, &opal_lrs->session },
2212 { setup_locking_range, opal_lrs },
2213 { end_opal_session, },
2214 { NULL, }
455a7b23
SB
2215 };
2216 int ret;
2217
2218 mutex_lock(&dev->dev_lock);
eed64951 2219 setup_opal_dev(dev, lr_steps);
455a7b23
SB
2220 ret = next(dev);
2221 mutex_unlock(&dev->dev_lock);
2222 return ret;
2223}
2224
2225static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2226{
eed64951
JD
2227 const struct opal_step pw_steps[] = {
2228 { opal_discovery0, },
2229 { start_auth_opal_session, &opal_pw->session },
2230 { set_new_pw, &opal_pw->new_user_pw },
2231 { end_opal_session, },
2232 { NULL }
455a7b23 2233 };
455a7b23
SB
2234 int ret;
2235
2236 if (opal_pw->session.who < OPAL_ADMIN1 ||
2237 opal_pw->session.who > OPAL_USER9 ||
2238 opal_pw->new_user_pw.who < OPAL_ADMIN1 ||
2239 opal_pw->new_user_pw.who > OPAL_USER9)
2240 return -EINVAL;
2241
2242 mutex_lock(&dev->dev_lock);
eed64951 2243 setup_opal_dev(dev, pw_steps);
455a7b23
SB
2244 ret = next(dev);
2245 mutex_unlock(&dev->dev_lock);
2246 return ret;
2247}
2248
2249static int opal_activate_user(struct opal_dev *dev,
2250 struct opal_session_info *opal_session)
2251{
eed64951
JD
2252 const struct opal_step act_steps[] = {
2253 { opal_discovery0, },
2254 { start_admin1LSP_opal_session, &opal_session->opal_key },
2255 { internal_activate_user, opal_session },
2256 { end_opal_session, },
2257 { NULL, }
455a7b23 2258 };
455a7b23
SB
2259 int ret;
2260
2261 /* We can't activate Admin1 it's active as manufactured */
b0bfdfc2 2262 if (opal_session->who < OPAL_USER1 ||
455a7b23 2263 opal_session->who > OPAL_USER9) {
591c59d1 2264 pr_debug("Who was not a valid user: %d\n", opal_session->who);
455a7b23
SB
2265 return -EINVAL;
2266 }
2267
2268 mutex_lock(&dev->dev_lock);
eed64951 2269 setup_opal_dev(dev, act_steps);
455a7b23
SB
2270 ret = next(dev);
2271 mutex_unlock(&dev->dev_lock);
2272 return ret;
2273}
2274
2275bool opal_unlock_from_suspend(struct opal_dev *dev)
2276{
2277 struct opal_suspend_data *suspend;
455a7b23
SB
2278 bool was_failure = false;
2279 int ret = 0;
2280
2281 if (!dev)
2282 return false;
2283 if (!dev->supported)
2284 return false;
2285
2286 mutex_lock(&dev->dev_lock);
2287 setup_opal_dev(dev, NULL);
455a7b23
SB
2288
2289 list_for_each_entry(suspend, &dev->unlk_lst, node) {
455a7b23
SB
2290 dev->tsn = 0;
2291 dev->hsn = 0;
2292
eed64951 2293 ret = __opal_lock_unlock(dev, &suspend->unlk);
455a7b23 2294 if (ret) {
591c59d1
SB
2295 pr_debug("Failed to unlock LR %hhu with sum %d\n",
2296 suspend->unlk.session.opal_key.lr,
2297 suspend->unlk.session.sum);
455a7b23
SB
2298 was_failure = true;
2299 }
dbec491b
SB
2300 if (dev->mbr_enabled) {
2301 ret = __opal_set_mbr_done(dev, &suspend->unlk.session.opal_key);
2302 if (ret)
2303 pr_debug("Failed to set MBR Done in S3 resume\n");
2304 }
455a7b23
SB
2305 }
2306 mutex_unlock(&dev->dev_lock);
2307 return was_failure;
2308}
2309EXPORT_SYMBOL(opal_unlock_from_suspend);
2310
e225c20e 2311int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
455a7b23 2312{
e225c20e
SB
2313 void *p;
2314 int ret = -ENOTTY;
455a7b23
SB
2315
2316 if (!capable(CAP_SYS_ADMIN))
2317 return -EACCES;
4f1244c8
CH
2318 if (!dev)
2319 return -ENOTSUPP;
591c59d1 2320 if (!dev->supported)
455a7b23 2321 return -ENOTSUPP;
455a7b23 2322
eed64951 2323 p = memdup_user(arg, _IOC_SIZE(cmd));
e225c20e
SB
2324 if (IS_ERR(p))
2325 return PTR_ERR(p);
455a7b23 2326
e225c20e
SB
2327 switch (cmd) {
2328 case IOC_OPAL_SAVE:
2329 ret = opal_save(dev, p);
2330 break;
2331 case IOC_OPAL_LOCK_UNLOCK:
2332 ret = opal_lock_unlock(dev, p);
2333 break;
2334 case IOC_OPAL_TAKE_OWNERSHIP:
2335 ret = opal_take_ownership(dev, p);
2336 break;
2337 case IOC_OPAL_ACTIVATE_LSP:
2338 ret = opal_activate_lsp(dev, p);
2339 break;
2340 case IOC_OPAL_SET_PW:
2341 ret = opal_set_new_pw(dev, p);
2342 break;
2343 case IOC_OPAL_ACTIVATE_USR:
2344 ret = opal_activate_user(dev, p);
2345 break;
2346 case IOC_OPAL_REVERT_TPR:
2347 ret = opal_reverttper(dev, p);
2348 break;
2349 case IOC_OPAL_LR_SETUP:
2350 ret = opal_setup_locking_range(dev, p);
2351 break;
2352 case IOC_OPAL_ADD_USR_TO_LR:
2353 ret = opal_add_user_to_lr(dev, p);
2354 break;
2355 case IOC_OPAL_ENABLE_DISABLE_MBR:
2356 ret = opal_enable_disable_shadow_mbr(dev, p);
2357 break;
2358 case IOC_OPAL_ERASE_LR:
2359 ret = opal_erase_locking_range(dev, p);
2360 break;
2361 case IOC_OPAL_SECURE_ERASE_LR:
2362 ret = opal_secure_erase_locking_range(dev, p);
2363 break;
455a7b23 2364 default:
591c59d1 2365 break;
455a7b23 2366 }
e225c20e
SB
2367
2368 kfree(p);
2369 return ret;
455a7b23
SB
2370}
2371EXPORT_SYMBOL_GPL(sed_ioctl);