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