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