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