LCOV - code coverage report
Current view: top level - lib/nvme - nvme_opal.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 63 1305 4.8 %
Date: 2024-12-14 20:56:31 Functions: 7 84 8.3 %

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

Generated by: LCOV version 1.15