LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_opal.c (source / functions) Hit Total Coverage
Test: Combined Lines: 369 1305 28.3 %
Date: 2024-07-15 10:08:26 Functions: 39 84 46.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 147 604 24.3 %

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

Generated by: LCOV version 1.14