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