xref: /spdk/lib/nvme/nvme_opal.c (revision 407e88fd2ab020d753e33014cf759353a9901b51)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include "spdk/opal.h"
34 #include "spdk_internal/event.h"
35 #include "spdk_internal/log.h"
36 #include "spdk/util.h"
37 
38 #include "nvme_opal_internal.h"
39 
40 static const char *
41 opal_error_to_human(int error)
42 {
43 	if (error == SPDK_OPAL_FAILED) {
44 		return "FAILED";
45 	}
46 
47 	if ((size_t)error >= SPDK_COUNTOF(spdk_opal_errors) || error < 0) {
48 		return "UNKNOWN ERROR";
49 	}
50 
51 	return spdk_opal_errors[error];
52 }
53 
54 static int
55 opal_send_cmd(struct spdk_opal_dev *dev)
56 {
57 	return spdk_nvme_ctrlr_security_send(dev->dev_handler, SPDK_SCSI_SECP_TCG, dev->comid,
58 					     0, dev->cmd, IO_BUFFER_LENGTH);
59 }
60 
61 static int
62 opal_recv_cmd(struct spdk_opal_dev *dev)
63 {
64 	void *response = dev->resp;
65 	struct spdk_opal_header *header = response;
66 	int ret = 0;
67 	uint64_t start = spdk_get_ticks();
68 	uint64_t now;
69 
70 	do {
71 		ret = spdk_nvme_ctrlr_security_receive(dev->dev_handler, SPDK_SCSI_SECP_TCG, dev->comid,
72 						       0, dev->resp, IO_BUFFER_LENGTH);
73 		if (ret) {
74 			SPDK_ERRLOG("Security Receive Error on dev = %p\n", dev);
75 			return ret;
76 		}
77 		SPDK_DEBUGLOG(SPDK_LOG_OPAL, "outstanding_data=%d, minTransfer=%d\n",
78 			      header->com_packet.outstanding_data,
79 			      header->com_packet.min_transfer);
80 
81 		if (header->com_packet.outstanding_data == 0 &&
82 		    header->com_packet.min_transfer == 0) {
83 			return 0;	/* return if all the response data are ready by tper and received by host */
84 		} else {	/* check timeout */
85 			now = spdk_get_ticks();
86 			if (now - start > dev->timeout * spdk_get_ticks_hz()) {
87 				SPDK_ERRLOG("Secutiy Receive Timeout on dev = %p\n", dev);
88 				return 0x0F; /* TPer Malfunction */
89 			}
90 		}
91 
92 		memset(response, 0, IO_BUFFER_LENGTH);
93 	} while (!ret);
94 
95 	return ret;
96 }
97 
98 static int
99 opal_send_recv(struct spdk_opal_dev *dev, spdk_opal_cb *cb, void *data)
100 {
101 	int ret;
102 
103 	ret = opal_send_cmd(dev);
104 	if (ret) {
105 		return ret;
106 	}
107 	ret = opal_recv_cmd(dev);
108 	if (ret) {
109 		return ret;
110 	}
111 	return cb(dev, data);
112 }
113 
114 static void
115 opal_add_token_u8(int *err, struct spdk_opal_dev *dev, uint8_t token)
116 {
117 	if (*err) {
118 		return;
119 	}
120 	if (dev->cmd_pos >= IO_BUFFER_LENGTH - 1) {
121 		SPDK_ERRLOG("Error adding u8: end of buffer.\n");
122 		*err = -ERANGE;
123 		return;
124 	}
125 	dev->cmd[dev->cmd_pos++] = token;
126 }
127 
128 static void
129 opal_add_short_atom_header(struct spdk_opal_dev *dev, bool bytestring,
130 			   bool has_sign, size_t len)
131 {
132 	uint8_t atom;
133 	int err = 0;
134 
135 	atom = SPDK_SHORT_ATOM_ID;
136 	atom |= bytestring ? SPDK_SHORT_ATOM_BYTESTRING_FLAG : 0;
137 	atom |= has_sign ? SPDK_SHORT_ATOM_SIGN_FLAG : 0;
138 	atom |= len & SPDK_SHORT_ATOM_LEN_MASK;
139 
140 	opal_add_token_u8(&err, dev, atom);
141 }
142 
143 static void
144 opal_add_medium_atom_header(struct spdk_opal_dev *dev, bool bytestring,
145 			    bool has_sign, size_t len)
146 {
147 	uint8_t header;
148 
149 	header = SPDK_MEDIUM_ATOM_ID;
150 	header |= bytestring ? SPDK_MEDIUM_ATOM_BYTESTRING_FLAG : 0;
151 	header |= has_sign ? SPDK_MEDIUM_ATOM_SIGN_FLAG : 0;
152 	header |= (len >> 8) & SPDK_MEDIUM_ATOM_LEN_MASK;
153 	dev->cmd[dev->cmd_pos++] = header;
154 	dev->cmd[dev->cmd_pos++] = len;
155 }
156 
157 static void
158 opal_add_token_bytestring(int *err, struct spdk_opal_dev *dev,
159 			  const uint8_t *bytestring, size_t len)
160 {
161 	size_t header_len = 1;
162 	bool is_short_atom = true;
163 
164 	if (*err) {
165 		return;
166 	}
167 
168 	if (len & ~SPDK_SHORT_ATOM_LEN_MASK) {
169 		header_len = 2;
170 		is_short_atom = false;
171 	}
172 
173 	if (len >= IO_BUFFER_LENGTH - dev->cmd_pos - header_len) {
174 		SPDK_ERRLOG("Error adding bytestring: end of buffer.\n");
175 		*err = -ERANGE;
176 		return;
177 	}
178 
179 	if (is_short_atom) {
180 		opal_add_short_atom_header(dev, true, false, len);
181 	} else {
182 		opal_add_medium_atom_header(dev, true, false, len);
183 	}
184 
185 	memcpy(&dev->cmd[dev->cmd_pos], bytestring, len);
186 	dev->cmd_pos += len;
187 }
188 
189 static void
190 opal_add_token_u64(int *err, struct spdk_opal_dev *dev, uint64_t number)
191 {
192 	int startat = 0;
193 
194 	if (*err) {
195 		return;
196 	}
197 
198 	/* add header first */
199 	if (number <= SPDK_TINY_ATOM_DATA_MASK) {
200 		dev->cmd[dev->cmd_pos++] = (uint8_t) number & SPDK_TINY_ATOM_DATA_MASK;
201 	} else {
202 		if (number < 0x100) {
203 			dev->cmd[dev->cmd_pos++] = 0x81; /* short atom, 1 byte length */
204 			startat = 0;
205 		} else if (number < 0x10000) {
206 			dev->cmd[dev->cmd_pos++] = 0x82; /* short atom, 2 byte length */
207 			startat = 1;
208 		} else if (number < 0x100000000) {
209 			dev->cmd[dev->cmd_pos++] = 0x84; /* short atom, 4 byte length */
210 			startat = 3;
211 		} else {
212 			dev->cmd[dev->cmd_pos++] = 0x88; /* short atom, 8 byte length */
213 			startat = 7;
214 		}
215 
216 		/* add number value */
217 		for (int i = startat; i > -1; i--) {
218 			dev->cmd[dev->cmd_pos++] = (uint8_t)((number >> (i * 8)) & 0xff);
219 		}
220 	}
221 }
222 
223 static void
224 opal_add_tokens(int *err, struct spdk_opal_dev *dev, int num, ...)
225 {
226 	int i;
227 	va_list args_ptr;
228 	enum spdk_opal_token tmp;
229 
230 	va_start(args_ptr, num);
231 
232 	for (i = 0; i < num; i++) {
233 		tmp = va_arg(args_ptr, enum spdk_opal_token);
234 		opal_add_token_u8(err, dev, tmp);
235 		if (*err != 0) { break; }
236 	}
237 
238 	va_end(args_ptr);
239 }
240 
241 static int
242 opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eod)
243 {
244 	struct spdk_opal_header *hdr;
245 	int err = 0;
246 
247 	if (eod) {
248 		opal_add_tokens(&err, dev, 6, SPDK_OPAL_ENDOFDATA,
249 				SPDK_OPAL_STARTLIST,
250 				0, 0, 0,
251 				SPDK_OPAL_ENDLIST);
252 	}
253 
254 	if (err) {
255 		SPDK_ERRLOG("Error finalizing command.\n");
256 		return -EFAULT;
257 	}
258 
259 	hdr = (struct spdk_opal_header *)dev->cmd;
260 
261 	to_be32(&hdr->packet.session_tsn, tsn);
262 	to_be32(&hdr->packet.session_hsn, hsn);
263 
264 	to_be32(&hdr->sub_packet.length, dev->cmd_pos - sizeof(*hdr));
265 	while (dev->cmd_pos % 4) {
266 		if (dev->cmd_pos >= IO_BUFFER_LENGTH) {
267 			SPDK_ERRLOG("Error: Buffer overrun\n");
268 			return -ERANGE;
269 		}
270 		dev->cmd[dev->cmd_pos++] = 0;
271 	}
272 	to_be32(&hdr->packet.length, dev->cmd_pos - sizeof(hdr->com_packet) -
273 		sizeof(hdr->packet));
274 	to_be32(&hdr->com_packet.length, dev->cmd_pos - sizeof(hdr->com_packet));
275 
276 	return 0;
277 }
278 
279 static int
280 opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb, void *data)
281 {
282 	int ret;
283 
284 	ret = opal_cmd_finalize(dev, dev->hsn, dev->tsn, eod);
285 	if (ret) {
286 		SPDK_ERRLOG("Error finalizing command buffer: %d\n", ret);
287 		return ret;
288 	}
289 
290 	return opal_send_recv(dev, cb, data);
291 }
292 
293 static size_t
294 opal_response_parse_tiny(struct spdk_opal_resp_token *token,
295 			 const uint8_t *pos)
296 {
297 	token->pos = pos;
298 	token->len = 1;
299 	token->width = OPAL_WIDTH_TINY;
300 
301 	if (pos[0] & SPDK_TINY_ATOM_SIGN_FLAG) {
302 		token->type = OPAL_DTA_TOKENID_SINT;
303 	} else {
304 		token->type = OPAL_DTA_TOKENID_UINT;
305 		token->stored.unsigned_num = pos[0] & SPDK_TINY_ATOM_DATA_MASK;
306 	}
307 
308 	return token->len;
309 }
310 
311 static int
312 opal_response_parse_short(struct spdk_opal_resp_token *token,
313 			  const uint8_t *pos)
314 {
315 	token->pos = pos;
316 	token->len = (pos[0] & SPDK_SHORT_ATOM_LEN_MASK) + 1; /* plus 1-byte header */
317 	token->width = OPAL_WIDTH_SHORT;
318 
319 	if (pos[0] & SPDK_SHORT_ATOM_BYTESTRING_FLAG) {
320 		token->type = OPAL_DTA_TOKENID_BYTESTRING;
321 	} else if (pos[0] & SPDK_SHORT_ATOM_SIGN_FLAG) {
322 		token->type = OPAL_DTA_TOKENID_SINT;
323 	} else {
324 		uint64_t u_integer = 0;
325 		size_t i, b = 0;
326 
327 		token->type = OPAL_DTA_TOKENID_UINT;
328 		if (token->len > 9) {
329 			SPDK_ERRLOG("uint64 with more than 8 bytes\n");
330 			return -EINVAL;
331 		}
332 		for (i = token->len - 1; i > 0; i--) {
333 			u_integer |= ((uint64_t)pos[i] << (8 * b));
334 			b++;
335 		}
336 		token->stored.unsigned_num = u_integer;
337 	}
338 
339 	return token->len;
340 }
341 
342 static size_t
343 opal_response_parse_medium(struct spdk_opal_resp_token *token,
344 			   const uint8_t *pos)
345 {
346 	token->pos = pos;
347 	token->len = (((pos[0] & SPDK_MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2; /* plus 2-byte header */
348 	token->width = OPAL_WIDTH_MEDIUM;
349 
350 	if (pos[0] & SPDK_MEDIUM_ATOM_BYTESTRING_FLAG) {
351 		token->type = OPAL_DTA_TOKENID_BYTESTRING;
352 	} else if (pos[0] & SPDK_MEDIUM_ATOM_SIGN_FLAG) {
353 		token->type = OPAL_DTA_TOKENID_SINT;
354 	} else {
355 		token->type = OPAL_DTA_TOKENID_UINT;
356 	}
357 
358 	return token->len;
359 }
360 
361 static size_t
362 opal_response_parse_long(struct spdk_opal_resp_token *token,
363 			 const uint8_t *pos)
364 {
365 	token->pos = pos;
366 	token->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4; /* plus 4-byte header */
367 	token->width = OPAL_WIDTH_LONG;
368 
369 	if (pos[0] & SPDK_LONG_ATOM_BYTESTRING_FLAG) {
370 		token->type = OPAL_DTA_TOKENID_BYTESTRING;
371 	} else if (pos[0] & SPDK_LONG_ATOM_SIGN_FLAG) {
372 		token->type = OPAL_DTA_TOKENID_SINT;
373 	} else {
374 		token->type = OPAL_DTA_TOKENID_UINT;
375 	}
376 
377 	return token->len;
378 }
379 
380 static size_t
381 opal_response_parse_token(struct spdk_opal_resp_token *token,
382 			  const uint8_t *pos)
383 {
384 	token->pos = pos;
385 	token->len = 1;
386 	token->type = OPAL_DTA_TOKENID_TOKEN;
387 	token->width = OPAL_WIDTH_TOKEN;
388 
389 	return token->len;
390 }
391 
392 static int
393 opal_response_parse(const uint8_t *buf, size_t length,
394 		    struct spdk_opal_resp_parsed *resp)
395 {
396 	const struct spdk_opal_header *hdr;
397 	struct spdk_opal_resp_token *token_iter;
398 	int num_entries = 0;
399 	int total;
400 	size_t token_length;
401 	const uint8_t *pos;
402 	uint32_t clen, plen, slen;
403 
404 	if (!buf || !resp) {
405 		return -EINVAL;
406 	}
407 
408 	hdr = (struct spdk_opal_header *)buf;
409 	pos = buf + sizeof(*hdr);
410 
411 	clen = from_be32(&hdr->com_packet.length);
412 	plen = from_be32(&hdr->packet.length);
413 	slen = from_be32(&hdr->sub_packet.length);
414 	SPDK_DEBUGLOG(SPDK_LOG_OPAL, "Response size: cp: %u, pkt: %u, subpkt: %u\n",
415 		      clen, plen, slen);
416 
417 	if (clen == 0 || plen == 0 || slen == 0 ||
418 	    slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
419 		SPDK_ERRLOG("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
420 			    clen, plen, slen);
421 		return -EINVAL;
422 	}
423 
424 	if (pos > buf + length) {
425 		SPDK_ERRLOG("Pointer out of range\n");
426 		return -EFAULT;
427 	}
428 
429 	token_iter = resp->resp_tokens;
430 	total = slen;
431 
432 	while (total > 0) {
433 		if (pos[0] <= SPDK_TINY_ATOM_TYPE_MAX) { /* tiny atom */
434 			token_length = opal_response_parse_tiny(token_iter, pos);
435 		} else if (pos[0] <= SPDK_SHORT_ATOM_TYPE_MAX) { /* short atom */
436 			token_length = opal_response_parse_short(token_iter, pos);
437 		} else if (pos[0] <= SPDK_MEDIUM_ATOM_TYPE_MAX) { /* medium atom */
438 			token_length = opal_response_parse_medium(token_iter, pos);
439 		} else if (pos[0] <= SPDK_LONG_ATOM_TYPE_MAX) { /* long atom */
440 			token_length = opal_response_parse_long(token_iter, pos);
441 		} else { /* TOKEN */
442 			token_length = opal_response_parse_token(token_iter, pos);
443 		}
444 
445 		if (token_length <= 0) {
446 			SPDK_ERRLOG("Parse response failure.\n");
447 			return -EINVAL;
448 		}
449 
450 		pos += token_length;
451 		total -= token_length;
452 		token_iter++;
453 		num_entries++;
454 
455 		if (total < 0) {
456 			SPDK_ERRLOG("Length not matching.\n");
457 			return -EINVAL;
458 		}
459 	}
460 
461 	if (num_entries == 0) {
462 		SPDK_ERRLOG("Couldn't parse response.\n");
463 		return -EINVAL;
464 	}
465 	resp->num = num_entries;
466 
467 	return 0;
468 }
469 
470 static inline bool
471 opal_response_token_matches(const struct spdk_opal_resp_token *token,
472 			    uint8_t match)
473 {
474 	if (!token ||
475 	    token->type != OPAL_DTA_TOKENID_TOKEN ||
476 	    token->pos[0] != match) {
477 		return false;
478 	}
479 	return true;
480 }
481 
482 static const struct spdk_opal_resp_token *
483 opal_response_get_token(const struct spdk_opal_resp_parsed *resp, int index)
484 {
485 	const struct spdk_opal_resp_token *token;
486 
487 	if (index >= resp->num) {
488 		SPDK_ERRLOG("Token number doesn't exist: %d, resp: %d\n",
489 			    index, resp->num);
490 		return NULL;
491 	}
492 
493 	token = &resp->resp_tokens[index];
494 	if (token->len == 0) {
495 		SPDK_ERRLOG("Token length must be non-zero\n");
496 		return NULL;
497 	}
498 
499 	return token;
500 }
501 
502 static uint64_t
503 opal_response_get_u64(const struct spdk_opal_resp_parsed *resp, int index)
504 {
505 	if (!resp) {
506 		SPDK_ERRLOG("Response is NULL\n");
507 		return 0;
508 	}
509 
510 	if (resp->resp_tokens[index].type != OPAL_DTA_TOKENID_UINT) {
511 		SPDK_ERRLOG("Token is not unsigned int: %d\n",
512 			    resp->resp_tokens[index].type);
513 		return 0;
514 	}
515 
516 	if (!(resp->resp_tokens[index].width == OPAL_WIDTH_TINY ||
517 	      resp->resp_tokens[index].width == OPAL_WIDTH_SHORT)) {
518 		SPDK_ERRLOG("Atom is not short or tiny: %d\n",
519 			    resp->resp_tokens[index].width);
520 		return 0;
521 	}
522 
523 	return resp->resp_tokens[index].stored.unsigned_num;
524 }
525 
526 static uint16_t
527 opal_response_get_u16(const struct spdk_opal_resp_parsed *resp, int index)
528 {
529 	uint64_t i = opal_response_get_u64(resp, index);
530 	if (i > 0xffffull) {
531 		SPDK_ERRLOG("parse reponse u16 failed. Overflow\n");
532 		return 0;
533 	}
534 	return (uint16_t) i;
535 }
536 
537 static uint8_t
538 opal_response_get_u8(const struct spdk_opal_resp_parsed *resp, int index)
539 {
540 	uint64_t i = opal_response_get_u64(resp, index);
541 	if (i > 0xffull) {
542 		SPDK_ERRLOG("parse reponse u8 failed. Overflow\n");
543 		return 0;
544 	}
545 	return (uint8_t) i;
546 }
547 
548 static size_t
549 opal_response_get_string(const struct spdk_opal_resp_parsed *resp, int n,
550 			 const char **store)
551 {
552 	uint8_t header_len;
553 	struct spdk_opal_resp_token token = resp->resp_tokens[n];
554 
555 	*store = NULL;
556 	if (!resp) {
557 		SPDK_ERRLOG("Response is NULL\n");
558 		return 0;
559 	}
560 
561 	if (n > resp->num) {
562 		SPDK_ERRLOG("Response has %d tokens. Can't access %d\n",
563 			    resp->num, n);
564 		return 0;
565 	}
566 
567 	if (token.type != OPAL_DTA_TOKENID_BYTESTRING) {
568 		SPDK_ERRLOG("Token is not a byte string!\n");
569 		return 0;
570 	}
571 
572 	switch (token.width) {
573 	case OPAL_WIDTH_SHORT:
574 		header_len = 1;
575 		break;
576 	case OPAL_WIDTH_MEDIUM:
577 		header_len = 2;
578 		break;
579 	case OPAL_WIDTH_LONG:
580 		header_len = 4;
581 		break;
582 	default:
583 		SPDK_ERRLOG("Can't get string from this Token\n");
584 		return 0;
585 	}
586 
587 	*store = token.pos + header_len;
588 	return token.len - header_len;
589 }
590 
591 static int
592 opal_response_status(const struct spdk_opal_resp_parsed *resp)
593 {
594 	const struct spdk_opal_resp_token *tok;
595 
596 	/* if we get an EOS token, just return 0 */
597 	tok = opal_response_get_token(resp, 0);
598 	if (opal_response_token_matches(tok, SPDK_OPAL_ENDOFSESSION)) {
599 		return 0;
600 	}
601 
602 	if (resp->num < 5) {
603 		return SPDK_DTAERROR_NO_METHOD_STATUS;
604 	}
605 
606 	tok = opal_response_get_token(resp, resp->num - 5); /* the first token should be STARTLIST */
607 	if (!opal_response_token_matches(tok, SPDK_OPAL_STARTLIST)) {
608 		return SPDK_DTAERROR_NO_METHOD_STATUS;
609 	}
610 
611 	tok = opal_response_get_token(resp, resp->num - 1); /* the last token should be ENDLIST */
612 	if (!opal_response_token_matches(tok, SPDK_OPAL_ENDLIST)) {
613 		return SPDK_DTAERROR_NO_METHOD_STATUS;
614 	}
615 
616 	/* The second and third values in the status list are reserved, and are
617 	defined in core spec to be 0x00 and 0x00 and SHOULD be ignored by the host. */
618 	return (int)opal_response_get_u64(resp,
619 					  resp->num - 4); /* We only need the first value in the status list. */
620 }
621 
622 static int
623 opal_parse_and_check_status(struct spdk_opal_dev *dev, void *data)
624 {
625 	int error;
626 
627 	error = opal_response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed_resp);
628 	if (error) {
629 		SPDK_ERRLOG("Couldn't parse response.\n");
630 		return error;
631 	}
632 	return opal_response_status(&dev->parsed_resp);
633 }
634 
635 static inline void
636 opal_clear_cmd(struct spdk_opal_dev *dev)
637 {
638 	dev->cmd_pos = sizeof(struct spdk_opal_header);
639 	memset(dev->cmd, 0, IO_BUFFER_LENGTH);
640 }
641 
642 static inline void
643 opal_set_comid(struct spdk_opal_dev *dev, uint16_t comid)
644 {
645 	struct spdk_opal_header *hdr = (struct spdk_opal_header *)dev->cmd;
646 
647 	hdr->com_packet.comid[0] = comid >> 8;
648 	hdr->com_packet.comid[1] = comid;
649 	hdr->com_packet.extended_comid[0] = 0;
650 	hdr->com_packet.extended_comid[1] = 0;
651 }
652 
653 static inline int
654 opal_init_key(struct spdk_opal_key *opal_key, const char *passwd,
655 	      enum spdk_opal_locking_range locking_range)
656 {
657 	int len;
658 
659 	if (passwd == NULL || passwd[0] == '\0') {
660 		SPDK_ERRLOG("Password is empty. Create key failed\n");
661 		return -EINVAL;
662 	}
663 
664 	len = strlen(passwd);
665 
666 	if (len >= OPAL_KEY_MAX) {
667 		SPDK_ERRLOG("Password too long. Create key failed\n");
668 		return -EINVAL;
669 	}
670 
671 	memset(opal_key, 0, sizeof(struct spdk_opal_key));
672 	opal_key->key_len = len;
673 	memcpy(opal_key->key, passwd, opal_key->key_len);
674 	opal_key->locking_range = locking_range;
675 
676 	return 0;
677 }
678 
679 static int
680 opal_build_locking_user(uint8_t *buffer, size_t length, uint8_t user)
681 {
682 	if (length < OPAL_UID_LENGTH) {
683 		SPDK_ERRLOG("Can't build locking range user, buffer overflow\n");
684 		return -ERANGE;
685 	}
686 
687 	memcpy(buffer, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
688 
689 	buffer[7] = user;
690 
691 	return 0;
692 }
693 
694 static int
695 opal_build_locking_range(uint8_t *buffer, size_t length, uint8_t locking_range)
696 {
697 	if (length < OPAL_UID_LENGTH) {
698 		SPDK_ERRLOG("Can't build locking range. Buffer overflow\n");
699 		return -ERANGE;
700 	}
701 
702 	memcpy(buffer, spdk_opal_uid[UID_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
703 
704 	/* global */
705 	if (locking_range == 0) {
706 		return 0;
707 	}
708 
709 	/* non-global */
710 	buffer[5] = LOCKING_RANGE_NON_GLOBAL;
711 	buffer[7] = locking_range;
712 	return 0;
713 }
714 
715 static void
716 opal_check_tper(struct spdk_opal_dev *dev, const void *data)
717 {
718 	const struct spdk_d0_tper_features *tper = data;
719 	struct spdk_opal_info *opal_info = dev->opal_info;
720 
721 	opal_info->opal_ssc_dev = 1;
722 	opal_info->tper = 1;
723 	opal_info->tper_acknack = tper->acknack;
724 	opal_info->tper_async = tper->async;
725 	opal_info->tper_buffer_mgt = tper->buffer_management;
726 	opal_info->tper_comid_mgt = tper->comid_management;
727 	opal_info->tper_streaming = tper->streaming;
728 	opal_info->tper_sync = tper->sync;
729 }
730 
731 /*
732  * check single user mode
733  */
734 static bool
735 opal_check_sum(struct spdk_opal_dev *dev, const void *data)
736 {
737 	const struct spdk_d0_sum *sum = data;
738 	uint32_t num_locking_objects = from_be32(&sum->num_locking_objects);
739 	struct spdk_opal_info *opal_info = dev->opal_info;
740 
741 	if (num_locking_objects == 0) {
742 		SPDK_NOTICELOG("Need at least one locking object.\n");
743 		return false;
744 	}
745 
746 	opal_info->single_user_mode = 1;
747 	opal_info->single_user_locking_objects = num_locking_objects;
748 	opal_info->single_user_any = sum->any;
749 	opal_info->single_user_all = sum->all;
750 	opal_info->single_user_policy = sum->policy;
751 
752 	return true;
753 }
754 
755 static void
756 opal_check_lock(struct spdk_opal_dev *dev, const void *data)
757 {
758 	const struct spdk_d0_locking_features *lock = data;
759 	struct spdk_opal_info *opal_info = dev->opal_info;
760 
761 	opal_info->locking = 1;
762 	opal_info->locking_locked = lock->locked;
763 	opal_info->locking_locking_enabled = lock->locking_enabled;
764 	opal_info->locking_locking_supported = lock->locking_supported;
765 	opal_info->locking_mbr_done = lock->mbr_done;
766 	opal_info->locking_mbr_enabled = lock->mbr_enabled;
767 	opal_info->locking_media_encrypt = lock->media_encryption;
768 }
769 
770 static void
771 opal_check_geometry(struct spdk_opal_dev *dev, const void *data)
772 {
773 	const struct spdk_d0_geo_features *geo = data;
774 	struct spdk_opal_info *opal_info = dev->opal_info;
775 	uint64_t align = from_be64(&geo->alignment_granularity);
776 	uint64_t lowest_lba = from_be64(&geo->lowest_aligned_lba);
777 
778 	dev->align = align;
779 	dev->lowest_lba = lowest_lba;
780 
781 	opal_info->geometry = 1;
782 	opal_info->geometry_align = geo->align;
783 	opal_info->geometry_logical_block_size = from_be32(&geo->logical_block_size);
784 	opal_info->geometry_lowest_aligned_lba = lowest_lba;
785 	opal_info->geometry_alignment_granularity = align;
786 }
787 
788 static void
789 opal_check_datastore(struct spdk_opal_dev *dev, const void *data)
790 {
791 	const struct spdk_d0_datastore_features *datastore = data;
792 	struct spdk_opal_info *opal_info = dev->opal_info;
793 
794 	opal_info->datastore = 1;
795 	opal_info->datastore_max_tables = from_be16(&datastore->max_tables);
796 	opal_info->datastore_max_table_size = from_be32(&datastore->max_table_size);
797 	opal_info->datastore_alignment = from_be32(&datastore->alignment);
798 }
799 
800 static uint16_t
801 opal_get_comid_v100(struct spdk_opal_dev *dev, const void *data)
802 {
803 	const struct spdk_d0_opal_v100 *v100 = data;
804 	struct spdk_opal_info *opal_info = dev->opal_info;
805 	uint16_t base_comid = from_be16(&v100->base_comid);
806 
807 	opal_info->opal_v100 = 1;
808 	opal_info->opal_v100_base_comid = base_comid;
809 	opal_info->opal_v100_num_comid = from_be16(&v100->number_comids);
810 	opal_info->opal_v100_range_crossing = v100->range_crossing;
811 
812 	return base_comid;
813 }
814 
815 static uint16_t
816 opal_get_comid_v200(struct spdk_opal_dev *dev, const void *data)
817 {
818 	const struct spdk_d0_opal_v200 *v200 = data;
819 	struct spdk_opal_info *opal_info = dev->opal_info;
820 	uint16_t base_comid = from_be16(&v200->base_comid);
821 
822 	opal_info->opal_v200 = 1;
823 	opal_info->opal_v200_base_comid = base_comid;
824 	opal_info->opal_v200_num_comid = from_be16(&v200->num_comids);
825 	opal_info->opal_v200_range_crossing = v200->range_crossing;
826 	opal_info->opal_v200_num_admin = from_be16(&v200->num_locking_admin_auth);
827 	opal_info->opal_v200_num_user = from_be16(&v200->num_locking_user_auth);
828 
829 	opal_info->opal_v200_initial_pin = v200->initial_pin;
830 	opal_info->opal_v200_reverted_pin = v200->reverted_pin;
831 
832 	return base_comid;
833 }
834 
835 static int
836 opal_discovery0_end(struct spdk_opal_dev *dev)
837 {
838 	bool found_com_id = false, supported = false, single_user = false;
839 	const struct spdk_d0_header *hdr = (struct spdk_d0_header *)dev->resp;
840 	const uint8_t *epos = dev->resp, *cpos = dev->resp;
841 	uint16_t comid = 0;
842 	uint32_t hlen = from_be32(&(hdr->length));
843 
844 	if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
845 		SPDK_ERRLOG("Discovery length overflows buffer (%zu+%u)/%u\n",
846 			    sizeof(*hdr), hlen, IO_BUFFER_LENGTH);
847 		return -EFAULT;
848 	}
849 
850 	epos += hlen; /* end of buffer */
851 	cpos += sizeof(*hdr); /* current position on buffer */
852 
853 	while (cpos < epos) {
854 		const union spdk_discovery0_features *body =
855 				(const union spdk_discovery0_features *)cpos;
856 		uint16_t feature_code = from_be16(&(body->tper.feature_code));
857 
858 		switch (feature_code) {
859 		case FEATURECODE_TPER:
860 			opal_check_tper(dev, body);
861 			break;
862 		case FEATURECODE_SINGLEUSER:
863 			single_user = opal_check_sum(dev, body);
864 			break;
865 		case FEATURECODE_GEOMETRY:
866 			opal_check_geometry(dev, body);
867 			break;
868 		case FEATURECODE_LOCKING:
869 			opal_check_lock(dev, body);
870 			break;
871 		case FEATURECODE_DATASTORE:
872 			opal_check_datastore(dev, body);
873 			break;
874 		case FEATURECODE_OPALV100:
875 			comid = opal_get_comid_v100(dev, body);
876 			found_com_id = true;
877 			supported = true;
878 			break;
879 		case FEATURECODE_OPALV200:
880 			comid = opal_get_comid_v200(dev, body);
881 			found_com_id = true;
882 			supported = true;
883 			break;
884 		default:
885 			SPDK_NOTICELOG("Unknow feature code: %d\n", feature_code);
886 		}
887 		cpos += body->tper.length + 4;
888 	}
889 
890 	if (supported == false) {
891 		SPDK_ERRLOG("Opal Not Supported.\n");
892 		return SPDK_OPAL_NOT_SUPPORTED;
893 	}
894 
895 	if (single_user == false) {
896 		SPDK_NOTICELOG("Single User Mode Not Supported\n");
897 	}
898 
899 	if (found_com_id == false) {
900 		SPDK_ERRLOG("Could not find OPAL comid for device. Returning early\n");
901 		return -EINVAL;
902 	}
903 
904 	dev->comid = comid;
905 	return 0;
906 }
907 
908 static int
909 opal_discovery0(struct spdk_opal_dev *dev)
910 {
911 	int ret;
912 
913 	memset(dev->resp, 0, IO_BUFFER_LENGTH);
914 	dev->comid = LV0_DISCOVERY_COMID;
915 	ret = opal_recv_cmd(dev);
916 	if (ret) {
917 		return ret;
918 	}
919 
920 	return opal_discovery0_end(dev);
921 }
922 
923 static inline void
924 opal_setup_dev(struct spdk_opal_dev *dev)
925 {
926 	dev->tsn = 0;
927 	dev->hsn = 0;
928 	dev->prev_data = NULL;
929 	dev->timeout = SPDK_OPAL_TPER_TIMEOUT;
930 }
931 
932 static int
933 opal_end_session_cb(struct spdk_opal_dev *dev, void *data)
934 {
935 	dev->hsn = 0;
936 	dev->tsn = 0;
937 	return opal_parse_and_check_status(dev, NULL);
938 }
939 
940 static int
941 opal_end_session(struct spdk_opal_dev *dev)
942 {
943 	int err = 0;
944 	bool eod = 0;
945 
946 	opal_clear_cmd(dev);
947 	opal_set_comid(dev, dev->comid);
948 	opal_add_token_u8(&err, dev, SPDK_OPAL_ENDOFSESSION);
949 
950 	if (err < 0) {
951 		return err;
952 	}
953 	return opal_finalize_and_send(dev, eod, opal_end_session_cb, NULL);
954 }
955 
956 static int
957 opal_check_support(struct spdk_opal_dev *dev)
958 {
959 	int ret;
960 
961 	opal_setup_dev(dev);
962 	ret = opal_discovery0(dev);
963 
964 	dev->supported = (ret == 0 ? true : false);
965 
966 	return ret;
967 }
968 
969 void
970 spdk_opal_close(struct spdk_opal_dev *dev)
971 {
972 	pthread_mutex_destroy(&dev->mutex_lock);
973 	if (dev->max_ranges > 0) {
974 		for (int i = 0; i < dev->max_ranges; i++) {
975 			free(dev->locking_range_info[i]);
976 		}
977 	}
978 	free(dev->opal_info);
979 	free(dev);
980 }
981 
982 static int
983 opal_start_session_cb(struct spdk_opal_dev *dev, void *data)
984 {
985 	uint32_t hsn, tsn;
986 	int error = 0;
987 
988 	error = opal_parse_and_check_status(dev, NULL);
989 	if (error) {
990 		return error;
991 	}
992 
993 	hsn = opal_response_get_u64(&dev->parsed_resp, 4);
994 	tsn = opal_response_get_u64(&dev->parsed_resp, 5);
995 
996 	if (hsn == 0 && tsn == 0) {
997 		SPDK_ERRLOG("Couldn't authenticate session\n");
998 		return -EPERM;
999 	}
1000 
1001 	dev->hsn = hsn;
1002 	dev->tsn = tsn;
1003 	return 0;
1004 }
1005 
1006 static int
1007 opal_start_generic_session(struct spdk_opal_dev *dev,
1008 			   enum opal_uid_enum auth,
1009 			   enum opal_uid_enum sp_type,
1010 			   const char *key,
1011 			   uint8_t key_len)
1012 {
1013 	uint32_t hsn;
1014 	int err = 0;
1015 
1016 	if (key == NULL && auth != UID_ANYBODY) {
1017 		return OPAL_INVAL_PARAM;
1018 	}
1019 
1020 	opal_clear_cmd(dev);
1021 
1022 	opal_set_comid(dev, dev->comid);
1023 	hsn = GENERIC_HOST_SESSION_NUM;
1024 
1025 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1026 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_SMUID],
1027 				  OPAL_UID_LENGTH);
1028 	opal_add_token_bytestring(&err, dev, spdk_opal_method[STARTSESSION_METHOD],
1029 				  OPAL_UID_LENGTH);
1030 	opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
1031 	opal_add_token_u64(&err, dev, hsn);
1032 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[sp_type], OPAL_UID_LENGTH);
1033 	opal_add_token_u8(&err, dev, SPDK_OPAL_TRUE); /* Write */
1034 
1035 	switch (auth) {
1036 	case UID_ANYBODY:
1037 		opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
1038 		break;
1039 	case UID_ADMIN1:
1040 	case UID_SID:
1041 		opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
1042 		opal_add_token_u8(&err, dev, 0); /* HostChallenge */
1043 		opal_add_token_bytestring(&err, dev, key, key_len);
1044 		opal_add_tokens(&err, dev, 3,    /* number of token */
1045 				SPDK_OPAL_ENDNAME,
1046 				SPDK_OPAL_STARTNAME,
1047 				3);/* HostSignAuth */
1048 		opal_add_token_bytestring(&err, dev, spdk_opal_uid[auth],
1049 					  OPAL_UID_LENGTH);
1050 		opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
1051 		opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
1052 		break;
1053 	default:
1054 		SPDK_ERRLOG("Cannot start Admin SP session with auth %d\n", auth);
1055 		return -EINVAL;
1056 	}
1057 
1058 	if (err) {
1059 		SPDK_ERRLOG("Error building start adminsp session command.\n");
1060 		return err;
1061 	}
1062 
1063 	return opal_finalize_and_send(dev, 1, opal_start_session_cb, NULL);
1064 }
1065 
1066 
1067 static int
1068 opal_start_anybody_adminsp_session(struct spdk_opal_dev *dev)
1069 {
1070 	return opal_start_generic_session(dev, UID_ANYBODY,
1071 					  UID_ADMINSP, NULL, 0);
1072 }
1073 
1074 static int
1075 opal_start_admin_session(struct spdk_opal_dev *dev, void *data)
1076 {
1077 	struct spdk_opal_key *opal_key = data;
1078 
1079 	if (opal_key == NULL) {
1080 		SPDK_ERRLOG("No key found for auth session\n");
1081 		return -EINVAL;
1082 	}
1083 	return opal_start_generic_session(dev, UID_ADMIN1, UID_LOCKINGSP,
1084 					  opal_key->key, opal_key->key_len);
1085 }
1086 
1087 static int
1088 opal_get_msid_cpin_pin_cb(struct spdk_opal_dev *dev, void *data)
1089 {
1090 	const char *msid_pin;
1091 	size_t strlen;
1092 	int error = 0;
1093 
1094 	error = opal_parse_and_check_status(dev, NULL);
1095 	if (error) {
1096 		return error;
1097 	}
1098 
1099 	strlen = opal_response_get_string(&dev->parsed_resp, 4, &msid_pin);
1100 	if (!msid_pin) {
1101 		SPDK_ERRLOG("Couldn't extract PIN from response\n");
1102 		return -EINVAL;
1103 	}
1104 
1105 	dev->prev_d_len = strlen;
1106 	dev->prev_data = calloc(1, strlen);
1107 	if (!dev->prev_data) {
1108 		SPDK_ERRLOG("memory allocation error\n");
1109 		return -ENOMEM;
1110 	}
1111 	memcpy(dev->prev_data, msid_pin, strlen);
1112 
1113 	SPDK_DEBUGLOG(SPDK_LOG_OPAL, "MSID = %p\n", dev->prev_data);
1114 	return 0;
1115 }
1116 
1117 static int
1118 opal_get_msid_cpin_pin(struct spdk_opal_dev *dev)
1119 {
1120 	int err = 0;
1121 
1122 	opal_clear_cmd(dev);
1123 	opal_set_comid(dev, dev->comid);
1124 
1125 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1126 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_C_PIN_MSID],
1127 				  OPAL_UID_LENGTH);
1128 	opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1129 
1130 	opal_add_tokens(&err, dev, 12, SPDK_OPAL_STARTLIST,
1131 			SPDK_OPAL_STARTLIST,
1132 			SPDK_OPAL_STARTNAME,
1133 			SPDK_OPAL_STARTCOLUMN,
1134 			SPDK_OPAL_PIN,
1135 			SPDK_OPAL_ENDNAME,
1136 			SPDK_OPAL_STARTNAME,
1137 			SPDK_OPAL_ENDCOLUMN,
1138 			SPDK_OPAL_PIN,
1139 			SPDK_OPAL_ENDNAME,
1140 			SPDK_OPAL_ENDLIST,
1141 			SPDK_OPAL_ENDLIST);
1142 
1143 	if (err) {
1144 		SPDK_ERRLOG("Error building Get MSID CPIN PIN command.\n");
1145 		return err;
1146 	}
1147 
1148 	return opal_finalize_and_send(dev, 1, opal_get_msid_cpin_pin_cb, NULL);
1149 }
1150 
1151 static int
1152 opal_start_adminsp_session(struct spdk_opal_dev *dev, void *data)
1153 {
1154 	int ret;
1155 	uint8_t *key = dev->prev_data;
1156 
1157 	if (!key) {
1158 		const struct spdk_opal_key *okey = data;
1159 		if (okey == NULL) {
1160 			SPDK_ERRLOG("No key found for auth session\n");
1161 			return -EINVAL;
1162 		}
1163 		ret = opal_start_generic_session(dev, UID_SID,
1164 						 UID_ADMINSP,
1165 						 okey->key,
1166 						 okey->key_len);
1167 	} else {
1168 		ret = opal_start_generic_session(dev, UID_SID,
1169 						 UID_ADMINSP,
1170 						 key, dev->prev_d_len);
1171 		free(key);
1172 		dev->prev_data = NULL;
1173 	}
1174 
1175 	return ret;
1176 }
1177 
1178 static int
1179 opal_generic_pw_cmd(uint8_t *key, size_t key_len, uint8_t *cpin_uid,
1180 		    struct spdk_opal_dev *dev)
1181 {
1182 	int err = 0;
1183 
1184 	opal_clear_cmd(dev);
1185 	opal_set_comid(dev, dev->comid);
1186 
1187 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1188 	opal_add_token_bytestring(&err, dev, cpin_uid, OPAL_UID_LENGTH);
1189 	opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD],
1190 				  OPAL_UID_LENGTH);
1191 
1192 	opal_add_tokens(&err, dev, 6,
1193 			SPDK_OPAL_STARTLIST,
1194 			SPDK_OPAL_STARTNAME,
1195 			SPDK_OPAL_VALUES,
1196 			SPDK_OPAL_STARTLIST,
1197 			SPDK_OPAL_STARTNAME,
1198 			SPDK_OPAL_PIN);
1199 	opal_add_token_bytestring(&err, dev, key, key_len);
1200 	opal_add_tokens(&err, dev, 4,
1201 			SPDK_OPAL_ENDNAME,
1202 			SPDK_OPAL_ENDLIST,
1203 			SPDK_OPAL_ENDNAME,
1204 			SPDK_OPAL_ENDLIST);
1205 	return err;
1206 }
1207 
1208 static int
1209 opal_get_locking_sp_lifecycle_cb(struct spdk_opal_dev *dev, void *data)
1210 {
1211 	uint8_t lifecycle;
1212 	int error = 0;
1213 
1214 	error = opal_parse_and_check_status(dev, NULL);
1215 	if (error) {
1216 		return error;
1217 	}
1218 
1219 	lifecycle = opal_response_get_u64(&dev->parsed_resp, 4);
1220 	if (lifecycle != OPAL_MANUFACTURED_INACTIVE) { /* status before activate */
1221 		SPDK_ERRLOG("Couldn't determine the status of the Lifecycle state\n");
1222 		return -EINVAL;
1223 	}
1224 
1225 	return 0;
1226 }
1227 
1228 static int
1229 opal_get_locking_sp_lifecycle(struct spdk_opal_dev *dev)
1230 {
1231 	int err = 0;
1232 
1233 	opal_clear_cmd(dev);
1234 	opal_set_comid(dev, dev->comid);
1235 
1236 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1237 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_LOCKINGSP],
1238 				  OPAL_UID_LENGTH);
1239 	opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1240 
1241 	opal_add_tokens(&err, dev, 12, SPDK_OPAL_STARTLIST,
1242 			SPDK_OPAL_STARTLIST,
1243 			SPDK_OPAL_STARTNAME,
1244 			SPDK_OPAL_STARTCOLUMN,
1245 			SPDK_OPAL_LIFECYCLE,
1246 			SPDK_OPAL_ENDNAME,
1247 			SPDK_OPAL_STARTNAME,
1248 			SPDK_OPAL_ENDCOLUMN,
1249 			SPDK_OPAL_LIFECYCLE,
1250 			SPDK_OPAL_ENDNAME,
1251 			SPDK_OPAL_ENDLIST,
1252 			SPDK_OPAL_ENDLIST);
1253 
1254 	if (err) {
1255 		SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
1256 		return err;
1257 	}
1258 
1259 	return opal_finalize_and_send(dev, 1, opal_get_locking_sp_lifecycle_cb, NULL);
1260 }
1261 
1262 static int
1263 opal_activate(struct spdk_opal_dev *dev)
1264 {
1265 	int err = 0;
1266 
1267 	opal_clear_cmd(dev);
1268 	opal_set_comid(dev, dev->comid);
1269 
1270 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1271 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_LOCKINGSP],
1272 				  OPAL_UID_LENGTH);
1273 	opal_add_token_bytestring(&err, dev, spdk_opal_method[ACTIVATE_METHOD],
1274 				  OPAL_UID_LENGTH);
1275 
1276 	opal_add_tokens(&err, dev, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
1277 
1278 	if (err) {
1279 		SPDK_ERRLOG("Error building Activate LockingSP command.\n");
1280 		return err;
1281 	}
1282 
1283 	/* TODO: Single User Mode for activatation */
1284 
1285 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1286 }
1287 
1288 static int
1289 opal_start_auth_session(struct spdk_opal_dev *dev, struct opal_common_session *session)
1290 {
1291 	uint8_t uid_user[OPAL_UID_LENGTH];
1292 	size_t keylen = session->opal_key->key_len;
1293 	int err = 0;
1294 	uint8_t *key = session->opal_key->key;
1295 	uint32_t hsn = GENERIC_HOST_SESSION_NUM;
1296 
1297 	opal_clear_cmd(dev);
1298 	opal_set_comid(dev, dev->comid);
1299 
1300 	if (session->who != OPAL_ADMIN1) {
1301 		err = opal_build_locking_user(uid_user, sizeof(uid_user),
1302 					      session->who);
1303 		if (err) {
1304 			return err;
1305 		}
1306 	} else {
1307 		memcpy(uid_user, spdk_opal_uid[UID_ADMIN1], OPAL_UID_LENGTH);
1308 	}
1309 
1310 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1311 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_SMUID],
1312 				  OPAL_UID_LENGTH);
1313 	opal_add_token_bytestring(&err, dev, spdk_opal_method[STARTSESSION_METHOD],
1314 				  OPAL_UID_LENGTH);
1315 
1316 	opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
1317 	opal_add_token_u64(&err, dev, hsn);
1318 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_LOCKINGSP],
1319 				  OPAL_UID_LENGTH);
1320 	opal_add_tokens(&err, dev, 3, SPDK_OPAL_TRUE, SPDK_OPAL_STARTNAME,
1321 			0); /* True for a Read-Write session  */
1322 	opal_add_token_bytestring(&err, dev, key, keylen);
1323 	opal_add_tokens(&err, dev, 3, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME, 3); /* HostSignAuth */
1324 	opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);
1325 	opal_add_tokens(&err, dev, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_ENDLIST);
1326 
1327 	if (err) {
1328 		SPDK_ERRLOG("Error building STARTSESSION command.\n");
1329 		return err;
1330 	}
1331 
1332 	return opal_finalize_and_send(dev, 1, opal_start_session_cb, NULL);
1333 }
1334 
1335 static int
1336 opal_lock_unlock_range(struct spdk_opal_dev *dev, struct spdk_opal_locking_session *locking_session)
1337 {
1338 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1339 	uint8_t read_locked, write_locked;
1340 	int err = 0;
1341 
1342 	opal_clear_cmd(dev);
1343 	opal_set_comid(dev, dev->comid);
1344 
1345 	if (opal_build_locking_range(uid_locking_range, sizeof(uid_locking_range),
1346 				     locking_session->session.opal_key->locking_range) < 0) {
1347 		return -ERANGE;
1348 	}
1349 
1350 	switch (locking_session->l_state) {
1351 	case OPAL_READONLY:
1352 		read_locked = 0;
1353 		write_locked = 1;
1354 		break;
1355 	case OPAL_READWRITE:
1356 		read_locked = 0;
1357 		write_locked = 0;
1358 		break;
1359 	case OPAL_RWLOCK:
1360 		read_locked = 1;
1361 		write_locked = 1;
1362 		break;
1363 	default:
1364 		SPDK_ERRLOG("Tried to set an invalid locking state.\n");
1365 		return -EINVAL;
1366 	}
1367 
1368 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1369 	opal_add_token_bytestring(&err, dev, uid_locking_range, OPAL_UID_LENGTH);
1370 	opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1371 
1372 	opal_add_tokens(&err, dev, 15, SPDK_OPAL_STARTLIST,
1373 			SPDK_OPAL_STARTNAME,
1374 			SPDK_OPAL_VALUES,
1375 			SPDK_OPAL_STARTLIST,
1376 			SPDK_OPAL_STARTNAME,
1377 			SPDK_OPAL_READLOCKED,
1378 			read_locked,
1379 			SPDK_OPAL_ENDNAME,
1380 			SPDK_OPAL_STARTNAME,
1381 			SPDK_OPAL_WRITELOCKED,
1382 			write_locked,
1383 			SPDK_OPAL_ENDNAME,
1384 			SPDK_OPAL_ENDLIST,
1385 			SPDK_OPAL_ENDNAME,
1386 			SPDK_OPAL_ENDLIST);
1387 
1388 	if (err) {
1389 		SPDK_ERRLOG("Error building SET command.\n");
1390 		return err;
1391 	}
1392 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1393 }
1394 
1395 static int opal_generic_locking_range_enable_disable(struct spdk_opal_dev *dev,
1396 		uint8_t *uid, bool read_lock_enabled, bool write_lock_enabled,
1397 		bool read_locked, bool write_locked)
1398 {
1399 	int err = 0;
1400 
1401 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1402 	opal_add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
1403 	opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1404 
1405 	opal_add_tokens(&err, dev, 23, SPDK_OPAL_STARTLIST,
1406 			SPDK_OPAL_STARTNAME,
1407 			SPDK_OPAL_VALUES,
1408 			SPDK_OPAL_STARTLIST,
1409 
1410 			SPDK_OPAL_STARTNAME,
1411 			SPDK_OPAL_READLOCKENABLED,
1412 			read_lock_enabled,
1413 			SPDK_OPAL_ENDNAME,
1414 
1415 			SPDK_OPAL_STARTNAME,
1416 			SPDK_OPAL_WRITELOCKENABLED,
1417 			write_lock_enabled,
1418 			SPDK_OPAL_ENDNAME,
1419 
1420 			SPDK_OPAL_STARTNAME,
1421 			SPDK_OPAL_READLOCKED,
1422 			read_locked,
1423 			SPDK_OPAL_ENDNAME,
1424 
1425 			SPDK_OPAL_STARTNAME,
1426 			SPDK_OPAL_WRITELOCKED,
1427 			write_locked,
1428 			SPDK_OPAL_ENDNAME,
1429 
1430 			SPDK_OPAL_ENDLIST,
1431 			SPDK_OPAL_ENDNAME,
1432 			SPDK_OPAL_ENDLIST);
1433 	if (err) {
1434 		SPDK_ERRLOG("Error building locking range enable/disable command.\n");
1435 	}
1436 	return err;
1437 }
1438 
1439 static int
1440 spdk_enable_global_locking_range(struct spdk_opal_dev *dev, uint8_t *locking_range,
1441 				 struct opal_locking_range_setup_session *setup_session)
1442 {
1443 	int err;
1444 
1445 	err = opal_generic_locking_range_enable_disable(dev, locking_range,
1446 			setup_session->read_lock_enabled,
1447 			setup_session->write_lock_enabled,
1448 			0, 0);
1449 	if (err) {
1450 		SPDK_ERRLOG("Failed to create enable global locking range command\n");
1451 	}
1452 	return err;
1453 }
1454 
1455 static int
1456 opal_setup_locking_range(struct spdk_opal_dev *dev,
1457 			 struct opal_locking_range_setup_session *setup_session)
1458 {
1459 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1460 	uint8_t locking_range_id;
1461 	int err = 0;
1462 
1463 	opal_clear_cmd(dev);
1464 	opal_set_comid(dev, dev->comid);
1465 
1466 	locking_range_id = setup_session->session.opal_key->locking_range;
1467 	err = opal_build_locking_range(uid_locking_range, OPAL_UID_LENGTH, locking_range_id);
1468 	if (err) {
1469 		return err;
1470 	}
1471 
1472 	if (locking_range_id == 0) {
1473 		err = spdk_enable_global_locking_range(dev, uid_locking_range, setup_session);
1474 	} else {
1475 		opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1476 		opal_add_token_bytestring(&err, dev, uid_locking_range, OPAL_UID_LENGTH);
1477 		opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD],
1478 					  OPAL_UID_LENGTH);
1479 
1480 		opal_add_tokens(&err, dev, 6,
1481 				SPDK_OPAL_STARTLIST,
1482 				SPDK_OPAL_STARTNAME,
1483 				SPDK_OPAL_VALUES,
1484 				SPDK_OPAL_STARTLIST,
1485 				SPDK_OPAL_STARTNAME,
1486 				SPDK_OPAL_RANGESTART);
1487 		opal_add_token_u64(&err, dev, setup_session->range_start);
1488 		opal_add_tokens(&err, dev, 3,
1489 				SPDK_OPAL_ENDNAME,
1490 				SPDK_OPAL_STARTNAME,
1491 				SPDK_OPAL_RANGELENGTH);
1492 		opal_add_token_u64(&err, dev, setup_session->range_length);
1493 		opal_add_tokens(&err, dev, 3,
1494 				SPDK_OPAL_ENDNAME,
1495 				SPDK_OPAL_STARTNAME,
1496 				SPDK_OPAL_READLOCKENABLED);
1497 		opal_add_token_u64(&err, dev, setup_session->read_lock_enabled);
1498 		opal_add_tokens(&err, dev, 3,
1499 				SPDK_OPAL_ENDNAME,
1500 				SPDK_OPAL_STARTNAME,
1501 				SPDK_OPAL_WRITELOCKENABLED);
1502 		opal_add_token_u64(&err, dev, setup_session->write_lock_enabled);
1503 		opal_add_tokens(&err, dev, 4,
1504 				SPDK_OPAL_ENDNAME,
1505 				SPDK_OPAL_ENDLIST,
1506 				SPDK_OPAL_ENDNAME,
1507 				SPDK_OPAL_ENDLIST);
1508 	}
1509 	if (err) {
1510 		SPDK_ERRLOG("Error building Setup Locking range command.\n");
1511 		return err;
1512 
1513 	}
1514 
1515 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1516 }
1517 
1518 static int
1519 opal_get_max_ranges_cb(struct spdk_opal_dev *dev, void *data)
1520 {
1521 	uint8_t max_ranges;
1522 	int error = 0;
1523 
1524 	error = opal_parse_and_check_status(dev, NULL);
1525 	if (error) {
1526 		return error;
1527 	}
1528 
1529 	max_ranges = opal_response_get_u16(&dev->parsed_resp, 4); /* "MaxRanges" is token 4 of response */
1530 	dev->max_ranges = max_ranges;
1531 	return 0;
1532 }
1533 
1534 static int
1535 opal_get_max_ranges(struct spdk_opal_dev *dev)
1536 {
1537 	int err = 0;
1538 
1539 	opal_clear_cmd(dev);
1540 	opal_set_comid(dev, dev->comid);
1541 
1542 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1543 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_LOCKING_INFO_TABLE],
1544 				  OPAL_UID_LENGTH);
1545 	opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1546 
1547 	opal_add_tokens(&err, dev, 12, SPDK_OPAL_STARTLIST,
1548 			SPDK_OPAL_STARTLIST,
1549 			SPDK_OPAL_STARTNAME,
1550 			SPDK_OPAL_STARTCOLUMN,
1551 			SPDK_OPAL_MAXRANGES,
1552 			SPDK_OPAL_ENDNAME,
1553 			SPDK_OPAL_STARTNAME,
1554 			SPDK_OPAL_ENDCOLUMN,
1555 			SPDK_OPAL_MAXRANGES,
1556 			SPDK_OPAL_ENDNAME,
1557 			SPDK_OPAL_ENDLIST,
1558 			SPDK_OPAL_ENDLIST);
1559 
1560 	if (err) {
1561 		SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
1562 		return err;
1563 	}
1564 
1565 	return opal_finalize_and_send(dev, 1, opal_get_max_ranges_cb, NULL);
1566 }
1567 
1568 static int
1569 opal_get_locking_range_info_cb(struct spdk_opal_dev *dev, void *data)
1570 {
1571 	int error = 0;
1572 	uint8_t id = *(uint8_t *)data;
1573 
1574 	error = opal_parse_and_check_status(dev, NULL);
1575 	if (error) {
1576 		return error;
1577 	}
1578 
1579 	if (dev->max_ranges != 0 && id > dev->max_ranges) {
1580 		SPDK_ERRLOG("Locking range ID not valid\n");
1581 		return -EINVAL;
1582 	}
1583 
1584 	dev->locking_range_info[id]->range_start = opal_response_get_u64(&dev->parsed_resp, 4);
1585 	dev->locking_range_info[id]->range_length = opal_response_get_u64(&dev->parsed_resp, 8);
1586 	dev->locking_range_info[id]->read_lock_enabled = opal_response_get_u8(&dev->parsed_resp, 12);
1587 	dev->locking_range_info[id]->write_lock_enabled = opal_response_get_u8(&dev->parsed_resp, 16);
1588 	dev->locking_range_info[id]->read_locked = opal_response_get_u8(&dev->parsed_resp, 20);
1589 	dev->locking_range_info[id]->write_locked = opal_response_get_u8(&dev->parsed_resp, 24);
1590 
1591 	return 0;
1592 }
1593 
1594 static int
1595 opal_get_locking_range_info(struct spdk_opal_dev *dev,
1596 			    enum spdk_opal_locking_range locking_range_id)
1597 {
1598 	int err = 0;
1599 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1600 	struct spdk_opal_locking_range_info *info;
1601 
1602 	err = opal_build_locking_range(uid_locking_range, OPAL_UID_LENGTH, locking_range_id);
1603 	if (err) {
1604 		return err;
1605 	}
1606 
1607 	info = calloc(1, sizeof(struct spdk_opal_locking_range_info));
1608 	if (info == NULL) {
1609 		SPDK_ERRLOG("Memory allocation failed for spdk_opal_locking_range_info\n");
1610 		return -ENOMEM;
1611 	}
1612 
1613 	info->locking_range_id = locking_range_id;
1614 	dev->locking_range_info[locking_range_id] = info;
1615 
1616 	opal_clear_cmd(dev);
1617 	opal_set_comid(dev, dev->comid);
1618 
1619 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1620 	opal_add_token_bytestring(&err, dev, uid_locking_range, OPAL_UID_LENGTH);
1621 	opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1622 
1623 
1624 	opal_add_tokens(&err, dev, 12, SPDK_OPAL_STARTLIST,
1625 			SPDK_OPAL_STARTLIST,
1626 			SPDK_OPAL_STARTNAME,
1627 			SPDK_OPAL_STARTCOLUMN,
1628 			SPDK_OPAL_RANGESTART,
1629 			SPDK_OPAL_ENDNAME,
1630 			SPDK_OPAL_STARTNAME,
1631 			SPDK_OPAL_ENDCOLUMN,
1632 			SPDK_OPAL_WRITELOCKED,
1633 			SPDK_OPAL_ENDNAME,
1634 			SPDK_OPAL_ENDLIST,
1635 			SPDK_OPAL_ENDLIST);
1636 
1637 	if (err) {
1638 		SPDK_ERRLOG("Error Building get locking range info command\n");
1639 		return err;
1640 	}
1641 
1642 	return opal_finalize_and_send(dev, 1, opal_get_locking_range_info_cb, &locking_range_id);
1643 }
1644 
1645 static int
1646 opal_enable_user(struct spdk_opal_dev *dev, struct opal_common_session *session)
1647 {
1648 	int err = 0;
1649 	uint8_t uid_user[OPAL_UID_LENGTH];
1650 
1651 	err = opal_build_locking_user(uid_user, OPAL_UID_LENGTH, session->who);
1652 
1653 	opal_clear_cmd(dev);
1654 	opal_set_comid(dev, dev->comid);
1655 
1656 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1657 	opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);
1658 	opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1659 
1660 	opal_add_tokens(&err, dev, 11,
1661 			SPDK_OPAL_STARTLIST,
1662 			SPDK_OPAL_STARTNAME,
1663 			SPDK_OPAL_VALUES,
1664 			SPDK_OPAL_STARTLIST,
1665 			SPDK_OPAL_STARTNAME,
1666 			SPDK_OPAL_AUTH_ENABLE,
1667 			SPDK_OPAL_TRUE,
1668 			SPDK_OPAL_ENDNAME,
1669 			SPDK_OPAL_ENDLIST,
1670 			SPDK_OPAL_ENDNAME,
1671 			SPDK_OPAL_ENDLIST);
1672 
1673 	if (err) {
1674 		SPDK_ERRLOG("Error Building enable user command\n");
1675 		return err;
1676 	}
1677 
1678 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1679 }
1680 
1681 static int
1682 opal_add_user_to_locking_range(struct spdk_opal_dev *dev,
1683 			       struct spdk_opal_locking_session *locking_session)
1684 {
1685 	int err = 0;
1686 	uint8_t uid_user[OPAL_UID_LENGTH];
1687 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1688 
1689 	err = opal_build_locking_user(uid_user, OPAL_UID_LENGTH, locking_session->session.who);
1690 	if (err) {
1691 		return err;
1692 	}
1693 
1694 	switch (locking_session->l_state) {
1695 	case OPAL_READONLY:
1696 		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_RDLOCKED], OPAL_UID_LENGTH);
1697 		break;
1698 	case OPAL_READWRITE:
1699 		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_WRLOCKED], OPAL_UID_LENGTH);
1700 		break;
1701 	default:
1702 		SPDK_ERRLOG("locking state should only be OPAL_READONLY or OPAL_READWRITE\n");
1703 		return -EINVAL;
1704 	}
1705 
1706 	uid_locking_range[7] = locking_session->session.opal_key->locking_range;
1707 
1708 	opal_clear_cmd(dev);
1709 	opal_set_comid(dev, dev->comid);
1710 
1711 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1712 	opal_add_token_bytestring(&err, dev, uid_locking_range, OPAL_UID_LENGTH);
1713 	opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1714 
1715 	opal_add_tokens(&err, dev, 8,
1716 			SPDK_OPAL_STARTLIST,
1717 			SPDK_OPAL_STARTNAME,
1718 			SPDK_OPAL_VALUES,
1719 			SPDK_OPAL_STARTLIST,
1720 			SPDK_OPAL_STARTNAME,
1721 			SPDK_OPAL_BOOLEAN_EXPR,
1722 			SPDK_OPAL_STARTLIST,
1723 			SPDK_OPAL_STARTNAME);
1724 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
1725 				  OPAL_UID_LENGTH / 2);
1726 	opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);
1727 
1728 	opal_add_tokens(&err, dev, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
1729 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
1730 				  OPAL_UID_LENGTH / 2);
1731 	opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);
1732 
1733 	opal_add_tokens(&err, dev, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
1734 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_HALF_BOOLEAN_ACE], OPAL_UID_LENGTH / 2);
1735 	opal_add_tokens(&err, dev, 7,
1736 			SPDK_OPAL_TRUE,
1737 			SPDK_OPAL_ENDNAME,
1738 			SPDK_OPAL_ENDLIST,
1739 			SPDK_OPAL_ENDNAME,
1740 			SPDK_OPAL_ENDLIST,
1741 			SPDK_OPAL_ENDNAME,
1742 			SPDK_OPAL_ENDLIST);
1743 	if (err) {
1744 		SPDK_ERRLOG("Error building add user to locking range command\n");
1745 		return err;
1746 	}
1747 
1748 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1749 }
1750 
1751 static int
1752 opal_new_user_passwd(struct spdk_opal_dev *dev, struct opal_common_session *session)
1753 {
1754 	uint8_t uid_cpin[OPAL_UID_LENGTH];
1755 	int ret;
1756 
1757 	if (session->who == OPAL_ADMIN1) {
1758 		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1759 	} else {
1760 		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_USER1], OPAL_UID_LENGTH);
1761 		uid_cpin[7] = session->who;
1762 	}
1763 
1764 	ret = opal_generic_pw_cmd(session->opal_key->key, session->opal_key->key_len, uid_cpin, dev);
1765 	if (ret != 0) {
1766 		SPDK_ERRLOG("Error building set password command\n");
1767 		return ret;
1768 	}
1769 
1770 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1771 }
1772 
1773 static int
1774 opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data)
1775 {
1776 	uint8_t cpin_uid[OPAL_UID_LENGTH];
1777 	const char *new_passwd = data;
1778 	struct spdk_opal_key opal_key;
1779 	int ret;
1780 
1781 	ret = opal_init_key(&opal_key, new_passwd, OPAL_LOCKING_RANGE_GLOBAL);
1782 	if (ret != 0) {
1783 		return ret;
1784 	}
1785 
1786 	memcpy(cpin_uid, spdk_opal_uid[UID_C_PIN_SID], OPAL_UID_LENGTH);
1787 
1788 	if (opal_generic_pw_cmd(opal_key.key, opal_key.key_len, cpin_uid, dev)) {
1789 		SPDK_ERRLOG("Error building Set SID cpin\n");
1790 		return -ERANGE;
1791 	}
1792 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1793 }
1794 
1795 int
1796 spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd)
1797 {
1798 	int ret;
1799 
1800 	if (!dev || dev->supported == false) {
1801 		return -ENODEV;
1802 	}
1803 
1804 	pthread_mutex_lock(&dev->mutex_lock);
1805 	opal_setup_dev(dev);
1806 	ret = opal_start_anybody_adminsp_session(dev);
1807 	if (ret) {
1808 		SPDK_ERRLOG("start admin SP session error %d: %s\n", ret,
1809 			    opal_error_to_human(ret));
1810 		opal_end_session(dev);
1811 		goto end;
1812 	}
1813 
1814 	ret = opal_get_msid_cpin_pin(dev);
1815 	if (ret) {
1816 		SPDK_ERRLOG("get msid error %d: %s\n", ret,
1817 			    opal_error_to_human(ret));
1818 		opal_end_session(dev);
1819 		goto end;
1820 	}
1821 
1822 	ret = opal_end_session(dev);
1823 	if (ret) {
1824 		SPDK_ERRLOG("end session error %d: %s\n", ret,
1825 			    opal_error_to_human(ret));
1826 		goto end;
1827 	}
1828 
1829 	ret = opal_start_adminsp_session(dev, NULL); /* key stored in dev->prev_data */
1830 	if (ret) {
1831 		SPDK_ERRLOG("start admin SP session error %d: %s\n", ret,
1832 			    opal_error_to_human(ret));
1833 		opal_end_session(dev);
1834 		goto end;
1835 	}
1836 
1837 	ret = opal_set_sid_cpin_pin(dev, new_passwd);
1838 	if (ret) {
1839 		SPDK_ERRLOG("set cpin error %d: %s\n", ret,
1840 			    opal_error_to_human(ret));
1841 		opal_end_session(dev);
1842 		goto end;
1843 	}
1844 
1845 	ret = opal_end_session(dev);
1846 	if (ret) {
1847 		SPDK_ERRLOG("end session error %d: %s\n", ret,
1848 			    opal_error_to_human(ret));
1849 		goto end;
1850 	}
1851 
1852 end:
1853 	pthread_mutex_unlock(&dev->mutex_lock);
1854 	return ret;
1855 }
1856 
1857 struct spdk_opal_dev *
1858 spdk_opal_init_dev(void *dev_handler)
1859 {
1860 	struct spdk_opal_dev *dev;
1861 	struct spdk_opal_info *info;
1862 
1863 	dev = calloc(1, sizeof(*dev));
1864 	if (!dev) {
1865 		SPDK_ERRLOG("Memory allocation failed\n");
1866 		return NULL;
1867 	}
1868 
1869 	dev->dev_handler = dev_handler;
1870 
1871 	info = calloc(1, sizeof(struct spdk_opal_info));
1872 	if (info == NULL) {
1873 		free(dev);
1874 		SPDK_ERRLOG("Memory allocation failed\n");
1875 		return NULL;
1876 	}
1877 
1878 	dev->opal_info = info;
1879 	if (opal_check_support(dev) != 0) {
1880 		SPDK_INFOLOG(SPDK_LOG_OPAL, "Opal is not supported on this device\n");
1881 		dev->supported = false;
1882 	}
1883 
1884 	if (pthread_mutex_init(&dev->mutex_lock, NULL)) {
1885 		SPDK_ERRLOG("Mutex init failed\n");
1886 		free(dev->opal_info);
1887 		free(dev);
1888 		return NULL;
1889 	}
1890 
1891 	return dev;
1892 }
1893 
1894 int
1895 spdk_opal_cmd_scan(struct spdk_opal_dev *dev)
1896 {
1897 	int ret;
1898 
1899 	ret = opal_check_support(dev);
1900 	if (ret) {
1901 		SPDK_ERRLOG("check opal support failed: %d\n", ret);
1902 		spdk_opal_close(dev);
1903 	}
1904 	return ret;
1905 }
1906 
1907 static int
1908 opal_revert_tper(struct spdk_opal_dev *dev)
1909 {
1910 	int err = 0;
1911 
1912 	opal_clear_cmd(dev);
1913 	opal_set_comid(dev, dev->comid);
1914 
1915 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1916 	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_ADMINSP],
1917 				  OPAL_UID_LENGTH);
1918 	opal_add_token_bytestring(&err, dev, spdk_opal_method[REVERT_METHOD],
1919 				  OPAL_UID_LENGTH);
1920 	opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
1921 	opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
1922 	if (err) {
1923 		SPDK_ERRLOG("Error building REVERT TPER command.\n");
1924 		return err;
1925 	}
1926 
1927 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1928 }
1929 
1930 static int
1931 opal_gen_new_active_key(struct spdk_opal_dev *dev)
1932 {
1933 	uint8_t uid_data[OPAL_UID_LENGTH] = {0};
1934 	int err = 0;
1935 	int length;
1936 
1937 	opal_clear_cmd(dev);
1938 	opal_set_comid(dev, dev->comid);
1939 
1940 	if (dev->prev_data == NULL || dev->prev_d_len == 0) {
1941 		SPDK_ERRLOG("Error finding previous data to generate new active key\n");
1942 		return -EINVAL;
1943 	}
1944 
1945 	length = spdk_min(dev->prev_d_len, OPAL_UID_LENGTH);
1946 	memcpy(uid_data, dev->prev_data, length);
1947 	free(dev->prev_data);
1948 	dev->prev_data = NULL;
1949 
1950 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
1951 	opal_add_token_bytestring(&err, dev, uid_data, OPAL_UID_LENGTH);
1952 	opal_add_token_bytestring(&err, dev, spdk_opal_method[GENKEY_METHOD],
1953 				  OPAL_UID_LENGTH);
1954 
1955 	opal_add_tokens(&err, dev, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
1956 
1957 	if (err) {
1958 		SPDK_ERRLOG("Error building new key generation command.\n");
1959 		return err;
1960 	}
1961 
1962 	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
1963 }
1964 
1965 static int
1966 opal_get_active_key_cb(struct spdk_opal_dev *dev, void *data)
1967 {
1968 	const char *active_key;
1969 	size_t str_len;
1970 	int error = 0;
1971 
1972 	error = opal_parse_and_check_status(dev, NULL);
1973 	if (error) {
1974 		return error;
1975 	}
1976 
1977 	str_len = opal_response_get_string(&dev->parsed_resp, 4, &active_key);
1978 	if (!active_key) {
1979 		SPDK_ERRLOG("Couldn't extract active key from response\n");
1980 		return -EINVAL;
1981 	}
1982 
1983 	dev->prev_d_len = str_len;
1984 	dev->prev_data = calloc(1, str_len);
1985 	if (!dev->prev_data) {
1986 		SPDK_ERRLOG("memory allocation error\n");
1987 		return -ENOMEM;
1988 	}
1989 	memcpy(dev->prev_data, active_key, str_len);
1990 
1991 	SPDK_DEBUGLOG(SPDK_LOG_OPAL, "active key = %p\n", dev->prev_data);
1992 	return 0;
1993 }
1994 
1995 static int
1996 opal_get_active_key(struct spdk_opal_dev *dev, struct opal_common_session *session)
1997 {
1998 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1999 	uint8_t locking_range_id;
2000 	int err = 0;
2001 
2002 	opal_clear_cmd(dev);
2003 	opal_set_comid(dev, dev->comid);
2004 
2005 	locking_range_id = session->opal_key->locking_range;
2006 	err = opal_build_locking_range(uid_locking_range, OPAL_UID_LENGTH, locking_range_id);
2007 	if (err) {
2008 		return err;
2009 	}
2010 
2011 	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
2012 	opal_add_token_bytestring(&err, dev, uid_locking_range, OPAL_UID_LENGTH);
2013 	opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD],
2014 				  OPAL_UID_LENGTH);
2015 	opal_add_tokens(&err, dev, 12,
2016 			SPDK_OPAL_STARTLIST,
2017 			SPDK_OPAL_STARTLIST,
2018 			SPDK_OPAL_STARTNAME,
2019 			SPDK_OPAL_STARTCOLUMN,
2020 			SPDK_OPAL_ACTIVEKEY,
2021 			SPDK_OPAL_ENDNAME,
2022 			SPDK_OPAL_STARTNAME,
2023 			SPDK_OPAL_ENDCOLUMN,
2024 			SPDK_OPAL_ACTIVEKEY,
2025 			SPDK_OPAL_ENDNAME,
2026 			SPDK_OPAL_ENDLIST,
2027 			SPDK_OPAL_ENDLIST);
2028 
2029 	if (err) {
2030 		SPDK_ERRLOG("Error building get active key command.\n");
2031 		return err;
2032 	}
2033 
2034 	return opal_finalize_and_send(dev, 1, opal_get_active_key_cb, NULL);
2035 }
2036 
2037 int
2038 spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
2039 {
2040 	int ret;
2041 	struct spdk_opal_key opal_key;
2042 
2043 	if (!dev || dev->supported == false) {
2044 		return -ENODEV;
2045 	}
2046 
2047 	ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
2048 	if (ret != 0) {
2049 		return ret;
2050 	}
2051 
2052 	pthread_mutex_lock(&dev->mutex_lock);
2053 	opal_setup_dev(dev);
2054 
2055 	ret = opal_start_adminsp_session(dev, &opal_key);
2056 	if (ret) {
2057 		opal_end_session(dev);
2058 		SPDK_ERRLOG("Error on starting admin SP session with error %d: %s\n", ret,
2059 			    opal_error_to_human(ret));
2060 		goto end;
2061 	}
2062 
2063 	ret = opal_revert_tper(dev);
2064 	if (ret) {
2065 		opal_end_session(dev);
2066 		SPDK_ERRLOG("Error on reverting TPer with error %d: %s\n", ret,
2067 			    opal_error_to_human(ret));
2068 		goto end;
2069 	}
2070 
2071 	/* Controller will terminate session. No "end session" here needed. */
2072 
2073 end:
2074 	pthread_mutex_unlock(&dev->mutex_lock);
2075 	return ret;
2076 }
2077 
2078 int
2079 spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd)
2080 {
2081 	struct spdk_opal_key opal_key;
2082 	int ret;
2083 
2084 	ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
2085 	if (ret != 0) {
2086 		return ret;
2087 	}
2088 
2089 	pthread_mutex_lock(&dev->mutex_lock);
2090 	ret = opal_start_adminsp_session(dev, &opal_key);
2091 	if (ret) {
2092 		SPDK_ERRLOG("Error on starting admin SP session with error %d: %s\n", ret,
2093 			    opal_error_to_human(ret));
2094 		pthread_mutex_unlock(&dev->mutex_lock);
2095 		return ret;
2096 	}
2097 
2098 	ret = opal_get_locking_sp_lifecycle(dev);
2099 	if (ret) {
2100 		SPDK_ERRLOG("Error on getting SP lifecycle with error %d: %s\n", ret,
2101 			    opal_error_to_human(ret));
2102 		goto end;
2103 	}
2104 
2105 	ret = opal_activate(dev);
2106 	if (ret) {
2107 		SPDK_ERRLOG("Error on activation with error %d: %s\n", ret,
2108 			    opal_error_to_human(ret));
2109 		goto end;
2110 	}
2111 
2112 end:
2113 	ret += opal_end_session(dev);
2114 	if (ret) {
2115 		SPDK_ERRLOG("Error on ending session with error %d: %s\n", ret,
2116 			    opal_error_to_human(ret));
2117 	}
2118 
2119 	pthread_mutex_unlock(&dev->mutex_lock);
2120 	return ret;
2121 }
2122 
2123 int
2124 spdk_opal_cmd_lock_unlock(struct spdk_opal_dev *dev, enum spdk_opal_user user,
2125 			  enum spdk_opal_lock_state flag, enum spdk_opal_locking_range locking_range,
2126 			  const char *passwd)
2127 {
2128 	struct spdk_opal_locking_session locking_session;
2129 	struct spdk_opal_key opal_key;
2130 	int ret;
2131 
2132 	if (!dev || dev->supported == false) {
2133 		return -ENODEV;
2134 	}
2135 
2136 	ret = opal_init_key(&opal_key, passwd, locking_range);
2137 	if (ret != 0) {
2138 		return ret;
2139 	}
2140 
2141 	memset(&locking_session, 0, sizeof(struct spdk_opal_locking_session));
2142 	locking_session.l_state = flag;
2143 	locking_session.session.who = user;
2144 	locking_session.session.opal_key = &opal_key;
2145 
2146 	pthread_mutex_lock(&dev->mutex_lock);
2147 
2148 	ret = opal_start_auth_session(dev, &locking_session.session);
2149 	if (ret) {
2150 		SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
2151 		pthread_mutex_unlock(&dev->mutex_lock);
2152 		return ret;
2153 	}
2154 
2155 	ret = opal_lock_unlock_range(dev, &locking_session);
2156 	if (ret) {
2157 		SPDK_ERRLOG("lock unlock range error %d: %s\n", ret, opal_error_to_human(ret));
2158 		goto end;
2159 	}
2160 
2161 end:
2162 	ret += opal_end_session(dev);
2163 	if (ret) {
2164 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2165 	}
2166 
2167 	pthread_mutex_unlock(&dev->mutex_lock);
2168 	return ret;
2169 }
2170 
2171 int
2172 spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user,
2173 				  enum spdk_opal_locking_range locking_range_id, uint64_t range_start,
2174 				  uint64_t range_length, const char *passwd)
2175 {
2176 	struct opal_locking_range_setup_session setup_session;
2177 	struct spdk_opal_key opal_key;
2178 	int ret;
2179 
2180 	if (!dev || dev->supported == false) {
2181 		return -ENODEV;
2182 	}
2183 
2184 	ret = opal_init_key(&opal_key, passwd, locking_range_id);
2185 	if (ret != 0) {
2186 		return ret;
2187 	}
2188 
2189 	memset(&setup_session, 0, sizeof(struct opal_locking_range_setup_session));
2190 	setup_session.session.opal_key = &opal_key;
2191 	setup_session.session.who = user;
2192 	setup_session.id = locking_range_id;
2193 	setup_session.range_length = range_length;
2194 	setup_session.range_start = range_start;
2195 	setup_session.read_lock_enabled = true;
2196 	setup_session.write_lock_enabled = true;
2197 
2198 	pthread_mutex_lock(&dev->mutex_lock);
2199 	ret = opal_start_auth_session(dev, &setup_session.session);
2200 	if (ret) {
2201 		SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
2202 		pthread_mutex_unlock(&dev->mutex_lock);
2203 		return ret;
2204 	}
2205 
2206 	ret = opal_setup_locking_range(dev, &setup_session);
2207 	if (ret) {
2208 		SPDK_ERRLOG("setup locking range error %d: %s\n", ret, opal_error_to_human(ret));
2209 		goto end;
2210 	}
2211 
2212 end:
2213 	ret += opal_end_session(dev);
2214 	if (ret) {
2215 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2216 	}
2217 
2218 	pthread_mutex_unlock(&dev->mutex_lock);
2219 	return ret;
2220 }
2221 
2222 int
2223 spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd)
2224 {
2225 	struct spdk_opal_key opal_key;
2226 	struct opal_common_session session;
2227 	int ret;
2228 
2229 	if (!dev || dev->supported == false) {
2230 		return -ENODEV;
2231 	}
2232 
2233 	ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
2234 	if (ret != 0) {
2235 		return ret;
2236 	}
2237 
2238 	memset(&session, 0, sizeof(struct opal_common_session));
2239 	session.opal_key = &opal_key;
2240 	session.who = OPAL_ADMIN1;
2241 
2242 	pthread_mutex_lock(&dev->mutex_lock);
2243 	ret = opal_start_auth_session(dev, &session);
2244 	if (ret) {
2245 		SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
2246 		pthread_mutex_unlock(&dev->mutex_lock);
2247 		return ret;
2248 	}
2249 
2250 	ret = opal_get_max_ranges(dev);
2251 	if (ret) {
2252 		SPDK_ERRLOG("get max ranges error %d: %s\n", ret, opal_error_to_human(ret));
2253 		goto end;
2254 	}
2255 
2256 end:
2257 	ret += opal_end_session(dev);
2258 	if (ret) {
2259 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2260 	}
2261 
2262 	pthread_mutex_unlock(&dev->mutex_lock);
2263 	return ret;
2264 }
2265 
2266 int
2267 spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
2268 				     enum spdk_opal_user user_id,
2269 				     enum spdk_opal_locking_range locking_range_id)
2270 {
2271 	struct spdk_opal_key opal_key;
2272 	struct opal_common_session session;
2273 	int ret;
2274 
2275 	if (!dev || dev->supported == false) {
2276 		return -ENODEV;
2277 	}
2278 
2279 	ret = opal_init_key(&opal_key, passwd, locking_range_id);
2280 	if (ret != 0) {
2281 		return ret;
2282 	}
2283 
2284 	memset(&session, 0, sizeof(struct opal_common_session));
2285 	session.opal_key = &opal_key;
2286 	session.who = user_id;
2287 
2288 	pthread_mutex_lock(&dev->mutex_lock);
2289 	ret = opal_start_auth_session(dev, &session);
2290 	if (ret) {
2291 		SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
2292 		pthread_mutex_unlock(&dev->mutex_lock);
2293 		return ret;
2294 	}
2295 
2296 	ret = opal_get_locking_range_info(dev, locking_range_id);
2297 	if (ret) {
2298 		SPDK_ERRLOG("get locking range info error %d: %s\n", ret, opal_error_to_human(ret));
2299 		goto end;
2300 	}
2301 
2302 end:
2303 	ret += opal_end_session(dev);
2304 	if (ret) {
2305 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2306 	}
2307 
2308 	pthread_mutex_unlock(&dev->mutex_lock);
2309 	return ret;
2310 }
2311 
2312 int
2313 spdk_opal_cmd_enable_user(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2314 			  const char *passwd)
2315 {
2316 	struct spdk_opal_key opal_key;
2317 	struct opal_common_session session;
2318 	int ret;
2319 
2320 	if (!dev || dev->supported == false) {
2321 		return -ENODEV;
2322 	}
2323 
2324 	ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
2325 	if (ret != 0) {
2326 		return ret;
2327 	}
2328 
2329 	memset(&session, 0, sizeof(struct opal_common_session));
2330 	session.opal_key = &opal_key;
2331 	session.who = user_id;
2332 
2333 	pthread_mutex_lock(&dev->mutex_lock);
2334 	ret = opal_start_admin_session(dev, session.opal_key);
2335 	if (ret) {
2336 		SPDK_ERRLOG("start locking SP session error %d: %s\n", ret, opal_error_to_human(ret));
2337 		pthread_mutex_unlock(&dev->mutex_lock);
2338 		return ret;
2339 	}
2340 
2341 	ret = opal_enable_user(dev, &session);
2342 	if (ret) {
2343 		SPDK_ERRLOG("enable user error %d: %s\n", ret, opal_error_to_human(ret));
2344 		goto end;
2345 	}
2346 
2347 end:
2348 	ret += opal_end_session(dev);
2349 	if (ret) {
2350 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2351 	}
2352 
2353 	pthread_mutex_unlock(&dev->mutex_lock);
2354 	return ret;
2355 }
2356 
2357 int
2358 spdk_opal_cmd_add_user_to_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2359 					enum spdk_opal_locking_range locking_range_id,
2360 					enum spdk_opal_lock_state lock_flag, const char *passwd)
2361 {
2362 	struct spdk_opal_key opal_key;
2363 	struct spdk_opal_locking_session locking_session;
2364 	int ret;
2365 
2366 	if (!dev || dev->supported == false) {
2367 		return -ENODEV;
2368 	}
2369 
2370 	ret = opal_init_key(&opal_key, passwd, locking_range_id);
2371 	if (ret != 0) {
2372 		return ret;
2373 	}
2374 
2375 	memset(&locking_session, 0, sizeof(struct spdk_opal_locking_session));
2376 	locking_session.session.opal_key = &opal_key;
2377 	locking_session.session.who = user_id;
2378 	locking_session.l_state = lock_flag;
2379 
2380 	pthread_mutex_lock(&dev->mutex_lock);
2381 	ret = opal_start_admin_session(dev, locking_session.session.opal_key);
2382 	if (ret) {
2383 		SPDK_ERRLOG("start locking SP session error %d: %s\n", ret, opal_error_to_human(ret));
2384 		pthread_mutex_unlock(&dev->mutex_lock);
2385 		return ret;
2386 	}
2387 
2388 	ret = opal_add_user_to_locking_range(dev, &locking_session);
2389 	if (ret) {
2390 		SPDK_ERRLOG("add user to locking range error %d: %s\n", ret, opal_error_to_human(ret));
2391 		goto end;
2392 	}
2393 
2394 end:
2395 	ret += opal_end_session(dev);
2396 	if (ret) {
2397 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2398 	}
2399 
2400 	pthread_mutex_unlock(&dev->mutex_lock);
2401 	return ret;
2402 }
2403 
2404 int
2405 spdk_opal_cmd_set_new_passwd(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2406 			     const char *new_passwd, const char *old_passwd, bool new_user)
2407 {
2408 	struct spdk_opal_key old_key;
2409 	struct spdk_opal_key new_key;
2410 	struct spdk_opal_new_pw_session session;
2411 	int ret;
2412 
2413 	if (!dev || dev->supported == false) {
2414 		return -ENODEV;
2415 	}
2416 
2417 	ret = opal_init_key(&old_key, old_passwd, OPAL_LOCKING_RANGE_GLOBAL);
2418 	if (ret != 0) {
2419 		return ret;
2420 	}
2421 
2422 	ret = opal_init_key(&new_key, new_passwd, OPAL_LOCKING_RANGE_GLOBAL);
2423 	if (ret != 0) {
2424 		return ret;
2425 	}
2426 
2427 	memset(&session, 0, sizeof(struct spdk_opal_new_pw_session));
2428 	session.new_session.who = user_id;
2429 	session.new_session.opal_key = &new_key;
2430 	session.old_session.who = new_user ? OPAL_ADMIN1 : user_id;
2431 	session.old_session.opal_key = &old_key;
2432 
2433 	pthread_mutex_lock(&dev->mutex_lock);
2434 	ret = opal_start_auth_session(dev, &session.old_session);
2435 	if (ret) {
2436 		SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
2437 		pthread_mutex_unlock(&dev->mutex_lock);
2438 		return ret;
2439 	}
2440 
2441 	ret = opal_new_user_passwd(dev, &session.new_session);
2442 	if (ret) {
2443 		SPDK_ERRLOG("set new passwd error %d: %s\n", ret, opal_error_to_human(ret));
2444 		goto end;
2445 	}
2446 
2447 end:
2448 	ret += opal_end_session(dev);
2449 	if (ret) {
2450 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2451 	}
2452 
2453 	pthread_mutex_unlock(&dev->mutex_lock);
2454 	return ret;
2455 }
2456 
2457 int
2458 spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2459 				  enum spdk_opal_locking_range locking_range_id, const char *password)
2460 {
2461 	struct opal_common_session session = {};
2462 	struct spdk_opal_key opal_key;
2463 	int ret;
2464 
2465 	if (!dev || dev->supported == false) {
2466 		return -ENODEV;
2467 	}
2468 
2469 	ret = opal_init_key(&opal_key, password, locking_range_id);
2470 	if (ret != 0) {
2471 		return ret;
2472 	}
2473 
2474 	session.opal_key = &opal_key;
2475 	session.who = user_id;
2476 
2477 	pthread_mutex_lock(&dev->mutex_lock);
2478 	ret = opal_start_auth_session(dev, &session);
2479 	if (ret) {
2480 		SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
2481 		pthread_mutex_unlock(&dev->mutex_lock);
2482 		return ret;
2483 	}
2484 
2485 	ret = opal_get_active_key(dev, &session);
2486 	if (ret) {
2487 		SPDK_ERRLOG("get active key error %d: %s\n", ret, opal_error_to_human(ret));
2488 		goto end;
2489 	}
2490 
2491 	ret = opal_gen_new_active_key(dev);
2492 	if (ret) {
2493 		SPDK_ERRLOG("generate new active key error %d: %s\n", ret, opal_error_to_human(ret));
2494 		goto end;
2495 	}
2496 
2497 end:
2498 	ret += opal_end_session(dev);
2499 	if (ret) {
2500 		SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
2501 	}
2502 
2503 	pthread_mutex_unlock(&dev->mutex_lock);
2504 	return ret;
2505 }
2506 
2507 struct spdk_opal_info *
2508 spdk_opal_get_info(struct spdk_opal_dev *dev)
2509 {
2510 	return dev->opal_info;
2511 }
2512 
2513 bool
2514 spdk_opal_supported(struct spdk_opal_dev *dev)
2515 {
2516 	return dev->supported;
2517 }
2518 
2519 struct spdk_opal_locking_range_info *
2520 spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
2521 {
2522 	return dev->locking_range_info[id];
2523 }
2524 
2525 uint8_t
2526 spdk_opal_get_max_locking_ranges(struct spdk_opal_dev *dev)
2527 {
2528 	return dev->max_ranges;
2529 }
2530 
2531 /* Log component for opal submodule */
2532 SPDK_LOG_REGISTER_COMPONENT("opal", SPDK_LOG_OPAL)
2533