1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 #include "spdk/opal.h" 34 #include "spdk_internal/event.h" 35 #include "spdk_internal/log.h" 36 #include "spdk/util.h" 37 38 #include "nvme_opal_internal.h" 39 40 typedef int (spdk_opal_cb)(struct spdk_opal_dev *dev); 41 42 static int opal_end_session_error(struct spdk_opal_dev *dev); 43 44 static const char * 45 opal_error_to_human(int error) 46 { 47 if (error == SPDK_OPAL_FAILED) { 48 return "FAILED"; 49 } 50 51 if ((size_t)error >= SPDK_COUNTOF(spdk_opal_errors) || error < 0) { 52 return "UNKNOWN ERROR"; 53 } 54 55 return spdk_opal_errors[error]; 56 } 57 58 static int 59 opal_send_cmd(struct spdk_opal_dev *dev) 60 { 61 return spdk_nvme_ctrlr_security_send(dev->dev_handler, SPDK_SCSI_SECP_TCG, dev->comid, 62 0, dev->cmd, IO_BUFFER_LENGTH); 63 } 64 65 static int 66 opal_recv_cmd(struct spdk_opal_dev *dev) 67 { 68 void *response = dev->resp; 69 struct spdk_opal_header *header = response; 70 int ret = 0; 71 uint64_t start = spdk_get_ticks(); 72 uint64_t now; 73 74 do { 75 ret = spdk_nvme_ctrlr_security_receive(dev->dev_handler, SPDK_SCSI_SECP_TCG, dev->comid, 76 0, dev->resp, IO_BUFFER_LENGTH); 77 if (ret) { 78 SPDK_ERRLOG("Security Receive Error on dev = %p\n", dev); 79 return ret; 80 } 81 SPDK_DEBUGLOG(SPDK_LOG_OPAL, "outstanding_data=%d, minTransfer=%d\n", 82 header->com_packet.outstanding_data, 83 header->com_packet.min_transfer); 84 85 if (header->com_packet.outstanding_data == 0 && 86 header->com_packet.min_transfer == 0) { 87 return 0; /* return if all the response data are ready by tper and received by host */ 88 } else { /* check timeout */ 89 now = spdk_get_ticks(); 90 if (now - start > dev->timeout * spdk_get_ticks_hz()) { 91 SPDK_ERRLOG("Secutiy Receive Timeout on dev = %p\n", dev); 92 return 0x0F; /* TPer Malfunction */ 93 } 94 } 95 96 memset(response, 0, IO_BUFFER_LENGTH); 97 } while (!ret); 98 99 return ret; 100 } 101 102 static int 103 opal_send_recv(struct spdk_opal_dev *dev, spdk_opal_cb *cb) 104 { 105 int ret; 106 107 ret = opal_send_cmd(dev); 108 if (ret) { 109 return ret; 110 } 111 ret = opal_recv_cmd(dev); 112 if (ret) { 113 return ret; 114 } 115 return cb(dev); 116 } 117 118 static void 119 opal_add_token_u8(int *err, struct spdk_opal_dev *dev, uint8_t token) 120 { 121 if (*err) { 122 return; 123 } 124 if (dev->cmd_pos >= IO_BUFFER_LENGTH - 1) { 125 SPDK_ERRLOG("Error adding u8: end of buffer.\n"); 126 *err = -ERANGE; 127 return; 128 } 129 dev->cmd[dev->cmd_pos++] = token; 130 } 131 132 static int 133 opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eod) 134 { 135 struct spdk_opal_header *hdr; 136 int err = 0; 137 138 if (eod) { 139 opal_add_token_u8(&err, dev, SPDK_OPAL_ENDOFDATA); 140 opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST); 141 opal_add_token_u8(&err, dev, 0); 142 opal_add_token_u8(&err, dev, 0); 143 opal_add_token_u8(&err, dev, 0); 144 opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST); 145 } 146 147 if (err) { 148 SPDK_ERRLOG("Error finalizing command.\n"); 149 return -EFAULT; 150 } 151 152 hdr = (struct spdk_opal_header *)dev->cmd; 153 154 to_be32(&hdr->packet.session_tsn, tsn); 155 to_be32(&hdr->packet.session_hsn, hsn); 156 157 to_be32(&hdr->sub_packet.length, dev->cmd_pos - sizeof(*hdr)); 158 while (dev->cmd_pos % 4) { 159 if (dev->cmd_pos >= IO_BUFFER_LENGTH) { 160 SPDK_ERRLOG("Error: Buffer overrun\n"); 161 return -ERANGE; 162 } 163 dev->cmd[dev->cmd_pos++] = 0; 164 } 165 to_be32(&hdr->packet.length, dev->cmd_pos - sizeof(hdr->com_packet) - 166 sizeof(hdr->packet)); 167 to_be32(&hdr->com_packet.length, dev->cmd_pos - sizeof(hdr->com_packet)); 168 169 return 0; 170 } 171 172 static int 173 opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb) 174 { 175 int ret; 176 177 ret = opal_cmd_finalize(dev, dev->hsn, dev->tsn, eod); 178 if (ret) { 179 SPDK_ERRLOG("Error finalizing command buffer: %d\n", ret); 180 return ret; 181 } 182 183 return opal_send_recv(dev, cb); 184 } 185 186 static size_t 187 opal_response_parse_tiny(struct spdk_opal_resp_token *token, 188 const uint8_t *pos) 189 { 190 token->pos = pos; 191 token->len = 1; 192 token->width = OPAL_WIDTH_TINY; 193 194 if (pos[0] & SPDK_TINY_ATOM_SIGN_FLAG) { 195 token->type = OPAL_DTA_TOKENID_SINT; 196 } else { 197 token->type = OPAL_DTA_TOKENID_UINT; 198 token->stored.unsigned_num = pos[0] & SPDK_TINY_ATOM_DATA_MASK; 199 } 200 201 return token->len; 202 } 203 204 static int 205 opal_response_parse_short(struct spdk_opal_resp_token *token, 206 const uint8_t *pos) 207 { 208 token->pos = pos; 209 token->len = (pos[0] & SPDK_SHORT_ATOM_LEN_MASK) + 1; /* plus 1-byte header */ 210 token->width = OPAL_WIDTH_SHORT; 211 212 if (pos[0] & SPDK_SHORT_ATOM_BYTESTRING_FLAG) { 213 token->type = OPAL_DTA_TOKENID_BYTESTRING; 214 } else if (pos[0] & SPDK_SHORT_ATOM_SIGN_FLAG) { 215 token->type = OPAL_DTA_TOKENID_SINT; 216 } else { 217 uint64_t u_integer = 0; 218 size_t i, b = 0; 219 220 token->type = OPAL_DTA_TOKENID_UINT; 221 if (token->len > 9) { 222 SPDK_ERRLOG("uint64 with more than 8 bytes\n"); 223 return -EINVAL; 224 } 225 for (i = token->len - 1; i > 0; i--) { 226 u_integer |= ((uint64_t)pos[i] << (8 * b)); 227 b++; 228 } 229 token->stored.unsigned_num = u_integer; 230 } 231 232 return token->len; 233 } 234 235 static size_t 236 opal_response_parse_medium(struct spdk_opal_resp_token *token, 237 const uint8_t *pos) 238 { 239 token->pos = pos; 240 token->len = (((pos[0] & SPDK_MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2; /* plus 2-byte header */ 241 token->width = OPAL_WIDTH_MEDIUM; 242 243 if (pos[0] & SPDK_MEDIUM_ATOM_BYTESTRING_FLAG) { 244 token->type = OPAL_DTA_TOKENID_BYTESTRING; 245 } else if (pos[0] & SPDK_MEDIUM_ATOM_SIGN_FLAG) { 246 token->type = OPAL_DTA_TOKENID_SINT; 247 } else { 248 token->type = OPAL_DTA_TOKENID_UINT; 249 } 250 251 return token->len; 252 } 253 254 static size_t 255 opal_response_parse_long(struct spdk_opal_resp_token *token, 256 const uint8_t *pos) 257 { 258 token->pos = pos; 259 token->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4; /* plus 4-byte header */ 260 token->width = OPAL_WIDTH_LONG; 261 262 if (pos[0] & SPDK_LONG_ATOM_BYTESTRING_FLAG) { 263 token->type = OPAL_DTA_TOKENID_BYTESTRING; 264 } else if (pos[0] & SPDK_LONG_ATOM_SIGN_FLAG) { 265 token->type = OPAL_DTA_TOKENID_SINT; 266 } else { 267 token->type = OPAL_DTA_TOKENID_UINT; 268 } 269 270 return token->len; 271 } 272 273 static size_t 274 opal_response_parse_token(struct spdk_opal_resp_token *token, 275 const uint8_t *pos) 276 { 277 token->pos = pos; 278 token->len = 1; 279 token->type = OPAL_DTA_TOKENID_TOKEN; 280 token->width = OPAL_WIDTH_TOKEN; 281 282 return token->len; 283 } 284 285 static int 286 opal_response_parse(const uint8_t *buf, size_t length, 287 struct spdk_opal_resp_parsed *resp) 288 { 289 const struct spdk_opal_header *hdr; 290 struct spdk_opal_resp_token *token_iter; 291 int num_entries = 0; 292 int total; 293 size_t token_length; 294 const uint8_t *pos; 295 uint32_t clen, plen, slen; 296 297 if (!buf || !resp) { 298 return -EINVAL; 299 } 300 301 hdr = (struct spdk_opal_header *)buf; 302 pos = buf + sizeof(*hdr); 303 304 clen = from_be32(&hdr->com_packet.length); 305 plen = from_be32(&hdr->packet.length); 306 slen = from_be32(&hdr->sub_packet.length); 307 SPDK_DEBUGLOG(SPDK_LOG_OPAL, "Response size: cp: %u, pkt: %u, subpkt: %u\n", 308 clen, plen, slen); 309 310 if (clen == 0 || plen == 0 || slen == 0 || 311 slen > IO_BUFFER_LENGTH - sizeof(*hdr)) { 312 SPDK_ERRLOG("Bad header length. cp: %u, pkt: %u, subpkt: %u\n", 313 clen, plen, slen); 314 return -EINVAL; 315 } 316 317 if (pos > buf + length) { 318 SPDK_ERRLOG("Pointer out of range\n"); 319 return -EFAULT; 320 } 321 322 token_iter = resp->resp_tokens; 323 total = slen; 324 325 while (total > 0) { 326 if (pos[0] <= SPDK_TINY_ATOM_TYPE_MAX) { /* tiny atom */ 327 token_length = opal_response_parse_tiny(token_iter, pos); 328 } else if (pos[0] <= SPDK_SHORT_ATOM_TYPE_MAX) { /* short atom */ 329 token_length = opal_response_parse_short(token_iter, pos); 330 } else if (pos[0] <= SPDK_MEDIUM_ATOM_TYPE_MAX) { /* medium atom */ 331 token_length = opal_response_parse_medium(token_iter, pos); 332 } else if (pos[0] <= SPDK_LONG_ATOM_TYPE_MAX) { /* long atom */ 333 token_length = opal_response_parse_long(token_iter, pos); 334 } else { /* TOKEN */ 335 token_length = opal_response_parse_token(token_iter, pos); 336 } 337 338 if (token_length <= 0) { 339 SPDK_ERRLOG("Parse response failure.\n"); 340 return -EINVAL; 341 } 342 343 pos += token_length; 344 total -= token_length; 345 token_iter++; 346 num_entries++; 347 348 if (total < 0) { 349 SPDK_ERRLOG("Length not matching.\n"); 350 return -EINVAL; 351 } 352 } 353 354 if (num_entries == 0) { 355 SPDK_ERRLOG("Couldn't parse response.\n"); 356 return -EINVAL; 357 } 358 resp->num = num_entries; 359 360 return 0; 361 } 362 363 static inline bool 364 opal_response_token_matches(const struct spdk_opal_resp_token *token, 365 uint8_t match) 366 { 367 if (!token || 368 token->type != OPAL_DTA_TOKENID_TOKEN || 369 token->pos[0] != match) { 370 SPDK_ERRLOG("Token not matching\n"); 371 return false; 372 } 373 return true; 374 } 375 376 static const struct spdk_opal_resp_token * 377 opal_response_get_token(const struct spdk_opal_resp_parsed *resp, int index) 378 { 379 const struct spdk_opal_resp_token *token; 380 381 if (index >= resp->num) { 382 SPDK_ERRLOG("Token number doesn't exist: %d, resp: %d\n", 383 index, resp->num); 384 return NULL; 385 } 386 387 token = &resp->resp_tokens[index]; 388 if (token->len == 0) { 389 SPDK_ERRLOG("Token length must be non-zero\n"); 390 return NULL; 391 } 392 393 return token; 394 } 395 396 static uint64_t 397 opal_response_get_u64(const struct spdk_opal_resp_parsed *resp, int index) 398 { 399 if (!resp) { 400 SPDK_ERRLOG("Response is NULL\n"); 401 return 0; 402 } 403 404 if (resp->resp_tokens[index].type != OPAL_DTA_TOKENID_UINT) { 405 SPDK_ERRLOG("Token is not unsigned int: %d\n", 406 resp->resp_tokens[index].type); 407 return 0; 408 } 409 410 if (!(resp->resp_tokens[index].width == OPAL_WIDTH_TINY || 411 resp->resp_tokens[index].width == OPAL_WIDTH_SHORT)) { 412 SPDK_ERRLOG("Atom is not short or tiny: %d\n", 413 resp->resp_tokens[index].width); 414 return 0; 415 } 416 417 return resp->resp_tokens[index].stored.unsigned_num; 418 } 419 420 static int 421 opal_response_status(const struct spdk_opal_resp_parsed *resp) 422 { 423 const struct spdk_opal_resp_token *tok; 424 425 /* if we get an EOS token, just return 0 */ 426 tok = opal_response_get_token(resp, 0); 427 if (opal_response_token_matches(tok, SPDK_OPAL_ENDOFSESSION)) { 428 return 0; 429 } 430 431 if (resp->num < 5) { 432 return SPDK_DTAERROR_NO_METHOD_STATUS; 433 } 434 435 tok = opal_response_get_token(resp, resp->num - 5); /* the first token should be STARTLIST */ 436 if (!opal_response_token_matches(tok, SPDK_OPAL_STARTLIST)) { 437 return SPDK_DTAERROR_NO_METHOD_STATUS; 438 } 439 440 tok = opal_response_get_token(resp, resp->num - 1); /* the last token should be ENDLIST */ 441 if (!opal_response_token_matches(tok, SPDK_OPAL_ENDLIST)) { 442 return SPDK_DTAERROR_NO_METHOD_STATUS; 443 } 444 445 /* The second and third values in the status list are reserved, and are 446 defined in core spec to be 0x00 and 0x00 and SHOULD be ignored by the host. */ 447 return (int)opal_response_get_u64(resp, 448 resp->num - 4); /* We only need the first value in the status list. */ 449 } 450 451 static int 452 opal_parse_and_check_status(struct spdk_opal_dev *dev) 453 { 454 int error; 455 456 error = opal_response_parse(dev->resp, IO_BUFFER_LENGTH, &dev->parsed_resp); 457 if (error) { 458 SPDK_ERRLOG("Couldn't parse response.\n"); 459 return error; 460 } 461 return opal_response_status(&dev->parsed_resp); 462 } 463 464 static inline void 465 opal_clear_cmd(struct spdk_opal_dev *dev) 466 { 467 dev->cmd_pos = sizeof(struct spdk_opal_header); 468 memset(dev->cmd, 0, IO_BUFFER_LENGTH); 469 } 470 471 static inline void 472 opal_set_comid(struct spdk_opal_dev *dev, uint16_t comid) 473 { 474 struct spdk_opal_header *hdr = (struct spdk_opal_header *)dev->cmd; 475 476 hdr->com_packet.comid[0] = comid >> 8; 477 hdr->com_packet.comid[1] = comid; 478 hdr->com_packet.extended_comid[0] = 0; 479 hdr->com_packet.extended_comid[1] = 0; 480 } 481 482 static int 483 opal_next(struct spdk_opal_dev *dev) 484 { 485 const struct spdk_opal_step *step; 486 int state = 0, error = 0; 487 488 do { 489 step = &dev->steps[state]; 490 if (!step->opal_fn) { 491 if (state != 0) { 492 break; 493 } else { 494 SPDK_ERRLOG("First step is NULL\n"); 495 return -1; 496 } 497 } 498 499 error = step->opal_fn(dev, step->data); 500 if (error) { 501 SPDK_ERRLOG("Error on step function: %d with error %d: %s\n", 502 state, error, 503 opal_error_to_human(error)); 504 if (state > 1) { 505 opal_end_session_error(dev); 506 return error; 507 } 508 } 509 state++; 510 } while (!error); 511 512 return error; 513 } 514 515 static void 516 opal_check_tper(struct spdk_opal_dev *dev, const void *data) 517 { 518 const struct spdk_d0_tper_features *tper = data; 519 struct spdk_opal_info *opal_info = dev->opal_info; 520 521 opal_info->opal_ssc_dev = 1; 522 opal_info->tper = 1; 523 opal_info->tper_acknack = tper->acknack; 524 opal_info->tper_async = tper->async; 525 opal_info->tper_buffer_mgt = tper->buffer_management; 526 opal_info->tper_comid_mgt = tper->comid_management; 527 opal_info->tper_streaming = tper->streaming; 528 opal_info->tper_sync = tper->sync; 529 } 530 531 /* 532 * check single user mode 533 */ 534 static bool 535 opal_check_sum(struct spdk_opal_dev *dev, const void *data) 536 { 537 const struct spdk_d0_sum *sum = data; 538 uint32_t num_locking_objects = from_be32(&sum->num_locking_objects); 539 struct spdk_opal_info *opal_info = dev->opal_info; 540 541 if (num_locking_objects == 0) { 542 SPDK_NOTICELOG("Need at least one locking object.\n"); 543 return false; 544 } 545 546 opal_info->single_user_mode = 1; 547 opal_info->single_user_locking_objects = num_locking_objects; 548 opal_info->single_user_any = sum->any; 549 opal_info->single_user_all = sum->all; 550 opal_info->single_user_policy = sum->policy; 551 552 return true; 553 } 554 555 static void 556 opal_check_lock(struct spdk_opal_dev *dev, const void *data) 557 { 558 const struct spdk_d0_locking_features *lock = data; 559 struct spdk_opal_info *opal_info = dev->opal_info; 560 561 opal_info->locking = 1; 562 opal_info->locking_locked = lock->locked; 563 opal_info->locking_locking_enabled = lock->locking_enabled; 564 opal_info->locking_locking_supported = lock->locking_supported; 565 opal_info->locking_mbr_done = lock->mbr_done; 566 opal_info->locking_mbr_enabled = lock->mbr_enabled; 567 opal_info->locking_media_encrypt = lock->media_encryption; 568 } 569 570 static void 571 opal_check_geometry(struct spdk_opal_dev *dev, const void *data) 572 { 573 const struct spdk_d0_geo_features *geo = data; 574 struct spdk_opal_info *opal_info = dev->opal_info; 575 uint64_t align = from_be64(&geo->alignment_granularity); 576 uint64_t lowest_lba = from_be64(&geo->lowest_aligned_lba); 577 578 dev->align = align; 579 dev->lowest_lba = lowest_lba; 580 581 opal_info->geometry = 1; 582 opal_info->geometry_align = geo->align; 583 opal_info->geometry_logical_block_size = from_be64(&geo->logical_block_size); 584 opal_info->geometry_lowest_aligned_lba = lowest_lba; 585 opal_info->geometry_alignment_granularity = align; 586 } 587 588 static void 589 opal_check_datastore(struct spdk_opal_dev *dev, const void *data) 590 { 591 const struct spdk_d0_datastore_features *datastore = data; 592 struct spdk_opal_info *opal_info = dev->opal_info; 593 594 opal_info->datastore = 1; 595 opal_info->datastore_max_tables = from_be16(&datastore->max_tables); 596 opal_info->datastore_max_table_size = from_be32(&datastore->max_table_size); 597 opal_info->datastore_alignment = from_be32(&datastore->alignment); 598 } 599 600 static uint16_t 601 opal_get_comid_v100(struct spdk_opal_dev *dev, const void *data) 602 { 603 const struct spdk_d0_opal_v100 *v100 = data; 604 struct spdk_opal_info *opal_info = dev->opal_info; 605 uint16_t base_comid = from_be16(&v100->base_comid); 606 607 opal_info->opal_v100 = 1; 608 opal_info->opal_v100_base_comid = base_comid; 609 opal_info->opal_v100_num_comid = from_be16(&v100->number_comids); 610 opal_info->opal_v100_range_crossing = v100->range_crossing; 611 612 return base_comid; 613 } 614 615 static uint16_t 616 opal_get_comid_v200(struct spdk_opal_dev *dev, const void *data) 617 { 618 const struct spdk_d0_opal_v200 *v200 = data; 619 struct spdk_opal_info *opal_info = dev->opal_info; 620 uint16_t base_comid = from_be16(&v200->base_comid); 621 622 opal_info->opal_v200 = 1; 623 opal_info->opal_v200_base_comid = base_comid; 624 opal_info->opal_v200_num_comid = from_be16(&v200->num_comids); 625 opal_info->opal_v200_range_crossing = v200->range_crossing; 626 opal_info->opal_v200_num_admin = from_be16(&v200->num_locking_admin_auth); 627 opal_info->opal_v200_num_user = from_be16(&v200->num_locking_user_auth); 628 629 opal_info->opal_v200_initial_pin = v200->initial_pin; 630 opal_info->opal_v200_reverted_pin = v200->reverted_pin; 631 632 return base_comid; 633 } 634 635 static int 636 opal_discovery0_end(struct spdk_opal_dev *dev) 637 { 638 bool found_com_id = false, supported = false, single_user = false; 639 const struct spdk_d0_header *hdr = (struct spdk_d0_header *)dev->resp; 640 const uint8_t *epos = dev->resp, *cpos = dev->resp; 641 uint16_t comid = 0; 642 uint32_t hlen = from_be32(&(hdr->length)); 643 644 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) { 645 SPDK_ERRLOG("Discovery length overflows buffer (%zu+%u)/%u\n", 646 sizeof(*hdr), hlen, IO_BUFFER_LENGTH); 647 return -EFAULT; 648 } 649 650 epos += hlen; /* end of buffer */ 651 cpos += sizeof(*hdr); /* current position on buffer */ 652 653 while (cpos < epos) { 654 const union spdk_discovery0_features *body = 655 (const union spdk_discovery0_features *)cpos; 656 uint16_t feature_code = from_be16(&(body->tper.feature_code)); 657 658 switch (feature_code) { 659 case FEATURECODE_TPER: 660 opal_check_tper(dev, body); 661 break; 662 case FEATURECODE_SINGLEUSER: 663 single_user = opal_check_sum(dev, body); 664 break; 665 case FEATURECODE_GEOMETRY: 666 opal_check_geometry(dev, body); 667 break; 668 case FEATURECODE_LOCKING: 669 opal_check_lock(dev, body); 670 break; 671 case FEATURECODE_DATASTORE: 672 opal_check_datastore(dev, body); 673 break; 674 case FEATURECODE_OPALV100: 675 comid = opal_get_comid_v100(dev, body); 676 found_com_id = true; 677 supported = true; 678 break; 679 case FEATURECODE_OPALV200: 680 comid = opal_get_comid_v200(dev, body); 681 found_com_id = true; 682 supported = true; 683 break; 684 default: 685 SPDK_NOTICELOG("Unknow feature code: %d\n", feature_code); 686 } 687 cpos += body->tper.length + 4; 688 } 689 690 if (supported == false) { 691 SPDK_ERRLOG("Opal Not Supported.\n"); 692 return SPDK_OPAL_NOT_SUPPORTED; 693 } 694 695 if (single_user == false) { 696 SPDK_NOTICELOG("Single User Mode Not Supported\n"); 697 } 698 699 if (found_com_id == false) { 700 SPDK_ERRLOG("Could not find OPAL comid for device. Returning early\n"); 701 return -EINVAL; 702 } 703 704 dev->comid = comid; 705 return 0; 706 } 707 708 static int 709 opal_discovery0(struct spdk_opal_dev *dev, void *data) 710 { 711 int ret; 712 713 memset(dev->resp, 0, IO_BUFFER_LENGTH); 714 dev->comid = LV0_DISCOVERY_COMID; 715 ret = opal_recv_cmd(dev); 716 if (ret) { 717 return ret; 718 } 719 720 return opal_discovery0_end(dev); 721 } 722 723 static inline void 724 opal_setup_dev(struct spdk_opal_dev *dev, 725 const struct spdk_opal_step *steps) 726 { 727 dev->steps = steps; 728 dev->tsn = 0; 729 dev->hsn = 0; 730 dev->prev_data = NULL; 731 dev->timeout = SPDK_OPAL_TPER_TIMEOUT; 732 } 733 734 static int 735 opal_end_session_cb(struct spdk_opal_dev *dev) 736 { 737 dev->hsn = 0; 738 dev->tsn = 0; 739 return opal_parse_and_check_status(dev); 740 } 741 742 static int 743 opal_end_session(struct spdk_opal_dev *dev, void *data) 744 { 745 int err = 0; 746 bool eod = 0; 747 748 opal_clear_cmd(dev); 749 opal_set_comid(dev, dev->comid); 750 opal_add_token_u8(&err, dev, SPDK_OPAL_ENDOFSESSION); 751 752 if (err < 0) { 753 return err; 754 } 755 return opal_finalize_and_send(dev, eod, opal_end_session_cb); 756 } 757 758 static int 759 opal_end_session_error(struct spdk_opal_dev *dev) 760 { 761 const struct spdk_opal_step error_end_session[] = { 762 { opal_end_session, }, 763 { NULL, } 764 }; 765 dev->steps = error_end_session; 766 return opal_next(dev); 767 } 768 769 static int 770 opal_check_support(struct spdk_opal_dev *dev) 771 { 772 const struct spdk_opal_step steps[] = { 773 { opal_discovery0, }, 774 { NULL, } 775 }; 776 int ret; 777 778 opal_setup_dev(dev, steps); 779 ret = opal_next(dev); 780 if (ret == 0) { 781 dev->supported = true; 782 } else { 783 dev->supported = false; 784 } 785 786 return ret; 787 } 788 789 void 790 spdk_opal_close(struct spdk_opal_dev *dev) 791 { 792 free(dev->opal_info); 793 free(dev); 794 } 795 796 struct spdk_opal_dev * 797 spdk_opal_init_dev(void *dev_handler) 798 { 799 struct spdk_opal_dev *dev; 800 struct spdk_opal_info *info; 801 802 dev = calloc(1, sizeof(*dev)); 803 if (!dev) { 804 SPDK_ERRLOG("Memory allocation failed\n"); 805 return NULL; 806 } 807 808 dev->dev_handler = dev_handler; 809 810 info = calloc(1, sizeof(struct spdk_opal_info)); 811 if (info == NULL) { 812 free(dev); 813 SPDK_ERRLOG("Memory allocation failed\n"); 814 return NULL; 815 } 816 817 dev->opal_info = info; 818 if (opal_check_support(dev) != 0) { 819 SPDK_INFOLOG(SPDK_LOG_OPAL, "Opal is not supported on this device\n"); 820 dev->supported = false; 821 } 822 return dev; 823 } 824 825 void 826 spdk_opal_scan(struct spdk_opal_dev *dev) 827 { 828 int ret; 829 830 ret = opal_check_support(dev); 831 if (ret) { 832 SPDK_ERRLOG("check opal support failed: %d\n", ret); 833 spdk_opal_close(dev); 834 return; 835 } 836 } 837 838 struct spdk_opal_info * 839 spdk_opal_get_info(struct spdk_opal_dev *dev) 840 { 841 return dev->opal_info; 842 } 843 844 bool 845 spdk_opal_supported(struct spdk_opal_dev *dev) 846 { 847 return dev->supported; 848 } 849 850 /* Log component for opal submodule */ 851 SPDK_LOG_REGISTER_COMPONENT("opal", SPDK_LOG_OPAL) 852