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