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