d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * CDDL HEADER START
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * The contents of this file are subject to the terms of the
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Common Development and Distribution License (the "License").
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * You may not use this file except in compliance with the License.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * or http://www.opensolaris.org/os/licensing.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * See the License for the specific language governing permissions
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * and limitations under the License.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * When distributing Covered Code, include this CDDL HEADER in each
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * If applicable, add the following below this CDDL HEADER, with the
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * fields enclosed by brackets "[]" replaced with your own identifying
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * information: Portions Copyright [yyyy] [name of copyright owner]
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * CDDL HEADER END
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Use is subject to license terms.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * sd / ssd (SCSI Direct-attached Device) specific functions.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <libnvpair.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <stdio.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <stdlib.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <unistd.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <sys/types.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <sys/sysmacros.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <sys/queue.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <fcntl.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <string.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <errno.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <scsi/libscsi.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <libintl.h> /* for gettext(3c) */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#include <fwflash/fwflash.h>
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChentypedef struct sam4_statdesc {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen int status;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen char *message;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen} sam4_statdesc_t;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic sam4_statdesc_t sam4_status[] = {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_GOOD, "Status: GOOD (success)" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_CHECK_CONDITION, "Status: CHECK CONDITION" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_CONDITION_MET, "Status: CONDITION MET" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_BUSY, "Status: Device is BUSY" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_RESERVATION_CONFLICT, "Status: Device is RESERVED" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_TASK_SET_FULL,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "Status: TASK SET FULL (insufficient resources in command queue" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { SAM4_STATUS_TASK_ABORTED, "Status: TASK ABORTED" },
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen { NULL, NULL }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen};
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define NSAM4_STATUS \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (sizeof (sam4_status) / sizeof (sam4_status[0]))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_DEVPATH(devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen di_devfs_path_free((devpath)); \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_DEVICELIST(thisdev, devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free((thisdev)); \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_DEVPATH((devpath)) \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_DRV_NAME(thisdev, devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free((thisdev)->drvname); \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_DEVICELIST((thisdev), (devpath)) \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_CLS_NAME(thisdev, devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free((thisdev)->classname); \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_DRV_NAME((thisdev), (devpath)) \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen#define FW_SD_FREE_ACC_NAME(thisdev, devpath) { \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen free((thisdev)->access_devname); \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_CLS_NAME(thisdev, devpath) \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen }
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen#define FW_SD_FREE_ADDR(thisdev, devpath) { \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen free((thisdev)->addresses[0]); \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_ACC_NAME(thisdev, devpath) \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_IDENT(thisdev, devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free((thisdev)->ident); \
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_ADDR((thisdev), (devpath)) \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_IDENT_VID(thisdev, devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free((thisdev)->ident->vid); \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT((thisdev), (devpath)) \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_IDENT_PID(thisdev, devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free((thisdev)->ident->pid); \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT_VID((thisdev), (devpath)) \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen#define FW_SD_FREE_IDENT_ALL(thisdev, devpath) { \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free((thisdev)->ident->revid); \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT_PID((thisdev), (devpath)) \
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint errno;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenchar drivername[] = "sd\0";
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint plugin_version = FWPLUGIN_VERSION_2;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic char *devprefix = "/devices";
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenextern di_node_t rootnode;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenextern struct fw_plugin *self;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenextern struct vrfyplugin *verifier;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenextern int fwflash_debug;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/* required functions for this plugin */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint fw_readfw(struct devicelist *device, char *filename);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint fw_writefw(struct devicelist *device);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint fw_identify(int start);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint fw_devinfo(struct devicelist *thisdev);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenvoid fw_cleanup(struct devicelist *thisdev);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/* helper functions */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChenstatic char *find_link(di_node_t bnode, char *acc_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic int link_cb(di_devlink_t devlink, void *arg);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic int sd_idtfy_custmz(struct devicelist *device, char *sp);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * We don't currently support reading firmware from a disk. If we do eventually
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * support it, we would use the scsi READ BUFFER command to do so.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenfw_readfw(struct devicelist *flashdev, char *filename)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: not writing firmware for device %s to file %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen flashdev->drvname, flashdev->access_devname, filename);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("\n\nReading of firmware images from %s-attached "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "devices is not supported\n\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen flashdev->drvname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_SUCCESS);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenfw_writefw(struct devicelist *flashdev)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen int rv;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen int i = 0;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_hdl_t *handle;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_target_t *target;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_action_t *action;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_errno_t serr;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen spc3_write_buffer_cdb_t *wb_cdb;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sam4_status_t samstatus;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((verifier == NULL) || (verifier->imgsize == 0) ||
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (verifier->fwimage == NULL)) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* should _NOT_ happen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: Firmware image has not been verified\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen flashdev->drvname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: failed to initialize libscsi\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen flashdev->drvname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((target = libscsi_open(handle, NULL, flashdev->access_devname))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: unable to open device %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen flashdev->drvname, flashdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen action = libscsi_action_alloc(handle, SPC3_CMD_WRITE_BUFFER,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen LIBSCSI_AF_WRITE|LIBSCSI_AF_RQSENSE,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (void *)verifier->fwimage, (size_t)verifier->imgsize);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb = (spc3_write_buffer_cdb_t *)libscsi_action_get_cdb(action);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_mode = SPC3_WB_MODE_DL_UCODE_SAVE;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_bufferid = verifier->flashbuf;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_buffer_offset[0] = 0;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_buffer_offset[1] = 0;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_buffer_offset[2] = 0;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_parameter_list_len[0] =
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (verifier->imgsize & 0xff0000) >> 16;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_parameter_list_len[1] = (verifier->imgsize & 0xff00) >> 8;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen wb_cdb->wbc_parameter_list_len[2] = (verifier->imgsize & 0xff);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen rv = libscsi_exec(action, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen samstatus = libscsi_action_get_status(action);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "\nscsi_writebuffer: ret 0x%0x, samstatus 0x%0x\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen rv, samstatus);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_action_free(action);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (rv != FWFLASH_SUCCESS)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen for (i = 0; i < NSAM4_STATUS; i++) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (sam4_status[i].status == samstatus) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("RETURN STATUS: %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (sam4_status[i].message));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen break;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (i == NSAM4_STATUS)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("Status UNKNOWN\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (samstatus == SAM4_STATUS_GOOD) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("Note: For flash based disks "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(SSD, etc). You may need power off the system to wait a "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "few minutes for supercap to fully discharge, then power "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "on the system again to activate the new firmware\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_SUCCESS);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * The fw_identify() function walks the device
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * tree trying to find devices which this plugin
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * can work with.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * The parameter "start" gives us the starting index number
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * to give the device when we add it to the fw_devices list.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * firstdev is allocated by us and we add space as needed
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen *
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * When we store the desired information, inquiry-serial-no
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * goes in thisdev->addresses[1], and client-guid goes in
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * thisdev->addresses[2].
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenfw_identify(int start)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen int idx = start;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen int fw_sata_disk = 0;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen int *exists;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen di_node_t thisnode;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen struct devicelist *newdev = NULL;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen char *devpath = NULL;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen char *driver = NULL;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen char *sp_temp;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen char *sp_temp_cut;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* We need to inquiry information manually by sending probe command */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_hdl_t *handle;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_target_t *target;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_errno_t serr;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Just in case we've got an FC-attached device on sparc */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (strcmp(self->drvname, "ssd") == 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen driver = self->drvname;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen driver = drivername;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisnode = di_drv_first_node(driver, rootnode);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (thisnode == DI_NODE_NIL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "No %s nodes in this system\n", driver);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: failed to initialize "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "libscsi\n"), newdev->drvname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* we've found one, at least */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* Need to free by di_devfs_path_free */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if ((devpath = di_devfs_path(thisnode)) == NULL) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen logmsg(MSG_INFO, "unable to get device path for "
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen "current node with errno %d\n", errno);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen continue;
0bc9814f152db9078852cc4ec759a4d8b53a1b8bXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * We check if this is removable device, in which case
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * we really aren't interested, so exit stage left
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (di_prop_lookup_ints(DDI_DEV_T_ANY, thisnode,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "removable-media", &exists) > -1) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: not interested in removable media device\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s\n", driver, devpath);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_DEVPATH(devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen continue;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev = calloc(1, sizeof (struct devicelist)))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: identification function unable "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to allocate space for device entry\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen driver);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_DEVPATH(devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->drvname = calloc(1, strlen(driver) + 1))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: Unable to allocate space to store a "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "driver name\n"), driver);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_DEVICELIST(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (void) strlcpy(newdev->drvname, driver, strlen(driver) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->classname = calloc(1, strlen(driver) + 1))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: Unable to allocate space for a class "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "name\n"), drivername);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_DRV_NAME(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (void) strlcpy(newdev->classname, driver, strlen(driver) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* Get the access name for current node */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen logmsg(MSG_ERROR,
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen gettext("%s: Unable to allocate space for a devfs "
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen "name\n"), driver);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen libscsi_fini(handle);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_CLS_NAME(newdev, devpath)
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen return (FWFLASH_FAILURE);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen }
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* The slice number may be 2 or 0, we will try 2 first */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen (void) snprintf(newdev->access_devname, MAXPATHLEN,
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen "%s%s:c,raw", devprefix, devpath);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if ((target = libscsi_open(handle, NULL,
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen newdev->access_devname)) == NULL) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* try 0 for EFI label */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen (void) snprintf(newdev->access_devname, MAXPATHLEN,
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen "%s%s:a,raw", devprefix, devpath);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if ((target = libscsi_open(handle, NULL,
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen newdev->access_devname)) == NULL) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen logmsg(MSG_INFO,
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen "%s: unable to open device %s\n",
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen newdev->drvname, newdev->access_devname);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_ACC_NAME(newdev, devpath)
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen continue;
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen }
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen }
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /* and the /dev/rdsk/ name */
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if ((newdev->addresses[0] = find_link(thisnode,
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen newdev->access_devname)) == NULL) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen libscsi_fini(handle);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_ACC_NAME(newdev, devpath)
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen return (FWFLASH_FAILURE);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen }
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Only alloc as much as we truly need, and DON'T forget
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * that libdevinfo manages the memory!
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: Unable to allocate space for SCSI "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "INQUIRY data\n"), driver);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_ADDR(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* We don't use new->ident->encap_ident currently */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Retrive information by using libscsi */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Vendor ID */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sp_temp = (char *)libscsi_vendor(target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (strncmp(sp_temp, "ATA", 3) == 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* We need to do customize the output for SATA disks */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen fw_sata_disk = 1;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen fw_sata_disk = 0;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident->vid =
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen calloc(1, strlen(sp_temp) + 1)) == NULL ||
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sp_temp == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (!sp_temp) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: unable "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to get vendor id of %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->drvname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("Memory "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "allocation failure\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlcpy(newdev->ident->vid, sp_temp,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlen(sp_temp) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Product ID */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sp_temp = (char *)libscsi_product(target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (fw_sata_disk) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sp_temp_cut = strchr(sp_temp, ' ');
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (!sp_temp_cut) {
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen /*
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen * There is no SPACE character in the PID field
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen * Customize strings for special SATA disks
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (sd_idtfy_custmz(newdev, sp_temp)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen != FWFLASH_SUCCESS) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* The first string is vendor id */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident->vid = calloc(1,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (sp_temp_cut - sp_temp + 1))) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: unable "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to get sata vendor id of %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->drvname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlcpy(newdev->ident->vid, sp_temp,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sp_temp_cut - sp_temp + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* The second string is product id */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident->pid =
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen calloc(1, strlen(sp_temp) -
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlen(newdev->ident->vid))) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: unable "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "to get sata product id of %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->drvname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT_VID(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlcpy(newdev->ident->pid, sp_temp_cut + 1,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlen(sp_temp) -
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlen(newdev->ident->vid));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident->pid =
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen calloc(1, strlen(sp_temp) + 1)) == NULL ||
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sp_temp == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: unable to get "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "product id of %s\n"), newdev->drvname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT_VID(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlcpy(newdev->ident->pid, sp_temp,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlen(sp_temp) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Revision ID */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen sp_temp = (char *)libscsi_revision(target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((newdev->ident->revid = calloc(1, strlen(sp_temp) + 1))
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen == NULL || sp_temp == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("%s: unable to get revision "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "id of %s\n"), newdev->drvname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen FW_SD_FREE_IDENT_PID(newdev, devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlcpy(newdev->ident->revid, sp_temp, strlen(sp_temp) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Finish using libscsi */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_close(handle, target);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "inquiry-serial-no", &newdev->addresses[1]) < 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: no inquiry-serial-no property for %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen driver, newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "The errno is %d\n", errno);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "client-guid", &newdev->addresses[2])) < 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: no client-guid property "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "for device %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen driver, newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* try fallback */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "guid", &newdev->addresses[2])) < 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "%s: no guid property for device %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen driver, newdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "client-guid property: %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->addresses[2]);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->index = idx;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen ++idx;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen newdev->plugin = self;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen FW_SD_FREE_DEVPATH(devpath)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen libscsi_fini(handle);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Check if sd targets presented are all unflashable. */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (idx == start)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (fwflash_debug != 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen struct devicelist *tempdev;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "%s:fw_identify:\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen driver);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\ttempdev @ 0x%lx\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taccess_devname: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tdrvname: %s\tclassname: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tident->vid: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tident->pid: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tident->revid: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tindex: %d\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taddress[0]: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taddress[1]: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\taddress[2]: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\t\tplugin @ 0x%lx\n\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen &tempdev,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen tempdev->access_devname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen tempdev->drvname, newdev->classname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen tempdev->ident->vid,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen tempdev->ident->pid,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen tempdev->ident->revid,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen tempdev->index,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen tempdev->addresses[0],
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (tempdev->addresses[1] ? tempdev->addresses[1] :
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (tempdev->addresses[2] ? tempdev->addresses[2] :
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen &tempdev->plugin);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_SUCCESS);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenint
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenfw_devinfo(struct devicelist *thisdev)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen fprintf(stdout, gettext("Device[%d]\t\t\t%s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen " Class [%s]\t\t\t%s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisdev->index, thisdev->access_devname,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisdev->classname, thisdev->addresses[0]);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen fprintf(stdout,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext(
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tVendor\t\t\t: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tProduct\t\t\t: %s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tFirmware revision\t: %-s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tInquiry Serial Number : %-s\n"
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "\tGUID\t\t\t: %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisdev->ident->vid,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisdev->ident->pid,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisdev->ident->revid,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (thisdev->addresses[1] ? thisdev->addresses[1] :
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (thisdev->addresses[2] ? thisdev->addresses[2] :
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "(not supported)"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen fprintf(stdout, "\n\n");
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_SUCCESS);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenvoid
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenfw_cleanup(struct devicelist *thisdev)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Function to clean up all the memory allocated
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * by this plugin, for thisdev.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(thisdev->access_devname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(thisdev->drvname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(thisdev->classname);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Note that we DO NOT free addresses[1,2] because _IF_
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * these elements are valid, they are managed by libdevinfo
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * and we didn't allocate any space for them.
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(thisdev->addresses[0]);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* what this points to is freed in common code */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisdev->plugin = NULL;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(thisdev->ident->vid);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(thisdev->ident->pid);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(thisdev->ident->revid);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen thisdev->ident = NULL;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen/*
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen * Helper functions
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic int
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenlink_cb(di_devlink_t devlink, void *arg)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen const char *result;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen result = di_devlink_path(devlink);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (result == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen arg = (void *)"(null)";
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen (void) strlcpy(arg, result, strlen(result) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n",
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen ((result != NULL) ? result : "(null)"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (DI_WALK_CONTINUE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic char *
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChenfind_link(di_node_t bnode, char *acc_devname)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen di_minor_t devminor = DI_MINOR_NIL;
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen di_devlink_handle_t hdl;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen char *cbresult = NULL;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen char linkname[] = "^rdsk/\0";
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (bnode == DI_NODE_NIL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("find_link must be called with non-null "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "di_node_t\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (NULL);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if ((cbresult = calloc(1, MAXPATHLEN)) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("unable to allocate space for dev "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "link\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (NULL);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen devminor = di_minor_next(bnode, devminor);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen errno = 0;
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (hdl == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (errno == EPERM || errno == EACCES) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("%s: You must be super-user to use this "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "plugin.\n"), drivername);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("unable to take devlink snapshot: %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strerror(errno));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen free(cbresult);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (NULL);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen errno = 0;
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen if (di_devlink_walk(hdl, linkname, acc_devname + strlen(devprefix),
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen DI_PRIMARY_LINK, (void *)cbresult, link_cb) < 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("Unable to walk devlink snapshot for %s: %s\n"),
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen acc_devname, strerror(errno));
4b3dc1e28d71ec83965913203b49cb68c2a9a4a6XinChen free(cbresult);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (NULL);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (di_devlink_fini(&hdl) < 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR,
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen gettext("Unable to close devlink snapshot: %s\n"),
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strerror(errno));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_INFO, "cbresult: %s\n", cbresult);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (cbresult);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChenstatic int
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChensd_idtfy_custmz(struct devicelist *device, char *sp)
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen{
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* vid customization */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if (strncmp(sp, "ST", 2) == 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Customize retail Seagate disks */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((device->ident->vid = strdup("SEAGATE")) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else if (strncmp(sp, "SSD", 3) == 0) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* Customize retail INTEL disks */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((device->ident->vid = strdup("INTEL")) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen } else {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* disks to do in the furture, fill 'ATA' first */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((device->ident->vid = strdup("ATA")) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen /* pid customization */
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen if ((device->ident->pid = calloc(1, strlen(sp) + 1)) == NULL) {
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen logmsg(MSG_ERROR, gettext("Unable to allocate space for "
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen "product id\n"));
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen free(device->ident->vid);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_FAILURE);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen }
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen strlcpy(device->ident->pid, sp, strlen(sp) + 1);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen return (FWFLASH_SUCCESS);
d65b419ea7828ceaecc8f2ed7188237add6b14dcXinChen}