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