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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Copyright 2016 Joyent, Inc. 27 */ 28 29 /* 30 * sd / ssd (SCSI Direct-attached Device) specific functions. 31 */ 32 33 #include <libnvpair.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <sys/types.h> 38 #include <sys/sysmacros.h> 39 #include <sys/queue.h> 40 #include <sys/stat.h> 41 #include <fcntl.h> 42 #include <string.h> 43 #include <errno.h> 44 #include <scsi/libscsi.h> 45 #include <sys/scsi/scsi_types.h> 46 #include <libintl.h> /* for gettext(3c) */ 47 #include <fwflash/fwflash.h> 48 #include <sys/debug.h> 49 #include <umem.h> 50 51 typedef struct sam4_statdesc { 52 int sam_status; 53 char *sam_message; 54 } sam4_statdesc_t; 55 56 static sam4_statdesc_t sam4_status[] = { 57 { SAM4_STATUS_GOOD, "Status: GOOD (success)" }, 58 { SAM4_STATUS_CHECK_CONDITION, "Status: CHECK CONDITION" }, 59 { SAM4_STATUS_CONDITION_MET, "Status: CONDITION MET" }, 60 { SAM4_STATUS_BUSY, "Status: Device is BUSY" }, 61 { SAM4_STATUS_RESERVATION_CONFLICT, "Status: Device is RESERVED" }, 62 { SAM4_STATUS_TASK_SET_FULL, 63 "Status: TASK SET FULL (insufficient resources in command queue" }, 64 { SAM4_STATUS_TASK_ABORTED, "Status: TASK ABORTED" } 65 }; 66 67 #define NSAM4_STATUS (sizeof (sam4_status) / sizeof (sam4_status[0])) 68 69 #define FW_SD_FREE_DEVPATH(devpath) { \ 70 di_devfs_path_free((devpath)); \ 71 } 72 #define FW_SD_FREE_DEVICELIST(thisdev, devpath) { \ 73 free((thisdev)); \ 74 FW_SD_FREE_DEVPATH((devpath)) \ 75 } 76 #define FW_SD_FREE_DRV_NAME(thisdev, devpath) { \ 77 free((thisdev)->drvname); \ 78 FW_SD_FREE_DEVICELIST((thisdev), (devpath)) \ 79 } 80 #define FW_SD_FREE_CLS_NAME(thisdev, devpath) { \ 81 free((thisdev)->classname); \ 82 FW_SD_FREE_DRV_NAME((thisdev), (devpath)) \ 83 } 84 #define FW_SD_FREE_ACC_NAME(thisdev, devpath) { \ 85 free((thisdev)->access_devname); \ 86 FW_SD_FREE_CLS_NAME(thisdev, devpath) \ 87 } 88 #define FW_SD_FREE_ADDR(thisdev, devpath) { \ 89 free((thisdev)->addresses[0]); \ 90 FW_SD_FREE_ACC_NAME(thisdev, devpath) \ 91 } 92 #define FW_SD_FREE_IDENT(thisdev, devpath) { \ 93 free((thisdev)->ident); \ 94 FW_SD_FREE_ADDR((thisdev), (devpath)) \ 95 } 96 #define FW_SD_FREE_IDENT_VID(thisdev, devpath) { \ 97 free((thisdev)->ident->vid); \ 98 FW_SD_FREE_IDENT((thisdev), (devpath)) \ 99 } 100 #define FW_SD_FREE_IDENT_PID(thisdev, devpath) { \ 101 free((thisdev)->ident->pid); \ 102 FW_SD_FREE_IDENT_VID((thisdev), (devpath)) \ 103 } 104 #define FW_SD_FREE_IDENT_ALL(thisdev, devpath) { \ 105 free((thisdev)->ident->revid); \ 106 FW_SD_FREE_IDENT_PID((thisdev), (devpath)) \ 107 } 108 109 /* 110 * This is our default partial write size when we encounter a situation where we 111 * need to upgrade disks whose firmware image cannot be done in a single write. 112 * While in theory we should just use the maximum transfer size and make sure 113 * it's aligned, that's proven to be problematic for some Seagate disks. Hence 114 * we just make sure that if partial writes are required that this value fits in 115 * the required alignment and in the actual maximum transfer size. 116 */ 117 #define FW_SD_PARTIAL_WRITE_SIZE (64 * 1024) 118 119 /* 120 * Declarations required for fwflash 121 */ 122 char drivername[] = "sd\0"; 123 int plugin_version = FWPLUGIN_VERSION_2; 124 125 /* 126 * Data provided by fwflash 127 */ 128 extern di_node_t rootnode; 129 extern struct fw_plugin *self; 130 extern struct vrfyplugin *verifier; 131 extern int fwflash_debug; 132 133 static char *sdfw_devprefix = "/devices"; 134 135 static char *sdfw_find_link(di_node_t bnode, char *acc_devname); 136 static int sdfw_link_cb(di_devlink_t devlink, void *arg); 137 static int sdfw_idtfy_custmz(struct devicelist *device, char *sp); 138 139 /* 140 * We don't currently support reading firmware from a disk. If we do eventually 141 * support it, we would use the scsi READ BUFFER command to do so. 142 */ 143 int 144 fw_readfw(struct devicelist *flashdev, char *filename) 145 { 146 147 logmsg(MSG_INFO, 148 "%s: not writing firmware for device %s to file %s\n", 149 flashdev->drvname, flashdev->access_devname, filename); 150 logmsg(MSG_ERROR, 151 gettext("\n\nReading of firmware images from %s-attached " 152 "devices is not supported\n\n"), 153 flashdev->drvname); 154 155 return (FWFLASH_SUCCESS); 156 } 157 158 159 static int 160 sdfw_read_descriptor(struct devicelist *flashdev, libscsi_hdl_t *hdl, 161 libscsi_target_t *targ, uint8_t *align) 162 { 163 spc3_read_buffer_cdb_t *rb_cdb; 164 size_t nwritten; 165 libscsi_action_t *action = NULL; 166 uint8_t descbuf[4]; 167 sam4_status_t samstatus; 168 169 VERIFY3P(hdl, !=, NULL); 170 VERIFY3P(targ, !=, NULL); 171 VERIFY3P(align, !=, NULL); 172 173 if ((action = libscsi_action_alloc(hdl, SPC3_CMD_READ_BUFFER, 174 LIBSCSI_AF_READ, descbuf, sizeof (descbuf))) == NULL) { 175 logmsg(MSG_ERROR, gettext("%s: failed to alloc scsi action: " 176 "%s\n"), 177 flashdev->drvname, libscsi_errmsg(hdl)); 178 return (FWFLASH_FAILURE); 179 } 180 181 rb_cdb = (spc3_read_buffer_cdb_t *)libscsi_action_get_cdb(action); 182 183 rb_cdb->rbc_mode = SPC3_RB_MODE_DESCRIPTOR; 184 185 /* 186 * Microcode upgrade usually only uses the first buffer ID which is 187 * sequentially indexed from zero. Strictly speaking these are all 188 * vendor defined, but so far most vendors we've seen use index zero 189 * for this. 190 */ 191 rb_cdb->rbc_bufferid = 0; 192 193 rb_cdb->rbc_allocation_len[0] = 0; 194 rb_cdb->rbc_allocation_len[1] = 0; 195 rb_cdb->rbc_allocation_len[2] = sizeof (descbuf); 196 197 if (libscsi_exec(action, targ) != 0) { 198 logmsg(MSG_ERROR, gettext("%s: failed to execute SCSI buffer " 199 "data read: %s\n"), 200 flashdev->drvname, libscsi_errmsg(hdl)); 201 libscsi_action_free(action); 202 return (FWFLASH_FAILURE); 203 } 204 205 if ((samstatus = libscsi_action_get_status(action)) != 206 SAM4_STATUS_GOOD) { 207 int i; 208 for (i = 0; i < NSAM4_STATUS; i++) { 209 if (samstatus == sam4_status[i].sam_status) { 210 logmsg(MSG_ERROR, gettext("%s: SCSI buffer " 211 "data read failed: %s\n"), 212 flashdev->drvname, 213 sam4_status[i].sam_message); 214 libscsi_action_free(action); 215 return (FWFLASH_FAILURE); 216 } 217 } 218 logmsg(MSG_ERROR, gettext("%s: SCSI buffer data read failed: " 219 "unknown error: %d\n"), flashdev->drvname, samstatus); 220 libscsi_action_free(action); 221 return (FWFLASH_FAILURE); 222 } 223 224 if (libscsi_action_get_buffer(action, NULL, NULL, &nwritten) != 0) { 225 logmsg(MSG_ERROR, gettext("%s: failed to get actual data " 226 "size: %s\n"), 227 flashdev->drvname, libscsi_errmsg(hdl)); 228 libscsi_action_free(action); 229 return (FWFLASH_FAILURE); 230 } 231 libscsi_action_free(action); 232 233 if (nwritten != sizeof (descbuf)) { 234 logmsg(MSG_ERROR, gettext("%s: received a short read from the " 235 "SCSI READ BUFFER command, expected %u bytes, read %zu\n"), 236 flashdev->drvname, sizeof (descbuf), nwritten); 237 return (FWFLASH_FAILURE); 238 } 239 240 if (descbuf[0] == 0 && descbuf[1] == 0 && descbuf[2] == 0 && 241 descbuf[3] == 0) { 242 logmsg(MSG_ERROR, gettext("%s: devices %s does not support " 243 "firmware upgrade\n"), verifier->vendor, 244 flashdev->access_devname); 245 return (FWFLASH_FAILURE); 246 } 247 248 *align = descbuf[0]; 249 250 return (FWFLASH_SUCCESS); 251 } 252 253 static int 254 sdfw_write(struct devicelist *flashdev, libscsi_hdl_t *handle, 255 libscsi_target_t *target, size_t len, size_t off, void *buf) 256 { 257 sam4_status_t samstatus; 258 libscsi_action_t *action = NULL; 259 spc3_write_buffer_cdb_t *wb_cdb; 260 261 logmsg(MSG_INFO, "%s: writing %u bytes of image %s at offset %zu from " 262 "address %p\n", flashdev->drvname, len, verifier->imgfile, off, 263 buf); 264 logmsg(MSG_INFO, "%s: writing to buffer id %u\n", 265 flashdev->drvname, verifier->flashbuf); 266 267 VERIFY3P(flashdev, !=, NULL); 268 VERIFY3P(handle, !=, NULL); 269 VERIFY3P(target, !=, NULL); 270 VERIFY3P(buf, !=, NULL); 271 VERIFY3U(len, >, 0); 272 VERIFY3U(off + len, <=, verifier->imgsize); 273 274 action = libscsi_action_alloc(handle, SPC3_CMD_WRITE_BUFFER, 275 LIBSCSI_AF_WRITE | LIBSCSI_AF_RQSENSE | LIBSCSI_AF_ISOLATE, buf, 276 len); 277 if (action == NULL) { 278 logmsg(MSG_ERROR, gettext("%s: failed to alloc scsi action: " 279 "%s\n"), flashdev->drvname, libscsi_errmsg(handle)); 280 goto err; 281 } 282 283 wb_cdb = (spc3_write_buffer_cdb_t *)libscsi_action_get_cdb(action); 284 285 wb_cdb->wbc_mode = SPC3_WB_MODE_DL_UCODE_OFFS_SAVE; 286 287 wb_cdb->wbc_buffer_offset[0] = (off >> 16) & 0xff; 288 wb_cdb->wbc_buffer_offset[1] = (off >> 8) & 0xff; 289 wb_cdb->wbc_buffer_offset[2] = off & 0xff; 290 291 wb_cdb->wbc_bufferid = verifier->flashbuf; 292 293 wb_cdb->wbc_parameter_list_len[0] = (len >> 16) & 0xff; 294 wb_cdb->wbc_parameter_list_len[1] = (len >> 8) & 0xff; 295 wb_cdb->wbc_parameter_list_len[2] = len & 0xff; 296 297 logmsg(MSG_INFO, "%s: spc3_write_buffer_cdb_t opcode: %u\n", 298 flashdev->drvname, wb_cdb->wbc_opcode); 299 300 if (libscsi_exec(action, target) != 0) { 301 logmsg(MSG_ERROR, gettext("%s: failed to execute SCSI WRITE " 302 "BUFFER: %s\n"), 303 flashdev->drvname, libscsi_errmsg(handle)); 304 goto err; 305 } 306 307 if ((samstatus = libscsi_action_get_status(action)) == 308 SAM4_STATUS_CHECK_CONDITION) { 309 uint64_t asc = 0, ascq = 0, key = 0; 310 const char *code, *keystr; 311 312 if (libscsi_action_parse_sense(action, &key, &asc, &ascq, 313 NULL) != 0) { 314 logmsg(MSG_ERROR, gettext("%s: failed to write " 315 "firmware. Received CHECK_CONDITION that cannot be " 316 "parsed.\n"), 317 flashdev->drvname); 318 goto err; 319 } 320 321 code = libscsi_sense_code_name(asc, ascq); 322 keystr = libscsi_sense_key_name(key); 323 324 logmsg(MSG_ERROR, gettext("%s: failed to write firmware: " 325 "received sense key %" PRIu64 " (%s) additional sense code " 326 "0x%" PRIx64 "/0x%" PRIx64 " (%s)\n"), flashdev->drvname, 327 key, keystr != NULL ? keystr : "<unknown>", 328 asc, ascq, code != NULL ? code : "<unknown>"); 329 goto err; 330 } else if (samstatus != SAM4_STATUS_GOOD) { 331 int i; 332 333 logmsg(MSG_ERROR, gettext("%s: SCSI buffer data write failed:"), 334 flashdev->drvname); 335 for (i = 0; i < NSAM4_STATUS; i++) { 336 if (samstatus == sam4_status[i].sam_status) { 337 logmsg(MSG_ERROR, gettext("%s\n"), 338 sam4_status[i].sam_message); 339 goto err; 340 } 341 } 342 logmsg(MSG_ERROR, gettext("unknown error: %d\n"), samstatus); 343 goto err; 344 } else { 345 logmsg(MSG_INFO, "%s: received STATUS GOOD\n", 346 flashdev->drvname); 347 } 348 349 libscsi_action_free(action); 350 return (FWFLASH_SUCCESS); 351 352 err: 353 if (action != NULL) 354 libscsi_action_free(action); 355 return (FWFLASH_FAILURE); 356 } 357 358 int 359 fw_writefw(struct devicelist *flashdev) 360 { 361 libscsi_hdl_t *handle; 362 libscsi_target_t *target; 363 libscsi_errno_t serr; 364 size_t maxxfer, nwrite; 365 uint8_t align; 366 int ret = FWFLASH_FAILURE; 367 368 if ((verifier == NULL) || (verifier->imgsize == 0) || 369 (verifier->fwimage == NULL)) { 370 /* should _NOT_ happen */ 371 logmsg(MSG_ERROR, 372 gettext("%s: Firmware image has not been verified\n"), 373 flashdev->drvname); 374 return (FWFLASH_FAILURE); 375 } 376 377 if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) { 378 logmsg(MSG_ERROR, gettext("%s: failed to initialize libscsi\n"), 379 flashdev->drvname); 380 return (FWFLASH_FAILURE); 381 } 382 383 if ((target = libscsi_open(handle, NULL, flashdev->access_devname)) == 384 NULL) { 385 logmsg(MSG_ERROR, 386 gettext("%s: unable to open device %s\n"), 387 flashdev->drvname, flashdev->access_devname); 388 libscsi_fini(handle); 389 return (FWFLASH_FAILURE); 390 } 391 392 if (libscsi_max_transfer(target, &maxxfer) != 0) { 393 logmsg(MSG_ERROR, gettext("%s: failed to determine device " 394 "maximum transfer size: %s\n"), flashdev->drvname, 395 libscsi_errmsg(handle)); 396 goto err; 397 } 398 399 if (sdfw_read_descriptor(flashdev, handle, target, &align) != 400 FWFLASH_SUCCESS) { 401 goto err; 402 } 403 404 /* 405 * If the maximum transfer size is less than the maximum image size then 406 * we have to do some additional work. We need to read the descriptor 407 * via a READ BUFFER command and make sure that we support the required 408 * offset alignment. Note that an alignment of 0xff indicates that the 409 * device does not support partial writes and must receive the firmware 410 * in a single WRITE BUFFER. Otherwise a value in align represents a 411 * required offset alignment of 2^off. From there, we make sure that 412 * this works for our partial write size and that our partial write size 413 * fits in the maximum transfer size. 414 */ 415 if (maxxfer < verifier->imgsize) { 416 logmsg(MSG_INFO, "%s: Maximum transfer is %zu, required " 417 "alignment is 2^%u\n", flashdev->drvname, maxxfer, align); 418 if (FW_SD_PARTIAL_WRITE_SIZE > maxxfer) { 419 logmsg(MSG_ERROR, gettext("%s: cannot write firmware " 420 "image: HBA enforces a maximum transfer size of " 421 "%zu bytes, but the default partial transfer size " 422 "is %u bytes\n"), flashdev->drvname, maxxfer, 423 FW_SD_PARTIAL_WRITE_SIZE); 424 goto err; 425 } 426 maxxfer = FW_SD_PARTIAL_WRITE_SIZE; 427 428 if (ffsll(maxxfer) < align || align == 0xff) { 429 logmsg(MSG_ERROR, gettext("%s: cannot write firmware " 430 "image: device requires partial writes aligned " 431 "to an unsupported value\n"), flashdev->drvname); 432 goto err; 433 } 434 435 logmsg(MSG_INFO, "%s: final transfer block size is %zu\n", 436 flashdev->drvname, maxxfer); 437 } 438 439 logmsg(MSG_INFO, "%s: Writing out %u bytes to %s\n", flashdev->drvname, 440 verifier->imgsize, flashdev->access_devname); 441 nwrite = 0; 442 for (;;) { 443 uintptr_t buf; 444 size_t towrite = MIN(maxxfer, verifier->imgsize - nwrite); 445 446 if (towrite == 0) 447 break; 448 449 buf = (uintptr_t)verifier->fwimage; 450 buf += nwrite; 451 452 if (sdfw_write(flashdev, handle, target, towrite, nwrite, 453 (void *)buf) != FWFLASH_SUCCESS) { 454 logmsg(MSG_ERROR, gettext("%s: failed to write to %s " 455 "successfully: %s\n"), flashdev->drvname, 456 flashdev->access_devname, libscsi_errmsg(handle)); 457 goto err; 458 } 459 460 nwrite += towrite; 461 } 462 463 logmsg(MSG_ERROR, gettext("Note: For flash based disks " 464 "(SSD, etc). You may need power off the system to wait a " 465 "few minutes for supercap to fully discharge, then power " 466 "on the system again to activate the new firmware\n")); 467 ret = FWFLASH_SUCCESS; 468 469 err: 470 if (target != NULL) 471 libscsi_close(handle, target); 472 if (handle != NULL) 473 libscsi_fini(handle); 474 475 return (ret); 476 } 477 478 /* 479 * The fw_identify() function walks the device 480 * tree trying to find devices which this plugin 481 * can work with. 482 * 483 * The parameter "start" gives us the starting index number 484 * to give the device when we add it to the fw_devices list. 485 * 486 * firstdev is allocated by us and we add space as needed 487 * 488 * When we store the desired information, inquiry-serial-no 489 * goes in thisdev->addresses[1], and client-guid goes in 490 * thisdev->addresses[2]. 491 */ 492 int 493 fw_identify(int start) 494 { 495 int idx = start; 496 int fw_sata_disk = 0; 497 int *exists; 498 di_node_t thisnode; 499 struct devicelist *newdev = NULL; 500 char *devpath = NULL; 501 char *driver = NULL; 502 char *sp_temp; 503 char *sp_temp_cut; 504 505 /* We need to inquiry information manually by sending probe command */ 506 libscsi_hdl_t *handle; 507 libscsi_target_t *target; 508 libscsi_errno_t serr; 509 510 /* Just in case we've got an FC-attached device on sparc */ 511 if (strcmp(self->drvname, "ssd") == 0) { 512 driver = self->drvname; 513 } else 514 driver = drivername; 515 516 thisnode = di_drv_first_node(driver, rootnode); 517 518 if (thisnode == DI_NODE_NIL) { 519 logmsg(MSG_INFO, "No %s nodes in this system\n", driver); 520 return (FWFLASH_FAILURE); 521 } 522 523 if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) { 524 logmsg(MSG_ERROR, gettext("%s: failed to initialize " 525 "libscsi\n"), newdev->drvname); 526 return (FWFLASH_FAILURE); 527 } 528 529 /* we've found one, at least */ 530 for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) { 531 /* Need to free by di_devfs_path_free */ 532 if ((devpath = di_devfs_path(thisnode)) == NULL) { 533 logmsg(MSG_INFO, "unable to get device path for " 534 "current node with errno %d\n", errno); 535 continue; 536 } 537 /* 538 * We check if this is removable device, in which case 539 * we really aren't interested, so exit stage left 540 */ 541 if (di_prop_lookup_ints(DDI_DEV_T_ANY, thisnode, 542 "removable-media", &exists) > -1) { 543 logmsg(MSG_INFO, 544 "%s: not interested in removable media device\n" 545 "%s\n", driver, devpath); 546 FW_SD_FREE_DEVPATH(devpath) 547 continue; 548 } 549 550 if ((newdev = calloc(1, sizeof (struct devicelist))) == 551 NULL) { 552 logmsg(MSG_ERROR, 553 gettext("%s: identification function unable " 554 "to allocate space for device entry\n"), 555 driver); 556 libscsi_fini(handle); 557 FW_SD_FREE_DEVPATH(devpath) 558 return (FWFLASH_FAILURE); 559 } 560 561 if ((newdev->drvname = calloc(1, strlen(driver) + 1)) == 562 NULL) { 563 logmsg(MSG_ERROR, 564 gettext("%s: Unable to allocate space to store a " 565 "driver name\n"), driver); 566 libscsi_fini(handle); 567 FW_SD_FREE_DEVICELIST(newdev, devpath) 568 return (FWFLASH_FAILURE); 569 } 570 (void) strlcpy(newdev->drvname, driver, strlen(driver) + 1); 571 572 if ((newdev->classname = calloc(1, strlen(driver) + 1)) == 573 NULL) { 574 logmsg(MSG_ERROR, 575 gettext("%s: Unable to allocate space for a class " 576 "name\n"), drivername); 577 libscsi_fini(handle); 578 FW_SD_FREE_DRV_NAME(newdev, devpath) 579 return (FWFLASH_FAILURE); 580 } 581 (void) strlcpy(newdev->classname, driver, strlen(driver) + 1); 582 583 /* Get the access name for current node */ 584 if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) { 585 logmsg(MSG_ERROR, 586 gettext("%s: Unable to allocate space for a devfs " 587 "name\n"), driver); 588 libscsi_fini(handle); 589 FW_SD_FREE_CLS_NAME(newdev, devpath) 590 return (FWFLASH_FAILURE); 591 } 592 593 /* The slice number may be 2 or 0, we will try 2 first */ 594 (void) snprintf(newdev->access_devname, MAXPATHLEN, 595 "%s%s:c,raw", sdfw_devprefix, devpath); 596 if ((target = libscsi_open(handle, NULL, 597 newdev->access_devname)) == NULL) { 598 /* try 0 for EFI label */ 599 (void) snprintf(newdev->access_devname, MAXPATHLEN, 600 "%s%s:a,raw", sdfw_devprefix, devpath); 601 if ((target = libscsi_open(handle, NULL, 602 newdev->access_devname)) == NULL) { 603 logmsg(MSG_INFO, 604 "%s: unable to open device %s\n", 605 newdev->drvname, newdev->access_devname); 606 FW_SD_FREE_ACC_NAME(newdev, devpath) 607 continue; 608 } 609 } 610 611 /* and the /dev/rdsk/ name */ 612 if ((newdev->addresses[0] = sdfw_find_link(thisnode, 613 newdev->access_devname)) == NULL) { 614 libscsi_fini(handle); 615 FW_SD_FREE_ACC_NAME(newdev, devpath) 616 return (FWFLASH_FAILURE); 617 } 618 619 /* 620 * Only alloc as much as we truly need, and DON'T forget 621 * that libdevinfo manages the memory! 622 */ 623 if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) { 624 logmsg(MSG_ERROR, 625 gettext("%s: Unable to allocate space for SCSI " 626 "INQUIRY data\n"), driver); 627 libscsi_fini(handle); 628 FW_SD_FREE_ADDR(newdev, devpath) 629 return (FWFLASH_FAILURE); 630 } 631 632 /* We don't use new->ident->encap_ident currently */ 633 634 /* Retrive information by using libscsi */ 635 /* Vendor ID */ 636 sp_temp = (char *)libscsi_vendor(target); 637 if (strncmp(sp_temp, "ATA", 3) == 0) { 638 /* We need to do customize the output for SATA disks */ 639 fw_sata_disk = 1; 640 } else { 641 fw_sata_disk = 0; 642 if ((newdev->ident->vid = 643 calloc(1, strlen(sp_temp) + 1)) == NULL || 644 sp_temp == NULL) { 645 if (!sp_temp) { 646 logmsg(MSG_ERROR, gettext("%s: unable " 647 "to get vendor id of %s\n"), 648 newdev->drvname, 649 newdev->access_devname); 650 } else { 651 logmsg(MSG_ERROR, gettext("Memory " 652 "allocation failure\n")); 653 } 654 655 libscsi_close(handle, target); 656 libscsi_fini(handle); 657 FW_SD_FREE_IDENT(newdev, devpath) 658 return (FWFLASH_FAILURE); 659 } 660 strlcpy(newdev->ident->vid, sp_temp, 661 strlen(sp_temp) + 1); 662 } 663 664 /* Product ID */ 665 sp_temp = (char *)libscsi_product(target); 666 if (fw_sata_disk) { 667 sp_temp_cut = strchr(sp_temp, ' '); 668 if (!sp_temp_cut) { 669 /* 670 * There is no SPACE character in the PID field 671 * Customize strings for special SATA disks 672 */ 673 if (sdfw_idtfy_custmz(newdev, sp_temp) 674 != FWFLASH_SUCCESS) { 675 libscsi_close(handle, target); 676 libscsi_fini(handle); 677 FW_SD_FREE_IDENT(newdev, devpath) 678 return (FWFLASH_FAILURE); 679 } 680 } else { 681 /* The first string is vendor id */ 682 if ((newdev->ident->vid = calloc(1, 683 (sp_temp_cut - sp_temp + 1))) == NULL) { 684 logmsg(MSG_ERROR, gettext("%s: unable " 685 "to get sata vendor id of %s\n"), 686 newdev->drvname, 687 newdev->access_devname); 688 689 libscsi_close(handle, target); 690 libscsi_fini(handle); 691 FW_SD_FREE_IDENT(newdev, devpath) 692 return (FWFLASH_FAILURE); 693 } 694 strlcpy(newdev->ident->vid, sp_temp, 695 sp_temp_cut - sp_temp + 1); 696 697 /* The second string is product id */ 698 if ((newdev->ident->pid = 699 calloc(1, strlen(sp_temp) - 700 strlen(newdev->ident->vid))) == NULL) { 701 logmsg(MSG_ERROR, gettext("%s: unable " 702 "to get sata product id of %s\n"), 703 newdev->drvname, 704 newdev->access_devname); 705 706 libscsi_close(handle, target); 707 libscsi_fini(handle); 708 FW_SD_FREE_IDENT_VID(newdev, devpath) 709 return (FWFLASH_FAILURE); 710 } 711 strlcpy(newdev->ident->pid, sp_temp_cut + 1, 712 strlen(sp_temp) - 713 strlen(newdev->ident->vid)); 714 } 715 } else { 716 if ((newdev->ident->pid = 717 calloc(1, strlen(sp_temp) + 1)) == NULL || 718 sp_temp == NULL) { 719 logmsg(MSG_ERROR, gettext("%s: unable to get " 720 "product id of %s\n"), newdev->drvname, 721 newdev->access_devname); 722 FW_SD_FREE_IDENT_VID(newdev, devpath) 723 libscsi_close(handle, target); 724 libscsi_fini(handle); 725 return (FWFLASH_FAILURE); 726 } 727 strlcpy(newdev->ident->pid, sp_temp, 728 strlen(sp_temp) + 1); 729 } 730 731 /* Revision ID */ 732 sp_temp = (char *)libscsi_revision(target); 733 if ((newdev->ident->revid = calloc(1, strlen(sp_temp) + 1)) == 734 NULL || sp_temp == NULL) { 735 logmsg(MSG_ERROR, gettext("%s: unable to get revision " 736 "id of %s\n"), newdev->drvname, 737 newdev->access_devname); 738 libscsi_close(handle, target); 739 libscsi_fini(handle); 740 FW_SD_FREE_IDENT_PID(newdev, devpath) 741 return (FWFLASH_FAILURE); 742 } 743 strlcpy(newdev->ident->revid, sp_temp, strlen(sp_temp) + 1); 744 745 /* Finish using libscsi */ 746 libscsi_close(handle, target); 747 748 if (di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode, 749 "inquiry-serial-no", &newdev->addresses[1]) < 0) { 750 logmsg(MSG_INFO, 751 "%s: no inquiry-serial-no property for %s\n", 752 driver, newdev->access_devname); 753 logmsg(MSG_INFO, "The errno is %d\n", errno); 754 } 755 756 if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode, 757 "client-guid", &newdev->addresses[2])) < 0) { 758 logmsg(MSG_INFO, 759 "%s: no client-guid property " 760 "for device %s\n", 761 driver, newdev->access_devname); 762 /* try fallback */ 763 if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode, 764 "guid", &newdev->addresses[2])) < 0) { 765 logmsg(MSG_INFO, 766 "%s: no guid property for device %s\n", 767 driver, newdev->access_devname); 768 } 769 } else { 770 logmsg(MSG_INFO, 771 "client-guid property: %s\n", 772 newdev->addresses[2]); 773 } 774 775 newdev->index = idx; 776 ++idx; 777 newdev->plugin = self; 778 779 TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev); 780 FW_SD_FREE_DEVPATH(devpath) 781 } 782 libscsi_fini(handle); 783 784 /* Check if sd targets presented are all unflashable. */ 785 if (idx == start) 786 return (FWFLASH_FAILURE); 787 788 if (fwflash_debug != 0) { 789 struct devicelist *tempdev; 790 791 TAILQ_FOREACH(tempdev, fw_devices, nextdev) { 792 logmsg(MSG_INFO, "%s:fw_identify:\n", 793 driver); 794 logmsg(MSG_INFO, 795 "\ttempdev @ 0x%lx\n" 796 "\t\taccess_devname: %s\n" 797 "\t\tdrvname: %s\tclassname: %s\n" 798 "\t\tident->vid: %s\n" 799 "\t\tident->pid: %s\n" 800 "\t\tident->revid: %s\n" 801 "\t\tindex: %d\n" 802 "\t\taddress[0]: %s\n" 803 "\t\taddress[1]: %s\n" 804 "\t\taddress[2]: %s\n" 805 "\t\tplugin @ 0x%lx\n\n", 806 &tempdev, 807 tempdev->access_devname, 808 tempdev->drvname, newdev->classname, 809 tempdev->ident->vid, 810 tempdev->ident->pid, 811 tempdev->ident->revid, 812 tempdev->index, 813 tempdev->addresses[0], 814 (tempdev->addresses[1] ? tempdev->addresses[1] : 815 "(not supported)"), 816 (tempdev->addresses[2] ? tempdev->addresses[2] : 817 "(not supported)"), 818 &tempdev->plugin); 819 } 820 } 821 return (FWFLASH_SUCCESS); 822 } 823 824 int 825 fw_devinfo(struct devicelist *thisdev) 826 { 827 fprintf(stdout, gettext("Device[%d]\t\t\t%s\n" 828 " Class [%s]\t\t\t%s\n"), 829 thisdev->index, thisdev->access_devname, 830 thisdev->classname, thisdev->addresses[0]); 831 832 fprintf(stdout, 833 gettext( 834 "\tVendor\t\t\t: %s\n" 835 "\tProduct\t\t\t: %s\n" 836 "\tFirmware revision\t: %-s\n" 837 "\tInquiry Serial Number : %-s\n" 838 "\tGUID\t\t\t: %s\n"), 839 thisdev->ident->vid, 840 thisdev->ident->pid, 841 thisdev->ident->revid, 842 (thisdev->addresses[1] ? thisdev->addresses[1] : 843 "(not supported)"), 844 (thisdev->addresses[2] ? thisdev->addresses[2] : 845 "(not supported)")); 846 847 fprintf(stdout, "\n\n"); 848 849 return (FWFLASH_SUCCESS); 850 } 851 852 void 853 fw_cleanup(struct devicelist *thisdev) 854 { 855 /* 856 * Function to clean up all the memory allocated 857 * by this plugin, for thisdev. 858 */ 859 free(thisdev->access_devname); 860 free(thisdev->drvname); 861 free(thisdev->classname); 862 863 /* 864 * Note that we DO NOT free addresses[1,2] because _IF_ 865 * these elements are valid, they are managed by libdevinfo 866 * and we didn't allocate any space for them. 867 */ 868 free(thisdev->addresses[0]); 869 870 /* what this points to is freed in common code */ 871 thisdev->plugin = NULL; 872 873 free(thisdev->ident->vid); 874 free(thisdev->ident->pid); 875 free(thisdev->ident->revid); 876 877 thisdev->ident = NULL; 878 } 879 880 /* 881 * Helper functions 882 */ 883 static int 884 sdfw_link_cb(di_devlink_t devlink, void *arg) 885 { 886 const char *result; 887 888 result = di_devlink_path(devlink); 889 if (result == NULL) { 890 arg = (void *)"(null)"; 891 } else { 892 (void) strlcpy(arg, result, strlen(result) + 1); 893 } 894 895 logmsg(MSG_INFO, "\nsdfw_link_cb::linkdata->resultstr = %s\n", 896 ((result != NULL) ? result : "(null)")); 897 898 return (DI_WALK_CONTINUE); 899 } 900 901 static char * 902 sdfw_find_link(di_node_t bnode, char *acc_devname) 903 { 904 di_minor_t devminor = DI_MINOR_NIL; 905 di_devlink_handle_t hdl; 906 char *cbresult = NULL; 907 char linkname[] = "^rdsk/\0"; 908 909 if (bnode == DI_NODE_NIL) { 910 logmsg(MSG_ERROR, 911 gettext("sdfw_find_link must be called with non-null " 912 "di_node_t\n")); 913 return (NULL); 914 } 915 916 if ((cbresult = calloc(1, MAXPATHLEN)) == NULL) { 917 logmsg(MSG_ERROR, gettext("unable to allocate space for dev " 918 "link\n")); 919 return (NULL); 920 } 921 922 devminor = di_minor_next(bnode, devminor); 923 errno = 0; 924 hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK); 925 if (hdl == NULL) { 926 if (errno == EPERM || errno == EACCES) { 927 logmsg(MSG_ERROR, 928 gettext("%s: You must be super-user to use this " 929 "plugin.\n"), drivername); 930 } else { 931 logmsg(MSG_ERROR, 932 gettext("unable to take devlink snapshot: %s\n"), 933 strerror(errno)); 934 } 935 free(cbresult); 936 return (NULL); 937 } 938 939 errno = 0; 940 if (di_devlink_walk(hdl, linkname, acc_devname + strlen(sdfw_devprefix), 941 DI_PRIMARY_LINK, (void *)cbresult, sdfw_link_cb) < 0) { 942 logmsg(MSG_ERROR, 943 gettext("Unable to walk devlink snapshot for %s: %s\n"), 944 acc_devname, strerror(errno)); 945 free(cbresult); 946 return (NULL); 947 } 948 949 if (di_devlink_fini(&hdl) < 0) { 950 logmsg(MSG_ERROR, 951 gettext("Unable to close devlink snapshot: %s\n"), 952 strerror(errno)); 953 } 954 955 logmsg(MSG_INFO, "cbresult: %s\n", cbresult); 956 return (cbresult); 957 } 958 959 static int 960 sdfw_idtfy_custmz(struct devicelist *device, char *sp) 961 { 962 /* vid customization */ 963 if (strncmp(sp, "ST", 2) == 0) { 964 /* Customize retail Seagate disks */ 965 if ((device->ident->vid = strdup("SEAGATE")) == NULL) { 966 return (FWFLASH_FAILURE); 967 } 968 } else if (strncmp(sp, "SSD", 3) == 0) { 969 /* Customize retail INTEL disks */ 970 if ((device->ident->vid = strdup("INTEL")) == NULL) { 971 return (FWFLASH_FAILURE); 972 } 973 } else { 974 /* disks to do in the future, fill 'ATA' first */ 975 if ((device->ident->vid = strdup("ATA")) == NULL) { 976 return (FWFLASH_FAILURE); 977 } 978 } 979 980 /* pid customization */ 981 if ((device->ident->pid = calloc(1, strlen(sp) + 1)) == NULL) { 982 logmsg(MSG_ERROR, gettext("Unable to allocate space for " 983 "product id\n")); 984 free(device->ident->vid); 985 return (FWFLASH_FAILURE); 986 } 987 strlcpy(device->ident->pid, sp, strlen(sp) + 1); 988 989 return (FWFLASH_SUCCESS); 990 } 991