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-07-10 17:38:26 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             : 
     579             :         /* if we get an EOS token, just return 0 */
     580           0 :         tok = opal_response_get_token(resp, 0);
     581           0 :         if (opal_response_token_matches(tok, SPDK_OPAL_ENDOFSESSION)) {
     582           0 :                 return 0;
     583             :         }
     584             : 
     585           0 :         if (resp->num < 5) {
     586           0 :                 return SPDK_DTAERROR_NO_METHOD_STATUS;
     587             :         }
     588             : 
     589           0 :         tok = opal_response_get_token(resp, resp->num - 5); /* the first token should be STARTLIST */
     590           0 :         if (!opal_response_token_matches(tok, SPDK_OPAL_STARTLIST)) {
     591           0 :                 return SPDK_DTAERROR_NO_METHOD_STATUS;
     592             :         }
     593             : 
     594           0 :         tok = opal_response_get_token(resp, resp->num - 1); /* the last token should be ENDLIST */
     595           0 :         if (!opal_response_token_matches(tok, SPDK_OPAL_ENDLIST)) {
     596           0 :                 return SPDK_DTAERROR_NO_METHOD_STATUS;
     597             :         }
     598             : 
     599             :         /* The second and third values in the status list are reserved, and are
     600             :         defined in core spec to be 0x00 and 0x00 and SHOULD be ignored by the host. */
     601           0 :         return (int)opal_response_get_u64(resp,
     602           0 :                                           resp->num - 4); /* We only need the first value in the status list. */
     603             : }
     604             : 
     605             : static int
     606           0 : opal_parse_and_check_status(struct opal_session *sess)
     607             : {
     608             :         int error;
     609             : 
     610           0 :         error = opal_response_parse(sess->resp, IO_BUFFER_LENGTH, &sess->parsed_resp);
     611           0 :         if (error) {
     612           0 :                 SPDK_ERRLOG("Couldn't parse response.\n");
     613           0 :                 return error;
     614             :         }
     615           0 :         return opal_response_status(&sess->parsed_resp);
     616             : }
     617             : 
     618             : static inline void
     619           0 : opal_clear_cmd(struct opal_session *sess)
     620             : {
     621           0 :         sess->cmd_pos = sizeof(struct spdk_opal_header);
     622           0 :         memset(sess->cmd, 0, IO_BUFFER_LENGTH);
     623           0 : }
     624             : 
     625             : static inline void
     626           0 : opal_set_comid(struct opal_session *sess, uint16_t comid)
     627             : {
     628           0 :         struct spdk_opal_header *hdr = (struct spdk_opal_header *)sess->cmd;
     629             : 
     630           0 :         hdr->com_packet.comid[0] = comid >> 8;
     631           0 :         hdr->com_packet.comid[1] = comid;
     632           0 :         hdr->com_packet.extended_comid[0] = 0;
     633           0 :         hdr->com_packet.extended_comid[1] = 0;
     634           0 : }
     635             : 
     636             : static inline int
     637           0 : opal_init_key(struct spdk_opal_key *opal_key, const char *passwd)
     638             : {
     639             :         int len;
     640             : 
     641           0 :         if (passwd == NULL || passwd[0] == '\0') {
     642           0 :                 SPDK_ERRLOG("Password is empty. Create key failed\n");
     643           0 :                 return -EINVAL;
     644             :         }
     645             : 
     646           0 :         len = strlen(passwd);
     647             : 
     648           0 :         if (len >= OPAL_KEY_MAX) {
     649           0 :                 SPDK_ERRLOG("Password too long. Create key failed\n");
     650           0 :                 return -EINVAL;
     651             :         }
     652             : 
     653           0 :         opal_key->key_len = len;
     654           0 :         memcpy(opal_key->key, passwd, opal_key->key_len);
     655             : 
     656           0 :         return 0;
     657             : }
     658             : 
     659             : static void
     660           0 : opal_build_locking_range(uint8_t *buffer, uint8_t locking_range)
     661             : {
     662           0 :         memcpy(buffer, spdk_opal_uid[UID_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
     663             : 
     664             :         /* global */
     665           0 :         if (locking_range == 0) {
     666           0 :                 return;
     667             :         }
     668             : 
     669             :         /* non-global */
     670           0 :         buffer[5] = LOCKING_RANGE_NON_GLOBAL;
     671           0 :         buffer[7] = locking_range;
     672             : }
     673             : 
     674             : static void
     675           0 : opal_check_tper(struct spdk_opal_dev *dev, const void *data)
     676             : {
     677           0 :         const struct spdk_opal_d0_tper_feat *tper = data;
     678             : 
     679           0 :         dev->feat_info.tper = *tper;
     680           0 : }
     681             : 
     682             : /*
     683             :  * check single user mode
     684             :  */
     685             : static bool
     686           0 : opal_check_sum(struct spdk_opal_dev *dev, const void *data)
     687             : {
     688           0 :         const struct spdk_opal_d0_single_user_mode_feat *sum = data;
     689           0 :         uint32_t num_locking_objects = from_be32(&sum->num_locking_objects);
     690             : 
     691           0 :         if (num_locking_objects == 0) {
     692           0 :                 SPDK_NOTICELOG("Need at least one locking object.\n");
     693           0 :                 return false;
     694             :         }
     695             : 
     696           0 :         dev->feat_info.single_user = *sum;
     697             : 
     698           0 :         return true;
     699             : }
     700             : 
     701             : static void
     702           0 : opal_check_lock(struct spdk_opal_dev *dev, const void *data)
     703             : {
     704           0 :         const struct spdk_opal_d0_locking_feat *lock = data;
     705             : 
     706           0 :         dev->feat_info.locking = *lock;
     707           0 : }
     708             : 
     709             : static void
     710           0 : opal_check_geometry(struct spdk_opal_dev *dev, const void *data)
     711             : {
     712           0 :         const struct spdk_opal_d0_geo_feat *geo = data;
     713             : 
     714           0 :         dev->feat_info.geo = *geo;
     715           0 : }
     716             : 
     717             : static void
     718           0 : opal_check_datastore(struct spdk_opal_dev *dev, const void *data)
     719             : {
     720           0 :         const struct spdk_opal_d0_datastore_feat *datastore = data;
     721             : 
     722           0 :         dev->feat_info.datastore = *datastore;
     723           0 : }
     724             : 
     725             : static uint16_t
     726           0 : opal_get_comid_v100(struct spdk_opal_dev *dev, const void *data)
     727             : {
     728           0 :         const struct spdk_opal_d0_v100_feat *v100 = data;
     729           0 :         uint16_t base_comid = from_be16(&v100->base_comid);
     730             : 
     731           0 :         dev->feat_info.v100 = *v100;
     732             : 
     733           0 :         return base_comid;
     734             : }
     735             : 
     736             : static uint16_t
     737           0 : opal_get_comid_v200(struct spdk_opal_dev *dev, const void *data)
     738             : {
     739           0 :         const struct spdk_opal_d0_v200_feat *v200 = data;
     740           0 :         uint16_t base_comid = from_be16(&v200->base_comid);
     741             : 
     742           0 :         dev->feat_info.v200 = *v200;
     743             : 
     744           0 :         return base_comid;
     745             : }
     746             : 
     747             : static int
     748           0 : opal_discovery0_end(struct spdk_opal_dev *dev, void *payload, uint32_t payload_size)
     749             : {
     750           0 :         bool supported = false, single_user = false;
     751           0 :         const struct spdk_opal_d0_hdr *hdr = (struct spdk_opal_d0_hdr *)payload;
     752             :         struct spdk_opal_d0_feat_hdr *feat_hdr;
     753           0 :         const uint8_t *epos = payload, *cpos = payload;
     754           0 :         uint16_t comid = 0;
     755           0 :         uint32_t hlen = from_be32(&(hdr->length));
     756             : 
     757           0 :         if (hlen > payload_size - sizeof(*hdr)) {
     758           0 :                 SPDK_ERRLOG("Discovery length overflows buffer (%zu+%u)/%u\n",
     759             :                             sizeof(*hdr), hlen, payload_size);
     760           0 :                 return -EFAULT;
     761             :         }
     762             : 
     763           0 :         epos += hlen; /* end of buffer */
     764           0 :         cpos += sizeof(*hdr); /* current position on buffer */
     765             : 
     766           0 :         while (cpos < epos) {
     767           0 :                 feat_hdr = (struct spdk_opal_d0_feat_hdr *)cpos;
     768           0 :                 uint16_t feat_code = from_be16(&feat_hdr->code);
     769             : 
     770           0 :                 switch (feat_code) {
     771           0 :                 case FEATURECODE_TPER:
     772           0 :                         opal_check_tper(dev, cpos);
     773           0 :                         break;
     774           0 :                 case FEATURECODE_SINGLEUSER:
     775           0 :                         single_user = opal_check_sum(dev, cpos);
     776           0 :                         break;
     777           0 :                 case FEATURECODE_GEOMETRY:
     778           0 :                         opal_check_geometry(dev, cpos);
     779           0 :                         break;
     780           0 :                 case FEATURECODE_LOCKING:
     781           0 :                         opal_check_lock(dev, cpos);
     782           0 :                         break;
     783           0 :                 case FEATURECODE_DATASTORE:
     784           0 :                         opal_check_datastore(dev, cpos);
     785           0 :                         break;
     786           0 :                 case FEATURECODE_OPALV100:
     787           0 :                         comid = opal_get_comid_v100(dev, cpos);
     788           0 :                         supported = true;
     789           0 :                         break;
     790           0 :                 case FEATURECODE_OPALV200:
     791           0 :                         comid = opal_get_comid_v200(dev, cpos);
     792           0 :                         supported = true;
     793           0 :                         break;
     794           0 :                 default:
     795           0 :                         SPDK_INFOLOG(opal, "Unknown feature code: %d\n", feat_code);
     796             :                 }
     797           0 :                 cpos += feat_hdr->length + sizeof(*feat_hdr);
     798             :         }
     799             : 
     800           0 :         if (supported == false) {
     801           0 :                 SPDK_INFOLOG(opal, "Opal Not Supported.\n");
     802           0 :                 return -ENOTSUP;
     803             :         }
     804             : 
     805           0 :         if (single_user == false) {
     806           0 :                 SPDK_INFOLOG(opal, "Single User Mode Not Supported\n");
     807             :         }
     808             : 
     809           0 :         dev->comid = comid;
     810           0 :         return 0;
     811             : }
     812             : 
     813             : static int
     814           0 : opal_discovery0(struct spdk_opal_dev *dev, void *payload, uint32_t payload_size)
     815             : {
     816             :         int ret;
     817             :         uint16_t i, sp_list_len;
     818             :         uint8_t *sp_list;
     819           0 :         bool sp_tcg_supported = false;
     820             : 
     821             :         /* NVMe 1.4 chapter 5.25.2 Security Protocol 00h */
     822           0 :         ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_INFO, 0,
     823             :                                                0, payload, payload_size);
     824           0 :         if (ret) {
     825           0 :                 return ret;
     826             :         }
     827             : 
     828             :         /* spc4r31 chapter 7.7.1.3 Supported security protocols list description */
     829           0 :         sp_list_len = from_be16((uint8_t *)payload + 6);
     830           0 :         sp_list = (uint8_t *)payload + 8;
     831             : 
     832           0 :         if (sp_list_len + 8 > (int)payload_size) {
     833           0 :                 return -EINVAL;
     834             :         }
     835             : 
     836           0 :         for (i = 0; i < sp_list_len; i++) {
     837           0 :                 if (sp_list[i] == SPDK_SCSI_SECP_TCG) {
     838           0 :                         sp_tcg_supported = true;
     839           0 :                         break;
     840             :                 }
     841             :         }
     842             : 
     843           0 :         if (!sp_tcg_supported) {
     844           0 :                 return -ENOTSUP;
     845             :         }
     846             : 
     847           0 :         memset(payload, 0, payload_size);
     848           0 :         ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG, LV0_DISCOVERY_COMID,
     849             :                                                0, payload, payload_size);
     850           0 :         if (ret) {
     851           0 :                 return ret;
     852             :         }
     853             : 
     854           0 :         return opal_discovery0_end(dev, payload, payload_size);
     855             : }
     856             : 
     857             : static int
     858           0 : opal_end_session(struct spdk_opal_dev *dev, struct opal_session *sess, uint16_t comid)
     859             : {
     860           0 :         int err = 0;
     861             :         int ret;
     862             : 
     863           0 :         opal_clear_cmd(sess);
     864           0 :         opal_set_comid(sess, comid);
     865           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_ENDOFSESSION);
     866             : 
     867           0 :         if (err < 0) {
     868           0 :                 return err;
     869             :         }
     870             : 
     871           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, false);
     872           0 :         if (ret) {
     873           0 :                 return ret;
     874             :         }
     875             : 
     876           0 :         ret = opal_send_recv(dev, sess);
     877           0 :         if (ret) {
     878           0 :                 return ret;
     879             :         }
     880             : 
     881           0 :         sess->hsn = 0;
     882           0 :         sess->tsn = 0;
     883             : 
     884           0 :         return opal_parse_and_check_status(sess);
     885             : }
     886             : 
     887             : void
     888           0 : spdk_opal_dev_destruct(struct spdk_opal_dev *dev)
     889             : {
     890           0 :         free(dev);
     891           0 : }
     892             : 
     893             : static int
     894           0 : opal_start_session_done(struct opal_session *sess)
     895             : {
     896             :         uint32_t hsn, tsn;
     897           0 :         int error = 0;
     898             : 
     899           0 :         error = opal_parse_and_check_status(sess);
     900           0 :         if (error) {
     901           0 :                 return error;
     902             :         }
     903             : 
     904           0 :         hsn = opal_response_get_u64(&sess->parsed_resp, 4);
     905           0 :         tsn = opal_response_get_u64(&sess->parsed_resp, 5);
     906             : 
     907           0 :         if (hsn == 0 && tsn == 0) {
     908           0 :                 SPDK_ERRLOG("Couldn't authenticate session\n");
     909           0 :                 return -EPERM;
     910             :         }
     911             : 
     912           0 :         sess->hsn = hsn;
     913           0 :         sess->tsn = tsn;
     914             : 
     915           0 :         return 0;
     916             : }
     917             : 
     918             : static int
     919           0 : opal_start_generic_session(struct spdk_opal_dev *dev,
     920             :                            struct opal_session *sess,
     921             :                            enum opal_uid_enum auth,
     922             :                            enum opal_uid_enum sp_type,
     923             :                            const char *key,
     924             :                            uint8_t key_len)
     925             : {
     926             :         uint32_t hsn;
     927           0 :         int err = 0;
     928             :         int ret;
     929             : 
     930           0 :         if (key == NULL && auth != UID_ANYBODY) {
     931           0 :                 return OPAL_INVAL_PARAM;
     932             :         }
     933             : 
     934           0 :         opal_clear_cmd(sess);
     935             : 
     936           0 :         opal_set_comid(sess, dev->comid);
     937           0 :         hsn = GENERIC_HOST_SESSION_NUM;
     938             : 
     939           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
     940           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_SMUID],
     941             :                                   OPAL_UID_LENGTH);
     942           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[STARTSESSION_METHOD],
     943             :                                   OPAL_UID_LENGTH);
     944           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
     945           0 :         opal_add_token_u64(&err, sess, hsn);
     946           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[sp_type], OPAL_UID_LENGTH);
     947           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_TRUE); /* Write */
     948             : 
     949           0 :         switch (auth) {
     950           0 :         case UID_ANYBODY:
     951           0 :                 opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
     952           0 :                 break;
     953           0 :         case UID_ADMIN1:
     954             :         case UID_SID:
     955           0 :                 opal_add_token_u8(&err, sess, SPDK_OPAL_STARTNAME);
     956           0 :                 opal_add_token_u8(&err, sess, 0); /* HostChallenge */
     957           0 :                 opal_add_token_bytestring(&err, sess, key, key_len);
     958           0 :                 opal_add_tokens(&err, sess, 3,    /* number of token */
     959             :                                 SPDK_OPAL_ENDNAME,
     960             :                                 SPDK_OPAL_STARTNAME,
     961             :                                 3);/* HostSignAuth */
     962           0 :                 opal_add_token_bytestring(&err, sess, spdk_opal_uid[auth],
     963             :                                           OPAL_UID_LENGTH);
     964           0 :                 opal_add_token_u8(&err, sess, SPDK_OPAL_ENDNAME);
     965           0 :                 opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
     966           0 :                 break;
     967           0 :         default:
     968           0 :                 SPDK_ERRLOG("Cannot start Admin SP session with auth %d\n", auth);
     969           0 :                 return -EINVAL;
     970             :         }
     971             : 
     972           0 :         if (err) {
     973           0 :                 SPDK_ERRLOG("Error building start adminsp session command.\n");
     974           0 :                 return err;
     975             :         }
     976             : 
     977           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
     978           0 :         if (ret) {
     979           0 :                 return ret;
     980             :         }
     981             : 
     982           0 :         ret = opal_send_recv(dev, sess);
     983           0 :         if (ret) {
     984           0 :                 return ret;
     985             :         }
     986             : 
     987           0 :         return opal_start_session_done(sess);
     988             : }
     989             : 
     990             : static int
     991           0 : opal_get_msid_cpin_pin_done(struct opal_session *sess,
     992             :                             struct spdk_opal_key *opal_key)
     993             : {
     994           0 :         const char *msid_pin;
     995             :         size_t strlen;
     996           0 :         int error = 0;
     997             : 
     998           0 :         error = opal_parse_and_check_status(sess);
     999           0 :         if (error) {
    1000           0 :                 return error;
    1001             :         }
    1002             : 
    1003           0 :         strlen = opal_response_get_string(&sess->parsed_resp, 4, &msid_pin);
    1004           0 :         if (!msid_pin) {
    1005           0 :                 SPDK_ERRLOG("Couldn't extract PIN from response\n");
    1006           0 :                 return -EINVAL;
    1007             :         }
    1008             : 
    1009           0 :         opal_key->key_len = strlen;
    1010           0 :         memcpy(opal_key->key, msid_pin, opal_key->key_len);
    1011             : 
    1012           0 :         SPDK_DEBUGLOG(opal, "MSID = %p\n", opal_key->key);
    1013           0 :         return 0;
    1014             : }
    1015             : 
    1016             : static int
    1017           0 : opal_get_msid_cpin_pin(struct spdk_opal_dev *dev, struct opal_session *sess,
    1018             :                        struct spdk_opal_key *opal_key)
    1019             : {
    1020           0 :         int err = 0;
    1021             :         int ret;
    1022             : 
    1023           0 :         opal_clear_cmd(sess);
    1024           0 :         opal_set_comid(sess, dev->comid);
    1025             : 
    1026           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1027           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_C_PIN_MSID],
    1028             :                                   OPAL_UID_LENGTH);
    1029           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
    1030             : 
    1031           0 :         opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
    1032             :                         SPDK_OPAL_STARTLIST,
    1033             :                         SPDK_OPAL_STARTNAME,
    1034             :                         SPDK_OPAL_STARTCOLUMN,
    1035             :                         SPDK_OPAL_PIN,
    1036             :                         SPDK_OPAL_ENDNAME,
    1037             :                         SPDK_OPAL_STARTNAME,
    1038             :                         SPDK_OPAL_ENDCOLUMN,
    1039             :                         SPDK_OPAL_PIN,
    1040             :                         SPDK_OPAL_ENDNAME,
    1041             :                         SPDK_OPAL_ENDLIST,
    1042             :                         SPDK_OPAL_ENDLIST);
    1043             : 
    1044           0 :         if (err) {
    1045           0 :                 SPDK_ERRLOG("Error building Get MSID CPIN PIN command.\n");
    1046           0 :                 return err;
    1047             :         }
    1048             : 
    1049           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1050           0 :         if (ret) {
    1051           0 :                 return ret;
    1052             :         }
    1053             : 
    1054           0 :         ret = opal_send_recv(dev, sess);
    1055           0 :         if (ret) {
    1056           0 :                 return ret;
    1057             :         }
    1058             : 
    1059           0 :         return opal_get_msid_cpin_pin_done(sess, opal_key);
    1060             : }
    1061             : 
    1062             : static int
    1063           0 : opal_build_generic_pw_cmd(struct opal_session *sess, uint8_t *key, size_t key_len,
    1064             :                           uint8_t *cpin_uid, struct spdk_opal_dev *dev)
    1065             : {
    1066           0 :         int err = 0;
    1067             : 
    1068           0 :         opal_clear_cmd(sess);
    1069           0 :         opal_set_comid(sess, dev->comid);
    1070             : 
    1071           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1072           0 :         opal_add_token_bytestring(&err, sess, cpin_uid, OPAL_UID_LENGTH);
    1073           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD],
    1074             :                                   OPAL_UID_LENGTH);
    1075             : 
    1076           0 :         opal_add_tokens(&err, sess, 6,
    1077             :                         SPDK_OPAL_STARTLIST,
    1078             :                         SPDK_OPAL_STARTNAME,
    1079             :                         SPDK_OPAL_VALUES,
    1080             :                         SPDK_OPAL_STARTLIST,
    1081             :                         SPDK_OPAL_STARTNAME,
    1082             :                         SPDK_OPAL_PIN);
    1083           0 :         opal_add_token_bytestring(&err, sess, key, key_len);
    1084           0 :         opal_add_tokens(&err, sess, 4,
    1085             :                         SPDK_OPAL_ENDNAME,
    1086             :                         SPDK_OPAL_ENDLIST,
    1087             :                         SPDK_OPAL_ENDNAME,
    1088             :                         SPDK_OPAL_ENDLIST);
    1089           0 :         if (err) {
    1090           0 :                 return err;
    1091             :         }
    1092             : 
    1093           0 :         return opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1094             : }
    1095             : 
    1096             : static int
    1097           0 : opal_get_locking_sp_lifecycle_done(struct opal_session *sess)
    1098             : {
    1099             :         uint8_t lifecycle;
    1100           0 :         int error = 0;
    1101             : 
    1102           0 :         error = opal_parse_and_check_status(sess);
    1103           0 :         if (error) {
    1104           0 :                 return error;
    1105             :         }
    1106             : 
    1107           0 :         lifecycle = opal_response_get_u64(&sess->parsed_resp, 4);
    1108           0 :         if (lifecycle != OPAL_MANUFACTURED_INACTIVE) { /* status before activate */
    1109           0 :                 SPDK_ERRLOG("Couldn't determine the status of the Lifecycle state\n");
    1110           0 :                 return -EINVAL;
    1111             :         }
    1112             : 
    1113           0 :         return 0;
    1114             : }
    1115             : 
    1116             : static int
    1117           0 : opal_get_locking_sp_lifecycle(struct spdk_opal_dev *dev, struct opal_session *sess)
    1118             : {
    1119           0 :         int err = 0;
    1120             :         int ret;
    1121             : 
    1122           0 :         opal_clear_cmd(sess);
    1123           0 :         opal_set_comid(sess, dev->comid);
    1124             : 
    1125           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1126           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
    1127             :                                   OPAL_UID_LENGTH);
    1128           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
    1129             : 
    1130           0 :         opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
    1131             :                         SPDK_OPAL_STARTLIST,
    1132             :                         SPDK_OPAL_STARTNAME,
    1133             :                         SPDK_OPAL_STARTCOLUMN,
    1134             :                         SPDK_OPAL_LIFECYCLE,
    1135             :                         SPDK_OPAL_ENDNAME,
    1136             :                         SPDK_OPAL_STARTNAME,
    1137             :                         SPDK_OPAL_ENDCOLUMN,
    1138             :                         SPDK_OPAL_LIFECYCLE,
    1139             :                         SPDK_OPAL_ENDNAME,
    1140             :                         SPDK_OPAL_ENDLIST,
    1141             :                         SPDK_OPAL_ENDLIST);
    1142             : 
    1143           0 :         if (err) {
    1144           0 :                 SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
    1145           0 :                 return err;
    1146             :         }
    1147             : 
    1148           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1149           0 :         if (ret) {
    1150           0 :                 return ret;
    1151             :         }
    1152             : 
    1153           0 :         ret = opal_send_recv(dev, sess);
    1154           0 :         if (ret) {
    1155           0 :                 return ret;
    1156             :         }
    1157             : 
    1158           0 :         return opal_get_locking_sp_lifecycle_done(sess);
    1159             : }
    1160             : 
    1161             : static int
    1162           0 : opal_activate(struct spdk_opal_dev *dev, struct opal_session *sess)
    1163             : {
    1164           0 :         int err = 0;
    1165             :         int ret;
    1166             : 
    1167           0 :         opal_clear_cmd(sess);
    1168           0 :         opal_set_comid(sess, dev->comid);
    1169             : 
    1170           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1171           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
    1172             :                                   OPAL_UID_LENGTH);
    1173           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[ACTIVATE_METHOD],
    1174             :                                   OPAL_UID_LENGTH);
    1175             : 
    1176           0 :         opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
    1177             : 
    1178           0 :         if (err) {
    1179           0 :                 SPDK_ERRLOG("Error building Activate LockingSP command.\n");
    1180           0 :                 return err;
    1181             :         }
    1182             : 
    1183             :         /* TODO: Single User Mode for activation */
    1184             : 
    1185           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1186           0 :         if (ret) {
    1187           0 :                 return ret;
    1188             :         }
    1189             : 
    1190           0 :         ret = opal_send_recv(dev, sess);
    1191           0 :         if (ret) {
    1192           0 :                 return ret;
    1193             :         }
    1194             : 
    1195           0 :         return opal_parse_and_check_status(sess);
    1196             : }
    1197             : 
    1198             : static int
    1199           0 : opal_start_auth_session(struct spdk_opal_dev *dev,
    1200             :                         struct opal_session *sess,
    1201             :                         enum spdk_opal_user user,
    1202             :                         struct spdk_opal_key *opal_key)
    1203             : {
    1204           0 :         uint8_t uid_user[OPAL_UID_LENGTH];
    1205           0 :         int err = 0;
    1206             :         int ret;
    1207           0 :         uint32_t hsn = GENERIC_HOST_SESSION_NUM;
    1208             : 
    1209           0 :         opal_clear_cmd(sess);
    1210           0 :         opal_set_comid(sess, dev->comid);
    1211             : 
    1212           0 :         if (user != OPAL_ADMIN1) {
    1213           0 :                 memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
    1214           0 :                 uid_user[7] = user;
    1215             :         } else {
    1216           0 :                 memcpy(uid_user, spdk_opal_uid[UID_ADMIN1], OPAL_UID_LENGTH);
    1217             :         }
    1218             : 
    1219           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1220           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_SMUID],
    1221             :                                   OPAL_UID_LENGTH);
    1222           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[STARTSESSION_METHOD],
    1223             :                                   OPAL_UID_LENGTH);
    1224             : 
    1225           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
    1226           0 :         opal_add_token_u64(&err, sess, hsn);
    1227           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
    1228             :                                   OPAL_UID_LENGTH);
    1229           0 :         opal_add_tokens(&err, sess, 3, SPDK_OPAL_TRUE, SPDK_OPAL_STARTNAME,
    1230             :                         0); /* True for a Read-Write session  */
    1231           0 :         opal_add_token_bytestring(&err, sess, opal_key->key, opal_key->key_len);
    1232           0 :         opal_add_tokens(&err, sess, 3, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME, 3); /* HostSignAuth */
    1233           0 :         opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
    1234           0 :         opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_ENDLIST);
    1235             : 
    1236           0 :         if (err) {
    1237           0 :                 SPDK_ERRLOG("Error building STARTSESSION command.\n");
    1238           0 :                 return err;
    1239             :         }
    1240             : 
    1241           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1242           0 :         if (ret) {
    1243           0 :                 return ret;
    1244             :         }
    1245             : 
    1246           0 :         ret = opal_send_recv(dev, sess);
    1247           0 :         if (ret) {
    1248           0 :                 return ret;
    1249             :         }
    1250             : 
    1251           0 :         return opal_start_session_done(sess);
    1252             : }
    1253             : 
    1254             : static int
    1255           0 : opal_lock_unlock_range(struct spdk_opal_dev *dev, struct opal_session *sess,
    1256             :                        enum spdk_opal_locking_range locking_range,
    1257             :                        enum spdk_opal_lock_state l_state)
    1258             : {
    1259           0 :         uint8_t uid_locking_range[OPAL_UID_LENGTH];
    1260             :         uint8_t read_locked, write_locked;
    1261           0 :         int err = 0;
    1262             :         int ret;
    1263             : 
    1264           0 :         opal_clear_cmd(sess);
    1265           0 :         opal_set_comid(sess, dev->comid);
    1266             : 
    1267           0 :         opal_build_locking_range(uid_locking_range, locking_range);
    1268             : 
    1269           0 :         switch (l_state) {
    1270           0 :         case OPAL_READONLY:
    1271           0 :                 read_locked = 0;
    1272           0 :                 write_locked = 1;
    1273           0 :                 break;
    1274           0 :         case OPAL_READWRITE:
    1275           0 :                 read_locked = 0;
    1276           0 :                 write_locked = 0;
    1277           0 :                 break;
    1278           0 :         case OPAL_RWLOCK:
    1279           0 :                 read_locked = 1;
    1280           0 :                 write_locked = 1;
    1281           0 :                 break;
    1282           0 :         default:
    1283           0 :                 SPDK_ERRLOG("Tried to set an invalid locking state.\n");
    1284           0 :                 return -EINVAL;
    1285             :         }
    1286             : 
    1287           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1288           0 :         opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
    1289           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
    1290             : 
    1291           0 :         opal_add_tokens(&err, sess, 15, SPDK_OPAL_STARTLIST,
    1292             :                         SPDK_OPAL_STARTNAME,
    1293             :                         SPDK_OPAL_VALUES,
    1294             :                         SPDK_OPAL_STARTLIST,
    1295             :                         SPDK_OPAL_STARTNAME,
    1296             :                         SPDK_OPAL_READLOCKED,
    1297             :                         read_locked,
    1298             :                         SPDK_OPAL_ENDNAME,
    1299             :                         SPDK_OPAL_STARTNAME,
    1300             :                         SPDK_OPAL_WRITELOCKED,
    1301             :                         write_locked,
    1302             :                         SPDK_OPAL_ENDNAME,
    1303             :                         SPDK_OPAL_ENDLIST,
    1304             :                         SPDK_OPAL_ENDNAME,
    1305             :                         SPDK_OPAL_ENDLIST);
    1306             : 
    1307           0 :         if (err) {
    1308           0 :                 SPDK_ERRLOG("Error building SET command.\n");
    1309           0 :                 return err;
    1310             :         }
    1311           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1312           0 :         if (ret) {
    1313           0 :                 return ret;
    1314             :         }
    1315             : 
    1316           0 :         ret = opal_send_recv(dev, sess);
    1317           0 :         if (ret) {
    1318           0 :                 return ret;
    1319             :         }
    1320             : 
    1321           0 :         return opal_parse_and_check_status(sess);
    1322             : }
    1323             : 
    1324             : static int
    1325           0 : opal_generic_locking_range_enable_disable(struct spdk_opal_dev *dev,
    1326             :                 struct opal_session *sess,
    1327             :                 uint8_t *uid, bool read_lock_enabled, bool write_lock_enabled)
    1328             : {
    1329           0 :         int err = 0;
    1330             : 
    1331           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1332           0 :         opal_add_token_bytestring(&err, sess, uid, OPAL_UID_LENGTH);
    1333           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
    1334             : 
    1335           0 :         opal_add_tokens(&err, sess, 23, SPDK_OPAL_STARTLIST,
    1336             :                         SPDK_OPAL_STARTNAME,
    1337             :                         SPDK_OPAL_VALUES,
    1338             :                         SPDK_OPAL_STARTLIST,
    1339             : 
    1340             :                         SPDK_OPAL_STARTNAME,
    1341             :                         SPDK_OPAL_READLOCKENABLED,
    1342             :                         read_lock_enabled,
    1343             :                         SPDK_OPAL_ENDNAME,
    1344             : 
    1345             :                         SPDK_OPAL_STARTNAME,
    1346             :                         SPDK_OPAL_WRITELOCKENABLED,
    1347             :                         write_lock_enabled,
    1348             :                         SPDK_OPAL_ENDNAME,
    1349             : 
    1350             :                         SPDK_OPAL_STARTNAME,
    1351             :                         SPDK_OPAL_READLOCKED,
    1352             :                         0,
    1353             :                         SPDK_OPAL_ENDNAME,
    1354             : 
    1355             :                         SPDK_OPAL_STARTNAME,
    1356             :                         SPDK_OPAL_WRITELOCKED,
    1357             :                         0,
    1358             :                         SPDK_OPAL_ENDNAME,
    1359             : 
    1360             :                         SPDK_OPAL_ENDLIST,
    1361             :                         SPDK_OPAL_ENDNAME,
    1362             :                         SPDK_OPAL_ENDLIST);
    1363           0 :         if (err) {
    1364           0 :                 SPDK_ERRLOG("Error building locking range enable/disable command.\n");
    1365             :         }
    1366           0 :         return err;
    1367             : }
    1368             : 
    1369             : static int
    1370           0 : opal_setup_locking_range(struct spdk_opal_dev *dev, struct opal_session *sess,
    1371             :                          enum spdk_opal_locking_range locking_range,
    1372             :                          uint64_t range_start, uint64_t range_length,
    1373             :                          bool read_lock_enabled, bool write_lock_enabled)
    1374             : {
    1375           0 :         uint8_t uid_locking_range[OPAL_UID_LENGTH];
    1376           0 :         int err = 0;
    1377             :         int ret;
    1378             : 
    1379           0 :         opal_clear_cmd(sess);
    1380           0 :         opal_set_comid(sess, dev->comid);
    1381             : 
    1382           0 :         opal_build_locking_range(uid_locking_range, locking_range);
    1383             : 
    1384           0 :         if (locking_range == 0) {
    1385           0 :                 err = opal_generic_locking_range_enable_disable(dev, sess, uid_locking_range,
    1386             :                                 read_lock_enabled, write_lock_enabled);
    1387             :         } else {
    1388           0 :                 opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1389           0 :                 opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
    1390           0 :                 opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD],
    1391             :                                           OPAL_UID_LENGTH);
    1392             : 
    1393           0 :                 opal_add_tokens(&err, sess, 6,
    1394             :                                 SPDK_OPAL_STARTLIST,
    1395             :                                 SPDK_OPAL_STARTNAME,
    1396             :                                 SPDK_OPAL_VALUES,
    1397             :                                 SPDK_OPAL_STARTLIST,
    1398             :                                 SPDK_OPAL_STARTNAME,
    1399             :                                 SPDK_OPAL_RANGESTART);
    1400           0 :                 opal_add_token_u64(&err, sess, range_start);
    1401           0 :                 opal_add_tokens(&err, sess, 3,
    1402             :                                 SPDK_OPAL_ENDNAME,
    1403             :                                 SPDK_OPAL_STARTNAME,
    1404             :                                 SPDK_OPAL_RANGELENGTH);
    1405           0 :                 opal_add_token_u64(&err, sess, range_length);
    1406           0 :                 opal_add_tokens(&err, sess, 3,
    1407             :                                 SPDK_OPAL_ENDNAME,
    1408             :                                 SPDK_OPAL_STARTNAME,
    1409             :                                 SPDK_OPAL_READLOCKENABLED);
    1410           0 :                 opal_add_token_u64(&err, sess, read_lock_enabled);
    1411           0 :                 opal_add_tokens(&err, sess, 3,
    1412             :                                 SPDK_OPAL_ENDNAME,
    1413             :                                 SPDK_OPAL_STARTNAME,
    1414             :                                 SPDK_OPAL_WRITELOCKENABLED);
    1415           0 :                 opal_add_token_u64(&err, sess, write_lock_enabled);
    1416           0 :                 opal_add_tokens(&err, sess, 4,
    1417             :                                 SPDK_OPAL_ENDNAME,
    1418             :                                 SPDK_OPAL_ENDLIST,
    1419             :                                 SPDK_OPAL_ENDNAME,
    1420             :                                 SPDK_OPAL_ENDLIST);
    1421             :         }
    1422           0 :         if (err) {
    1423           0 :                 SPDK_ERRLOG("Error building Setup Locking range command.\n");
    1424           0 :                 return err;
    1425             : 
    1426             :         }
    1427             : 
    1428           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1429           0 :         if (ret) {
    1430           0 :                 return ret;
    1431             :         }
    1432             : 
    1433           0 :         ret = opal_send_recv(dev, sess);
    1434           0 :         if (ret) {
    1435           0 :                 return ret;
    1436             :         }
    1437             : 
    1438           0 :         return opal_parse_and_check_status(sess);
    1439             : }
    1440             : 
    1441             : static int
    1442           0 : opal_get_max_ranges_done(struct opal_session *sess)
    1443             : {
    1444           0 :         int error = 0;
    1445             : 
    1446           0 :         error = opal_parse_and_check_status(sess);
    1447           0 :         if (error) {
    1448           0 :                 return error;
    1449             :         }
    1450             : 
    1451             :         /* "MaxRanges" is token 4 of response */
    1452           0 :         return opal_response_get_u16(&sess->parsed_resp, 4);
    1453             : }
    1454             : 
    1455             : static int
    1456           0 : opal_get_max_ranges(struct spdk_opal_dev *dev, struct opal_session *sess)
    1457             : {
    1458           0 :         int err = 0;
    1459             :         int ret;
    1460             : 
    1461           0 :         opal_clear_cmd(sess);
    1462           0 :         opal_set_comid(sess, dev->comid);
    1463             : 
    1464           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1465           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKING_INFO_TABLE],
    1466             :                                   OPAL_UID_LENGTH);
    1467           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
    1468             : 
    1469           0 :         opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
    1470             :                         SPDK_OPAL_STARTLIST,
    1471             :                         SPDK_OPAL_STARTNAME,
    1472             :                         SPDK_OPAL_STARTCOLUMN,
    1473             :                         SPDK_OPAL_MAXRANGES,
    1474             :                         SPDK_OPAL_ENDNAME,
    1475             :                         SPDK_OPAL_STARTNAME,
    1476             :                         SPDK_OPAL_ENDCOLUMN,
    1477             :                         SPDK_OPAL_MAXRANGES,
    1478             :                         SPDK_OPAL_ENDNAME,
    1479             :                         SPDK_OPAL_ENDLIST,
    1480             :                         SPDK_OPAL_ENDLIST);
    1481             : 
    1482           0 :         if (err) {
    1483           0 :                 SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
    1484           0 :                 return err;
    1485             :         }
    1486             : 
    1487           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1488           0 :         if (ret) {
    1489           0 :                 return ret;
    1490             :         }
    1491             : 
    1492           0 :         ret = opal_send_recv(dev, sess);
    1493           0 :         if (ret) {
    1494           0 :                 return ret;
    1495             :         }
    1496             : 
    1497           0 :         return opal_get_max_ranges_done(sess);
    1498             : }
    1499             : 
    1500             : static int
    1501           0 : opal_get_locking_range_info_done(struct opal_session *sess,
    1502             :                                  struct spdk_opal_locking_range_info *info)
    1503             : {
    1504           0 :         int error = 0;
    1505             : 
    1506           0 :         error = opal_parse_and_check_status(sess);
    1507           0 :         if (error) {
    1508           0 :                 return error;
    1509             :         }
    1510             : 
    1511           0 :         info->range_start = opal_response_get_u64(&sess->parsed_resp, 4);
    1512           0 :         info->range_length = opal_response_get_u64(&sess->parsed_resp, 8);
    1513           0 :         info->read_lock_enabled = opal_response_get_u8(&sess->parsed_resp, 12);
    1514           0 :         info->write_lock_enabled = opal_response_get_u8(&sess->parsed_resp, 16);
    1515           0 :         info->read_locked = opal_response_get_u8(&sess->parsed_resp, 20);
    1516           0 :         info->write_locked = opal_response_get_u8(&sess->parsed_resp, 24);
    1517             : 
    1518           0 :         return 0;
    1519             : }
    1520             : 
    1521             : static int
    1522           0 : opal_get_locking_range_info(struct spdk_opal_dev *dev,
    1523             :                             struct opal_session *sess,
    1524             :                             enum spdk_opal_locking_range locking_range_id)
    1525             : {
    1526           0 :         int err = 0;
    1527             :         int ret;
    1528           0 :         uint8_t uid_locking_range[OPAL_UID_LENGTH];
    1529             :         struct spdk_opal_locking_range_info *info;
    1530             : 
    1531           0 :         opal_build_locking_range(uid_locking_range, locking_range_id);
    1532             : 
    1533           0 :         assert(locking_range_id < SPDK_OPAL_MAX_LOCKING_RANGE);
    1534           0 :         info = &dev->locking_ranges[locking_range_id];
    1535           0 :         memset(info, 0, sizeof(*info));
    1536           0 :         info->locking_range_id = locking_range_id;
    1537             : 
    1538           0 :         opal_clear_cmd(sess);
    1539           0 :         opal_set_comid(sess, dev->comid);
    1540             : 
    1541           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1542           0 :         opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
    1543           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
    1544             : 
    1545             : 
    1546           0 :         opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
    1547             :                         SPDK_OPAL_STARTLIST,
    1548             :                         SPDK_OPAL_STARTNAME,
    1549             :                         SPDK_OPAL_STARTCOLUMN,
    1550             :                         SPDK_OPAL_RANGESTART,
    1551             :                         SPDK_OPAL_ENDNAME,
    1552             :                         SPDK_OPAL_STARTNAME,
    1553             :                         SPDK_OPAL_ENDCOLUMN,
    1554             :                         SPDK_OPAL_WRITELOCKED,
    1555             :                         SPDK_OPAL_ENDNAME,
    1556             :                         SPDK_OPAL_ENDLIST,
    1557             :                         SPDK_OPAL_ENDLIST);
    1558             : 
    1559           0 :         if (err) {
    1560           0 :                 SPDK_ERRLOG("Error Building get locking range info command\n");
    1561           0 :                 return err;
    1562             :         }
    1563             : 
    1564           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1565           0 :         if (ret) {
    1566           0 :                 return ret;
    1567             :         }
    1568             : 
    1569           0 :         ret = opal_send_recv(dev, sess);
    1570           0 :         if (ret) {
    1571           0 :                 return ret;
    1572             :         }
    1573             : 
    1574           0 :         return opal_get_locking_range_info_done(sess, info);
    1575             : }
    1576             : 
    1577             : static int
    1578           0 : opal_enable_user(struct spdk_opal_dev *dev, struct opal_session *sess,
    1579             :                  enum spdk_opal_user user)
    1580             : {
    1581           0 :         int err = 0;
    1582             :         int ret;
    1583           0 :         uint8_t uid_user[OPAL_UID_LENGTH];
    1584             : 
    1585           0 :         memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
    1586           0 :         uid_user[7] = user;
    1587             : 
    1588           0 :         opal_clear_cmd(sess);
    1589           0 :         opal_set_comid(sess, dev->comid);
    1590             : 
    1591           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1592           0 :         opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
    1593           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
    1594             : 
    1595           0 :         opal_add_tokens(&err, sess, 11,
    1596             :                         SPDK_OPAL_STARTLIST,
    1597             :                         SPDK_OPAL_STARTNAME,
    1598             :                         SPDK_OPAL_VALUES,
    1599             :                         SPDK_OPAL_STARTLIST,
    1600             :                         SPDK_OPAL_STARTNAME,
    1601             :                         SPDK_OPAL_AUTH_ENABLE,
    1602             :                         SPDK_OPAL_TRUE,
    1603             :                         SPDK_OPAL_ENDNAME,
    1604             :                         SPDK_OPAL_ENDLIST,
    1605             :                         SPDK_OPAL_ENDNAME,
    1606             :                         SPDK_OPAL_ENDLIST);
    1607             : 
    1608           0 :         if (err) {
    1609           0 :                 SPDK_ERRLOG("Error Building enable user command\n");
    1610           0 :                 return err;
    1611             :         }
    1612             : 
    1613           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1614           0 :         if (ret) {
    1615           0 :                 return ret;
    1616             :         }
    1617             : 
    1618           0 :         ret = opal_send_recv(dev, sess);
    1619           0 :         if (ret) {
    1620           0 :                 return ret;
    1621             :         }
    1622             : 
    1623           0 :         return opal_parse_and_check_status(sess);
    1624             : }
    1625             : 
    1626             : static int
    1627           0 : opal_add_user_to_locking_range(struct spdk_opal_dev *dev,
    1628             :                                struct opal_session *sess,
    1629             :                                enum spdk_opal_user user,
    1630             :                                enum spdk_opal_locking_range locking_range,
    1631             :                                enum spdk_opal_lock_state l_state)
    1632             : {
    1633           0 :         int err = 0;
    1634             :         int ret;
    1635           0 :         uint8_t uid_user[OPAL_UID_LENGTH];
    1636           0 :         uint8_t uid_locking_range[OPAL_UID_LENGTH];
    1637             : 
    1638           0 :         memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
    1639           0 :         uid_user[7] = user;
    1640             : 
    1641           0 :         switch (l_state) {
    1642           0 :         case OPAL_READONLY:
    1643           0 :                 memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_RDLOCKED], OPAL_UID_LENGTH);
    1644           0 :                 break;
    1645           0 :         case OPAL_READWRITE:
    1646           0 :                 memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_WRLOCKED], OPAL_UID_LENGTH);
    1647           0 :                 break;
    1648           0 :         default:
    1649           0 :                 SPDK_ERRLOG("locking state should only be OPAL_READONLY or OPAL_READWRITE\n");
    1650           0 :                 return -EINVAL;
    1651             :         }
    1652             : 
    1653           0 :         uid_locking_range[7] = locking_range;
    1654             : 
    1655           0 :         opal_clear_cmd(sess);
    1656           0 :         opal_set_comid(sess, dev->comid);
    1657             : 
    1658           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1659           0 :         opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
    1660           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
    1661             : 
    1662           0 :         opal_add_tokens(&err, sess, 8,
    1663             :                         SPDK_OPAL_STARTLIST,
    1664             :                         SPDK_OPAL_STARTNAME,
    1665             :                         SPDK_OPAL_VALUES,
    1666             :                         SPDK_OPAL_STARTLIST,
    1667             :                         SPDK_OPAL_STARTNAME,
    1668             :                         SPDK_OPAL_BOOLEAN_EXPR,
    1669             :                         SPDK_OPAL_STARTLIST,
    1670             :                         SPDK_OPAL_STARTNAME);
    1671           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
    1672             :                                   OPAL_UID_LENGTH / 2);
    1673           0 :         opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
    1674             : 
    1675           0 :         opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
    1676           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
    1677             :                                   OPAL_UID_LENGTH / 2);
    1678           0 :         opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
    1679             : 
    1680           0 :         opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
    1681           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_BOOLEAN_ACE], OPAL_UID_LENGTH / 2);
    1682           0 :         opal_add_tokens(&err, sess, 7,
    1683             :                         SPDK_OPAL_TRUE,
    1684             :                         SPDK_OPAL_ENDNAME,
    1685             :                         SPDK_OPAL_ENDLIST,
    1686             :                         SPDK_OPAL_ENDNAME,
    1687             :                         SPDK_OPAL_ENDLIST,
    1688             :                         SPDK_OPAL_ENDNAME,
    1689             :                         SPDK_OPAL_ENDLIST);
    1690           0 :         if (err) {
    1691           0 :                 SPDK_ERRLOG("Error building add user to locking range command\n");
    1692           0 :                 return err;
    1693             :         }
    1694             : 
    1695           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1696           0 :         if (ret) {
    1697           0 :                 return ret;
    1698             :         }
    1699             : 
    1700           0 :         ret = opal_send_recv(dev, sess);
    1701           0 :         if (ret) {
    1702           0 :                 return ret;
    1703             :         }
    1704             : 
    1705           0 :         return opal_parse_and_check_status(sess);
    1706             : }
    1707             : 
    1708             : static int
    1709           0 : opal_new_user_passwd(struct spdk_opal_dev *dev, struct opal_session *sess,
    1710             :                      enum spdk_opal_user user,
    1711             :                      struct spdk_opal_key *opal_key)
    1712             : {
    1713           0 :         uint8_t uid_cpin[OPAL_UID_LENGTH];
    1714             :         int ret;
    1715             : 
    1716           0 :         if (user == OPAL_ADMIN1) {
    1717           0 :                 memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_ADMIN1], OPAL_UID_LENGTH);
    1718             :         } else {
    1719           0 :                 memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_USER1], OPAL_UID_LENGTH);
    1720           0 :                 uid_cpin[7] = user;
    1721             :         }
    1722             : 
    1723           0 :         ret = opal_build_generic_pw_cmd(sess, opal_key->key, opal_key->key_len, uid_cpin, dev);
    1724           0 :         if (ret != 0) {
    1725           0 :                 SPDK_ERRLOG("Error building set password command\n");
    1726           0 :                 return ret;
    1727             :         }
    1728             : 
    1729           0 :         ret = opal_send_recv(dev, sess);
    1730           0 :         if (ret) {
    1731           0 :                 return ret;
    1732             :         }
    1733             : 
    1734           0 :         return opal_parse_and_check_status(sess);
    1735             : }
    1736             : 
    1737             : static int
    1738           0 : opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, struct opal_session *sess, char *new_passwd)
    1739             : {
    1740           0 :         uint8_t cpin_uid[OPAL_UID_LENGTH];
    1741           0 :         struct spdk_opal_key opal_key = {};
    1742             :         int ret;
    1743             : 
    1744           0 :         ret = opal_init_key(&opal_key, new_passwd);
    1745           0 :         if (ret != 0) {
    1746           0 :                 return ret;
    1747             :         }
    1748             : 
    1749           0 :         memcpy(cpin_uid, spdk_opal_uid[UID_C_PIN_SID], OPAL_UID_LENGTH);
    1750             : 
    1751           0 :         if (opal_build_generic_pw_cmd(sess, opal_key.key, opal_key.key_len, cpin_uid, dev)) {
    1752           0 :                 SPDK_ERRLOG("Error building Set SID cpin\n");
    1753           0 :                 return -ERANGE;
    1754             :         }
    1755             : 
    1756           0 :         ret = opal_send_recv(dev, sess);
    1757           0 :         if (ret) {
    1758           0 :                 return ret;
    1759             :         }
    1760             : 
    1761           0 :         return opal_parse_and_check_status(sess);
    1762             : }
    1763             : 
    1764             : int
    1765           0 : spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd)
    1766             : {
    1767             :         int ret;
    1768           0 :         struct spdk_opal_key opal_key = {};
    1769             :         struct opal_session *sess;
    1770             : 
    1771           0 :         assert(dev != NULL);
    1772             : 
    1773           0 :         sess = opal_alloc_session(dev);
    1774           0 :         if (!sess) {
    1775           0 :                 return -ENOMEM;
    1776             :         }
    1777             : 
    1778           0 :         ret = opal_start_generic_session(dev, sess, UID_ANYBODY, UID_ADMINSP, NULL, 0);
    1779           0 :         if (ret) {
    1780           0 :                 SPDK_ERRLOG("start admin SP session error %d\n", ret);
    1781           0 :                 goto end;
    1782             :         }
    1783             : 
    1784           0 :         ret = opal_get_msid_cpin_pin(dev, sess, &opal_key);
    1785           0 :         if (ret) {
    1786           0 :                 SPDK_ERRLOG("get msid error %d\n", ret);
    1787           0 :                 opal_end_session(dev, sess, dev->comid);
    1788           0 :                 goto end;
    1789             :         }
    1790             : 
    1791           0 :         ret = opal_end_session(dev, sess, dev->comid);
    1792           0 :         if (ret) {
    1793           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    1794           0 :                 goto end;
    1795             :         }
    1796             : 
    1797             :         /* reuse the session structure */
    1798           0 :         memset(sess, 0, sizeof(*sess));
    1799           0 :         sess->dev = dev;
    1800           0 :         ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
    1801           0 :                                          opal_key.key, opal_key.key_len);
    1802           0 :         if (ret) {
    1803           0 :                 SPDK_ERRLOG("start admin SP session error %d\n", ret);
    1804           0 :                 goto end;
    1805             :         }
    1806           0 :         memset(&opal_key, 0, sizeof(struct spdk_opal_key));
    1807             : 
    1808           0 :         ret = opal_set_sid_cpin_pin(dev, sess, new_passwd);
    1809           0 :         if (ret) {
    1810           0 :                 SPDK_ERRLOG("set cpin error %d\n", ret);
    1811           0 :                 opal_end_session(dev, sess, dev->comid);
    1812           0 :                 goto end;
    1813             :         }
    1814             : 
    1815           0 :         ret = opal_end_session(dev, sess, dev->comid);
    1816           0 :         if (ret) {
    1817           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    1818             :         }
    1819             : 
    1820           0 : end:
    1821           0 :         free(sess);
    1822           0 :         return ret;
    1823             : }
    1824             : 
    1825             : struct spdk_opal_dev *
    1826           0 :         spdk_opal_dev_construct(struct spdk_nvme_ctrlr *ctrlr)
    1827             : {
    1828             :         struct spdk_opal_dev *dev;
    1829             :         void *payload;
    1830             : 
    1831           0 :         dev = calloc(1, sizeof(*dev));
    1832           0 :         if (!dev) {
    1833           0 :                 SPDK_ERRLOG("Memory allocation failed\n");
    1834           0 :                 return NULL;
    1835             :         }
    1836             : 
    1837           0 :         dev->ctrlr = ctrlr;
    1838             : 
    1839           0 :         payload = calloc(1, IO_BUFFER_LENGTH);
    1840           0 :         if (!payload) {
    1841           0 :                 free(dev);
    1842           0 :                 return NULL;
    1843             :         }
    1844             : 
    1845           0 :         if (opal_discovery0(dev, payload, IO_BUFFER_LENGTH)) {
    1846           0 :                 SPDK_INFOLOG(opal, "Opal is not supported on this device\n");
    1847           0 :                 free(dev);
    1848           0 :                 free(payload);
    1849           0 :                 return NULL;
    1850             :         }
    1851             : 
    1852           0 :         free(payload);
    1853           0 :         return dev;
    1854             : }
    1855             : 
    1856             : static int
    1857           0 : opal_build_revert_tper_cmd(struct spdk_opal_dev *dev, struct opal_session *sess)
    1858             : {
    1859           0 :         int err = 0;
    1860             : 
    1861           0 :         opal_clear_cmd(sess);
    1862           0 :         opal_set_comid(sess, dev->comid);
    1863             : 
    1864           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1865           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_ADMINSP],
    1866             :                                   OPAL_UID_LENGTH);
    1867           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[REVERT_METHOD],
    1868             :                                   OPAL_UID_LENGTH);
    1869           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
    1870           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
    1871           0 :         if (err) {
    1872           0 :                 SPDK_ERRLOG("Error building REVERT TPER command.\n");
    1873           0 :                 return -ERANGE;
    1874             :         }
    1875             : 
    1876           0 :         return opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1877             : }
    1878             : 
    1879             : static int
    1880           0 : opal_gen_new_active_key(struct spdk_opal_dev *dev, struct opal_session *sess,
    1881             :                         struct spdk_opal_key *active_key)
    1882             : {
    1883           0 :         uint8_t uid_data[OPAL_UID_LENGTH] = {0};
    1884           0 :         int err = 0;
    1885             :         int length;
    1886             :         int ret;
    1887             : 
    1888           0 :         opal_clear_cmd(sess);
    1889           0 :         opal_set_comid(sess, dev->comid);
    1890             : 
    1891           0 :         if (active_key->key_len == 0) {
    1892           0 :                 SPDK_ERRLOG("Error finding previous data to generate new active key\n");
    1893           0 :                 return -EINVAL;
    1894             :         }
    1895             : 
    1896           0 :         length = spdk_min(active_key->key_len, OPAL_UID_LENGTH);
    1897           0 :         memcpy(uid_data, active_key->key, length);
    1898             : 
    1899           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1900           0 :         opal_add_token_bytestring(&err, sess, uid_data, OPAL_UID_LENGTH);
    1901           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[GENKEY_METHOD],
    1902             :                                   OPAL_UID_LENGTH);
    1903             : 
    1904           0 :         opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
    1905             : 
    1906           0 :         if (err) {
    1907           0 :                 SPDK_ERRLOG("Error building new key generation command.\n");
    1908           0 :                 return err;
    1909             :         }
    1910             : 
    1911           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1912           0 :         if (ret) {
    1913           0 :                 return ret;
    1914             :         }
    1915             : 
    1916           0 :         ret = opal_send_recv(dev, sess);
    1917           0 :         if (ret) {
    1918           0 :                 return ret;
    1919             :         }
    1920             : 
    1921           0 :         return opal_parse_and_check_status(sess);
    1922             : }
    1923             : 
    1924             : static int
    1925           0 : opal_get_active_key_done(struct opal_session *sess, struct spdk_opal_key *active_key)
    1926             : {
    1927           0 :         const char *key;
    1928             :         size_t str_len;
    1929           0 :         int error = 0;
    1930             : 
    1931           0 :         error = opal_parse_and_check_status(sess);
    1932           0 :         if (error) {
    1933           0 :                 return error;
    1934             :         }
    1935             : 
    1936           0 :         str_len = opal_response_get_string(&sess->parsed_resp, 4, &key);
    1937           0 :         if (!key) {
    1938           0 :                 SPDK_ERRLOG("Couldn't extract active key from response\n");
    1939           0 :                 return -EINVAL;
    1940             :         }
    1941             : 
    1942           0 :         active_key->key_len = str_len;
    1943           0 :         memcpy(active_key->key, key, active_key->key_len);
    1944             : 
    1945           0 :         SPDK_DEBUGLOG(opal, "active key = %p\n", active_key->key);
    1946           0 :         return 0;
    1947             : }
    1948             : 
    1949             : static int
    1950           0 : opal_get_active_key(struct spdk_opal_dev *dev, struct opal_session *sess,
    1951             :                     enum spdk_opal_locking_range locking_range,
    1952             :                     struct spdk_opal_key *active_key)
    1953             : {
    1954           0 :         uint8_t uid_locking_range[OPAL_UID_LENGTH];
    1955           0 :         int err = 0;
    1956             :         int ret;
    1957             : 
    1958           0 :         opal_clear_cmd(sess);
    1959           0 :         opal_set_comid(sess, dev->comid);
    1960             : 
    1961           0 :         opal_build_locking_range(uid_locking_range, locking_range);
    1962             : 
    1963           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    1964           0 :         opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
    1965           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD],
    1966             :                                   OPAL_UID_LENGTH);
    1967           0 :         opal_add_tokens(&err, sess, 12,
    1968             :                         SPDK_OPAL_STARTLIST,
    1969             :                         SPDK_OPAL_STARTLIST,
    1970             :                         SPDK_OPAL_STARTNAME,
    1971             :                         SPDK_OPAL_STARTCOLUMN,
    1972             :                         SPDK_OPAL_ACTIVEKEY,
    1973             :                         SPDK_OPAL_ENDNAME,
    1974             :                         SPDK_OPAL_STARTNAME,
    1975             :                         SPDK_OPAL_ENDCOLUMN,
    1976             :                         SPDK_OPAL_ACTIVEKEY,
    1977             :                         SPDK_OPAL_ENDNAME,
    1978             :                         SPDK_OPAL_ENDLIST,
    1979             :                         SPDK_OPAL_ENDLIST);
    1980             : 
    1981           0 :         if (err) {
    1982           0 :                 SPDK_ERRLOG("Error building get active key command.\n");
    1983           0 :                 return err;
    1984             :         }
    1985             : 
    1986           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    1987           0 :         if (ret) {
    1988           0 :                 return ret;
    1989             :         }
    1990             : 
    1991           0 :         ret = opal_send_recv(dev, sess);
    1992           0 :         if (ret) {
    1993           0 :                 return ret;
    1994             :         }
    1995             : 
    1996           0 :         return opal_get_active_key_done(sess, active_key);
    1997             : }
    1998             : 
    1999             : static int
    2000           0 : opal_erase_locking_range(struct spdk_opal_dev *dev, struct opal_session *sess,
    2001             :                          enum spdk_opal_locking_range locking_range)
    2002             : {
    2003           0 :         uint8_t uid_locking_range[OPAL_UID_LENGTH];
    2004           0 :         int err = 0;
    2005             :         int ret;
    2006             : 
    2007           0 :         opal_clear_cmd(sess);
    2008           0 :         opal_set_comid(sess, dev->comid);
    2009             : 
    2010           0 :         opal_build_locking_range(uid_locking_range, locking_range);
    2011             : 
    2012           0 :         opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
    2013           0 :         opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
    2014           0 :         opal_add_token_bytestring(&err, sess, spdk_opal_method[ERASE_METHOD],
    2015             :                                   OPAL_UID_LENGTH);
    2016           0 :         opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
    2017             : 
    2018           0 :         if (err) {
    2019           0 :                 SPDK_ERRLOG("Error building erase locking range.\n");
    2020           0 :                 return err;
    2021             :         }
    2022             : 
    2023           0 :         ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
    2024           0 :         if (ret) {
    2025           0 :                 return ret;
    2026             :         }
    2027             : 
    2028           0 :         ret = opal_send_recv(dev, sess);
    2029           0 :         if (ret) {
    2030           0 :                 return ret;
    2031             :         }
    2032             : 
    2033           0 :         return opal_parse_and_check_status(sess);
    2034             : }
    2035             : 
    2036             : int
    2037           0 : spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
    2038             : {
    2039             :         int ret;
    2040             :         struct opal_session *sess;
    2041           0 :         struct spdk_opal_key opal_key = {};
    2042             : 
    2043           0 :         assert(dev != NULL);
    2044             : 
    2045           0 :         ret = opal_init_key(&opal_key, passwd);
    2046           0 :         if (ret) {
    2047           0 :                 SPDK_ERRLOG("Init key failed\n");
    2048           0 :                 return ret;
    2049             :         }
    2050             : 
    2051           0 :         sess = opal_alloc_session(dev);
    2052           0 :         if (!sess) {
    2053           0 :                 return -ENOMEM;
    2054             :         }
    2055             : 
    2056           0 :         ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
    2057           0 :                                          opal_key.key, opal_key.key_len);
    2058           0 :         if (ret) {
    2059           0 :                 SPDK_ERRLOG("Error on starting admin SP session with error %d\n", ret);
    2060           0 :                 free(sess);
    2061           0 :                 return ret;
    2062             :         }
    2063             : 
    2064           0 :         ret = opal_build_revert_tper_cmd(dev, sess);
    2065           0 :         if (ret) {
    2066           0 :                 opal_end_session(dev, sess, dev->comid);
    2067           0 :                 SPDK_ERRLOG("Build revert tper command with error %d\n", ret);
    2068           0 :                 goto end;
    2069             :         }
    2070             : 
    2071           0 :         ret = opal_send_recv(dev, sess);
    2072           0 :         if (ret) {
    2073           0 :                 opal_end_session(dev, sess, dev->comid);
    2074           0 :                 SPDK_ERRLOG("Error on reverting TPer with error %d\n", ret);
    2075           0 :                 goto end;
    2076             :         }
    2077             : 
    2078           0 :         ret = opal_parse_and_check_status(sess);
    2079           0 :         if (ret) {
    2080           0 :                 opal_end_session(dev, sess, dev->comid);
    2081           0 :                 SPDK_ERRLOG("Error on reverting TPer with error %d\n", ret);
    2082             :         }
    2083             :         /* No opal_end_session() required here for successful case */
    2084             : 
    2085           0 : end:
    2086           0 :         free(sess);
    2087           0 :         return ret;
    2088             : }
    2089             : 
    2090             : int
    2091           0 : spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd)
    2092             : {
    2093             :         struct opal_session *sess;
    2094           0 :         struct spdk_opal_key opal_key = {};
    2095             :         int ret;
    2096             : 
    2097           0 :         ret = opal_init_key(&opal_key, passwd);
    2098           0 :         if (ret != 0) {
    2099           0 :                 return ret;
    2100             :         }
    2101             : 
    2102           0 :         sess = opal_alloc_session(dev);
    2103           0 :         if (!sess) {
    2104           0 :                 return -ENOMEM;
    2105             :         }
    2106             : 
    2107           0 :         ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
    2108           0 :                                          opal_key.key, opal_key.key_len);
    2109           0 :         if (ret) {
    2110           0 :                 SPDK_ERRLOG("Error on starting admin SP session with error %d\n", ret);
    2111           0 :                 free(sess);
    2112           0 :                 return ret;
    2113             :         }
    2114             : 
    2115           0 :         ret = opal_get_locking_sp_lifecycle(dev, sess);
    2116           0 :         if (ret) {
    2117           0 :                 SPDK_ERRLOG("Error on getting SP lifecycle with error %d\n", ret);
    2118           0 :                 goto end;
    2119             :         }
    2120             : 
    2121           0 :         ret = opal_activate(dev, sess);
    2122           0 :         if (ret) {
    2123           0 :                 SPDK_ERRLOG("Error on activation with error %d\n", ret);
    2124             :         }
    2125             : 
    2126           0 : end:
    2127           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2128           0 :         if (ret) {
    2129           0 :                 SPDK_ERRLOG("Error on ending session with error %d\n", ret);
    2130             :         }
    2131             : 
    2132           0 :         free(sess);
    2133           0 :         return ret;
    2134             : }
    2135             : 
    2136             : int
    2137           0 : spdk_opal_cmd_lock_unlock(struct spdk_opal_dev *dev, enum spdk_opal_user user,
    2138             :                           enum spdk_opal_lock_state flag, enum spdk_opal_locking_range locking_range,
    2139             :                           const char *passwd)
    2140             : {
    2141             :         struct opal_session *sess;
    2142           0 :         struct spdk_opal_key opal_key = {};
    2143             :         int ret;
    2144             : 
    2145           0 :         assert(dev != NULL);
    2146             : 
    2147           0 :         ret = opal_init_key(&opal_key, passwd);
    2148           0 :         if (ret != 0) {
    2149           0 :                 return ret;
    2150             :         }
    2151             : 
    2152           0 :         sess = opal_alloc_session(dev);
    2153           0 :         if (!sess) {
    2154           0 :                 return -ENOMEM;
    2155             :         }
    2156             : 
    2157           0 :         ret = opal_start_auth_session(dev, sess, user, &opal_key);
    2158           0 :         if (ret) {
    2159           0 :                 SPDK_ERRLOG("start authenticate session error %d\n", ret);
    2160           0 :                 free(sess);
    2161           0 :                 return ret;
    2162             :         }
    2163             : 
    2164           0 :         ret = opal_lock_unlock_range(dev, sess, locking_range, flag);
    2165           0 :         if (ret) {
    2166           0 :                 SPDK_ERRLOG("lock unlock range error %d\n", ret);
    2167             :         }
    2168             : 
    2169           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2170           0 :         if (ret) {
    2171           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2172             :         }
    2173             : 
    2174           0 :         free(sess);
    2175           0 :         return ret;
    2176             : }
    2177             : 
    2178             : int
    2179           0 : spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user,
    2180             :                                   enum spdk_opal_locking_range locking_range_id, uint64_t range_start,
    2181             :                                   uint64_t range_length, const char *passwd)
    2182             : {
    2183             :         struct opal_session *sess;
    2184           0 :         struct spdk_opal_key opal_key = {};
    2185             :         int ret;
    2186             : 
    2187           0 :         assert(dev != NULL);
    2188             : 
    2189           0 :         ret = opal_init_key(&opal_key, passwd);
    2190           0 :         if (ret != 0) {
    2191           0 :                 return ret;
    2192             :         }
    2193             : 
    2194           0 :         sess = opal_alloc_session(dev);
    2195           0 :         if (!sess) {
    2196           0 :                 return -ENOMEM;
    2197             :         }
    2198             : 
    2199           0 :         ret = opal_start_auth_session(dev, sess, user, &opal_key);
    2200           0 :         if (ret) {
    2201           0 :                 SPDK_ERRLOG("start authenticate session error %d\n", ret);
    2202           0 :                 free(sess);
    2203           0 :                 return ret;
    2204             :         }
    2205             : 
    2206           0 :         ret = opal_setup_locking_range(dev, sess, locking_range_id, range_start, range_length, true,
    2207             :                                        true);
    2208           0 :         if (ret) {
    2209           0 :                 SPDK_ERRLOG("setup locking range error %d\n", ret);
    2210             :         }
    2211             : 
    2212           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2213           0 :         if (ret) {
    2214           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2215             :         }
    2216             : 
    2217           0 :         free(sess);
    2218           0 :         return ret;
    2219             : }
    2220             : 
    2221             : int
    2222           0 : spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd)
    2223             : {
    2224             :         struct opal_session *sess;
    2225           0 :         struct spdk_opal_key opal_key = {};
    2226             :         int ret;
    2227             : 
    2228           0 :         assert(dev != NULL);
    2229             : 
    2230           0 :         if (dev->max_ranges) {
    2231           0 :                 return dev->max_ranges;
    2232             :         }
    2233             : 
    2234           0 :         ret = opal_init_key(&opal_key, passwd);
    2235           0 :         if (ret != 0) {
    2236           0 :                 return ret;
    2237             :         }
    2238             : 
    2239           0 :         sess = opal_alloc_session(dev);
    2240           0 :         if (!sess) {
    2241           0 :                 return -ENOMEM;
    2242             :         }
    2243             : 
    2244           0 :         ret = opal_start_auth_session(dev, sess, OPAL_ADMIN1, &opal_key);
    2245           0 :         if (ret) {
    2246           0 :                 SPDK_ERRLOG("start authenticate session error %d\n", ret);
    2247           0 :                 free(sess);
    2248           0 :                 return ret;
    2249             :         }
    2250             : 
    2251           0 :         ret = opal_get_max_ranges(dev, sess);
    2252           0 :         if (ret > 0) {
    2253           0 :                 dev->max_ranges = ret;
    2254             :         }
    2255             : 
    2256           0 :         ret = opal_end_session(dev, sess, dev->comid);
    2257           0 :         if (ret) {
    2258           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2259             :         }
    2260             : 
    2261           0 :         free(sess);
    2262             : 
    2263           0 :         return (ret == 0 ? dev->max_ranges : ret);
    2264             : }
    2265             : 
    2266             : int
    2267           0 : spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
    2268             :                                      enum spdk_opal_user user_id,
    2269             :                                      enum spdk_opal_locking_range locking_range_id)
    2270             : {
    2271             :         struct opal_session *sess;
    2272           0 :         struct spdk_opal_key opal_key = {};
    2273             :         int ret;
    2274             : 
    2275           0 :         assert(dev != NULL);
    2276             : 
    2277           0 :         ret = opal_init_key(&opal_key, passwd);
    2278           0 :         if (ret != 0) {
    2279           0 :                 return ret;
    2280             :         }
    2281             : 
    2282           0 :         sess = opal_alloc_session(dev);
    2283           0 :         if (!sess) {
    2284           0 :                 return -ENOMEM;
    2285             :         }
    2286             : 
    2287           0 :         ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
    2288           0 :         if (ret) {
    2289           0 :                 SPDK_ERRLOG("start authenticate session error %d\n", ret);
    2290           0 :                 free(sess);
    2291           0 :                 return ret;
    2292             :         }
    2293             : 
    2294           0 :         ret = opal_get_locking_range_info(dev, sess, locking_range_id);
    2295           0 :         if (ret) {
    2296           0 :                 SPDK_ERRLOG("get locking range info error %d\n", ret);
    2297             :         }
    2298             : 
    2299           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2300           0 :         if (ret) {
    2301           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2302             :         }
    2303             : 
    2304           0 :         free(sess);
    2305           0 :         return ret;
    2306             : }
    2307             : 
    2308             : int
    2309           0 : spdk_opal_cmd_enable_user(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
    2310             :                           const char *passwd)
    2311             : {
    2312             :         struct opal_session *sess;
    2313           0 :         struct spdk_opal_key opal_key = {};
    2314             :         int ret;
    2315             : 
    2316           0 :         assert(dev != NULL);
    2317             : 
    2318           0 :         ret = opal_init_key(&opal_key, passwd);
    2319           0 :         if (ret != 0) {
    2320           0 :                 return ret;
    2321             :         }
    2322             : 
    2323           0 :         sess = opal_alloc_session(dev);
    2324           0 :         if (!sess) {
    2325           0 :                 return -ENOMEM;
    2326             :         }
    2327             : 
    2328           0 :         ret =  opal_start_generic_session(dev, sess, UID_ADMIN1, UID_LOCKINGSP,
    2329           0 :                                           opal_key.key, opal_key.key_len);
    2330           0 :         if (ret) {
    2331           0 :                 SPDK_ERRLOG("start locking SP session error %d\n", ret);
    2332           0 :                 free(sess);
    2333           0 :                 return ret;
    2334             :         }
    2335             : 
    2336           0 :         ret = opal_enable_user(dev, sess, user_id);
    2337           0 :         if (ret) {
    2338           0 :                 SPDK_ERRLOG("enable user error %d\n", ret);
    2339             :         }
    2340             : 
    2341           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2342           0 :         if (ret) {
    2343           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2344             :         }
    2345             : 
    2346           0 :         free(sess);
    2347           0 :         return ret;
    2348             : }
    2349             : 
    2350             : int
    2351           0 : spdk_opal_cmd_add_user_to_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
    2352             :                                         enum spdk_opal_locking_range locking_range_id,
    2353             :                                         enum spdk_opal_lock_state lock_flag, const char *passwd)
    2354             : {
    2355             :         struct opal_session *sess;
    2356           0 :         struct spdk_opal_key opal_key = {};
    2357             :         int ret;
    2358             : 
    2359           0 :         assert(dev != NULL);
    2360             : 
    2361           0 :         ret = opal_init_key(&opal_key, passwd);
    2362           0 :         if (ret != 0) {
    2363           0 :                 return ret;
    2364             :         }
    2365             : 
    2366           0 :         sess = opal_alloc_session(dev);
    2367           0 :         if (!sess) {
    2368           0 :                 return -ENOMEM;
    2369             :         }
    2370             : 
    2371           0 :         ret =  opal_start_generic_session(dev, sess, UID_ADMIN1, UID_LOCKINGSP,
    2372           0 :                                           opal_key.key, opal_key.key_len);
    2373           0 :         if (ret) {
    2374           0 :                 SPDK_ERRLOG("start locking SP session error %d\n", ret);
    2375           0 :                 free(sess);
    2376           0 :                 return ret;
    2377             :         }
    2378             : 
    2379           0 :         ret = opal_add_user_to_locking_range(dev, sess, user_id, locking_range_id, lock_flag);
    2380           0 :         if (ret) {
    2381           0 :                 SPDK_ERRLOG("add user to locking range error %d\n", ret);
    2382             :         }
    2383             : 
    2384           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2385           0 :         if (ret) {
    2386           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2387             :         }
    2388             : 
    2389           0 :         free(sess);
    2390           0 :         return ret;
    2391             : }
    2392             : 
    2393             : int
    2394           0 : spdk_opal_cmd_set_new_passwd(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
    2395             :                              const char *new_passwd, const char *old_passwd, bool new_user)
    2396             : {
    2397             :         struct opal_session *sess;
    2398           0 :         struct spdk_opal_key old_key = {};
    2399           0 :         struct spdk_opal_key new_key = {};
    2400             :         int ret;
    2401             : 
    2402           0 :         assert(dev != NULL);
    2403             : 
    2404           0 :         ret = opal_init_key(&old_key, old_passwd);
    2405           0 :         if (ret != 0) {
    2406           0 :                 return ret;
    2407             :         }
    2408             : 
    2409           0 :         ret = opal_init_key(&new_key, new_passwd);
    2410           0 :         if (ret != 0) {
    2411           0 :                 return ret;
    2412             :         }
    2413             : 
    2414           0 :         sess = opal_alloc_session(dev);
    2415           0 :         if (!sess) {
    2416           0 :                 return -ENOMEM;
    2417             :         }
    2418             : 
    2419           0 :         ret = opal_start_auth_session(dev, sess, new_user ? OPAL_ADMIN1 : user_id,
    2420             :                                       &old_key);
    2421           0 :         if (ret) {
    2422           0 :                 SPDK_ERRLOG("start authenticate session error %d\n", ret);
    2423           0 :                 free(sess);
    2424           0 :                 return ret;
    2425             :         }
    2426             : 
    2427           0 :         ret = opal_new_user_passwd(dev, sess, user_id, &new_key);
    2428           0 :         if (ret) {
    2429           0 :                 SPDK_ERRLOG("set new passwd error %d\n", ret);
    2430             :         }
    2431             : 
    2432           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2433           0 :         if (ret) {
    2434           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2435             :         }
    2436             : 
    2437           0 :         free(sess);
    2438           0 :         return ret;
    2439             : }
    2440             : 
    2441             : int
    2442           0 : spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
    2443             :                                   enum spdk_opal_locking_range locking_range_id, const char *password)
    2444             : {
    2445             :         struct opal_session *sess;
    2446           0 :         struct spdk_opal_key opal_key = {};
    2447             :         int ret;
    2448             : 
    2449           0 :         assert(dev != NULL);
    2450             : 
    2451           0 :         ret = opal_init_key(&opal_key, password);
    2452           0 :         if (ret != 0) {
    2453           0 :                 return ret;
    2454             :         }
    2455             : 
    2456           0 :         sess = opal_alloc_session(dev);
    2457           0 :         if (!sess) {
    2458           0 :                 return -ENOMEM;
    2459             :         }
    2460             : 
    2461           0 :         ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
    2462           0 :         if (ret) {
    2463           0 :                 SPDK_ERRLOG("start authenticate session error %d\n", ret);
    2464           0 :                 free(sess);
    2465           0 :                 return ret;
    2466             :         }
    2467             : 
    2468           0 :         ret = opal_erase_locking_range(dev, sess, locking_range_id);
    2469           0 :         if (ret) {
    2470           0 :                 SPDK_ERRLOG("get active key error %d\n", ret);
    2471             :         }
    2472             : 
    2473           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2474           0 :         if (ret) {
    2475           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2476             :         }
    2477             : 
    2478           0 :         free(sess);
    2479           0 :         return ret;
    2480             : }
    2481             : 
    2482             : int
    2483           0 : spdk_opal_cmd_secure_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
    2484             :                 enum spdk_opal_locking_range locking_range_id, const char *password)
    2485             : {
    2486             :         struct opal_session *sess;
    2487           0 :         struct spdk_opal_key opal_key = {};
    2488             :         struct spdk_opal_key *active_key;
    2489             :         int ret;
    2490             : 
    2491           0 :         assert(dev != NULL);
    2492             : 
    2493           0 :         ret = opal_init_key(&opal_key, password);
    2494           0 :         if (ret != 0) {
    2495           0 :                 return ret;
    2496             :         }
    2497             : 
    2498           0 :         active_key = calloc(1, sizeof(*active_key));
    2499           0 :         if (!active_key) {
    2500           0 :                 return -ENOMEM;
    2501             :         }
    2502             : 
    2503           0 :         sess = opal_alloc_session(dev);
    2504           0 :         if (!sess) {
    2505           0 :                 free(active_key);
    2506           0 :                 return -ENOMEM;
    2507             :         }
    2508             : 
    2509           0 :         ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
    2510           0 :         if (ret) {
    2511           0 :                 SPDK_ERRLOG("start authenticate session error %d\n", ret);
    2512           0 :                 free(active_key);
    2513           0 :                 free(sess);
    2514           0 :                 return ret;
    2515             :         }
    2516             : 
    2517           0 :         ret = opal_get_active_key(dev, sess, locking_range_id, active_key);
    2518           0 :         if (ret) {
    2519           0 :                 SPDK_ERRLOG("get active key error %d\n", ret);
    2520           0 :                 goto end;
    2521             :         }
    2522             : 
    2523           0 :         ret = opal_gen_new_active_key(dev, sess, active_key);
    2524           0 :         if (ret) {
    2525           0 :                 SPDK_ERRLOG("generate new active key error %d\n", ret);
    2526           0 :                 goto end;
    2527             :         }
    2528           0 :         memset(active_key, 0, sizeof(struct spdk_opal_key));
    2529             : 
    2530           0 : end:
    2531           0 :         ret += opal_end_session(dev, sess, dev->comid);
    2532           0 :         if (ret) {
    2533           0 :                 SPDK_ERRLOG("end session error %d\n", ret);
    2534             :         }
    2535           0 :         free(active_key);
    2536           0 :         free(sess);
    2537           0 :         return ret;
    2538             : }
    2539             : 
    2540             : struct spdk_opal_d0_features_info *
    2541           0 : spdk_opal_get_d0_features_info(struct spdk_opal_dev *dev)
    2542             : {
    2543           0 :         return &dev->feat_info;
    2544             : }
    2545             : 
    2546             : struct spdk_opal_locking_range_info *
    2547           0 : spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
    2548             : {
    2549           0 :         assert(id < SPDK_OPAL_MAX_LOCKING_RANGE);
    2550           0 :         return &dev->locking_ranges[id];
    2551             : }
    2552             : 
    2553             : void
    2554           0 : spdk_opal_free_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
    2555             : {
    2556             :         struct spdk_opal_locking_range_info *info;
    2557             : 
    2558           0 :         assert(id < SPDK_OPAL_MAX_LOCKING_RANGE);
    2559           0 :         info = &dev->locking_ranges[id];
    2560           0 :         memset(info, 0, sizeof(*info));
    2561           0 : }
    2562             : 
    2563             : /* Log component for opal submodule */
    2564           1 : SPDK_LOG_REGISTER_COMPONENT(opal)

Generated by: LCOV version 1.15