blob: b02ef2ff0d75a01d251038bfb033d026a6d29579 [file] [log] [blame]
Christoph Hellwig8c165672019-04-30 14:42:39 -04001// SPDX-License-Identifier: GPL-2.0
Scott Bauer455a7b22017-02-03 12:50:31 -07002/*
3 * Copyright © 2016 Intel Corporation
4 *
5 * Authors:
6 * Scott Bauer <scott.bauer@intel.com>
7 * Rafael Antognolli <rafael.antognolli@intel.com>
Scott Bauer455a7b22017-02-03 12:50:31 -07008 */
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
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010026#define IO_BUFFER_LENGTH 2048
27#define MAX_TOKS 64
28
Jonas Rabensteina9b25b42019-05-21 22:46:45 +020029/* Number of bytes needed by cmd_finalize. */
30#define CMD_FINALIZE_BYTES_NEEDED 7
31
Jon Derrickeed64952017-02-22 07:55:13 -070032struct opal_step {
33 int (*fn)(struct opal_dev *dev, void *data);
34 void *data;
35};
36typedef int (cont_fn)(struct opal_dev *dev);
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010037
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;
Scott Bauerdbec491b2017-09-01 08:53:35 -060078 bool mbr_enabled;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010079
80 void *data;
81 sec_send_recv *send_recv;
82
Christoph Hellwig4f1244c2017-02-17 13:59:39 +010083 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
Scott Bauer455a7b22017-02-03 12:50:31 -0700102static const u8 opaluid[][OPAL_UID_LENGTH] = {
103 /* users */
104 [OPAL_SMUID_UID] =
105 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
106 [OPAL_THISSP_UID] =
107 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
108 [OPAL_ADMINSP_UID] =
109 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },
110 [OPAL_LOCKINGSP_UID] =
111 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },
112 [OPAL_ENTERPRISE_LOCKINGSP_UID] =
113 { 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 },
114 [OPAL_ANYBODY_UID] =
115 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },
116 [OPAL_SID_UID] =
117 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },
118 [OPAL_ADMIN1_UID] =
119 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },
120 [OPAL_USER1_UID] =
121 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },
122 [OPAL_USER2_UID] =
123 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },
124 [OPAL_PSID_UID] =
125 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },
126 [OPAL_ENTERPRISE_BANDMASTER0_UID] =
127 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 },
128 [OPAL_ENTERPRISE_ERASEMASTER_UID] =
129 { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 },
130
131 /* tables */
132
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 },
151
152 /* C_PIN_TABLE object ID's */
153
David Kozub1e815b32019-02-14 01:15:54 +0100154 [OPAL_C_PIN_MSID] =
Scott Bauer455a7b22017-02-03 12:50:31 -0700155 { 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) */
162
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 */
Jonas Rabenstein1b6b75b2019-02-14 01:15:55 +0100178static const u8 opalmethod[][OPAL_METHOD_LENGTH] = {
Scott Bauer455a7b22017-02-03 12:50:31 -0700179 [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
Scott Bauer455a7b22017-02-03 12:50:31 -0700213static int end_opal_session_error(struct opal_dev *dev);
David Kozub0af26482019-02-14 01:16:07 +0100214static int opal_discovery0_step(struct opal_dev *dev);
Scott Bauer455a7b22017-02-03 12:50:31 -0700215
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)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600274 pr_debug("TPer sync not supported. flags = %d\n",
275 tper->supported_features);
Scott Bauer455a7b22017-02-03 12:50:31 -0700276 return false;
277 }
278
279 return true;
280}
281
Scott Bauerdbec491b2017-09-01 08:53:35 -0600282static bool check_mbrenabled(const void *data)
283{
284 const struct d0_locking_features *lfeat = data;
285 u8 sup_feat = lfeat->supported_features;
286
287 return !!(sup_feat & MBR_ENABLED_MASK);
288}
289
Scott Bauer455a7b22017-02-03 12:50:31 -0700290static bool check_sum(const void *data)
291{
292 const struct d0_single_user_mode *sum = data;
293 u32 nlo = be32_to_cpu(sum->num_locking_objects);
294
295 if (nlo == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600296 pr_debug("Need at least one locking object.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700297 return false;
298 }
299
300 pr_debug("Number of locking objects: %d\n", nlo);
301
302 return true;
303}
304
305static u16 get_comid_v100(const void *data)
306{
307 const struct d0_opal_v100 *v100 = data;
308
309 return be16_to_cpu(v100->baseComID);
310}
311
312static u16 get_comid_v200(const void *data)
313{
314 const struct d0_opal_v200 *v200 = data;
315
316 return be16_to_cpu(v200->baseComID);
317}
318
319static int opal_send_cmd(struct opal_dev *dev)
320{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +0100321 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
Scott Bauer455a7b22017-02-03 12:50:31 -0700322 dev->cmd, IO_BUFFER_LENGTH,
323 true);
324}
325
326static int opal_recv_cmd(struct opal_dev *dev)
327{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +0100328 return dev->send_recv(dev->data, dev->comid, TCG_SECP_01,
Scott Bauer455a7b22017-02-03 12:50:31 -0700329 dev->resp, IO_BUFFER_LENGTH,
330 false);
331}
332
333static int opal_recv_check(struct opal_dev *dev)
334{
335 size_t buflen = IO_BUFFER_LENGTH;
336 void *buffer = dev->resp;
337 struct opal_header *hdr = buffer;
338 int ret;
339
340 do {
341 pr_debug("Sent OPAL command: outstanding=%d, minTransfer=%d\n",
342 hdr->cp.outstandingData,
343 hdr->cp.minTransfer);
344
345 if (hdr->cp.outstandingData == 0 ||
346 hdr->cp.minTransfer != 0)
347 return 0;
348
349 memset(buffer, 0, buflen);
350 ret = opal_recv_cmd(dev);
351 } while (!ret);
352
353 return ret;
354}
355
356static int opal_send_recv(struct opal_dev *dev, cont_fn *cont)
357{
358 int ret;
359
360 ret = opal_send_cmd(dev);
361 if (ret)
362 return ret;
363 ret = opal_recv_cmd(dev);
364 if (ret)
365 return ret;
366 ret = opal_recv_check(dev);
367 if (ret)
368 return ret;
369 return cont(dev);
370}
371
372static void check_geometry(struct opal_dev *dev, const void *data)
373{
374 const struct d0_geometry_features *geo = data;
375
376 dev->align = geo->alignment_granularity;
377 dev->lowest_lba = geo->lowest_aligned_lba;
378}
379
David Kozub0af26482019-02-14 01:16:07 +0100380static int execute_step(struct opal_dev *dev,
381 const struct opal_step *step, size_t stepIndex)
382{
383 int error = step->fn(dev, step->data);
384
385 if (error) {
386 pr_debug("Step %zu (%pS) failed with error %d: %s\n",
387 stepIndex, step->fn, error,
388 opal_error_to_human(error));
389 }
390
391 return error;
392}
393
David Kozuba80f36c2019-02-14 01:16:08 +0100394static int execute_steps(struct opal_dev *dev,
395 const struct opal_step *steps, size_t n_steps)
Scott Bauer455a7b22017-02-03 12:50:31 -0700396{
David Kozub0af26482019-02-14 01:16:07 +0100397 size_t state = 0;
398 int error;
399
400 /* first do a discovery0 */
401 error = opal_discovery0_step(dev);
402 if (error)
403 return error;
Scott Bauer455a7b22017-02-03 12:50:31 -0700404
David Kozub3db87232019-02-14 01:16:06 +0100405 for (state = 0; state < n_steps; state++) {
David Kozub0af26482019-02-14 01:16:07 +0100406 error = execute_step(dev, &steps[state], state);
David Kozub3db87232019-02-14 01:16:06 +0100407 if (error)
408 goto out_error;
409 }
Scott Bauer455a7b22017-02-03 12:50:31 -0700410
David Kozub3db87232019-02-14 01:16:06 +0100411 return 0;
Scott Bauer2d190202017-02-22 10:15:08 -0700412
David Kozub3db87232019-02-14 01:16:06 +0100413out_error:
414 /*
David Kozub0af26482019-02-14 01:16:07 +0100415 * For each OPAL command the first step in steps starts some sort of
416 * session. If an error occurred in the initial discovery0 or if an
417 * error occurred in the first step (and thus stopping the loop with
418 * state == 0) then there was an error before or during the attempt to
419 * start a session. Therefore we shouldn't attempt to terminate a
420 * session, as one has not yet been created.
David Kozub3db87232019-02-14 01:16:06 +0100421 */
David Kozub0af26482019-02-14 01:16:07 +0100422 if (state > 0)
David Kozub3db87232019-02-14 01:16:06 +0100423 end_opal_session_error(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -0700424
425 return error;
426}
427
428static int opal_discovery0_end(struct opal_dev *dev)
429{
430 bool found_com_id = false, supported = true, single_user = false;
431 const struct d0_header *hdr = (struct d0_header *)dev->resp;
432 const u8 *epos = dev->resp, *cpos = dev->resp;
433 u16 comid = 0;
Jon Derrick77039b92017-02-21 11:59:15 -0700434 u32 hlen = be32_to_cpu(hdr->length);
Scott Bauer455a7b22017-02-03 12:50:31 -0700435
Jon Derrick77039b92017-02-21 11:59:15 -0700436 print_buffer(dev->resp, hlen);
Scott Bauerdbec491b2017-09-01 08:53:35 -0600437 dev->mbr_enabled = false;
Scott Bauer455a7b22017-02-03 12:50:31 -0700438
Jon Derrick77039b92017-02-21 11:59:15 -0700439 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600440 pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n",
441 sizeof(*hdr), hlen, IO_BUFFER_LENGTH);
Jon Derrick77039b92017-02-21 11:59:15 -0700442 return -EFAULT;
443 }
444
445 epos += hlen; /* end of buffer */
Scott Bauer455a7b22017-02-03 12:50:31 -0700446 cpos += sizeof(*hdr); /* current position on buffer */
447
448 while (cpos < epos && supported) {
449 const struct d0_features *body =
450 (const struct d0_features *)cpos;
451
452 switch (be16_to_cpu(body->code)) {
453 case FC_TPER:
454 supported = check_tper(body->features);
455 break;
456 case FC_SINGLEUSER:
457 single_user = check_sum(body->features);
458 break;
459 case FC_GEOMETRY:
460 check_geometry(dev, body);
461 break;
462 case FC_LOCKING:
Scott Bauerdbec491b2017-09-01 08:53:35 -0600463 dev->mbr_enabled = check_mbrenabled(body->features);
464 break;
Scott Bauer455a7b22017-02-03 12:50:31 -0700465 case FC_ENTERPRISE:
466 case FC_DATASTORE:
467 /* some ignored properties */
468 pr_debug("Found OPAL feature description: %d\n",
469 be16_to_cpu(body->code));
470 break;
471 case FC_OPALV100:
472 comid = get_comid_v100(body->features);
473 found_com_id = true;
474 break;
475 case FC_OPALV200:
476 comid = get_comid_v200(body->features);
477 found_com_id = true;
478 break;
479 case 0xbfff ... 0xffff:
480 /* vendor specific, just ignore */
481 break;
482 default:
483 pr_debug("OPAL Unknown feature: %d\n",
484 be16_to_cpu(body->code));
485
486 }
487 cpos += body->length + 4;
488 }
489
490 if (!supported) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100491 pr_debug("This device is not Opal enabled. Not Supported!\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700492 return -EOPNOTSUPP;
493 }
494
495 if (!single_user)
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100496 pr_debug("Device doesn't support single user mode\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700497
498
499 if (!found_com_id) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +0100500 pr_debug("Could not find OPAL comid for device. Returning early\n");
Ingo Molnared7158b2018-02-22 10:54:55 +0100501 return -EOPNOTSUPP;
Scott Bauer455a7b22017-02-03 12:50:31 -0700502 }
503
504 dev->comid = comid;
505
506 return 0;
507}
508
Jon Derrickeed64952017-02-22 07:55:13 -0700509static int opal_discovery0(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -0700510{
511 int ret;
512
513 memset(dev->resp, 0, IO_BUFFER_LENGTH);
514 dev->comid = OPAL_DISCOVERY_COMID;
515 ret = opal_recv_cmd(dev);
516 if (ret)
517 return ret;
518 return opal_discovery0_end(dev);
519}
520
David Kozub0af26482019-02-14 01:16:07 +0100521static int opal_discovery0_step(struct opal_dev *dev)
522{
523 const struct opal_step discovery0_step = {
524 opal_discovery0,
525 };
526 return execute_step(dev, &discovery0_step, 0);
527}
528
Jonas Rabensteina9b25b42019-05-21 22:46:45 +0200529static size_t remaining_size(struct opal_dev *cmd)
530{
531 return IO_BUFFER_LENGTH - cmd->pos;
532}
533
Jonas Rabensteine2821a52019-02-14 01:15:56 +0100534static bool can_add(int *err, struct opal_dev *cmd, size_t len)
Scott Bauer455a7b22017-02-03 12:50:31 -0700535{
536 if (*err)
Jonas Rabensteine2821a52019-02-14 01:15:56 +0100537 return false;
538
Jonas Rabensteina9b25b42019-05-21 22:46:45 +0200539 if (remaining_size(cmd) < len) {
Jonas Rabensteine2821a52019-02-14 01:15:56 +0100540 pr_debug("Error adding %zu bytes: end of buffer.\n", len);
Scott Bauer455a7b22017-02-03 12:50:31 -0700541 *err = -ERANGE;
Jonas Rabensteine2821a52019-02-14 01:15:56 +0100542 return false;
Scott Bauer455a7b22017-02-03 12:50:31 -0700543 }
Jonas Rabensteine2821a52019-02-14 01:15:56 +0100544
545 return true;
546}
547
548static void add_token_u8(int *err, struct opal_dev *cmd, u8 tok)
549{
550 if (!can_add(err, cmd, 1))
551 return;
Scott Bauer455a7b22017-02-03 12:50:31 -0700552 cmd->cmd[cmd->pos++] = tok;
553}
554
555static void add_short_atom_header(struct opal_dev *cmd, bool bytestring,
556 bool has_sign, int len)
557{
558 u8 atom;
559 int err = 0;
560
561 atom = SHORT_ATOM_ID;
562 atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;
563 atom |= has_sign ? SHORT_ATOM_SIGNED : 0;
564 atom |= len & SHORT_ATOM_LEN_MASK;
565
566 add_token_u8(&err, cmd, atom);
567}
568
569static void add_medium_atom_header(struct opal_dev *cmd, bool bytestring,
570 bool has_sign, int len)
571{
572 u8 header0;
573
574 header0 = MEDIUM_ATOM_ID;
575 header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;
576 header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;
577 header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;
578 cmd->cmd[cmd->pos++] = header0;
579 cmd->cmd[cmd->pos++] = len;
580}
581
582static void add_token_u64(int *err, struct opal_dev *cmd, u64 number)
583{
Scott Bauer455a7b22017-02-03 12:50:31 -0700584 size_t len;
585 int msb;
Scott Bauer455a7b22017-02-03 12:50:31 -0700586
587 if (!(number & ~TINY_ATOM_DATA_MASK)) {
588 add_token_u8(err, cmd, number);
589 return;
590 }
591
Jonas Rabenstein5f990d32018-03-07 17:55:56 +0100592 msb = fls64(number);
593 len = DIV_ROUND_UP(msb, 8);
Scott Bauer455a7b22017-02-03 12:50:31 -0700594
Jonas Rabensteine2821a52019-02-14 01:15:56 +0100595 if (!can_add(err, cmd, len + 1)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600596 pr_debug("Error adding u64: end of buffer.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700597 return;
598 }
599 add_short_atom_header(cmd, false, false, len);
Jonas Rabenstein5f990d32018-03-07 17:55:56 +0100600 while (len--)
601 add_token_u8(err, cmd, number >> (len * 8));
Scott Bauer455a7b22017-02-03 12:50:31 -0700602}
603
Jonas Rabenstein28559952019-02-14 01:16:02 +0100604static u8 *add_bytestring_header(int *err, struct opal_dev *cmd, size_t len)
Scott Bauer455a7b22017-02-03 12:50:31 -0700605{
606 size_t header_len = 1;
607 bool is_short_atom = true;
608
Scott Bauer455a7b22017-02-03 12:50:31 -0700609 if (len & ~SHORT_ATOM_LEN_MASK) {
610 header_len = 2;
611 is_short_atom = false;
612 }
613
Jonas Rabensteine2821a52019-02-14 01:15:56 +0100614 if (!can_add(err, cmd, header_len + len)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600615 pr_debug("Error adding bytestring: end of buffer.\n");
Jonas Rabenstein28559952019-02-14 01:16:02 +0100616 return NULL;
Scott Bauer455a7b22017-02-03 12:50:31 -0700617 }
618
619 if (is_short_atom)
620 add_short_atom_header(cmd, true, false, len);
621 else
622 add_medium_atom_header(cmd, true, false, len);
623
Jonas Rabenstein28559952019-02-14 01:16:02 +0100624 return &cmd->cmd[cmd->pos];
625}
Scott Bauer455a7b22017-02-03 12:50:31 -0700626
Jonas Rabenstein28559952019-02-14 01:16:02 +0100627static void add_token_bytestring(int *err, struct opal_dev *cmd,
628 const u8 *bytestring, size_t len)
629{
630 u8 *start;
631
632 start = add_bytestring_header(err, cmd, len);
633 if (!start)
634 return;
635 memcpy(start, bytestring, len);
636 cmd->pos += len;
Scott Bauer455a7b22017-02-03 12:50:31 -0700637}
638
639static int build_locking_range(u8 *buffer, size_t length, u8 lr)
640{
641 if (length > OPAL_UID_LENGTH) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600642 pr_debug("Can't build locking range. Length OOB\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700643 return -ERANGE;
644 }
645
646 memcpy(buffer, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
647
648 if (lr == 0)
649 return 0;
650 buffer[5] = LOCKING_RANGE_NON_GLOBAL;
651 buffer[7] = lr;
652
653 return 0;
654}
655
656static int build_locking_user(u8 *buffer, size_t length, u8 lr)
657{
658 if (length > OPAL_UID_LENGTH) {
David Kozub1e815b32019-02-14 01:15:54 +0100659 pr_debug("Can't build locking range user. Length OOB\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700660 return -ERANGE;
661 }
662
663 memcpy(buffer, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
664
665 buffer[7] = lr + 1;
666
667 return 0;
668}
669
670static void set_comid(struct opal_dev *cmd, u16 comid)
671{
672 struct opal_header *hdr = (struct opal_header *)cmd->cmd;
673
674 hdr->cp.extendedComID[0] = comid >> 8;
675 hdr->cp.extendedComID[1] = comid;
676 hdr->cp.extendedComID[2] = 0;
677 hdr->cp.extendedComID[3] = 0;
678}
679
680static int cmd_finalize(struct opal_dev *cmd, u32 hsn, u32 tsn)
681{
682 struct opal_header *hdr;
683 int err = 0;
684
Jonas Rabensteina9b25b42019-05-21 22:46:45 +0200685 /*
686 * Close the parameter list opened from cmd_start.
687 * The number of bytes added must be equal to
688 * CMD_FINALIZE_BYTES_NEEDED.
689 */
David Kozub78d584c2019-02-14 01:15:57 +0100690 add_token_u8(&err, cmd, OPAL_ENDLIST);
691
Scott Bauer455a7b22017-02-03 12:50:31 -0700692 add_token_u8(&err, cmd, OPAL_ENDOFDATA);
693 add_token_u8(&err, cmd, OPAL_STARTLIST);
694 add_token_u8(&err, cmd, 0);
695 add_token_u8(&err, cmd, 0);
696 add_token_u8(&err, cmd, 0);
697 add_token_u8(&err, cmd, OPAL_ENDLIST);
698
699 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600700 pr_debug("Error finalizing command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700701 return -EFAULT;
702 }
703
704 hdr = (struct opal_header *) cmd->cmd;
705
706 hdr->pkt.tsn = cpu_to_be32(tsn);
707 hdr->pkt.hsn = cpu_to_be32(hsn);
708
709 hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
710 while (cmd->pos % 4) {
711 if (cmd->pos >= IO_BUFFER_LENGTH) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600712 pr_debug("Error: Buffer overrun\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700713 return -ERANGE;
714 }
715 cmd->cmd[cmd->pos++] = 0;
716 }
717 hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
718 sizeof(hdr->pkt));
719 hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
720
721 return 0;
722}
723
Jon Derrickcccb9242017-02-21 11:59:14 -0700724static const struct opal_resp_tok *response_get_token(
725 const struct parsed_resp *resp,
726 int n)
Scott Bauer455a7b22017-02-03 12:50:31 -0700727{
728 const struct opal_resp_tok *tok;
729
David Kozub7d9b62a2019-02-14 01:15:59 +0100730 if (!resp) {
731 pr_debug("Response is NULL\n");
732 return ERR_PTR(-EINVAL);
733 }
734
Scott Bauer455a7b22017-02-03 12:50:31 -0700735 if (n >= resp->num) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600736 pr_debug("Token number doesn't exist: %d, resp: %d\n",
737 n, resp->num);
Jon Derrickcccb9242017-02-21 11:59:14 -0700738 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700739 }
740
741 tok = &resp->toks[n];
742 if (tok->len == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600743 pr_debug("Token length must be non-zero\n");
Jon Derrickcccb9242017-02-21 11:59:14 -0700744 return ERR_PTR(-EINVAL);
Scott Bauer455a7b22017-02-03 12:50:31 -0700745 }
746
Jon Derrickcccb9242017-02-21 11:59:14 -0700747 return tok;
Scott Bauer455a7b22017-02-03 12:50:31 -0700748}
749
Jon Derrickaedb6e22017-02-21 11:59:13 -0700750static ssize_t response_parse_tiny(struct opal_resp_tok *tok,
751 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700752{
753 tok->pos = pos;
754 tok->len = 1;
755 tok->width = OPAL_WIDTH_TINY;
756
757 if (pos[0] & TINY_ATOM_SIGNED) {
758 tok->type = OPAL_DTA_TOKENID_SINT;
759 } else {
760 tok->type = OPAL_DTA_TOKENID_UINT;
761 tok->stored.u = pos[0] & 0x3f;
762 }
763
764 return tok->len;
765}
766
Jon Derrickaedb6e22017-02-21 11:59:13 -0700767static ssize_t response_parse_short(struct opal_resp_tok *tok,
768 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700769{
770 tok->pos = pos;
771 tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
772 tok->width = OPAL_WIDTH_SHORT;
773
774 if (pos[0] & SHORT_ATOM_BYTESTRING) {
775 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
776 } else if (pos[0] & SHORT_ATOM_SIGNED) {
777 tok->type = OPAL_DTA_TOKENID_SINT;
778 } else {
779 u64 u_integer = 0;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700780 ssize_t i, b = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700781
782 tok->type = OPAL_DTA_TOKENID_UINT;
783 if (tok->len > 9) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600784 pr_debug("uint64 with more than 8 bytes\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700785 return -EINVAL;
786 }
787 for (i = tok->len - 1; i > 0; i--) {
788 u_integer |= ((u64)pos[i] << (8 * b));
789 b++;
790 }
791 tok->stored.u = u_integer;
792 }
793
794 return tok->len;
795}
796
Jon Derrickaedb6e22017-02-21 11:59:13 -0700797static ssize_t response_parse_medium(struct opal_resp_tok *tok,
798 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700799{
800 tok->pos = pos;
801 tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
802 tok->width = OPAL_WIDTH_MEDIUM;
803
804 if (pos[0] & MEDIUM_ATOM_BYTESTRING)
805 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
806 else if (pos[0] & MEDIUM_ATOM_SIGNED)
807 tok->type = OPAL_DTA_TOKENID_SINT;
808 else
809 tok->type = OPAL_DTA_TOKENID_UINT;
810
811 return tok->len;
812}
813
Jon Derrickaedb6e22017-02-21 11:59:13 -0700814static ssize_t response_parse_long(struct opal_resp_tok *tok,
815 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700816{
817 tok->pos = pos;
818 tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
819 tok->width = OPAL_WIDTH_LONG;
820
821 if (pos[0] & LONG_ATOM_BYTESTRING)
822 tok->type = OPAL_DTA_TOKENID_BYTESTRING;
823 else if (pos[0] & LONG_ATOM_SIGNED)
824 tok->type = OPAL_DTA_TOKENID_SINT;
825 else
826 tok->type = OPAL_DTA_TOKENID_UINT;
827
828 return tok->len;
829}
830
Jon Derrickaedb6e22017-02-21 11:59:13 -0700831static ssize_t response_parse_token(struct opal_resp_tok *tok,
832 const u8 *pos)
Scott Bauer455a7b22017-02-03 12:50:31 -0700833{
834 tok->pos = pos;
835 tok->len = 1;
836 tok->type = OPAL_DTA_TOKENID_TOKEN;
837 tok->width = OPAL_WIDTH_TOKEN;
838
839 return tok->len;
840}
841
842static int response_parse(const u8 *buf, size_t length,
843 struct parsed_resp *resp)
844{
845 const struct opal_header *hdr;
846 struct opal_resp_tok *iter;
847 int num_entries = 0;
848 int total;
Jon Derrickaedb6e22017-02-21 11:59:13 -0700849 ssize_t token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700850 const u8 *pos;
Jon Derrick77039b92017-02-21 11:59:15 -0700851 u32 clen, plen, slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700852
853 if (!buf)
854 return -EFAULT;
855
856 if (!resp)
857 return -EFAULT;
858
859 hdr = (struct opal_header *)buf;
860 pos = buf;
861 pos += sizeof(*hdr);
862
Jon Derrick77039b92017-02-21 11:59:15 -0700863 clen = be32_to_cpu(hdr->cp.length);
864 plen = be32_to_cpu(hdr->pkt.length);
865 slen = be32_to_cpu(hdr->subpkt.length);
866 pr_debug("Response size: cp: %u, pkt: %u, subpkt: %u\n",
867 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700868
Jon Derrick77039b92017-02-21 11:59:15 -0700869 if (clen == 0 || plen == 0 || slen == 0 ||
870 slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600871 pr_debug("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
872 clen, plen, slen);
Scott Bauer455a7b22017-02-03 12:50:31 -0700873 print_buffer(pos, sizeof(*hdr));
874 return -EINVAL;
875 }
876
877 if (pos > buf + length)
878 return -EFAULT;
879
880 iter = resp->toks;
Jon Derrick77039b92017-02-21 11:59:15 -0700881 total = slen;
Scott Bauer455a7b22017-02-03 12:50:31 -0700882 print_buffer(pos, total);
883 while (total > 0) {
884 if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */
885 token_length = response_parse_tiny(iter, pos);
886 else if (pos[0] <= SHORT_ATOM_BYTE) /* short atom */
887 token_length = response_parse_short(iter, pos);
888 else if (pos[0] <= MEDIUM_ATOM_BYTE) /* medium atom */
889 token_length = response_parse_medium(iter, pos);
890 else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
891 token_length = response_parse_long(iter, pos);
892 else /* TOKEN */
893 token_length = response_parse_token(iter, pos);
894
Jon Derrickaedb6e22017-02-21 11:59:13 -0700895 if (token_length < 0)
896 return token_length;
Scott Bauer455a7b22017-02-03 12:50:31 -0700897
898 pos += token_length;
899 total -= token_length;
900 iter++;
901 num_entries++;
902 }
903
904 if (num_entries == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600905 pr_debug("Couldn't parse response.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700906 return -EINVAL;
907 }
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{
Jonas Rabensteind15e11752018-03-01 14:26:37 +0100916 u8 skip;
David Kozubb68f09e2019-02-14 01:16:00 +0100917 const struct opal_resp_tok *tok;
Jonas Rabensteind15e11752018-03-01 14:26:37 +0100918
Scott Bauer455a7b22017-02-03 12:50:31 -0700919 *store = NULL;
David Kozubb68f09e2019-02-14 01:16:00 +0100920 tok = response_get_token(resp, n);
921 if (IS_ERR(tok))
Scott Bauer455a7b22017-02-03 12:50:31 -0700922 return 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700923
David Kozubb68f09e2019-02-14 01:16:00 +0100924 if (tok->type != OPAL_DTA_TOKENID_BYTESTRING) {
Scott Bauer591c59d2017-04-07 13:58:50 -0600925 pr_debug("Token is not a byte string!\n");
Scott Bauer455a7b22017-02-03 12:50:31 -0700926 return 0;
927 }
928
David Kozubb68f09e2019-02-14 01:16:00 +0100929 switch (tok->width) {
Jonas Rabensteind15e11752018-03-01 14:26:37 +0100930 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
David Kozubb68f09e2019-02-14 01:16:00 +0100945 *store = tok->pos + skip;
946 return tok->len - skip;
Scott Bauer455a7b22017-02-03 12:50:31 -0700947}
948
949static u64 response_get_u64(const struct parsed_resp *resp, int n)
950{
David Kozubb68f09e2019-02-14 01:16:00 +0100951 const struct opal_resp_tok *tok;
952
953 tok = response_get_token(resp, n);
954 if (IS_ERR(tok))
955 return 0;
956
957 if (tok->type != OPAL_DTA_TOKENID_UINT) {
958 pr_debug("Token is not unsigned int: %d\n", tok->type);
Scott Bauer455a7b22017-02-03 12:50:31 -0700959 return 0;
960 }
961
David Kozubb68f09e2019-02-14 01:16:00 +0100962 if (tok->width != OPAL_WIDTH_TINY && tok->width != OPAL_WIDTH_SHORT) {
963 pr_debug("Atom is not short or tiny: %d\n", tok->width);
Scott Bauer455a7b22017-02-03 12:50:31 -0700964 return 0;
965 }
966
David Kozubb68f09e2019-02-14 01:16:00 +0100967 return tok->stored.u;
Scott Bauer455a7b22017-02-03 12:50:31 -0700968}
969
Jon Derrickcccb9242017-02-21 11:59:14 -0700970static bool response_token_matches(const struct opal_resp_tok *token, u8 match)
971{
972 if (IS_ERR(token) ||
973 token->type != OPAL_DTA_TOKENID_TOKEN ||
974 token->pos[0] != match)
975 return false;
976 return true;
977}
978
Scott Bauer455a7b22017-02-03 12:50:31 -0700979static u8 response_status(const struct parsed_resp *resp)
980{
Jon Derrickcccb9242017-02-21 11:59:14 -0700981 const struct opal_resp_tok *tok;
982
983 tok = response_get_token(resp, 0);
984 if (response_token_matches(tok, OPAL_ENDOFSESSION))
Scott Bauer455a7b22017-02-03 12:50:31 -0700985 return 0;
Scott Bauer455a7b22017-02-03 12:50:31 -0700986
987 if (resp->num < 5)
988 return DTAERROR_NO_METHOD_STATUS;
989
Jon Derrickcccb9242017-02-21 11:59:14 -0700990 tok = response_get_token(resp, resp->num - 5);
991 if (!response_token_matches(tok, OPAL_STARTLIST))
992 return DTAERROR_NO_METHOD_STATUS;
993
994 tok = response_get_token(resp, resp->num - 1);
995 if (!response_token_matches(tok, OPAL_ENDLIST))
Scott Bauer455a7b22017-02-03 12:50:31 -0700996 return DTAERROR_NO_METHOD_STATUS;
997
998 return response_get_u64(resp, resp->num - 4);
999}
1000
1001/* Parses and checks for errors */
1002static int parse_and_check_status(struct opal_dev *dev)
1003{
1004 int error;
1005
1006 print_buffer(dev->cmd, dev->pos);
1007
1008 error = response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed);
1009 if (error) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001010 pr_debug("Couldn't parse response.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001011 return error;
1012 }
1013
1014 return response_status(&dev->parsed);
1015}
1016
1017static void clear_opal_cmd(struct opal_dev *dev)
1018{
1019 dev->pos = sizeof(struct opal_header);
1020 memset(dev->cmd, 0, IO_BUFFER_LENGTH);
1021}
1022
David Kozube8b29222019-02-14 01:15:58 +01001023static int cmd_start(struct opal_dev *dev, const u8 *uid, const u8 *method)
1024{
1025 int err = 0;
1026
1027 clear_opal_cmd(dev);
1028 set_comid(dev, dev->comid);
1029
1030 add_token_u8(&err, dev, OPAL_CALL);
1031 add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1032 add_token_bytestring(&err, dev, method, OPAL_METHOD_LENGTH);
1033
1034 /*
1035 * Every method call is followed by its parameters enclosed within
1036 * OPAL_STARTLIST and OPAL_ENDLIST tokens. We automatically open the
1037 * parameter list here and close it later in cmd_finalize.
1038 */
1039 add_token_u8(&err, dev, OPAL_STARTLIST);
1040
1041 return err;
1042}
1043
Scott Bauer455a7b22017-02-03 12:50:31 -07001044static int start_opal_session_cont(struct opal_dev *dev)
1045{
1046 u32 hsn, tsn;
1047 int error = 0;
1048
1049 error = parse_and_check_status(dev);
1050 if (error)
1051 return error;
1052
1053 hsn = response_get_u64(&dev->parsed, 4);
1054 tsn = response_get_u64(&dev->parsed, 5);
1055
1056 if (hsn == 0 && tsn == 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001057 pr_debug("Couldn't authenticate session\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001058 return -EPERM;
1059 }
1060
1061 dev->hsn = hsn;
1062 dev->tsn = tsn;
1063 return 0;
1064}
1065
1066static void add_suspend_info(struct opal_dev *dev,
1067 struct opal_suspend_data *sus)
1068{
1069 struct opal_suspend_data *iter;
1070
1071 list_for_each_entry(iter, &dev->unlk_lst, node) {
1072 if (iter->lr == sus->lr) {
1073 list_del(&iter->node);
1074 kfree(iter);
1075 break;
1076 }
1077 }
1078 list_add_tail(&sus->node, &dev->unlk_lst);
1079}
1080
1081static int end_session_cont(struct opal_dev *dev)
1082{
1083 dev->hsn = 0;
1084 dev->tsn = 0;
1085 return parse_and_check_status(dev);
1086}
1087
1088static int finalize_and_send(struct opal_dev *dev, cont_fn cont)
1089{
1090 int ret;
1091
1092 ret = cmd_finalize(dev, dev->hsn, dev->tsn);
1093 if (ret) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001094 pr_debug("Error finalizing command buffer: %d\n", ret);
Scott Bauer455a7b22017-02-03 12:50:31 -07001095 return ret;
1096 }
1097
1098 print_buffer(dev->cmd, dev->pos);
1099
1100 return opal_send_recv(dev, cont);
1101}
1102
David Kozub3fff2342019-02-14 01:16:04 +01001103/*
1104 * request @column from table @table on device @dev. On success, the column
1105 * data will be available in dev->resp->tok[4]
1106 */
1107static int generic_get_column(struct opal_dev *dev, const u8 *table,
1108 u64 column)
1109{
1110 int err;
1111
1112 err = cmd_start(dev, table, opalmethod[OPAL_GET]);
1113
1114 add_token_u8(&err, dev, OPAL_STARTLIST);
1115
1116 add_token_u8(&err, dev, OPAL_STARTNAME);
1117 add_token_u8(&err, dev, OPAL_STARTCOLUMN);
1118 add_token_u64(&err, dev, column);
1119 add_token_u8(&err, dev, OPAL_ENDNAME);
1120
1121 add_token_u8(&err, dev, OPAL_STARTNAME);
1122 add_token_u8(&err, dev, OPAL_ENDCOLUMN);
1123 add_token_u64(&err, dev, column);
1124 add_token_u8(&err, dev, OPAL_ENDNAME);
1125
1126 add_token_u8(&err, dev, OPAL_ENDLIST);
1127
1128 if (err)
1129 return err;
1130
1131 return finalize_and_send(dev, parse_and_check_status);
1132}
1133
Jon Derrickeed64952017-02-22 07:55:13 -07001134static int gen_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001135{
Scott Bauer455a7b22017-02-03 12:50:31 -07001136 u8 uid[OPAL_UID_LENGTH];
David Kozube8b29222019-02-14 01:15:58 +01001137 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001138
1139 memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
Scott Bauer455a7b22017-02-03 12:50:31 -07001140 kfree(dev->prev_data);
1141 dev->prev_data = NULL;
1142
David Kozube8b29222019-02-14 01:15:58 +01001143 err = cmd_start(dev, uid, opalmethod[OPAL_GENKEY]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001144
1145 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001146 pr_debug("Error building gen key command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001147 return err;
1148
1149 }
1150 return finalize_and_send(dev, parse_and_check_status);
1151}
1152
1153static int get_active_key_cont(struct opal_dev *dev)
1154{
1155 const char *activekey;
1156 size_t keylen;
1157 int error = 0;
1158
1159 error = parse_and_check_status(dev);
1160 if (error)
1161 return error;
1162 keylen = response_get_string(&dev->parsed, 4, &activekey);
1163 if (!activekey) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001164 pr_debug("%s: Couldn't extract the Activekey from the response\n",
1165 __func__);
Scott Bauer455a7b22017-02-03 12:50:31 -07001166 return OPAL_INVAL_PARAM;
1167 }
1168 dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
1169
1170 if (!dev->prev_data)
1171 return -ENOMEM;
1172
1173 dev->prev_d_len = keylen;
1174
1175 return 0;
1176}
1177
Jon Derrickeed64952017-02-22 07:55:13 -07001178static int get_active_key(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001179{
1180 u8 uid[OPAL_UID_LENGTH];
David Kozube8b29222019-02-14 01:15:58 +01001181 int err;
Jon Derrickeed64952017-02-22 07:55:13 -07001182 u8 *lr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001183
Scott Bauer455a7b22017-02-03 12:50:31 -07001184 err = build_locking_range(uid, sizeof(uid), *lr);
1185 if (err)
1186 return err;
1187
David Kozub3fff2342019-02-14 01:16:04 +01001188 err = generic_get_column(dev, uid, OPAL_ACTIVEKEY);
1189 if (err)
Scott Bauer455a7b22017-02-03 12:50:31 -07001190 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001191
David Kozub3fff2342019-02-14 01:16:04 +01001192 return get_active_key_cont(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07001193}
1194
1195static int generic_lr_enable_disable(struct opal_dev *dev,
1196 u8 *uid, bool rle, bool wle,
1197 bool rl, bool wl)
1198{
David Kozube8b29222019-02-14 01:15:58 +01001199 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001200
David Kozube8b29222019-02-14 01:15:58 +01001201 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001202
Scott Bauer455a7b22017-02-03 12:50:31 -07001203 add_token_u8(&err, dev, OPAL_STARTNAME);
1204 add_token_u8(&err, dev, OPAL_VALUES);
1205 add_token_u8(&err, dev, OPAL_STARTLIST);
1206
1207 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001208 add_token_u8(&err, dev, OPAL_READLOCKENABLED);
Scott Bauer455a7b22017-02-03 12:50:31 -07001209 add_token_u8(&err, dev, rle);
1210 add_token_u8(&err, dev, OPAL_ENDNAME);
1211
1212 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001213 add_token_u8(&err, dev, OPAL_WRITELOCKENABLED);
Scott Bauer455a7b22017-02-03 12:50:31 -07001214 add_token_u8(&err, dev, wle);
1215 add_token_u8(&err, dev, OPAL_ENDNAME);
1216
1217 add_token_u8(&err, dev, OPAL_STARTNAME);
1218 add_token_u8(&err, dev, OPAL_READLOCKED);
1219 add_token_u8(&err, dev, rl);
1220 add_token_u8(&err, dev, OPAL_ENDNAME);
1221
1222 add_token_u8(&err, dev, OPAL_STARTNAME);
1223 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1224 add_token_u8(&err, dev, wl);
1225 add_token_u8(&err, dev, OPAL_ENDNAME);
1226
1227 add_token_u8(&err, dev, OPAL_ENDLIST);
1228 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001229 return err;
1230}
1231
1232static inline int enable_global_lr(struct opal_dev *dev, u8 *uid,
1233 struct opal_user_lr_setup *setup)
1234{
1235 int err;
1236
1237 err = generic_lr_enable_disable(dev, uid, !!setup->RLE, !!setup->WLE,
1238 0, 0);
1239 if (err)
Scott Bauer591c59d2017-04-07 13:58:50 -06001240 pr_debug("Failed to create enable global lr command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001241 return err;
1242}
1243
Jon Derrickeed64952017-02-22 07:55:13 -07001244static int setup_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001245{
1246 u8 uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001247 struct opal_user_lr_setup *setup = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001248 u8 lr;
David Kozube8b29222019-02-14 01:15:58 +01001249 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001250
Scott Bauer455a7b22017-02-03 12:50:31 -07001251 lr = setup->session.opal_key.lr;
1252 err = build_locking_range(uid, sizeof(uid), lr);
1253 if (err)
1254 return err;
1255
1256 if (lr == 0)
1257 err = enable_global_lr(dev, uid, setup);
1258 else {
David Kozube8b29222019-02-14 01:15:58 +01001259 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001260
Scott Bauer455a7b22017-02-03 12:50:31 -07001261 add_token_u8(&err, dev, OPAL_STARTNAME);
1262 add_token_u8(&err, dev, OPAL_VALUES);
1263 add_token_u8(&err, dev, OPAL_STARTLIST);
1264
1265 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001266 add_token_u8(&err, dev, OPAL_RANGESTART);
Scott Bauer455a7b22017-02-03 12:50:31 -07001267 add_token_u64(&err, dev, setup->range_start);
1268 add_token_u8(&err, dev, OPAL_ENDNAME);
1269
1270 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001271 add_token_u8(&err, dev, OPAL_RANGELENGTH);
Scott Bauer455a7b22017-02-03 12:50:31 -07001272 add_token_u64(&err, dev, setup->range_length);
1273 add_token_u8(&err, dev, OPAL_ENDNAME);
1274
1275 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001276 add_token_u8(&err, dev, OPAL_READLOCKENABLED);
Scott Bauer455a7b22017-02-03 12:50:31 -07001277 add_token_u64(&err, dev, !!setup->RLE);
1278 add_token_u8(&err, dev, OPAL_ENDNAME);
1279
1280 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001281 add_token_u8(&err, dev, OPAL_WRITELOCKENABLED);
Scott Bauer455a7b22017-02-03 12:50:31 -07001282 add_token_u64(&err, dev, !!setup->WLE);
1283 add_token_u8(&err, dev, OPAL_ENDNAME);
1284
1285 add_token_u8(&err, dev, OPAL_ENDLIST);
1286 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001287 }
1288 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001289 pr_debug("Error building Setup Locking range command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001290 return err;
1291
1292 }
1293
1294 return finalize_and_send(dev, parse_and_check_status);
1295}
1296
1297static int start_generic_opal_session(struct opal_dev *dev,
1298 enum opal_uid auth,
1299 enum opal_uid sp_type,
1300 const char *key,
1301 u8 key_len)
1302{
1303 u32 hsn;
David Kozube8b29222019-02-14 01:15:58 +01001304 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001305
Scott Bauer591c59d2017-04-07 13:58:50 -06001306 if (key == NULL && auth != OPAL_ANYBODY_UID)
Scott Bauer455a7b22017-02-03 12:50:31 -07001307 return OPAL_INVAL_PARAM;
Scott Bauer455a7b22017-02-03 12:50:31 -07001308
Scott Bauer455a7b22017-02-03 12:50:31 -07001309 hsn = GENERIC_HOST_SESSION_NUM;
David Kozube8b29222019-02-14 01:15:58 +01001310 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1311 opalmethod[OPAL_STARTSESSION]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001312
Scott Bauer455a7b22017-02-03 12:50:31 -07001313 add_token_u64(&err, dev, hsn);
1314 add_token_bytestring(&err, dev, opaluid[sp_type], OPAL_UID_LENGTH);
1315 add_token_u8(&err, dev, 1);
1316
1317 switch (auth) {
1318 case OPAL_ANYBODY_UID:
Scott Bauer455a7b22017-02-03 12:50:31 -07001319 break;
1320 case OPAL_ADMIN1_UID:
1321 case OPAL_SID_UID:
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06001322 case OPAL_PSID_UID:
Scott Bauer455a7b22017-02-03 12:50:31 -07001323 add_token_u8(&err, dev, OPAL_STARTNAME);
1324 add_token_u8(&err, dev, 0); /* HostChallenge */
1325 add_token_bytestring(&err, dev, key, key_len);
1326 add_token_u8(&err, dev, OPAL_ENDNAME);
1327 add_token_u8(&err, dev, OPAL_STARTNAME);
1328 add_token_u8(&err, dev, 3); /* HostSignAuth */
1329 add_token_bytestring(&err, dev, opaluid[auth],
1330 OPAL_UID_LENGTH);
1331 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001332 break;
1333 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06001334 pr_debug("Cannot start Admin SP session with auth %d\n", auth);
Scott Bauer455a7b22017-02-03 12:50:31 -07001335 return OPAL_INVAL_PARAM;
1336 }
1337
1338 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001339 pr_debug("Error building start adminsp session command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001340 return err;
1341 }
1342
1343 return finalize_and_send(dev, start_opal_session_cont);
1344}
1345
Jon Derrickeed64952017-02-22 07:55:13 -07001346static int start_anybodyASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001347{
1348 return start_generic_opal_session(dev, OPAL_ANYBODY_UID,
1349 OPAL_ADMINSP_UID, NULL, 0);
1350}
1351
Jon Derrickeed64952017-02-22 07:55:13 -07001352static int start_SIDASP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001353{
1354 int ret;
1355 const u8 *key = dev->prev_data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001356
1357 if (!key) {
Jon Derrickeed64952017-02-22 07:55:13 -07001358 const struct opal_key *okey = data;
David Kozub1e815b32019-02-14 01:15:54 +01001359
Scott Bauer455a7b22017-02-03 12:50:31 -07001360 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1361 OPAL_ADMINSP_UID,
1362 okey->key,
1363 okey->key_len);
1364 } else {
1365 ret = start_generic_opal_session(dev, OPAL_SID_UID,
1366 OPAL_ADMINSP_UID,
1367 key, dev->prev_d_len);
1368 kfree(key);
1369 dev->prev_data = NULL;
1370 }
1371 return ret;
1372}
1373
Jon Derrickeed64952017-02-22 07:55:13 -07001374static int start_admin1LSP_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001375{
Jon Derrickeed64952017-02-22 07:55:13 -07001376 struct opal_key *key = data;
David Kozub1e815b32019-02-14 01:15:54 +01001377
Scott Bauer455a7b22017-02-03 12:50:31 -07001378 return start_generic_opal_session(dev, OPAL_ADMIN1_UID,
1379 OPAL_LOCKINGSP_UID,
1380 key->key, key->key_len);
1381}
1382
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06001383static int start_PSID_opal_session(struct opal_dev *dev, void *data)
1384{
1385 const struct opal_key *okey = data;
1386
1387 return start_generic_opal_session(dev, OPAL_PSID_UID,
1388 OPAL_ADMINSP_UID,
1389 okey->key,
1390 okey->key_len);
1391}
1392
Jon Derrickeed64952017-02-22 07:55:13 -07001393static int start_auth_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001394{
Jon Derrickeed64952017-02-22 07:55:13 -07001395 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001396 u8 lk_ul_user[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001397 size_t keylen = session->opal_key.key_len;
Scott Bauer455a7b22017-02-03 12:50:31 -07001398 int err = 0;
1399
Scott Bauer455a7b22017-02-03 12:50:31 -07001400 u8 *key = session->opal_key.key;
1401 u32 hsn = GENERIC_HOST_SESSION_NUM;
1402
David Kozube8b29222019-02-14 01:15:58 +01001403 if (session->sum)
Scott Bauer455a7b22017-02-03 12:50:31 -07001404 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1405 session->opal_key.lr);
David Kozube8b29222019-02-14 01:15:58 +01001406 else if (session->who != OPAL_ADMIN1 && !session->sum)
Scott Bauer455a7b22017-02-03 12:50:31 -07001407 err = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
1408 session->who - 1);
David Kozube8b29222019-02-14 01:15:58 +01001409 else
Scott Bauer455a7b22017-02-03 12:50:31 -07001410 memcpy(lk_ul_user, opaluid[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
1411
David Kozube8b29222019-02-14 01:15:58 +01001412 if (err)
1413 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001414
David Kozube8b29222019-02-14 01:15:58 +01001415 err = cmd_start(dev, opaluid[OPAL_SMUID_UID],
1416 opalmethod[OPAL_STARTSESSION]);
1417
Scott Bauer455a7b22017-02-03 12:50:31 -07001418 add_token_u64(&err, dev, hsn);
1419 add_token_bytestring(&err, dev, opaluid[OPAL_LOCKINGSP_UID],
1420 OPAL_UID_LENGTH);
1421 add_token_u8(&err, dev, 1);
1422 add_token_u8(&err, dev, OPAL_STARTNAME);
1423 add_token_u8(&err, dev, 0);
1424 add_token_bytestring(&err, dev, key, keylen);
1425 add_token_u8(&err, dev, OPAL_ENDNAME);
1426 add_token_u8(&err, dev, OPAL_STARTNAME);
1427 add_token_u8(&err, dev, 3);
1428 add_token_bytestring(&err, dev, lk_ul_user, OPAL_UID_LENGTH);
1429 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001430
1431 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001432 pr_debug("Error building STARTSESSION command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001433 return err;
1434 }
1435
1436 return finalize_and_send(dev, start_opal_session_cont);
1437}
1438
Jon Derrickeed64952017-02-22 07:55:13 -07001439static int revert_tper(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001440{
David Kozube8b29222019-02-14 01:15:58 +01001441 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001442
David Kozube8b29222019-02-14 01:15:58 +01001443 err = cmd_start(dev, opaluid[OPAL_ADMINSP_UID],
1444 opalmethod[OPAL_REVERT]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001445 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001446 pr_debug("Error building REVERT TPER command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001447 return err;
1448 }
1449
1450 return finalize_and_send(dev, parse_and_check_status);
1451}
1452
Jon Derrickeed64952017-02-22 07:55:13 -07001453static int internal_activate_user(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001454{
Jon Derrickeed64952017-02-22 07:55:13 -07001455 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001456 u8 uid[OPAL_UID_LENGTH];
David Kozube8b29222019-02-14 01:15:58 +01001457 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001458
1459 memcpy(uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1460 uid[7] = session->who;
1461
David Kozube8b29222019-02-14 01:15:58 +01001462 err = cmd_start(dev, uid, opalmethod[OPAL_SET]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001463 add_token_u8(&err, dev, OPAL_STARTNAME);
1464 add_token_u8(&err, dev, OPAL_VALUES);
1465 add_token_u8(&err, dev, OPAL_STARTLIST);
1466 add_token_u8(&err, dev, OPAL_STARTNAME);
1467 add_token_u8(&err, dev, 5); /* Enabled */
1468 add_token_u8(&err, dev, OPAL_TRUE);
1469 add_token_u8(&err, dev, OPAL_ENDNAME);
1470 add_token_u8(&err, dev, OPAL_ENDLIST);
1471 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001472
1473 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001474 pr_debug("Error building Activate UserN command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001475 return err;
1476 }
1477
1478 return finalize_and_send(dev, parse_and_check_status);
1479}
1480
Jon Derrickeed64952017-02-22 07:55:13 -07001481static int erase_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001482{
Jon Derrickeed64952017-02-22 07:55:13 -07001483 struct opal_session_info *session = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001484 u8 uid[OPAL_UID_LENGTH];
David Kozube8b29222019-02-14 01:15:58 +01001485 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001486
1487 if (build_locking_range(uid, sizeof(uid), session->opal_key.lr) < 0)
1488 return -ERANGE;
1489
David Kozube8b29222019-02-14 01:15:58 +01001490 err = cmd_start(dev, uid, opalmethod[OPAL_ERASE]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001491
1492 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001493 pr_debug("Error building Erase Locking Range Command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001494 return err;
1495 }
1496 return finalize_and_send(dev, parse_and_check_status);
1497}
1498
Jon Derrickeed64952017-02-22 07:55:13 -07001499static int set_mbr_done(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001500{
Jon Derrickeed64952017-02-22 07:55:13 -07001501 u8 *mbr_done_tf = data;
David Kozube8b29222019-02-14 01:15:58 +01001502 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001503
David Kozube8b29222019-02-14 01:15:58 +01001504 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1505 opalmethod[OPAL_SET]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001506
Scott Bauer455a7b22017-02-03 12:50:31 -07001507 add_token_u8(&err, dev, OPAL_STARTNAME);
1508 add_token_u8(&err, dev, OPAL_VALUES);
1509 add_token_u8(&err, dev, OPAL_STARTLIST);
1510 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001511 add_token_u8(&err, dev, OPAL_MBRDONE);
Jon Derrickeed64952017-02-22 07:55:13 -07001512 add_token_u8(&err, dev, *mbr_done_tf); /* Done T or F */
Scott Bauer455a7b22017-02-03 12:50:31 -07001513 add_token_u8(&err, dev, OPAL_ENDNAME);
1514 add_token_u8(&err, dev, OPAL_ENDLIST);
1515 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001516
1517 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001518 pr_debug("Error Building set MBR Done command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001519 return err;
1520 }
1521
1522 return finalize_and_send(dev, parse_and_check_status);
1523}
1524
Jon Derrickeed64952017-02-22 07:55:13 -07001525static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001526{
Jon Derrickeed64952017-02-22 07:55:13 -07001527 u8 *mbr_en_dis = data;
David Kozube8b29222019-02-14 01:15:58 +01001528 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001529
David Kozube8b29222019-02-14 01:15:58 +01001530 err = cmd_start(dev, opaluid[OPAL_MBRCONTROL],
1531 opalmethod[OPAL_SET]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001532
Scott Bauer455a7b22017-02-03 12:50:31 -07001533 add_token_u8(&err, dev, OPAL_STARTNAME);
1534 add_token_u8(&err, dev, OPAL_VALUES);
1535 add_token_u8(&err, dev, OPAL_STARTLIST);
1536 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001537 add_token_u8(&err, dev, OPAL_MBRENABLE);
Jon Derrickeed64952017-02-22 07:55:13 -07001538 add_token_u8(&err, dev, *mbr_en_dis);
Scott Bauer455a7b22017-02-03 12:50:31 -07001539 add_token_u8(&err, dev, OPAL_ENDNAME);
1540 add_token_u8(&err, dev, OPAL_ENDLIST);
1541 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001542
1543 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001544 pr_debug("Error Building set MBR done command\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001545 return err;
1546 }
1547
1548 return finalize_and_send(dev, parse_and_check_status);
1549}
1550
Jonas Rabensteina9b25b42019-05-21 22:46:45 +02001551static int write_shadow_mbr(struct opal_dev *dev, void *data)
1552{
1553 struct opal_shadow_mbr *shadow = data;
1554 const u8 __user *src;
1555 u8 *dst;
1556 size_t off = 0;
1557 u64 len;
1558 int err = 0;
1559
1560 /* do the actual transmission(s) */
1561 src = (u8 __user *)(uintptr_t)shadow->data;
1562 while (off < shadow->size) {
1563 err = cmd_start(dev, opaluid[OPAL_MBR], opalmethod[OPAL_SET]);
1564 add_token_u8(&err, dev, OPAL_STARTNAME);
1565 add_token_u8(&err, dev, OPAL_WHERE);
1566 add_token_u64(&err, dev, shadow->offset + off);
1567 add_token_u8(&err, dev, OPAL_ENDNAME);
1568
1569 add_token_u8(&err, dev, OPAL_STARTNAME);
1570 add_token_u8(&err, dev, OPAL_VALUES);
1571
1572 /*
1573 * The bytestring header is either 1 or 2 bytes, so assume 2.
1574 * There also needs to be enough space to accommodate the
1575 * trailing OPAL_ENDNAME (1 byte) and tokens added by
1576 * cmd_finalize.
1577 */
1578 len = min(remaining_size(dev) - (2+1+CMD_FINALIZE_BYTES_NEEDED),
1579 (size_t)(shadow->size - off));
1580 pr_debug("MBR: write bytes %zu+%llu/%llu\n",
1581 off, len, shadow->size);
1582
1583 dst = add_bytestring_header(&err, dev, len);
1584 if (!dst)
1585 break;
1586 if (copy_from_user(dst, src + off, len))
1587 err = -EFAULT;
1588 dev->pos += len;
1589
1590 add_token_u8(&err, dev, OPAL_ENDNAME);
1591 if (err)
1592 break;
1593
1594 err = finalize_and_send(dev, parse_and_check_status);
1595 if (err)
1596 break;
1597
1598 off += len;
1599 }
1600 return err;
1601}
1602
Scott Bauer455a7b22017-02-03 12:50:31 -07001603static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1604 struct opal_dev *dev)
1605{
David Kozube8b29222019-02-14 01:15:58 +01001606 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001607
David Kozube8b29222019-02-14 01:15:58 +01001608 err = cmd_start(dev, cpin_uid, opalmethod[OPAL_SET]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001609
Scott Bauer455a7b22017-02-03 12:50:31 -07001610 add_token_u8(&err, dev, OPAL_STARTNAME);
1611 add_token_u8(&err, dev, OPAL_VALUES);
1612 add_token_u8(&err, dev, OPAL_STARTLIST);
1613 add_token_u8(&err, dev, OPAL_STARTNAME);
David Kozub372be402019-02-14 01:16:05 +01001614 add_token_u8(&err, dev, OPAL_PIN);
Scott Bauer455a7b22017-02-03 12:50:31 -07001615 add_token_bytestring(&err, dev, key, key_len);
1616 add_token_u8(&err, dev, OPAL_ENDNAME);
1617 add_token_u8(&err, dev, OPAL_ENDLIST);
1618 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001619
1620 return err;
1621}
1622
Jon Derrickeed64952017-02-22 07:55:13 -07001623static int set_new_pw(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001624{
1625 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001626 struct opal_session_info *usr = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001627
1628 memcpy(cpin_uid, opaluid[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1629
1630 if (usr->who != OPAL_ADMIN1) {
1631 cpin_uid[5] = 0x03;
1632 if (usr->sum)
1633 cpin_uid[7] = usr->opal_key.lr + 1;
1634 else
1635 cpin_uid[7] = usr->who;
1636 }
1637
1638 if (generic_pw_cmd(usr->opal_key.key, usr->opal_key.key_len,
1639 cpin_uid, dev)) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001640 pr_debug("Error building set password command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001641 return -ERANGE;
1642 }
1643
1644 return finalize_and_send(dev, parse_and_check_status);
1645}
1646
Jon Derrickeed64952017-02-22 07:55:13 -07001647static int set_sid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001648{
1649 u8 cpin_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001650 struct opal_key *key = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001651
1652 memcpy(cpin_uid, opaluid[OPAL_C_PIN_SID], OPAL_UID_LENGTH);
1653
1654 if (generic_pw_cmd(key->key, key->key_len, cpin_uid, dev)) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001655 pr_debug("Error building Set SID cpin\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001656 return -ERANGE;
1657 }
1658 return finalize_and_send(dev, parse_and_check_status);
1659}
1660
Jon Derrickeed64952017-02-22 07:55:13 -07001661static int add_user_to_lr(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001662{
1663 u8 lr_buffer[OPAL_UID_LENGTH];
1664 u8 user_uid[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001665 struct opal_lock_unlock *lkul = data;
David Kozube8b29222019-02-14 01:15:58 +01001666 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001667
Scott Bauer455a7b22017-02-03 12:50:31 -07001668 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
1669 OPAL_UID_LENGTH);
1670
1671 if (lkul->l_state == OPAL_RW)
1672 memcpy(lr_buffer, opaluid[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
1673 OPAL_UID_LENGTH);
1674
1675 lr_buffer[7] = lkul->session.opal_key.lr;
1676
1677 memcpy(user_uid, opaluid[OPAL_USER1_UID], OPAL_UID_LENGTH);
1678
1679 user_uid[7] = lkul->session.who;
1680
David Kozube8b29222019-02-14 01:15:58 +01001681 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001682
Scott Bauer455a7b22017-02-03 12:50:31 -07001683 add_token_u8(&err, dev, OPAL_STARTNAME);
1684 add_token_u8(&err, dev, OPAL_VALUES);
1685
1686 add_token_u8(&err, dev, OPAL_STARTLIST);
1687 add_token_u8(&err, dev, OPAL_STARTNAME);
1688 add_token_u8(&err, dev, 3);
1689
1690 add_token_u8(&err, dev, OPAL_STARTLIST);
1691
1692
1693 add_token_u8(&err, dev, OPAL_STARTNAME);
1694 add_token_bytestring(&err, dev,
1695 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1696 OPAL_UID_LENGTH/2);
1697 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1698 add_token_u8(&err, dev, OPAL_ENDNAME);
1699
1700
1701 add_token_u8(&err, dev, OPAL_STARTNAME);
1702 add_token_bytestring(&err, dev,
1703 opaluid[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
1704 OPAL_UID_LENGTH/2);
1705 add_token_bytestring(&err, dev, user_uid, OPAL_UID_LENGTH);
1706 add_token_u8(&err, dev, OPAL_ENDNAME);
1707
1708
1709 add_token_u8(&err, dev, OPAL_STARTNAME);
1710 add_token_bytestring(&err, dev, opaluid[OPAL_HALF_UID_BOOLEAN_ACE],
1711 OPAL_UID_LENGTH/2);
1712 add_token_u8(&err, dev, 1);
1713 add_token_u8(&err, dev, OPAL_ENDNAME);
1714
1715
1716 add_token_u8(&err, dev, OPAL_ENDLIST);
1717 add_token_u8(&err, dev, OPAL_ENDNAME);
1718 add_token_u8(&err, dev, OPAL_ENDLIST);
1719 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001720
1721 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001722 pr_debug("Error building add user to locking range command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001723 return err;
1724 }
1725
1726 return finalize_and_send(dev, parse_and_check_status);
1727}
1728
Jon Derrickeed64952017-02-22 07:55:13 -07001729static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001730{
1731 u8 lr_buffer[OPAL_UID_LENGTH];
Jon Derrickeed64952017-02-22 07:55:13 -07001732 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001733 u8 read_locked = 1, write_locked = 1;
1734 int err = 0;
1735
Scott Bauer455a7b22017-02-03 12:50:31 -07001736 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1737 lkul->session.opal_key.lr) < 0)
1738 return -ERANGE;
1739
1740 switch (lkul->l_state) {
1741 case OPAL_RO:
1742 read_locked = 0;
1743 write_locked = 1;
1744 break;
1745 case OPAL_RW:
1746 read_locked = 0;
1747 write_locked = 0;
1748 break;
1749 case OPAL_LK:
David Kozub1e815b32019-02-14 01:15:54 +01001750 /* vars are initialized to locked */
Scott Bauer455a7b22017-02-03 12:50:31 -07001751 break;
1752 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06001753 pr_debug("Tried to set an invalid locking state... returning to uland\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001754 return OPAL_INVAL_PARAM;
1755 }
1756
David Kozube8b29222019-02-14 01:15:58 +01001757 err = cmd_start(dev, lr_buffer, opalmethod[OPAL_SET]);
1758
Scott Bauer455a7b22017-02-03 12:50:31 -07001759 add_token_u8(&err, dev, OPAL_STARTNAME);
1760 add_token_u8(&err, dev, OPAL_VALUES);
1761 add_token_u8(&err, dev, OPAL_STARTLIST);
1762
1763 add_token_u8(&err, dev, OPAL_STARTNAME);
1764 add_token_u8(&err, dev, OPAL_READLOCKED);
1765 add_token_u8(&err, dev, read_locked);
1766 add_token_u8(&err, dev, OPAL_ENDNAME);
1767
1768 add_token_u8(&err, dev, OPAL_STARTNAME);
1769 add_token_u8(&err, dev, OPAL_WRITELOCKED);
1770 add_token_u8(&err, dev, write_locked);
1771 add_token_u8(&err, dev, OPAL_ENDNAME);
1772
1773 add_token_u8(&err, dev, OPAL_ENDLIST);
1774 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001775
1776 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001777 pr_debug("Error building SET command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001778 return err;
1779 }
1780 return finalize_and_send(dev, parse_and_check_status);
1781}
1782
1783
Jon Derrickeed64952017-02-22 07:55:13 -07001784static int lock_unlock_locking_range_sum(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001785{
1786 u8 lr_buffer[OPAL_UID_LENGTH];
1787 u8 read_locked = 1, write_locked = 1;
Jon Derrickeed64952017-02-22 07:55:13 -07001788 struct opal_lock_unlock *lkul = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001789 int ret;
1790
1791 clear_opal_cmd(dev);
1792 set_comid(dev, dev->comid);
1793
Scott Bauer455a7b22017-02-03 12:50:31 -07001794 if (build_locking_range(lr_buffer, sizeof(lr_buffer),
1795 lkul->session.opal_key.lr) < 0)
1796 return -ERANGE;
1797
1798 switch (lkul->l_state) {
1799 case OPAL_RO:
1800 read_locked = 0;
1801 write_locked = 1;
1802 break;
1803 case OPAL_RW:
1804 read_locked = 0;
1805 write_locked = 0;
1806 break;
1807 case OPAL_LK:
David Kozub1e815b32019-02-14 01:15:54 +01001808 /* vars are initialized to locked */
Scott Bauer455a7b22017-02-03 12:50:31 -07001809 break;
1810 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06001811 pr_debug("Tried to set an invalid locking state.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001812 return OPAL_INVAL_PARAM;
1813 }
1814 ret = generic_lr_enable_disable(dev, lr_buffer, 1, 1,
1815 read_locked, write_locked);
1816
1817 if (ret < 0) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001818 pr_debug("Error building SET command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001819 return ret;
1820 }
1821 return finalize_and_send(dev, parse_and_check_status);
1822}
1823
Jon Derrickeed64952017-02-22 07:55:13 -07001824static int activate_lsp(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001825{
Jon Derrickeed64952017-02-22 07:55:13 -07001826 struct opal_lr_act *opal_act = data;
Scott Bauer455a7b22017-02-03 12:50:31 -07001827 u8 user_lr[OPAL_UID_LENGTH];
1828 u8 uint_3 = 0x83;
David Kozube8b29222019-02-14 01:15:58 +01001829 int err, i;
Scott Bauer455a7b22017-02-03 12:50:31 -07001830
David Kozube8b29222019-02-14 01:15:58 +01001831 err = cmd_start(dev, opaluid[OPAL_LOCKINGSP_UID],
1832 opalmethod[OPAL_ACTIVATE]);
Scott Bauer455a7b22017-02-03 12:50:31 -07001833
1834 if (opal_act->sum) {
1835 err = build_locking_range(user_lr, sizeof(user_lr),
1836 opal_act->lr[0]);
1837 if (err)
1838 return err;
1839
Scott Bauer455a7b22017-02-03 12:50:31 -07001840 add_token_u8(&err, dev, OPAL_STARTNAME);
1841 add_token_u8(&err, dev, uint_3);
1842 add_token_u8(&err, dev, 6);
1843 add_token_u8(&err, dev, 0);
1844 add_token_u8(&err, dev, 0);
1845
1846 add_token_u8(&err, dev, OPAL_STARTLIST);
1847 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1848 for (i = 1; i < opal_act->num_lrs; i++) {
1849 user_lr[7] = opal_act->lr[i];
1850 add_token_bytestring(&err, dev, user_lr, OPAL_UID_LENGTH);
1851 }
1852 add_token_u8(&err, dev, OPAL_ENDLIST);
1853 add_token_u8(&err, dev, OPAL_ENDNAME);
Scott Bauer455a7b22017-02-03 12:50:31 -07001854 }
1855
1856 if (err) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001857 pr_debug("Error building Activate LockingSP command.\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001858 return err;
1859 }
1860
1861 return finalize_and_send(dev, parse_and_check_status);
1862}
1863
David Kozub3fff2342019-02-14 01:16:04 +01001864/* Determine if we're in the Manufactured Inactive or Active state */
1865static int get_lsp_lifecycle(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001866{
1867 u8 lc_status;
David Kozub3fff2342019-02-14 01:16:04 +01001868 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001869
David Kozub3fff2342019-02-14 01:16:04 +01001870 err = generic_get_column(dev, opaluid[OPAL_LOCKINGSP_UID],
1871 OPAL_LIFECYCLE);
1872 if (err)
1873 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001874
1875 lc_status = response_get_u64(&dev->parsed, 4);
David Kozub1e815b32019-02-14 01:15:54 +01001876 /* 0x08 is Manufactured Inactive */
Scott Bauer455a7b22017-02-03 12:50:31 -07001877 /* 0x09 is Manufactured */
1878 if (lc_status != OPAL_MANUFACTURED_INACTIVE) {
Scott Bauer591c59d2017-04-07 13:58:50 -06001879 pr_debug("Couldn't determine the status of the Lifecycle state\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001880 return -ENODEV;
1881 }
1882
1883 return 0;
1884}
1885
David Kozub3fff2342019-02-14 01:16:04 +01001886static int get_msid_cpin_pin(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001887{
1888 const char *msid_pin;
1889 size_t strlen;
David Kozub3fff2342019-02-14 01:16:04 +01001890 int err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001891
David Kozub3fff2342019-02-14 01:16:04 +01001892 err = generic_get_column(dev, opaluid[OPAL_C_PIN_MSID], OPAL_PIN);
1893 if (err)
1894 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001895
1896 strlen = response_get_string(&dev->parsed, 4, &msid_pin);
1897 if (!msid_pin) {
David Kozub3fff2342019-02-14 01:16:04 +01001898 pr_debug("Couldn't extract MSID_CPIN from response\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07001899 return OPAL_INVAL_PARAM;
1900 }
1901
1902 dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
1903 if (!dev->prev_data)
1904 return -ENOMEM;
1905
1906 dev->prev_d_len = strlen;
1907
1908 return 0;
1909}
1910
Jon Derrickeed64952017-02-22 07:55:13 -07001911static int end_opal_session(struct opal_dev *dev, void *data)
Scott Bauer455a7b22017-02-03 12:50:31 -07001912{
1913 int err = 0;
1914
1915 clear_opal_cmd(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07001916 set_comid(dev, dev->comid);
1917 add_token_u8(&err, dev, OPAL_ENDOFSESSION);
Scott Bauer455a7b22017-02-03 12:50:31 -07001918
Jon Derrickeed64952017-02-22 07:55:13 -07001919 if (err < 0)
1920 return err;
Scott Bauer455a7b22017-02-03 12:50:31 -07001921 return finalize_and_send(dev, end_session_cont);
1922}
1923
1924static int end_opal_session_error(struct opal_dev *dev)
1925{
David Kozub0af26482019-02-14 01:16:07 +01001926 const struct opal_step error_end_session = {
1927 end_opal_session,
Scott Bauer455a7b22017-02-03 12:50:31 -07001928 };
David Kozub0af26482019-02-14 01:16:07 +01001929 return execute_step(dev, &error_end_session, 0);
Scott Bauer455a7b22017-02-03 12:50:31 -07001930}
1931
David Kozub3db87232019-02-14 01:16:06 +01001932static inline void setup_opal_dev(struct opal_dev *dev)
Scott Bauer455a7b22017-02-03 12:50:31 -07001933{
Scott Bauer455a7b22017-02-03 12:50:31 -07001934 dev->tsn = 0;
1935 dev->hsn = 0;
Scott Bauer455a7b22017-02-03 12:50:31 -07001936 dev->prev_data = NULL;
1937}
1938
1939static int check_opal_support(struct opal_dev *dev)
1940{
Scott Bauer455a7b22017-02-03 12:50:31 -07001941 int ret;
1942
1943 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01001944 setup_opal_dev(dev);
David Kozub0af26482019-02-14 01:16:07 +01001945 ret = opal_discovery0_step(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07001946 dev->supported = !ret;
1947 mutex_unlock(&dev->dev_lock);
1948 return ret;
1949}
1950
Scott Bauer7d6d1572017-02-22 10:15:06 -07001951static void clean_opal_dev(struct opal_dev *dev)
1952{
1953
1954 struct opal_suspend_data *suspend, *next;
1955
1956 mutex_lock(&dev->dev_lock);
1957 list_for_each_entry_safe(suspend, next, &dev->unlk_lst, node) {
1958 list_del(&suspend->node);
1959 kfree(suspend);
1960 }
1961 mutex_unlock(&dev->dev_lock);
1962}
1963
1964void free_opal_dev(struct opal_dev *dev)
1965{
1966 if (!dev)
1967 return;
1968 clean_opal_dev(dev);
1969 kfree(dev);
1970}
1971EXPORT_SYMBOL(free_opal_dev);
1972
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01001973struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv)
Scott Bauer455a7b22017-02-03 12:50:31 -07001974{
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01001975 struct opal_dev *dev;
1976
1977 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
1978 if (!dev)
1979 return NULL;
1980
1981 INIT_LIST_HEAD(&dev->unlk_lst);
1982 mutex_init(&dev->dev_lock);
1983 dev->data = data;
1984 dev->send_recv = send_recv;
1985 if (check_opal_support(dev) != 0) {
Christoph Hellwigf5b37b72017-02-17 13:59:38 +01001986 pr_debug("Opal is not supported on this device\n");
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01001987 kfree(dev);
1988 return NULL;
1989 }
1990 return dev;
Scott Bauer455a7b22017-02-03 12:50:31 -07001991}
1992EXPORT_SYMBOL(init_opal_dev);
1993
1994static int opal_secure_erase_locking_range(struct opal_dev *dev,
1995 struct opal_session_info *opal_session)
1996{
Jon Derrickeed64952017-02-22 07:55:13 -07001997 const struct opal_step erase_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07001998 { start_auth_opal_session, opal_session },
1999 { get_active_key, &opal_session->opal_key.lr },
2000 { gen_key, },
David Kozub3db87232019-02-14 01:16:06 +01002001 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002002 };
2003 int ret;
2004
2005 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002006 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002007 ret = execute_steps(dev, erase_steps, ARRAY_SIZE(erase_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002008 mutex_unlock(&dev->dev_lock);
2009 return ret;
2010}
2011
2012static int opal_erase_locking_range(struct opal_dev *dev,
2013 struct opal_session_info *opal_session)
2014{
Jon Derrickeed64952017-02-22 07:55:13 -07002015 const struct opal_step erase_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002016 { start_auth_opal_session, opal_session },
2017 { erase_locking_range, opal_session },
David Kozub3db87232019-02-14 01:16:06 +01002018 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002019 };
2020 int ret;
2021
2022 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002023 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002024 ret = execute_steps(dev, erase_steps, ARRAY_SIZE(erase_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002025 mutex_unlock(&dev->dev_lock);
2026 return ret;
2027}
2028
2029static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
2030 struct opal_mbr_data *opal_mbr)
2031{
David Kozub78bf4732019-02-14 01:15:53 +01002032 u8 enable_disable = opal_mbr->enable_disable == OPAL_MBR_ENABLE ?
2033 OPAL_TRUE : OPAL_FALSE;
2034
Jon Derrickeed64952017-02-22 07:55:13 -07002035 const struct opal_step mbr_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002036 { start_admin1LSP_opal_session, &opal_mbr->key },
David Kozub78bf4732019-02-14 01:15:53 +01002037 { set_mbr_done, &enable_disable },
Jon Derrickeed64952017-02-22 07:55:13 -07002038 { end_opal_session, },
2039 { start_admin1LSP_opal_session, &opal_mbr->key },
David Kozub78bf4732019-02-14 01:15:53 +01002040 { set_mbr_enable_disable, &enable_disable },
David Kozub3db87232019-02-14 01:16:06 +01002041 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002042 };
2043 int ret;
2044
2045 if (opal_mbr->enable_disable != OPAL_MBR_ENABLE &&
2046 opal_mbr->enable_disable != OPAL_MBR_DISABLE)
2047 return -EINVAL;
2048
2049 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002050 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002051 ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002052 mutex_unlock(&dev->dev_lock);
2053 return ret;
2054}
2055
Jonas Rabensteinc9888442019-05-21 22:46:44 +02002056static int opal_set_mbr_done(struct opal_dev *dev,
2057 struct opal_mbr_done *mbr_done)
2058{
2059 u8 mbr_done_tf = mbr_done->done_flag == OPAL_MBR_DONE ?
2060 OPAL_TRUE : OPAL_FALSE;
2061
2062 const struct opal_step mbr_steps[] = {
2063 { start_admin1LSP_opal_session, &mbr_done->key },
2064 { set_mbr_done, &mbr_done_tf },
2065 { end_opal_session, }
2066 };
2067 int ret;
2068
2069 if (mbr_done->done_flag != OPAL_MBR_DONE &&
2070 mbr_done->done_flag != OPAL_MBR_NOT_DONE)
2071 return -EINVAL;
2072
2073 mutex_lock(&dev->dev_lock);
2074 setup_opal_dev(dev);
2075 ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps));
2076 mutex_unlock(&dev->dev_lock);
2077 return ret;
2078}
2079
Jonas Rabensteina9b25b42019-05-21 22:46:45 +02002080static int opal_write_shadow_mbr(struct opal_dev *dev,
2081 struct opal_shadow_mbr *info)
2082{
2083 const struct opal_step mbr_steps[] = {
2084 { start_admin1LSP_opal_session, &info->key },
2085 { write_shadow_mbr, info },
2086 { end_opal_session, }
2087 };
2088 int ret;
2089
2090 if (info->size == 0)
2091 return 0;
2092
2093 mutex_lock(&dev->dev_lock);
2094 setup_opal_dev(dev);
2095 ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps));
2096 mutex_unlock(&dev->dev_lock);
2097 return ret;
2098}
2099
Scott Bauer455a7b22017-02-03 12:50:31 -07002100static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2101{
2102 struct opal_suspend_data *suspend;
2103
2104 suspend = kzalloc(sizeof(*suspend), GFP_KERNEL);
2105 if (!suspend)
2106 return -ENOMEM;
2107
2108 suspend->unlk = *lk_unlk;
2109 suspend->lr = lk_unlk->session.opal_key.lr;
2110
2111 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002112 setup_opal_dev(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07002113 add_suspend_info(dev, suspend);
2114 mutex_unlock(&dev->dev_lock);
2115 return 0;
2116}
2117
2118static int opal_add_user_to_lr(struct opal_dev *dev,
2119 struct opal_lock_unlock *lk_unlk)
2120{
Jon Derrickeed64952017-02-22 07:55:13 -07002121 const struct opal_step steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002122 { start_admin1LSP_opal_session, &lk_unlk->session.opal_key },
2123 { add_user_to_lr, lk_unlk },
David Kozub3db87232019-02-14 01:16:06 +01002124 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002125 };
2126 int ret;
2127
2128 if (lk_unlk->l_state != OPAL_RO &&
2129 lk_unlk->l_state != OPAL_RW) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002130 pr_debug("Locking state was not RO or RW\n");
Scott Bauer455a7b22017-02-03 12:50:31 -07002131 return -EINVAL;
2132 }
Jon Derrickb0bfdfc2017-03-06 08:41:04 -07002133 if (lk_unlk->session.who < OPAL_USER1 ||
Scott Bauer455a7b22017-02-03 12:50:31 -07002134 lk_unlk->session.who > OPAL_USER9) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002135 pr_debug("Authority was not within the range of users: %d\n",
2136 lk_unlk->session.who);
Scott Bauer455a7b22017-02-03 12:50:31 -07002137 return -EINVAL;
2138 }
2139 if (lk_unlk->session.sum) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002140 pr_debug("%s not supported in sum. Use setup locking range\n",
2141 __func__);
Scott Bauer455a7b22017-02-03 12:50:31 -07002142 return -EINVAL;
2143 }
2144
2145 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002146 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002147 ret = execute_steps(dev, steps, ARRAY_SIZE(steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002148 mutex_unlock(&dev->dev_lock);
2149 return ret;
2150}
2151
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06002152static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psid)
Scott Bauer455a7b22017-02-03 12:50:31 -07002153{
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06002154 /* controller will terminate session */
Jon Derrickeed64952017-02-22 07:55:13 -07002155 const struct opal_step revert_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002156 { start_SIDASP_opal_session, opal },
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06002157 { revert_tper, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002158 };
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06002159 const struct opal_step psid_revert_steps[] = {
2160 { start_PSID_opal_session, opal },
2161 { revert_tper, }
2162 };
2163
Scott Bauer455a7b22017-02-03 12:50:31 -07002164 int ret;
2165
2166 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002167 setup_opal_dev(dev);
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06002168 if (psid)
2169 ret = execute_steps(dev, psid_revert_steps,
2170 ARRAY_SIZE(psid_revert_steps));
2171 else
2172 ret = execute_steps(dev, revert_steps,
2173 ARRAY_SIZE(revert_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002174 mutex_unlock(&dev->dev_lock);
Scott Bauer7d6d1572017-02-22 10:15:06 -07002175
2176 /*
2177 * If we successfully reverted lets clean
2178 * any saved locking ranges.
2179 */
2180 if (!ret)
2181 clean_opal_dev(dev);
2182
Scott Bauer455a7b22017-02-03 12:50:31 -07002183 return ret;
2184}
2185
Jon Derrickeed64952017-02-22 07:55:13 -07002186static int __opal_lock_unlock(struct opal_dev *dev,
2187 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002188{
Jon Derrickeed64952017-02-22 07:55:13 -07002189 const struct opal_step unlock_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002190 { start_auth_opal_session, &lk_unlk->session },
2191 { lock_unlock_locking_range, lk_unlk },
David Kozub3db87232019-02-14 01:16:06 +01002192 { end_opal_session, }
Jon Derrickeed64952017-02-22 07:55:13 -07002193 };
2194 const struct opal_step unlock_sum_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002195 { start_auth_opal_session, &lk_unlk->session },
2196 { lock_unlock_locking_range_sum, lk_unlk },
David Kozub3db87232019-02-14 01:16:06 +01002197 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002198 };
2199
David Kozub3db87232019-02-14 01:16:06 +01002200 if (lk_unlk->session.sum)
David Kozuba80f36c2019-02-14 01:16:08 +01002201 return execute_steps(dev, unlock_sum_steps,
2202 ARRAY_SIZE(unlock_sum_steps));
David Kozub3db87232019-02-14 01:16:06 +01002203 else
David Kozuba80f36c2019-02-14 01:16:08 +01002204 return execute_steps(dev, unlock_steps,
2205 ARRAY_SIZE(unlock_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002206}
2207
Scott Bauerdbec491b2017-09-01 08:53:35 -06002208static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
2209{
David Kozub78bf4732019-02-14 01:15:53 +01002210 u8 mbr_done_tf = OPAL_TRUE;
David Kozub1e815b32019-02-14 01:15:54 +01002211 const struct opal_step mbrdone_step[] = {
Scott Bauerdbec491b2017-09-01 08:53:35 -06002212 { start_admin1LSP_opal_session, key },
2213 { set_mbr_done, &mbr_done_tf },
David Kozub3db87232019-02-14 01:16:06 +01002214 { end_opal_session, }
Scott Bauerdbec491b2017-09-01 08:53:35 -06002215 };
2216
David Kozuba80f36c2019-02-14 01:16:08 +01002217 return execute_steps(dev, mbrdone_step, ARRAY_SIZE(mbrdone_step));
Scott Bauerdbec491b2017-09-01 08:53:35 -06002218}
2219
Jon Derrickeed64952017-02-22 07:55:13 -07002220static int opal_lock_unlock(struct opal_dev *dev,
2221 struct opal_lock_unlock *lk_unlk)
Scott Bauer455a7b22017-02-03 12:50:31 -07002222{
Scott Bauer455a7b22017-02-03 12:50:31 -07002223 int ret;
2224
Revanth Rajashekar15ddffc2019-06-27 16:31:09 -06002225 if (lk_unlk->session.who > OPAL_USER9)
Scott Bauer455a7b22017-02-03 12:50:31 -07002226 return -EINVAL;
2227
2228 mutex_lock(&dev->dev_lock);
Jon Derrickeed64952017-02-22 07:55:13 -07002229 ret = __opal_lock_unlock(dev, lk_unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002230 mutex_unlock(&dev->dev_lock);
2231 return ret;
2232}
2233
2234static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2235{
Jon Derrickeed64952017-02-22 07:55:13 -07002236 const struct opal_step owner_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002237 { start_anybodyASP_opal_session, },
2238 { get_msid_cpin_pin, },
2239 { end_opal_session, },
2240 { start_SIDASP_opal_session, opal },
2241 { set_sid_cpin_pin, opal },
David Kozub3db87232019-02-14 01:16:06 +01002242 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002243 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002244 int ret;
2245
2246 if (!dev)
2247 return -ENODEV;
2248
2249 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002250 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002251 ret = execute_steps(dev, owner_steps, ARRAY_SIZE(owner_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002252 mutex_unlock(&dev->dev_lock);
2253 return ret;
2254}
2255
David Kozub1e815b32019-02-14 01:15:54 +01002256static int opal_activate_lsp(struct opal_dev *dev,
2257 struct opal_lr_act *opal_lr_act)
Scott Bauer455a7b22017-02-03 12:50:31 -07002258{
Jon Derrickeed64952017-02-22 07:55:13 -07002259 const struct opal_step active_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002260 { start_SIDASP_opal_session, &opal_lr_act->key },
2261 { get_lsp_lifecycle, },
2262 { activate_lsp, opal_lr_act },
David Kozub3db87232019-02-14 01:16:06 +01002263 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002264 };
2265 int ret;
2266
2267 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
2268 return -EINVAL;
2269
2270 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002271 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002272 ret = execute_steps(dev, active_steps, ARRAY_SIZE(active_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002273 mutex_unlock(&dev->dev_lock);
2274 return ret;
2275}
2276
2277static int opal_setup_locking_range(struct opal_dev *dev,
2278 struct opal_user_lr_setup *opal_lrs)
2279{
Jon Derrickeed64952017-02-22 07:55:13 -07002280 const struct opal_step lr_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002281 { start_auth_opal_session, &opal_lrs->session },
2282 { setup_locking_range, opal_lrs },
David Kozub3db87232019-02-14 01:16:06 +01002283 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002284 };
2285 int ret;
2286
2287 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002288 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002289 ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002290 mutex_unlock(&dev->dev_lock);
2291 return ret;
2292}
2293
2294static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
2295{
Jon Derrickeed64952017-02-22 07:55:13 -07002296 const struct opal_step pw_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002297 { start_auth_opal_session, &opal_pw->session },
2298 { set_new_pw, &opal_pw->new_user_pw },
David Kozub3db87232019-02-14 01:16:06 +01002299 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002300 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002301 int ret;
2302
Revanth Rajashekar15ddffc2019-06-27 16:31:09 -06002303 if (opal_pw->session.who > OPAL_USER9 ||
Scott Bauer455a7b22017-02-03 12:50:31 -07002304 opal_pw->new_user_pw.who > OPAL_USER9)
2305 return -EINVAL;
2306
2307 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002308 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002309 ret = execute_steps(dev, pw_steps, ARRAY_SIZE(pw_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002310 mutex_unlock(&dev->dev_lock);
2311 return ret;
2312}
2313
2314static int opal_activate_user(struct opal_dev *dev,
2315 struct opal_session_info *opal_session)
2316{
Jon Derrickeed64952017-02-22 07:55:13 -07002317 const struct opal_step act_steps[] = {
Jon Derrickeed64952017-02-22 07:55:13 -07002318 { start_admin1LSP_opal_session, &opal_session->opal_key },
2319 { internal_activate_user, opal_session },
David Kozub3db87232019-02-14 01:16:06 +01002320 { end_opal_session, }
Scott Bauer455a7b22017-02-03 12:50:31 -07002321 };
Scott Bauer455a7b22017-02-03 12:50:31 -07002322 int ret;
2323
2324 /* We can't activate Admin1 it's active as manufactured */
Jon Derrickb0bfdfc2017-03-06 08:41:04 -07002325 if (opal_session->who < OPAL_USER1 ||
Scott Bauer455a7b22017-02-03 12:50:31 -07002326 opal_session->who > OPAL_USER9) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002327 pr_debug("Who was not a valid user: %d\n", opal_session->who);
Scott Bauer455a7b22017-02-03 12:50:31 -07002328 return -EINVAL;
2329 }
2330
2331 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002332 setup_opal_dev(dev);
David Kozuba80f36c2019-02-14 01:16:08 +01002333 ret = execute_steps(dev, act_steps, ARRAY_SIZE(act_steps));
Scott Bauer455a7b22017-02-03 12:50:31 -07002334 mutex_unlock(&dev->dev_lock);
2335 return ret;
2336}
2337
2338bool opal_unlock_from_suspend(struct opal_dev *dev)
2339{
2340 struct opal_suspend_data *suspend;
Scott Bauer455a7b22017-02-03 12:50:31 -07002341 bool was_failure = false;
2342 int ret = 0;
2343
2344 if (!dev)
2345 return false;
2346 if (!dev->supported)
2347 return false;
2348
2349 mutex_lock(&dev->dev_lock);
David Kozub3db87232019-02-14 01:16:06 +01002350 setup_opal_dev(dev);
Scott Bauer455a7b22017-02-03 12:50:31 -07002351
2352 list_for_each_entry(suspend, &dev->unlk_lst, node) {
Scott Bauer455a7b22017-02-03 12:50:31 -07002353 dev->tsn = 0;
2354 dev->hsn = 0;
2355
Jon Derrickeed64952017-02-22 07:55:13 -07002356 ret = __opal_lock_unlock(dev, &suspend->unlk);
Scott Bauer455a7b22017-02-03 12:50:31 -07002357 if (ret) {
Scott Bauer591c59d2017-04-07 13:58:50 -06002358 pr_debug("Failed to unlock LR %hhu with sum %d\n",
2359 suspend->unlk.session.opal_key.lr,
2360 suspend->unlk.session.sum);
Scott Bauer455a7b22017-02-03 12:50:31 -07002361 was_failure = true;
2362 }
Scott Bauerdbec491b2017-09-01 08:53:35 -06002363 if (dev->mbr_enabled) {
2364 ret = __opal_set_mbr_done(dev, &suspend->unlk.session.opal_key);
2365 if (ret)
2366 pr_debug("Failed to set MBR Done in S3 resume\n");
2367 }
Scott Bauer455a7b22017-02-03 12:50:31 -07002368 }
2369 mutex_unlock(&dev->dev_lock);
2370 return was_failure;
2371}
2372EXPORT_SYMBOL(opal_unlock_from_suspend);
2373
Scott Bauere225c202017-02-14 17:29:36 -07002374int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
Scott Bauer455a7b22017-02-03 12:50:31 -07002375{
Scott Bauere225c202017-02-14 17:29:36 -07002376 void *p;
2377 int ret = -ENOTTY;
Scott Bauer455a7b22017-02-03 12:50:31 -07002378
2379 if (!capable(CAP_SYS_ADMIN))
2380 return -EACCES;
Christoph Hellwig4f1244c2017-02-17 13:59:39 +01002381 if (!dev)
2382 return -ENOTSUPP;
Scott Bauer591c59d2017-04-07 13:58:50 -06002383 if (!dev->supported)
Scott Bauer455a7b22017-02-03 12:50:31 -07002384 return -ENOTSUPP;
Scott Bauer455a7b22017-02-03 12:50:31 -07002385
Jon Derrickeed64952017-02-22 07:55:13 -07002386 p = memdup_user(arg, _IOC_SIZE(cmd));
Scott Bauere225c202017-02-14 17:29:36 -07002387 if (IS_ERR(p))
2388 return PTR_ERR(p);
2389
Scott Bauer455a7b22017-02-03 12:50:31 -07002390 switch (cmd) {
Scott Bauere225c202017-02-14 17:29:36 -07002391 case IOC_OPAL_SAVE:
2392 ret = opal_save(dev, p);
2393 break;
2394 case IOC_OPAL_LOCK_UNLOCK:
2395 ret = opal_lock_unlock(dev, p);
2396 break;
2397 case IOC_OPAL_TAKE_OWNERSHIP:
2398 ret = opal_take_ownership(dev, p);
2399 break;
2400 case IOC_OPAL_ACTIVATE_LSP:
2401 ret = opal_activate_lsp(dev, p);
2402 break;
2403 case IOC_OPAL_SET_PW:
2404 ret = opal_set_new_pw(dev, p);
2405 break;
2406 case IOC_OPAL_ACTIVATE_USR:
2407 ret = opal_activate_user(dev, p);
2408 break;
2409 case IOC_OPAL_REVERT_TPR:
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06002410 ret = opal_reverttper(dev, p, false);
Scott Bauere225c202017-02-14 17:29:36 -07002411 break;
2412 case IOC_OPAL_LR_SETUP:
2413 ret = opal_setup_locking_range(dev, p);
2414 break;
2415 case IOC_OPAL_ADD_USR_TO_LR:
2416 ret = opal_add_user_to_lr(dev, p);
2417 break;
2418 case IOC_OPAL_ENABLE_DISABLE_MBR:
2419 ret = opal_enable_disable_shadow_mbr(dev, p);
2420 break;
Jonas Rabensteinc9888442019-05-21 22:46:44 +02002421 case IOC_OPAL_MBR_DONE:
2422 ret = opal_set_mbr_done(dev, p);
2423 break;
Jonas Rabensteina9b25b42019-05-21 22:46:45 +02002424 case IOC_OPAL_WRITE_SHADOW_MBR:
2425 ret = opal_write_shadow_mbr(dev, p);
2426 break;
Scott Bauere225c202017-02-14 17:29:36 -07002427 case IOC_OPAL_ERASE_LR:
2428 ret = opal_erase_locking_range(dev, p);
2429 break;
2430 case IOC_OPAL_SECURE_ERASE_LR:
2431 ret = opal_secure_erase_locking_range(dev, p);
2432 break;
Revanth Rajashekar5e4c7cf2019-06-27 16:30:02 -06002433 case IOC_OPAL_PSID_REVERT_TPR:
2434 ret = opal_reverttper(dev, p, true);
2435 break;
Scott Bauer455a7b22017-02-03 12:50:31 -07002436 default:
Scott Bauer591c59d2017-04-07 13:58:50 -06002437 break;
Scott Bauer455a7b22017-02-03 12:50:31 -07002438 }
Scott Bauere225c202017-02-14 17:29:36 -07002439
2440 kfree(p);
2441 return ret;
Scott Bauer455a7b22017-02-03 12:50:31 -07002442}
2443EXPORT_SYMBOL_GPL(sed_ioctl);