dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fwflash / plugins / transport / common / sd.c
blob318d8a51c05308804fe812c84be3ff859eb47585
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * sd / ssd (SCSI Direct-attached Device) specific functions.
29 #include <libnvpair.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/sysmacros.h>
35 #include <sys/queue.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <scsi/libscsi.h>
40 #include <libintl.h> /* for gettext(3c) */
41 #include <fwflash/fwflash.h>
43 typedef struct sam4_statdesc {
44 int status;
45 char *message;
46 } sam4_statdesc_t;
48 static sam4_statdesc_t sam4_status[] = {
49 { SAM4_STATUS_GOOD, "Status: GOOD (success)" },
50 { SAM4_STATUS_CHECK_CONDITION, "Status: CHECK CONDITION" },
51 { SAM4_STATUS_CONDITION_MET, "Status: CONDITION MET" },
52 { SAM4_STATUS_BUSY, "Status: Device is BUSY" },
53 { SAM4_STATUS_RESERVATION_CONFLICT, "Status: Device is RESERVED" },
54 { SAM4_STATUS_TASK_SET_FULL,
55 "Status: TASK SET FULL (insufficient resources in command queue" },
56 { SAM4_STATUS_TASK_ABORTED, "Status: TASK ABORTED" },
57 { 0, NULL }
60 #define NSAM4_STATUS \
61 (sizeof (sam4_status) / sizeof (sam4_status[0]))
63 #define FW_SD_FREE_DEVPATH(devpath) { \
64 di_devfs_path_free((devpath)); \
66 #define FW_SD_FREE_DEVICELIST(thisdev, devpath) { \
67 free((thisdev)); \
68 FW_SD_FREE_DEVPATH((devpath)) \
70 #define FW_SD_FREE_DRV_NAME(thisdev, devpath) { \
71 free((thisdev)->drvname); \
72 FW_SD_FREE_DEVICELIST((thisdev), (devpath)) \
74 #define FW_SD_FREE_CLS_NAME(thisdev, devpath) { \
75 free((thisdev)->classname); \
76 FW_SD_FREE_DRV_NAME((thisdev), (devpath)) \
78 #define FW_SD_FREE_ACC_NAME(thisdev, devpath) { \
79 free((thisdev)->access_devname); \
80 FW_SD_FREE_CLS_NAME(thisdev, devpath) \
82 #define FW_SD_FREE_ADDR(thisdev, devpath) { \
83 free((thisdev)->addresses[0]); \
84 FW_SD_FREE_ACC_NAME(thisdev, devpath) \
86 #define FW_SD_FREE_IDENT(thisdev, devpath) { \
87 free((thisdev)->ident); \
88 FW_SD_FREE_ADDR((thisdev), (devpath)) \
90 #define FW_SD_FREE_IDENT_VID(thisdev, devpath) { \
91 free((thisdev)->ident->vid); \
92 FW_SD_FREE_IDENT((thisdev), (devpath)) \
94 #define FW_SD_FREE_IDENT_PID(thisdev, devpath) { \
95 free((thisdev)->ident->pid); \
96 FW_SD_FREE_IDENT_VID((thisdev), (devpath)) \
98 #define FW_SD_FREE_IDENT_ALL(thisdev, devpath) { \
99 free((thisdev)->ident->revid); \
100 FW_SD_FREE_IDENT_PID((thisdev), (devpath)) \
103 int errno;
104 char drivername[] = "sd\0";
105 int plugin_version = FWPLUGIN_VERSION_2;
107 static char *devprefix = "/devices";
108 extern di_node_t rootnode;
109 extern struct fw_plugin *self;
110 extern struct vrfyplugin *verifier;
111 extern int fwflash_debug;
113 /* required functions for this plugin */
114 int fw_readfw(struct devicelist *device, char *filename);
115 int fw_writefw(struct devicelist *device);
116 int fw_identify(int start);
117 int fw_devinfo(struct devicelist *thisdev);
118 void fw_cleanup(struct devicelist *thisdev);
120 /* helper functions */
121 static char *find_link(di_node_t bnode, char *acc_devname);
122 static int link_cb(di_devlink_t devlink, void *arg);
123 static int sd_idtfy_custmz(struct devicelist *device, char *sp);
126 * We don't currently support reading firmware from a disk. If we do eventually
127 * support it, we would use the scsi READ BUFFER command to do so.
130 fw_readfw(struct devicelist *flashdev, char *filename)
133 logmsg(MSG_INFO,
134 "%s: not writing firmware for device %s to file %s\n",
135 flashdev->drvname, flashdev->access_devname, filename);
136 logmsg(MSG_ERROR,
137 gettext("\n\nReading of firmware images from %s-attached "
138 "devices is not supported\n\n"),
139 flashdev->drvname);
141 return (FWFLASH_SUCCESS);
145 fw_writefw(struct devicelist *flashdev)
147 int rv;
148 int i = 0;
149 libscsi_hdl_t *handle;
150 libscsi_target_t *target;
151 libscsi_action_t *action;
152 libscsi_errno_t serr;
153 spc3_write_buffer_cdb_t *wb_cdb;
154 sam4_status_t samstatus;
156 if ((verifier == NULL) || (verifier->imgsize == 0) ||
157 (verifier->fwimage == NULL)) {
158 /* should _NOT_ happen */
159 logmsg(MSG_ERROR,
160 gettext("%s: Firmware image has not been verified\n"),
161 flashdev->drvname);
162 return (FWFLASH_FAILURE);
165 if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
166 logmsg(MSG_ERROR, gettext("%s: failed to initialize libscsi\n"),
167 flashdev->drvname);
168 return (FWFLASH_FAILURE);
171 if ((target = libscsi_open(handle, NULL, flashdev->access_devname))
172 == NULL) {
173 logmsg(MSG_ERROR,
174 gettext("%s: unable to open device %s\n"),
175 flashdev->drvname, flashdev->access_devname);
176 libscsi_fini(handle);
177 return (FWFLASH_FAILURE);
180 action = libscsi_action_alloc(handle, SPC3_CMD_WRITE_BUFFER,
181 LIBSCSI_AF_WRITE|LIBSCSI_AF_RQSENSE,
182 (void *)verifier->fwimage, (size_t)verifier->imgsize);
184 wb_cdb = (spc3_write_buffer_cdb_t *)libscsi_action_get_cdb(action);
186 wb_cdb->wbc_mode = SPC3_WB_MODE_DL_UCODE_SAVE;
187 wb_cdb->wbc_bufferid = verifier->flashbuf;
189 wb_cdb->wbc_buffer_offset[0] = 0;
190 wb_cdb->wbc_buffer_offset[1] = 0;
191 wb_cdb->wbc_buffer_offset[2] = 0;
193 wb_cdb->wbc_parameter_list_len[0] =
194 (verifier->imgsize & 0xff0000) >> 16;
195 wb_cdb->wbc_parameter_list_len[1] = (verifier->imgsize & 0xff00) >> 8;
196 wb_cdb->wbc_parameter_list_len[2] = (verifier->imgsize & 0xff);
198 rv = libscsi_exec(action, target);
199 samstatus = libscsi_action_get_status(action);
201 logmsg(MSG_INFO, "\nscsi_writebuffer: ret 0x%0x, samstatus 0x%0x\n",
202 rv, samstatus);
204 libscsi_action_free(action);
205 libscsi_close(handle, target);
206 libscsi_fini(handle);
208 if (rv != FWFLASH_SUCCESS)
209 return (FWFLASH_FAILURE);
211 for (i = 0; i < NSAM4_STATUS; i++) {
212 if (sam4_status[i].status == samstatus) {
213 logmsg(MSG_ERROR, gettext("RETURN STATUS: %s\n"),
214 (sam4_status[i].message));
215 break;
218 if (i == NSAM4_STATUS)
219 logmsg(MSG_ERROR, gettext("Status UNKNOWN\n"));
221 if (samstatus == SAM4_STATUS_GOOD) {
222 logmsg(MSG_ERROR, gettext("Note: For flash based disks "
223 "(SSD, etc). You may need power off the system to wait a "
224 "few minutes for supercap to fully discharge, then power "
225 "on the system again to activate the new firmware\n"));
226 return (FWFLASH_SUCCESS);
228 return (FWFLASH_FAILURE);
232 * The fw_identify() function walks the device
233 * tree trying to find devices which this plugin
234 * can work with.
236 * The parameter "start" gives us the starting index number
237 * to give the device when we add it to the fw_devices list.
239 * firstdev is allocated by us and we add space as needed
241 * When we store the desired information, inquiry-serial-no
242 * goes in thisdev->addresses[1], and client-guid goes in
243 * thisdev->addresses[2].
246 fw_identify(int start)
248 int idx = start;
249 int fw_sata_disk = 0;
250 int *exists;
251 di_node_t thisnode;
252 struct devicelist *newdev = NULL;
253 char *devpath = NULL;
254 char *driver = NULL;
255 char *sp_temp;
256 char *sp_temp_cut;
258 /* We need to inquiry information manually by sending probe command */
259 libscsi_hdl_t *handle;
260 libscsi_target_t *target;
261 libscsi_errno_t serr;
263 /* Just in case we've got an FC-attached device on sparc */
264 if (strcmp(self->drvname, "ssd") == 0) {
265 driver = self->drvname;
266 } else
267 driver = drivername;
269 thisnode = di_drv_first_node(driver, rootnode);
271 if (thisnode == DI_NODE_NIL) {
272 logmsg(MSG_INFO, "No %s nodes in this system\n", driver);
273 return (FWFLASH_FAILURE);
276 if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
277 logmsg(MSG_ERROR, gettext("%s: failed to initialize "
278 "libscsi\n"), newdev->drvname);
279 return (FWFLASH_FAILURE);
282 /* we've found one, at least */
283 for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
284 /* Need to free by di_devfs_path_free */
285 if ((devpath = di_devfs_path(thisnode)) == NULL) {
286 logmsg(MSG_INFO, "unable to get device path for "
287 "current node with errno %d\n", errno);
288 continue;
291 * We check if this is removable device, in which case
292 * we really aren't interested, so exit stage left
294 if (di_prop_lookup_ints(DDI_DEV_T_ANY, thisnode,
295 "removable-media", &exists) > -1) {
296 logmsg(MSG_INFO,
297 "%s: not interested in removable media device\n"
298 "%s\n", driver, devpath);
299 FW_SD_FREE_DEVPATH(devpath)
300 continue;
303 if ((newdev = calloc(1, sizeof (struct devicelist)))
304 == NULL) {
305 logmsg(MSG_ERROR,
306 gettext("%s: identification function unable "
307 "to allocate space for device entry\n"),
308 driver);
309 libscsi_fini(handle);
310 FW_SD_FREE_DEVPATH(devpath)
311 return (FWFLASH_FAILURE);
314 if ((newdev->drvname = calloc(1, strlen(driver) + 1))
315 == NULL) {
316 logmsg(MSG_ERROR,
317 gettext("%s: Unable to allocate space to store a "
318 "driver name\n"), driver);
319 libscsi_fini(handle);
320 FW_SD_FREE_DEVICELIST(newdev, devpath)
321 return (FWFLASH_FAILURE);
323 (void) strlcpy(newdev->drvname, driver, strlen(driver) + 1);
325 if ((newdev->classname = calloc(1, strlen(driver) + 1))
326 == NULL) {
327 logmsg(MSG_ERROR,
328 gettext("%s: Unable to allocate space for a class "
329 "name\n"), drivername);
330 libscsi_fini(handle);
331 FW_SD_FREE_DRV_NAME(newdev, devpath)
332 return (FWFLASH_FAILURE);
334 (void) strlcpy(newdev->classname, driver, strlen(driver) + 1);
336 /* Get the access name for current node */
337 if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) {
338 logmsg(MSG_ERROR,
339 gettext("%s: Unable to allocate space for a devfs "
340 "name\n"), driver);
341 libscsi_fini(handle);
342 FW_SD_FREE_CLS_NAME(newdev, devpath)
343 return (FWFLASH_FAILURE);
346 /* The slice number may be 2 or 0, we will try 2 first */
347 (void) snprintf(newdev->access_devname, MAXPATHLEN,
348 "%s%s:c,raw", devprefix, devpath);
349 if ((target = libscsi_open(handle, NULL,
350 newdev->access_devname)) == NULL) {
351 /* try 0 for EFI label */
352 (void) snprintf(newdev->access_devname, MAXPATHLEN,
353 "%s%s:a,raw", devprefix, devpath);
354 if ((target = libscsi_open(handle, NULL,
355 newdev->access_devname)) == NULL) {
356 logmsg(MSG_INFO,
357 "%s: unable to open device %s\n",
358 newdev->drvname, newdev->access_devname);
359 FW_SD_FREE_ACC_NAME(newdev, devpath)
360 continue;
364 /* and the /dev/rdsk/ name */
365 if ((newdev->addresses[0] = find_link(thisnode,
366 newdev->access_devname)) == NULL) {
367 libscsi_fini(handle);
368 FW_SD_FREE_ACC_NAME(newdev, devpath)
369 return (FWFLASH_FAILURE);
373 * Only alloc as much as we truly need, and DON'T forget
374 * that libdevinfo manages the memory!
376 if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
377 logmsg(MSG_ERROR,
378 gettext("%s: Unable to allocate space for SCSI "
379 "INQUIRY data\n"), driver);
380 libscsi_fini(handle);
381 FW_SD_FREE_ADDR(newdev, devpath)
382 return (FWFLASH_FAILURE);
385 /* We don't use new->ident->encap_ident currently */
387 /* Retrive information by using libscsi */
388 /* Vendor ID */
389 sp_temp = (char *)libscsi_vendor(target);
390 if (strncmp(sp_temp, "ATA", 3) == 0) {
391 /* We need to do customize the output for SATA disks */
392 fw_sata_disk = 1;
393 } else {
394 fw_sata_disk = 0;
395 if ((newdev->ident->vid =
396 calloc(1, strlen(sp_temp) + 1)) == NULL ||
397 sp_temp == NULL) {
398 if (!sp_temp) {
399 logmsg(MSG_ERROR, gettext("%s: unable "
400 "to get vendor id of %s\n"),
401 newdev->drvname,
402 newdev->access_devname);
403 } else {
404 logmsg(MSG_ERROR, gettext("Memory "
405 "allocation failure\n"));
408 libscsi_close(handle, target);
409 libscsi_fini(handle);
410 FW_SD_FREE_IDENT(newdev, devpath)
411 return (FWFLASH_FAILURE);
413 strlcpy(newdev->ident->vid, sp_temp,
414 strlen(sp_temp) + 1);
417 /* Product ID */
418 sp_temp = (char *)libscsi_product(target);
419 if (fw_sata_disk) {
420 sp_temp_cut = strchr(sp_temp, ' ');
421 if (!sp_temp_cut) {
423 * There is no SPACE character in the PID field
424 * Customize strings for special SATA disks
426 if (sd_idtfy_custmz(newdev, sp_temp)
427 != FWFLASH_SUCCESS) {
428 libscsi_close(handle, target);
429 libscsi_fini(handle);
430 FW_SD_FREE_IDENT(newdev, devpath)
431 return (FWFLASH_FAILURE);
433 } else {
434 /* The first string is vendor id */
435 if ((newdev->ident->vid = calloc(1,
436 (sp_temp_cut - sp_temp + 1))) == NULL) {
437 logmsg(MSG_ERROR, gettext("%s: unable "
438 "to get sata vendor id of %s\n"),
439 newdev->drvname,
440 newdev->access_devname);
442 libscsi_close(handle, target);
443 libscsi_fini(handle);
444 FW_SD_FREE_IDENT(newdev, devpath)
445 return (FWFLASH_FAILURE);
447 strlcpy(newdev->ident->vid, sp_temp,
448 sp_temp_cut - sp_temp + 1);
450 /* The second string is product id */
451 if ((newdev->ident->pid =
452 calloc(1, strlen(sp_temp) -
453 strlen(newdev->ident->vid))) == NULL) {
454 logmsg(MSG_ERROR, gettext("%s: unable "
455 "to get sata product id of %s\n"),
456 newdev->drvname,
457 newdev->access_devname);
459 libscsi_close(handle, target);
460 libscsi_fini(handle);
461 FW_SD_FREE_IDENT_VID(newdev, devpath)
462 return (FWFLASH_FAILURE);
464 strlcpy(newdev->ident->pid, sp_temp_cut + 1,
465 strlen(sp_temp) -
466 strlen(newdev->ident->vid));
468 } else {
469 if ((newdev->ident->pid =
470 calloc(1, strlen(sp_temp) + 1)) == NULL ||
471 sp_temp == NULL) {
472 logmsg(MSG_ERROR, gettext("%s: unable to get "
473 "product id of %s\n"), newdev->drvname,
474 newdev->access_devname);
475 FW_SD_FREE_IDENT_VID(newdev, devpath)
476 libscsi_close(handle, target);
477 libscsi_fini(handle);
478 return (FWFLASH_FAILURE);
480 strlcpy(newdev->ident->pid, sp_temp,
481 strlen(sp_temp) + 1);
484 /* Revision ID */
485 sp_temp = (char *)libscsi_revision(target);
486 if ((newdev->ident->revid = calloc(1, strlen(sp_temp) + 1))
487 == NULL || sp_temp == NULL) {
488 logmsg(MSG_ERROR, gettext("%s: unable to get revision "
489 "id of %s\n"), newdev->drvname,
490 newdev->access_devname);
491 libscsi_close(handle, target);
492 libscsi_fini(handle);
493 FW_SD_FREE_IDENT_PID(newdev, devpath)
494 return (FWFLASH_FAILURE);
496 strlcpy(newdev->ident->revid, sp_temp, strlen(sp_temp) + 1);
498 /* Finish using libscsi */
499 libscsi_close(handle, target);
501 if (di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
502 "inquiry-serial-no", &newdev->addresses[1]) < 0) {
503 logmsg(MSG_INFO,
504 "%s: no inquiry-serial-no property for %s\n",
505 driver, newdev->access_devname);
506 logmsg(MSG_INFO, "The errno is %d\n", errno);
509 if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
510 "client-guid", &newdev->addresses[2])) < 0) {
511 logmsg(MSG_INFO,
512 "%s: no client-guid property "
513 "for device %s\n",
514 driver, newdev->access_devname);
515 /* try fallback */
516 if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
517 "guid", &newdev->addresses[2])) < 0) {
518 logmsg(MSG_INFO,
519 "%s: no guid property for device %s\n",
520 driver, newdev->access_devname);
522 } else {
523 logmsg(MSG_INFO,
524 "client-guid property: %s\n",
525 newdev->addresses[2]);
528 newdev->index = idx;
529 ++idx;
530 newdev->plugin = self;
532 TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
533 FW_SD_FREE_DEVPATH(devpath)
535 libscsi_fini(handle);
537 /* Check if sd targets presented are all unflashable. */
538 if (idx == start)
539 return (FWFLASH_FAILURE);
541 if (fwflash_debug != 0) {
542 struct devicelist *tempdev;
544 TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
545 logmsg(MSG_INFO, "%s:fw_identify:\n",
546 driver);
547 logmsg(MSG_INFO,
548 "\ttempdev @ 0x%lx\n"
549 "\t\taccess_devname: %s\n"
550 "\t\tdrvname: %s\tclassname: %s\n"
551 "\t\tident->vid: %s\n"
552 "\t\tident->pid: %s\n"
553 "\t\tident->revid: %s\n"
554 "\t\tindex: %d\n"
555 "\t\taddress[0]: %s\n"
556 "\t\taddress[1]: %s\n"
557 "\t\taddress[2]: %s\n"
558 "\t\tplugin @ 0x%lx\n\n",
559 &tempdev,
560 tempdev->access_devname,
561 tempdev->drvname, newdev->classname,
562 tempdev->ident->vid,
563 tempdev->ident->pid,
564 tempdev->ident->revid,
565 tempdev->index,
566 tempdev->addresses[0],
567 (tempdev->addresses[1] ? tempdev->addresses[1] :
568 "(not supported)"),
569 (tempdev->addresses[2] ? tempdev->addresses[2] :
570 "(not supported)"),
571 &tempdev->plugin);
574 return (FWFLASH_SUCCESS);
578 fw_devinfo(struct devicelist *thisdev)
580 fprintf(stdout, gettext("Device[%d]\t\t\t%s\n"
581 " Class [%s]\t\t\t%s\n"),
582 thisdev->index, thisdev->access_devname,
583 thisdev->classname, thisdev->addresses[0]);
585 fprintf(stdout,
586 gettext(
587 "\tVendor\t\t\t: %s\n"
588 "\tProduct\t\t\t: %s\n"
589 "\tFirmware revision\t: %-s\n"
590 "\tInquiry Serial Number : %-s\n"
591 "\tGUID\t\t\t: %s\n"),
592 thisdev->ident->vid,
593 thisdev->ident->pid,
594 thisdev->ident->revid,
595 (thisdev->addresses[1] ? thisdev->addresses[1] :
596 "(not supported)"),
597 (thisdev->addresses[2] ? thisdev->addresses[2] :
598 "(not supported)"));
600 fprintf(stdout, "\n\n");
602 return (FWFLASH_SUCCESS);
605 void
606 fw_cleanup(struct devicelist *thisdev)
609 * Function to clean up all the memory allocated
610 * by this plugin, for thisdev.
612 free(thisdev->access_devname);
613 free(thisdev->drvname);
614 free(thisdev->classname);
617 * Note that we DO NOT free addresses[1,2] because _IF_
618 * these elements are valid, they are managed by libdevinfo
619 * and we didn't allocate any space for them.
621 free(thisdev->addresses[0]);
623 /* what this points to is freed in common code */
624 thisdev->plugin = NULL;
626 free(thisdev->ident->vid);
627 free(thisdev->ident->pid);
628 free(thisdev->ident->revid);
630 thisdev->ident = NULL;
634 * Helper functions
636 static int
637 link_cb(di_devlink_t devlink, void *arg)
639 const char *result;
641 result = di_devlink_path(devlink);
642 if (result == NULL) {
643 arg = (void *)"(null)";
644 } else {
645 (void) strlcpy(arg, result, strlen(result) + 1);
648 logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n",
649 ((result != NULL) ? result : "(null)"));
651 return (DI_WALK_CONTINUE);
654 static char *
655 find_link(di_node_t bnode, char *acc_devname)
657 di_minor_t devminor = DI_MINOR_NIL;
658 di_devlink_handle_t hdl;
659 char *cbresult = NULL;
660 char linkname[] = "^rdsk/\0";
662 if (bnode == DI_NODE_NIL) {
663 logmsg(MSG_ERROR,
664 gettext("find_link must be called with non-null "
665 "di_node_t\n"));
666 return (NULL);
669 if ((cbresult = calloc(1, MAXPATHLEN)) == NULL) {
670 logmsg(MSG_ERROR, gettext("unable to allocate space for dev "
671 "link\n"));
672 return (NULL);
675 devminor = di_minor_next(bnode, devminor);
676 errno = 0;
677 hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
678 if (hdl == NULL) {
679 if (errno == EPERM || errno == EACCES) {
680 logmsg(MSG_ERROR,
681 gettext("%s: You must be super-user to use this "
682 "plugin.\n"), drivername);
683 } else {
684 logmsg(MSG_ERROR,
685 gettext("unable to take devlink snapshot: %s\n"),
686 strerror(errno));
688 free(cbresult);
689 return (NULL);
692 errno = 0;
693 if (di_devlink_walk(hdl, linkname, acc_devname + strlen(devprefix),
694 DI_PRIMARY_LINK, (void *)cbresult, link_cb) < 0) {
695 logmsg(MSG_ERROR,
696 gettext("Unable to walk devlink snapshot for %s: %s\n"),
697 acc_devname, strerror(errno));
698 free(cbresult);
699 return (NULL);
702 if (di_devlink_fini(&hdl) < 0) {
703 logmsg(MSG_ERROR,
704 gettext("Unable to close devlink snapshot: %s\n"),
705 strerror(errno));
708 logmsg(MSG_INFO, "cbresult: %s\n", cbresult);
709 return (cbresult);
712 static int
713 sd_idtfy_custmz(struct devicelist *device, char *sp)
715 /* vid customization */
716 if (strncmp(sp, "ST", 2) == 0) {
717 /* Customize retail Seagate disks */
718 if ((device->ident->vid = strdup("SEAGATE")) == NULL) {
719 return (FWFLASH_FAILURE);
721 } else if (strncmp(sp, "SSD", 3) == 0) {
722 /* Customize retail INTEL disks */
723 if ((device->ident->vid = strdup("INTEL")) == NULL) {
724 return (FWFLASH_FAILURE);
726 } else {
727 /* disks to do in the furture, fill 'ATA' first */
728 if ((device->ident->vid = strdup("ATA")) == NULL) {
729 return (FWFLASH_FAILURE);
733 /* pid customization */
734 if ((device->ident->pid = calloc(1, strlen(sp) + 1)) == NULL) {
735 logmsg(MSG_ERROR, gettext("Unable to allocate space for "
736 "product id\n"));
737 free(device->ident->vid);
738 return (FWFLASH_FAILURE);
740 strlcpy(device->ident->pid, sp, strlen(sp) + 1);
742 return (FWFLASH_SUCCESS);