1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * These functions are used to encode SCSI INQUIRY data into 30 * Solaris devid / guid values. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/stropts.h> 35 #include <sys/debug.h> 36 #include <sys/isa_defs.h> 37 #include <sys/dditypes.h> 38 #include <sys/ddi_impldefs.h> 39 #include <sys/scsi/scsi.h> 40 #include "devid_impl.h" 41 42 #define SCSI_INQUIRY_VID_POS 9 43 #define SCSI_INQUIRY_VID_SUN "SUN" 44 #define SCSI_INQUIRY_VID_SUN_LEN 3 45 #define SCSI_INQUIRY_VID_EMC "EMC " 46 #define SCSI_INQUIRY_VID_EMC_LEN 8 47 #define SCSI_INQUIRY_PID_EMC_SYMMETRIX "SYMMETRIX " 48 #define SCSI_INQUIRY_PID_EMC_SYMMETRIX_LEN 16 49 50 #define MSG_NOT_STANDARDS_COMPLIANT "!Page83 data not standards compliant " 51 #define MSG_NOT_STANDARDS_COMPLIANT_SIZE ( \ 52 sizeof (MSG_NOT_STANDARDS_COMPLIANT) + \ 53 sizeof (((struct scsi_inquiry *)NULL)->inq_vid) + \ 54 sizeof (((struct scsi_inquiry *)NULL)->inq_pid) + \ 55 sizeof (((struct scsi_inquiry *)NULL)->inq_revision) + 4) 56 57 #define IS_DEVID_GUID_TYPE(type) ((type == DEVID_SCSI3_WWN) || \ 58 (IS_DEVID_SCSI3_VPD_TYPE(type))) 59 60 #define IS_DEVID_SCSI_TYPE(type) ((IS_DEVID_GUID_TYPE(type)) || \ 61 (type == DEVID_SCSI_SERIAL)) 62 63 /* 64 * The max inquiry page 83 size as expected in the code today 65 * is 0xf0 bytes. Defining a constant to make it easy incase 66 * this needs to be changed at a later time. 67 */ 68 69 #define SCMD_MAX_INQUIRY_PAGE83_SIZE 0xFF 70 #define SCMD_MIN_INQUIRY_PAGE83_SIZE 0x08 71 #define SCMD_INQUIRY_PAGE83_HDR_SIZE 4 72 #define SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN 16 73 74 #define SCMD_MAX_INQUIRY_PAGE80_SIZE 0xFF 75 #define SCMD_MIN_INQUIRY_PAGE80_SIZE 0x04 76 77 #define SCMD_MIN_STANDARD_INQUIRY_SIZE 0x04 78 79 #define SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE 4 80 81 #define SCMD_INQUIRY_VPD_TYPE_T10 0x01 82 #define SCMD_INQUIRY_VPD_TYPE_EUI 0x02 83 #define SCMD_INQUIRY_VPD_TYPE_NAA 0x03 84 #define SCMD_INQUIRY_VPD_TYPE_RTP 0x04 85 #define SCMD_INQUIRY_VPD_TYPE_TPG 0x05 86 #define SCMD_INQUIRY_VPD_TYPE_LUG 0x06 87 #define SCMD_INQUIRY_VPD_TYPE_MD5 0x07 88 #define SCMD_INQUIRY_VPD_TYPE_SSN 0x08 89 90 static int is_page83_data_valid(uchar_t *inq83, size_t inq83_len); 91 static int is_page80_data_valid(uchar_t *inq80, size_t inq80_len); 92 static int is_initialized_id(uchar_t *id, size_t id_len); 93 94 static void encode_scsi3_page83(int version, uchar_t *inq83, 95 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 96 static void encode_scsi3_page83_emc(int version, uchar_t *inq83, 97 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 98 static void encode_serialnum(int version, uchar_t *inq, uchar_t *inq80, 99 size_t inq80_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 100 static void encode_sun_serialnum(int version, uchar_t *inq, 101 size_t inq_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 102 103 static int devid_scsi_init(char *driver_name, 104 uchar_t *raw_id, size_t raw_id_len, ushort_t raw_id_type, 105 ddi_devid_t *ret_devid); 106 107 /* 108 * Function: ddi_/devid_scsi_encode 109 * 110 * Description: This routine finds and encodes a unique devid 111 * 112 * Arguments: version - id encode algorithm version 113 * driver_name - binding driver name (if ! known use NULL) 114 * inq - standard inquiry buffer 115 * inq_len - standard inquiry buffer length 116 * inq80 - serial number inquiry buffer 117 * inq80_len - serial number inquiry buffer length 118 * inq83 - vpd inquiry buffer 119 * inq83_len - vpd inquiry buffer length 120 * devid - id returned 121 * 122 * Return Code: DEVID_SUCCESS - success 123 * DEVID_FAILURE - failure 124 * DEVID_RETRY - LUN is in a transitional state. A delay should 125 * occur and then this inquiry data should be re-acquired and 126 * this function should be called again. 127 */ 128 int 129 #ifdef _KERNEL 130 ddi_devid_scsi_encode( 131 #else /* ! _KERNEL */ 132 devid_scsi_encode( 133 #endif /* _KERNEL */ 134 int version, /* IN */ 135 char *driver_name, /* IN */ 136 uchar_t *inq, /* IN */ 137 size_t inq_len, /* IN */ 138 uchar_t *inq80, /* IN */ 139 size_t inq80_len, /* IN */ 140 uchar_t *inq83, /* IN */ 141 size_t inq83_len, /* IN */ 142 ddi_devid_t *devid) /* OUT */ 143 { 144 int rval = DEVID_FAILURE; 145 uchar_t *id = NULL; 146 size_t id_len = 0; 147 ushort_t id_type = DEVID_NONE; 148 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 149 #ifdef _KERNEL 150 char *msg = NULL; 151 #endif /* _KERNEL */ 152 153 DEVID_ASSERT(devid != NULL); 154 155 /* verify valid version */ 156 if (version > DEVID_SCSI_ENCODE_VERSION_LATEST) { 157 return (rval); 158 } 159 160 /* make sure minimum inquiry bytes are available */ 161 if (inq_len < SCMD_MIN_STANDARD_INQUIRY_SIZE) { 162 return (rval); 163 } 164 165 /* 166 * If 0x83 is availible, that is the best choice. Our next choice is 167 * 0x80. If neither are availible, we leave it to the caller to 168 * determine possible alternate ID, although discouraged. In the 169 * case of the target drivers they create a fabricated id which is 170 * stored in the acyl. The HBA drivers should avoid using an 171 * alternate id. Although has already created a hack of using the 172 * node wwn in some cases. Which needs to be carried forward for 173 * legacy reasons. 174 */ 175 if (inq83 != NULL) { 176 /* 177 * Perform page 83 validation tests and report offenders. 178 * We cannot enforce the page 83 specification because 179 * many Sun partners (ex. HDS) do not conform to the 180 * standards yet. 181 */ 182 if (is_page83_data_valid(inq83, inq83_len) == 183 DEVID_RET_INVALID) { 184 /* 185 * invalid page 83 data. bug 4939576 introduced 186 * handling for EMC non-standard data. 187 */ 188 if ((bcmp(inq_std->inq_vid, SCSI_INQUIRY_VID_EMC, 189 SCSI_INQUIRY_VID_EMC_LEN) == 0) && 190 (bcmp(inq_std->inq_pid, 191 SCSI_INQUIRY_PID_EMC_SYMMETRIX, 192 SCSI_INQUIRY_PID_EMC_SYMMETRIX_LEN) == 0)) { 193 encode_scsi3_page83_emc(version, inq83, 194 inq83_len, &id, &id_len, &id_type); 195 } 196 197 #ifdef _KERNEL 198 /* 199 * report the page 0x83 standards violation. 200 */ 201 msg = kmem_alloc(MSG_NOT_STANDARDS_COMPLIANT_SIZE, 202 KM_SLEEP); 203 (void) strcpy(msg, MSG_NOT_STANDARDS_COMPLIANT); 204 (void) strncat(msg, inq_std->inq_vid, 205 sizeof (inq_std->inq_vid)); 206 (void) strcat(msg, " "); 207 (void) strncat(msg, inq_std->inq_pid, 208 sizeof (inq_std->inq_pid)); 209 (void) strcat(msg, " "); 210 (void) strncat(msg, inq_std->inq_revision, 211 sizeof (inq_std->inq_revision)); 212 (void) strcat(msg, "\n"); 213 cmn_err(CE_WARN, msg); 214 kmem_free(msg, MSG_NOT_STANDARDS_COMPLIANT_SIZE); 215 #endif /* _KERNEL */ 216 } 217 218 if (id_type == DEVID_NONE) { 219 encode_scsi3_page83(version, inq83, 220 inq83_len, &id, &id_len, &id_type); 221 } 222 } 223 224 /* 225 * If no vpd page is available at this point then we 226 * attempt to use a SCSI serial number from page 0x80. 227 */ 228 if ((id_type == DEVID_NONE) && 229 (inq != NULL) && 230 (inq80 != NULL)) { 231 if (is_page80_data_valid(inq80, inq80_len) == DEVID_RET_VALID) { 232 encode_serialnum(version, inq, inq80, 233 inq80_len, &id, &id_len, &id_type); 234 } 235 } 236 237 /* 238 * If no vpd page or serial is available at this point and 239 * it's a SUN disk it conforms to the disk qual. 850 specifications 240 * and we can fabricate a serial number id based on the standard 241 * inquiry page. 242 */ 243 if ((id_type == DEVID_NONE) && 244 (inq != NULL)) { 245 encode_sun_serialnum(version, inq, inq_len, 246 &id, &id_len, &id_type); 247 } 248 249 if (id_type != DEVID_NONE) { 250 if (is_initialized_id(id, id_len) == DEVID_RET_VALID) { 251 rval = devid_scsi_init(driver_name, 252 id, id_len, id_type, devid); 253 } else { 254 rval = DEVID_RETRY; 255 } 256 DEVID_FREE(id, id_len); 257 } 258 259 return (rval); 260 } 261 262 263 /* 264 * Function: is_page83_data_valid 265 * 266 * Description: This routine is used to validate the page 0x83 data 267 * passed in valid based on the standards specification. 268 * 269 * Arguments: inq83 - 270 * inq83_len - 271 * 272 * Return Code: DEVID_RET_VALID 273 * DEVID_RET_INVALID 274 * 275 */ 276 static int 277 is_page83_data_valid(uchar_t *inq83, size_t inq83_len) 278 { 279 280 int covered_desc_len = 0; 281 int dlen = 0; 282 uchar_t *dblk = NULL; 283 284 DEVID_ASSERT(inq83 != NULL); 285 286 /* if not large enough fail */ 287 if (inq83_len < SCMD_MIN_INQUIRY_PAGE83_SIZE) 288 return (DEVID_RET_INVALID); 289 290 /* 291 * Ensuring that the Peripheral device type(bits 0 - 4) has 292 * the valid settings - the value 0x1f indicates no device type. 293 * Only this value can be validated since all other fields are 294 * either used or reserved. 295 */ 296 if ((inq83[0] & DTYPE_MASK) == DTYPE_UNKNOWN) { 297 /* failed-peripheral devtype */ 298 return (DEVID_RET_INVALID); 299 } 300 301 /* 302 * Ensure that the page length field - third and 4th bytes 303 * contain a non zero length value. Our implementation 304 * does not seem to expect more that 255 bytes of data... 305 * what is to be done if the reported size is > 255 bytes? 306 * Yes the device will return only 255 bytes as we provide 307 * buffer to house only that much data but the standards 308 * prevent the targets from reporting the truncated size 309 * in this field. 310 * 311 * Currently reporting sizes more than 255 as failure. 312 * 313 */ 314 315 if ((inq83[2] == 0) && (inq83[3] == 0)) { 316 /* length field is 0! */ 317 return (DEVID_RET_INVALID); 318 } 319 if (inq83[3] > (SCMD_MAX_INQUIRY_PAGE83_SIZE - 3)) { 320 /* length field exceeds expected size of 255 bytes */ 321 return (DEVID_RET_INVALID); 322 } 323 324 /* 325 * Validation of individual descriptor blocks are done in the 326 * following while loop. It is possible to have multiple 327 * descriptor blocks. 328 * the 'dblk' pointer will be pointing to the start of 329 * each entry of the descriptor block. 330 */ 331 covered_desc_len = 0; 332 dblk = &inq83[4]; /* start of first decriptor blk */ 333 while (covered_desc_len < inq83[3]) { 334 335 /* 336 * Ensure that the length field is non zero 337 * Further length validations will be done 338 * along with the 'identifier type' as some of 339 * the lengths are dependent on it. 340 */ 341 dlen = dblk[3]; 342 if (dlen == 0) { 343 /* descr length is 0 */ 344 return (DEVID_RET_INVALID); 345 } 346 347 /* 348 * ensure that the size of the descriptor block does 349 * not claim to be larger than the entire page83 350 * data that has been received. 351 */ 352 if ((covered_desc_len + dlen) > inq83[3]) { 353 /* failed-descr length */ 354 return (DEVID_RET_INVALID); 355 } 356 357 /* 358 * The spec says that if the PIV field is 0 OR the 359 * association field contains value other than 1 and 2, 360 * then the protocol identifier field should be ignored. 361 * If association field contains a value of 1 or 2 362 * and the PIV field is set, then the protocol identifier 363 * field has to be validated. 364 * The protocol identifier values 0 - f are either assigned 365 * or reserved. Nothing to validate here, hence skipping 366 * over to the next check. 367 */ 368 369 /* 370 * Check for valid code set values. 371 * All possible values are reserved or assigned. Nothing 372 * to validate - skipping over. 373 */ 374 375 /* 376 * Identifier Type validation 377 * All SPC3rev22 identified types and the expected lengths 378 * are validated. 379 */ 380 switch (dblk[1] & 0x0f) { 381 case SCMD_INQUIRY_VPD_TYPE_T10: /* T10 vendor Id */ 382 /* No specific length validation required */ 383 break; 384 385 case SCMD_INQUIRY_VPD_TYPE_EUI: /* EUI 64 ID */ 386 /* EUI-64: size is expected to be 8, 12, or 16 bytes */ 387 if ((dlen != 8) && (dlen != 12) && (dlen != 16)) { 388 /* page83 validation failed-EIU64 */ 389 return (DEVID_RET_INVALID); 390 } 391 break; 392 393 case SCMD_INQUIRY_VPD_TYPE_NAA: /* NAA Id type */ 394 395 /* 396 * the size for this varies - 397 * IEEE extended/registered is 8 bytes 398 * IEEE Registered extended is 16 bytes 399 */ 400 switch (dblk[4] & 0xf0) { 401 402 case 0x20: /* IEEE Ext */ 403 case 0x50: /* IEEE Reg */ 404 if (dlen != 8) { 405 /* failed-IEE E/R len */ 406 return (DEVID_RET_INVALID); 407 } 408 /* 409 * the codeSet for this MUST 410 * be set to 1 411 */ 412 if ((dblk[0] & 0x0f) != 1) { 413 /* 414 * failed-IEEE E/R 415 * codeSet != 1. 416 */ 417 return (DEVID_RET_INVALID); 418 } 419 break; 420 421 case 0x60: /* IEEE EXT REG */ 422 if (dlen != 16) { 423 /* failed-IEEE ER len */ 424 return (DEVID_RET_INVALID); 425 } 426 /* 427 * the codeSet for this MUST 428 * be set to 1 429 */ 430 if ((dblk[0] & 0x0f) != 1) { 431 /* 432 * failed-IEEE ER 433 * codeSet != 1. 434 */ 435 return (DEVID_RET_INVALID); 436 } 437 break; 438 439 default: 440 /* reserved values */ 441 break; 442 } 443 break; 444 445 case SCMD_INQUIRY_VPD_TYPE_RTP: /* Relative Target port */ 446 if (dlen != 4) { 447 /* failed-Rel target Port length */ 448 return (DEVID_RET_INVALID); 449 } 450 break; 451 452 case SCMD_INQUIRY_VPD_TYPE_TPG: /* Target port group */ 453 if (dlen != 4) { 454 /* failed-target Port group length */ 455 return (DEVID_RET_INVALID); 456 } 457 break; 458 459 case SCMD_INQUIRY_VPD_TYPE_LUG: /* Logical unit group */ 460 if (dlen != 4) { 461 /* failed-Logical Unit group length */ 462 return (DEVID_RET_INVALID); 463 } 464 break; 465 466 case SCMD_INQUIRY_VPD_TYPE_MD5: /* MD5 unit group */ 467 if (dlen != 16) { 468 /* failed-MD5 Unit grp */ 469 return (DEVID_RET_INVALID); 470 } 471 break; 472 473 default: 474 break; 475 } 476 477 /* 478 * Now lets advance to the next descriptor block 479 * and validate it. 480 * the descriptor block size is <descr Header> + <descr Data> 481 * <descr Header> is equal to 4 bytes 482 * <descr Data> is available in dlen or dblk[3]. 483 */ 484 dblk = &dblk[4 + dlen]; 485 486 /* 487 * update the covered_desc_len so that we can ensure that 488 * the 'while' loop terminates. 489 */ 490 covered_desc_len += (dlen + 4); 491 } 492 return (DEVID_RET_VALID); 493 } 494 495 496 /* 497 * Function: is_initialized_id 498 * 499 * Description: Routine to ensure that the ID calculated is not a 500 * space or zero filled ID. Returning a space / zero 501 * filled ID when the luns on the target are not fully 502 * initialized is a valid response from the target as 503 * per the T10 spec. When a space/zero filled ID is 504 * found its information needs to be polled again 505 * after sometime time to see if the luns are fully 506 * initialized to return a valid guid information. 507 * 508 * Arguments: id - raw id 509 * id_len - raw id len 510 * 511 * Return Code: DEVID_VALID - indicates a non space/zero filled id 512 * DEVID_INVALID - indicates id contains uninitialized data 513 * and suggests retry of the collection commands. 514 */ 515 static int 516 is_initialized_id(uchar_t *id, size_t id_len) 517 { 518 int idx; 519 520 if ((id == NULL) || 521 (id_len == 0)) { 522 /* got id length as 0 fetch info again */ 523 return (DEVID_RET_INVALID); 524 } 525 526 /* First lets check if the guid is filled with spaces */ 527 for (idx = 0; idx < id_len; idx++) { 528 if (id[idx] != ' ') { 529 break; 530 } 531 } 532 533 /* 534 * Lets exit if we find that it contains ALL spaces 535 * saying that it has an uninitialized guid 536 */ 537 if (idx >= id_len) { 538 /* guid filled with spaces found */ 539 return (DEVID_RET_INVALID); 540 } 541 542 /* 543 * Since we have found that it is not filled with spaces 544 * now lets ensure that the guid is not filled with only 545 * zeros. 546 */ 547 for (idx = 0; idx < id_len; idx ++) { 548 if (id[idx] != 0) { 549 return (DEVID_RET_VALID); 550 } 551 } 552 553 /* guid filled with zeros found */ 554 return (DEVID_RET_INVALID); 555 } 556 557 558 /* 559 * Function: is_page80_data_valid 560 * 561 * Description: This routine is used to validate the page 0x80 data 562 * passed in valid based on the standards specification. 563 * 564 * Arguments: inq80 - 565 * inq80_len - 566 * 567 * Return Code: DEVID_RET_VALID 568 * DEVID_RET_INVALID 569 * 570 */ 571 /* ARGSUSED */ 572 static int 573 is_page80_data_valid(uchar_t *inq80, size_t inq80_len) 574 { 575 DEVID_ASSERT(inq80); 576 577 /* if not large enough fail */ 578 if (inq80_len < SCMD_MIN_INQUIRY_PAGE80_SIZE) { 579 return (DEVID_RET_INVALID); 580 } 581 582 /* 583 * (inq80_len - 4) is the size of the buffer space available 584 * for the product serial number. So inq80[3] (ie. product 585 * serial number) should be <= (inq80_len -4). 586 */ 587 if (inq80[3] > (inq80_len - 4)) { 588 return (DEVID_RET_INVALID); 589 } 590 591 return (DEVID_RET_VALID); 592 } 593 594 595 /* 596 * Function: encode_devid_page 597 * 598 * Description: This routine finds the unique devid if available and 599 * fills the devid and length parameters. 600 * 601 * Arguments: version - encode version 602 * inq83 - driver soft state (unit) structure 603 * inq83_len - length of raw inq83 data 604 * id - raw id 605 * id_len - len of raw id 606 * id_type - type of id 607 * 608 * Note: DEVID_NONE is returned in the id_type field 609 * if no supported page 83 id is found. 610 */ 611 static void 612 encode_scsi3_page83(int version, uchar_t *inq83, size_t inq83_len, 613 uchar_t **id, size_t *id_len, ushort_t *id_type) 614 { 615 size_t descriptor_bytes_left = 0; 616 size_t offset = 0; 617 int idx = 0; 618 size_t offset_id_type[4]; 619 620 DEVID_ASSERT(inq83 != NULL); 621 /* inq83 length was already validate in is_page83_valid */ 622 DEVID_ASSERT(id != NULL); 623 DEVID_ASSERT(id_len != NULL); 624 DEVID_ASSERT(id_type != NULL); 625 626 /* preset defaults */ 627 *id = NULL; 628 *id_len = 0; 629 *id_type = DEVID_NONE; 630 631 /* verify we have enough memory for a ident header */ 632 if (inq83_len < SCMD_INQUIRY_PAGE83_HDR_SIZE) { 633 return; 634 } 635 636 /* 637 * Attempt to validate the page data. Once validated, we'll walk 638 * the descriptors, looking for certain identifier types that will 639 * mark this device with a unique id/wwn. Note the comment below 640 * for what we really want to receive. 641 */ 642 643 /* 644 * The format of the inq83 data (Device Identification VPD page) is 645 * a header (containing the total length of the page, from which 646 * descriptor_bytes_left is calculated), followed by a list of 647 * identification descriptors. Each identifcation descriptor has a 648 * header which includes the length of the individual identification 649 * descriptor). 650 * 651 * Set the offset to the beginning byte of the first identification 652 * descriptor. We'll index everything from there. 653 */ 654 offset = SCMD_INQUIRY_PAGE83_HDR_SIZE; 655 descriptor_bytes_left = (size_t)((inq83[2] << 8) | inq83[3]); 656 657 /* 658 * If the raw data states that the data is larger 659 * than what is actually received abort encode. 660 * Otherwise we will run off into unknown memory 661 * on the decode. 662 */ 663 if ((descriptor_bytes_left + offset) > inq83_len) { 664 return; 665 } 666 667 668 /* Zero out our offset array */ 669 bzero(offset_id_type, sizeof (offset_id_type)); 670 671 /* 672 * According to the scsi spec 8.4.3 SPC-2, there could be several 673 * descriptors associated with each lun. Some we care about and some 674 * we don't. This loop is set up to iterate through the descriptors. 675 * We want the 0x03 case which represents an FC-PH, FC-PH3 or FC-FS 676 * Name_Identifier. The spec mentions nothing about ordering, so we 677 * don't assume any. 678 * 679 * We need to check if we've finished walking the list of descriptors, 680 * we also perform additional checks to be sure the newly calculated 681 * offset is within the bounds of the buffer, and the identifier length 682 * (as calculated by the length field in the header) is valid. This is 683 * done to protect against devices which return bad page83 data. 684 */ 685 while ((descriptor_bytes_left > 0) && (offset_id_type[3] == 0) && 686 (offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE <= inq83_len) && 687 (offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE + 688 (size_t)inq83[offset + 3] <= inq83_len)) { 689 /* 690 * Inspect the Identification descriptor list. Store the 691 * offsets in the devid page separately for 0x03, 0x01 and 692 * 0x02. Identifiers 0x00 and 0x04 are not useful as they 693 * don't represent unique identifiers for a lun. We also 694 * check the association by masking with 0x3f because we want 695 * an association of 0x0 - indicating the identifier field is 696 * associated with the addressed physical or logical device 697 * and not the port. 698 */ 699 switch ((inq83[offset + 1] & 0x3f)) { 700 case SCMD_INQUIRY_VPD_TYPE_T10: 701 offset_id_type[SCMD_INQUIRY_VPD_TYPE_T10] = offset; 702 break; 703 case SCMD_INQUIRY_VPD_TYPE_EUI: 704 offset_id_type[SCMD_INQUIRY_VPD_TYPE_EUI] = offset; 705 break; 706 case SCMD_INQUIRY_VPD_TYPE_NAA: 707 offset_id_type[SCMD_INQUIRY_VPD_TYPE_NAA] = offset; 708 break; 709 default: 710 /* Devid page undesired id type */ 711 break; 712 } 713 /* 714 * Calculate the descriptor bytes left and move to 715 * the beginning byte of the next id descriptor. 716 */ 717 descriptor_bytes_left -= (size_t)(inq83[offset + 3] + 718 SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE); 719 offset += (SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE + 720 (size_t)inq83[offset + 3]); 721 } 722 723 offset = 0; 724 725 /* 726 * We can't depend on an order from a device by identifier type, but 727 * once we have them, we'll walk them in the same order to prevent a 728 * firmware upgrade from breaking our algorithm. Start with the one 729 * we want the most: id_offset_type[3]. 730 */ 731 for (idx = 3; idx > 0; idx--) { 732 if (offset_id_type[idx] > 0) { 733 offset = offset_id_type[idx]; 734 break; 735 } 736 } 737 738 /* 739 * We have a valid Device ID page, set the length of the 740 * identifier and copy the value into the wwn. 741 */ 742 if (offset > 0) { 743 *id_len = (size_t)inq83[offset + 3]; 744 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 745 *id_len = 0; 746 return; 747 } 748 bcopy(&inq83[offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE], 749 *id, *id_len); 750 751 /* set devid type */ 752 switch (version) { 753 /* In version 1 all page 83 types were grouped */ 754 case DEVID_SCSI_ENCODE_VERSION1: 755 *id_type = DEVID_SCSI3_WWN; 756 break; 757 /* In version 2 we break page 83 apart to be unique */ 758 case DEVID_SCSI_ENCODE_VERSION2: 759 switch (idx) { 760 case 3: 761 *id_type = DEVID_SCSI3_VPD_NAA; 762 break; 763 case 2: 764 *id_type = DEVID_SCSI3_VPD_EUI; 765 break; 766 case 1: 767 *id_type = DEVID_SCSI3_VPD_T10; 768 break; 769 default: 770 DEVID_FREE(*id, *id_len); 771 *id_len = 0; 772 break; 773 } 774 break; 775 default: 776 DEVID_FREE(*id, *id_len); 777 *id_len = 0; 778 break; 779 } 780 } 781 } 782 783 784 /* 785 * Function: encode_scsi3_page83_emc 786 * 787 * Description: Routine to handle proprietary page 83 of EMC Symmetrix 788 * device. Called by ssfcp_handle_page83() 789 * 790 * Arguments: version - encode version 791 * inq83 - scsi page 83 buffer 792 * inq83_len - scsi page 83 buffer size 793 * id - raw emc id 794 * id_len - len of raw emc id 795 * id_type - type of emc id 796 */ 797 static void 798 encode_scsi3_page83_emc(int version, uchar_t *inq83, 799 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 800 { 801 uchar_t *guidp = NULL; 802 803 DEVID_ASSERT(inq83 != NULL); 804 DEVID_ASSERT(id != NULL); 805 DEVID_ASSERT(id_len != NULL); 806 DEVID_ASSERT(id_type != NULL); 807 808 /* preset defaults */ 809 *id = NULL; 810 *id_len = 0; 811 *id_type = DEVID_NONE; 812 813 /* The initial devid algorithm didn't use EMC page 83 data */ 814 if (version == DEVID_SCSI_ENCODE_VERSION1) { 815 return; 816 } 817 818 /* EMC page 83 requires atleast 20 bytes */ 819 if (inq83_len < (SCMD_INQUIRY_PAGE83_HDR_SIZE + 820 SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN)) { 821 return; 822 } 823 824 /* 825 * The 4th byte in the page 83 info returned is most likely 826 * indicating the length of the id - which 0x10(16 bytes) 827 * and the 5th byte is indicating that the id is of 828 * IEEE Registered Extended Name format(6). Validate 829 * these code prints before proceeding further as the 830 * following proprietary approach is tied to the specific 831 * device type and incase the EMC firmware changes, we will 832 * have to validate for the changed device before we start 833 * supporting such a device. 834 */ 835 if ((inq83[3] != 0x10) || (inq83[4] != 0x60)) { 836 /* unsupported emc symtx device type */ 837 return; 838 } else { 839 guidp = &inq83[SCMD_INQUIRY_PAGE83_HDR_SIZE]; 840 /* 841 * The GUID returned by the EMC device is 842 * in the IEEE Registered Extended Name format(6) 843 * as a result it is of 16 bytes in length. 844 * An IEEE Registered Name format(5) will be of 845 * 8 bytes which is NOT what is being returned 846 * by the device type for which we are providing 847 * the support. 848 */ 849 *id_len = SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN; 850 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 851 *id_len = 0; 852 return; 853 } 854 bcopy(guidp, *id, *id_len); 855 856 /* emc id matches type 3 */ 857 *id_type = DEVID_SCSI3_VPD_NAA; 858 } 859 } 860 861 862 /* 863 * Function: encode_serialnum 864 * 865 * Description: This routine finds the unique devid from the inquiry page 866 * 0x80, serial number page. If available and fills the wwn 867 * and length parameters. 868 * 869 * Arguments: version - encode version 870 * inq - standard inquiry data 871 * inq80 - serial inquiry data 872 * inq80_len - serial inquiry data len 873 * id - raw id 874 * id_len - raw id len 875 * id_type - raw id type 876 */ 877 /* ARGSUSED */ 878 static void 879 encode_serialnum(int version, uchar_t *inq, uchar_t *inq80, 880 size_t inq80_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 881 { 882 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 883 int idx = 0; 884 885 DEVID_ASSERT(inq != NULL); 886 DEVID_ASSERT(inq80 != NULL); 887 DEVID_ASSERT(id != NULL); 888 DEVID_ASSERT(id_len != NULL); 889 DEVID_ASSERT(id_type != NULL); 890 891 /* preset defaults */ 892 *id = NULL; 893 *id_len = 0; 894 *id_type = DEVID_NONE; 895 896 /* verify inq80 buffer is large enough for a header */ 897 if (inq80_len < SCMD_MIN_INQUIRY_PAGE80_SIZE) { 898 return; 899 } 900 901 /* 902 * Attempt to validate the page data. Once validated, we'll check 903 * the serial number. 904 */ 905 *id_len = (size_t)inq80[3]; /* Store Product Serial Number length */ 906 907 /* verify buffer is large enough for serial number */ 908 if (inq80_len < (*id_len + SCMD_MIN_INQUIRY_PAGE80_SIZE)) { 909 return; 910 } 911 912 /* 913 * Device returns ASCII space (20h) in all the bytes of successful data 914 * transfer, if the product serial number is not available. So we end 915 * up having to check all the bytes for a space until we reach 916 * something else. 917 */ 918 for (idx = 0; idx < *id_len; idx++) { 919 if (inq80[4 + idx] == ' ') { 920 continue; 921 } 922 /* 923 * The serial number is valid, but since this is only vendor 924 * unique, we'll combine the inquiry vid and pid with the 925 * serial number. 926 */ 927 *id_len += sizeof (inq_std->inq_vid); 928 *id_len += sizeof (inq_std->inq_pid); 929 930 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 931 *id_len = 0; 932 return; 933 } 934 935 bcopy(&inq_std->inq_vid, *id, sizeof (inq_std->inq_vid)); 936 bcopy(&inq_std->inq_pid, &(*id)[sizeof (inq_std->inq_vid)], 937 sizeof (inq_std->inq_pid)); 938 bcopy(&inq80[4], &(*id)[sizeof (inq_std->inq_vid) + 939 sizeof (inq_std->inq_pid)], inq80[3]); 940 941 *id_type = DEVID_SCSI_SERIAL; 942 break; 943 } 944 945 /* 946 * The spec suggests that the command could succeed but return all 947 * spaces if the product serial number is not available. In this case 948 * we need to fail this routine. To accomplish this, we compare our 949 * length to the serial number length. If they are the same, then we 950 * never copied in the vid and updated the length. That being the case, 951 * we must not have found a valid serial number. 952 */ 953 if (*id_len == (size_t)inq80[3]) { 954 /* empty unit serial number */ 955 DEVID_FREE(*id, *id_len); 956 *id = NULL; 957 *id_len = 0; 958 } 959 } 960 961 962 /* 963 * Function: encode_sun_serialnum 964 * 965 * Description: This routine finds the unique devid from the inquiry page 966 * 0x80, serial number page. If available and fills the wwn 967 * and length parameters. 968 * 969 * Arguments: version - encode version 970 * inq - standard inquiry data 971 * inq_len - standard inquiry data len 972 * id - raw id 973 * id_len - raw id len 974 * id_type - raw id type 975 * 976 * Return Code: DEVID_SUCCESS 977 * DEVID_FAILURE 978 */ 979 /* ARGSUSED */ 980 static void 981 encode_sun_serialnum(int version, uchar_t *inq, 982 size_t inq_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 983 { 984 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 985 986 DEVID_ASSERT(inq != NULL); 987 DEVID_ASSERT(id != NULL); 988 DEVID_ASSERT(id_len != NULL); 989 DEVID_ASSERT(id_type != NULL); 990 991 /* verify enough buffer is available */ 992 if (inq_len < SCMD_MIN_STANDARD_INQUIRY_SIZE) { 993 return; 994 } 995 996 /* sun qual drive */ 997 if ((inq_std != NULL) && 998 (bcmp(&inq_std->inq_pid[SCSI_INQUIRY_VID_POS], 999 SCSI_INQUIRY_VID_SUN, SCSI_INQUIRY_VID_SUN_LEN) == 0)) { 1000 /* 1001 * VPD pages 0x83 and 0x80 are unavailable. This 1002 * is a Sun qualified disks as indicated by 1003 * "SUN" in bytes 25-27 of the inquiry data 1004 * (bytes 9-11 of the pid). Devid's are created 1005 * for Sun qualified disks by combining the 1006 * vendor id with the product id with the serial 1007 * number located in bytes 36-47 of the inquiry data. 1008 */ 1009 1010 /* get data size */ 1011 *id_len = sizeof (inq_std->inq_vid) + 1012 sizeof (inq_std->inq_pid) + 1013 sizeof (inq_std->inq_serial); 1014 1015 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 1016 *id_len = 0; 1017 return; 1018 } 1019 1020 /* copy the vid at the beginning */ 1021 bcopy(&inq_std->inq_vid, *id, 1022 sizeof (inq_std->inq_vid)); 1023 /* copy the pid after the vid */ 1024 bcopy(&inq_std->inq_pid, 1025 &(*id)[sizeof (inq_std->inq_vid)], 1026 sizeof (inq_std->inq_pid)); 1027 /* copy the serial number after the vid and pid */ 1028 bcopy(&inq_std->inq_serial, 1029 &(*id)[sizeof (inq_std->inq_vid) + 1030 sizeof (inq_std->inq_pid)], 1031 sizeof (inq_std->inq_serial)); 1032 /* devid formed from inquiry data */ 1033 *id_type = DEVID_SCSI_SERIAL; 1034 } 1035 } 1036 1037 1038 /* 1039 * Function: devid_scsi_init 1040 * 1041 * Description: This routine is used to create a devid for a scsi 1042 * devid type. 1043 * 1044 * Arguments: hint - driver soft state (unit) structure 1045 * raw_id - pass by reference variable to hold wwn 1046 * raw_id_len - wwn length 1047 * raw_id_type - 1048 * ret_devid - 1049 * 1050 * Return Code: DEVID_SUCCESS 1051 * DEVID_FAILURE 1052 * 1053 */ 1054 static int 1055 devid_scsi_init( 1056 char *driver_name, 1057 uchar_t *raw_id, 1058 size_t raw_id_len, 1059 ushort_t raw_id_type, 1060 ddi_devid_t *ret_devid) 1061 { 1062 impl_devid_t *i_devid = NULL; 1063 int i_devid_len = 0; 1064 int driver_name_len = 0; 1065 ushort_t u_raw_id_len = 0; 1066 1067 DEVID_ASSERT(raw_id != NULL); 1068 DEVID_ASSERT(ret_devid != NULL); 1069 1070 if (!IS_DEVID_SCSI_TYPE(raw_id_type)) { 1071 *ret_devid = NULL; 1072 return (DEVID_FAILURE); 1073 } 1074 1075 i_devid_len = sizeof (*i_devid) + raw_id_len - sizeof (i_devid->did_id); 1076 if ((i_devid = DEVID_MALLOC(i_devid_len)) == NULL) { 1077 *ret_devid = NULL; 1078 return (DEVID_FAILURE); 1079 } 1080 1081 i_devid->did_magic_hi = DEVID_MAGIC_MSB; 1082 i_devid->did_magic_lo = DEVID_MAGIC_LSB; 1083 i_devid->did_rev_hi = DEVID_REV_MSB; 1084 i_devid->did_rev_lo = DEVID_REV_LSB; 1085 DEVID_FORMTYPE(i_devid, raw_id_type); 1086 u_raw_id_len = raw_id_len; 1087 DEVID_FORMLEN(i_devid, u_raw_id_len); 1088 1089 /* Fill in driver name hint */ 1090 if (driver_name != NULL) { 1091 driver_name_len = strlen(driver_name); 1092 if (driver_name_len > DEVID_HINT_SIZE) { 1093 /* Pick up last four characters of driver name */ 1094 driver_name += driver_name_len - DEVID_HINT_SIZE; 1095 driver_name_len = DEVID_HINT_SIZE; 1096 } 1097 bcopy(driver_name, i_devid->did_driver, driver_name_len); 1098 } else { 1099 bzero(i_devid->did_driver, DEVID_HINT_SIZE); 1100 } 1101 1102 bcopy(raw_id, i_devid->did_id, raw_id_len); 1103 1104 /* return device id */ 1105 *ret_devid = (ddi_devid_t)i_devid; 1106 return (DEVID_SUCCESS); 1107 } 1108 1109 1110 /* 1111 * Function: devid_to_guid 1112 * 1113 * Description: This routine extracts a guid string form a devid. 1114 * The common use of this guid is for a HBA driver 1115 * to pass into mdi_pi_alloc(). 1116 * 1117 * Arguments: devid - devid to extract guid from 1118 * 1119 * Return Code: guid string - success 1120 * NULL - failure 1121 */ 1122 char * 1123 #ifdef _KERNEL 1124 ddi_devid_to_guid(ddi_devid_t devid) 1125 #else /* !_KERNEL */ 1126 devid_to_guid(ddi_devid_t devid) 1127 #endif /* _KERNEL */ 1128 { 1129 impl_devid_t *id = (impl_devid_t *)devid; 1130 int len = 0; 1131 int idx = 0; 1132 int num = 0; 1133 char *guid = NULL; 1134 char *ptr = NULL; 1135 char *dp = NULL; 1136 1137 DEVID_ASSERT(devid != NULL); 1138 1139 /* NULL devid -> NULL guid */ 1140 if (devid == NULL) 1141 return (NULL); 1142 1143 if (!IS_DEVID_GUID_TYPE(DEVID_GETTYPE(id))) 1144 return (NULL); 1145 1146 /* guid is always converted to ascii, append NULL */ 1147 len = DEVID_GETLEN(id); 1148 1149 /* allocate guid string */ 1150 if ((guid = DEVID_MALLOC((len * 2) + 1)) == NULL) 1151 return (NULL); 1152 1153 /* perform encode of id to hex string */ 1154 ptr = guid; 1155 for (idx = 0, dp = &id->did_id[0]; idx < len; idx++, dp++) { 1156 num = ((*dp) >> 4) & 0xF; 1157 *ptr++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 1158 num = (*dp) & 0xF; 1159 *ptr++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 1160 } 1161 *ptr = 0; 1162 1163 return (guid); 1164 } 1165 1166 /* 1167 * Function: devid_free_guid 1168 * 1169 * Description: This routine frees a guid allocated by 1170 * devid_to_guid(). 1171 * 1172 * Arguments: guid - guid to free 1173 */ 1174 void 1175 #ifdef _KERNEL 1176 ddi_devid_free_guid(char *guid) 1177 #else /* !_KERNEL */ 1178 devid_free_guid(char *guid) 1179 #endif /* _KERNEL */ 1180 { 1181 if (guid != NULL) { 1182 DEVID_FREE(guid, strlen(guid) + 1); 1183 } 1184 } 1185