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