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