sd.c revision 0bc9814f152db9078852cc4ec759a4d8b53a1b8b
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* sd / ssd (SCSI Direct-attached Device) specific functions.
*/
#include <libnvpair.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <libintl.h> /* for gettext(3c) */
typedef struct sam4_statdesc {
int status;
char *message;
static sam4_statdesc_t sam4_status[] = {
{ SAM4_STATUS_GOOD, "Status: GOOD (success)" },
{ SAM4_STATUS_CHECK_CONDITION, "Status: CHECK CONDITION" },
{ SAM4_STATUS_CONDITION_MET, "Status: CONDITION MET" },
{ SAM4_STATUS_BUSY, "Status: Device is BUSY" },
{ SAM4_STATUS_RESERVATION_CONFLICT, "Status: Device is RESERVED" },
"Status: TASK SET FULL (insufficient resources in command queue" },
{ SAM4_STATUS_TASK_ABORTED, "Status: TASK ABORTED" },
};
#define NSAM4_STATUS \
(sizeof (sam4_status) / sizeof (sam4_status[0]))
#define FW_SD_FREE_DEVPATH(devpath) { \
di_devfs_path_free((devpath)); \
}
}
}
}
}
}
}
}
}
}
int errno;
char drivername[] = "sd\0";
int plugin_version = FWPLUGIN_VERSION_2;
static char *devprefix = "/devices";
extern struct vrfyplugin *verifier;
extern int fwflash_debug;
/* required functions for this plugin */
int fw_identify(int start);
/* helper functions */
/*
* We don't currently support reading firmware from a disk. If we do eventually
* support it, we would use the scsi READ BUFFER command to do so.
*/
int
{
"%s: not writing firmware for device %s to file %s\n",
gettext("\n\nReading of firmware images from %s-attached "
"devices is not supported\n\n"),
return (FWFLASH_SUCCESS);
}
int
{
int rv;
int i = 0;
/* should _NOT_ happen */
gettext("%s: Firmware image has not been verified\n"),
return (FWFLASH_FAILURE);
}
return (FWFLASH_FAILURE);
}
== NULL) {
gettext("%s: unable to open device %s\n"),
return (FWFLASH_FAILURE);
}
wb_cdb->wbc_buffer_offset[0] = 0;
wb_cdb->wbc_parameter_list_len[0] =
if (rv != FWFLASH_SUCCESS)
return (FWFLASH_FAILURE);
for (i = 0; i < NSAM4_STATUS; i++) {
(sam4_status[i].message));
break;
}
}
if (i == NSAM4_STATUS)
if (samstatus == SAM4_STATUS_GOOD) {
"(SSD, etc). You may need power off the system to wait a "
"few minutes for supercap to fully discharge, then power "
"on the system again to activate the new firmware\n"));
return (FWFLASH_SUCCESS);
}
return (FWFLASH_FAILURE);
}
/*
* The fw_identify() function walks the device
* tree trying to find devices which this plugin
* can work with.
*
* The parameter "start" gives us the starting index number
* to give the device when we add it to the fw_devices list.
*
* firstdev is allocated by us and we add space as needed
*
* When we store the desired information, inquiry-serial-no
* goes in thisdev->addresses[1], and client-guid goes in
* thisdev->addresses[2].
*/
int
fw_identify(int start)
{
int fw_sata_disk = 0;
int *exists;
char *sp_temp;
char *sp_temp_cut;
/* We need to inquiry information manually by sending probe command */
/* Just in case we've got an FC-attached device on sparc */
} else
driver = drivername;
if (thisnode == DI_NODE_NIL) {
return (FWFLASH_FAILURE);
}
return (FWFLASH_FAILURE);
}
/* we've found one, at least */
/* Need to free by di_devfs_path_free */
"current node with errno %d\n", errno);
continue;
}
/*
* We check if this is removable device, in which case
* we really aren't interested, so exit stage left
*/
"%s: not interested in removable media device\n"
continue;
}
== NULL) {
gettext("%s: identification function unable "
"to allocate space for device entry\n"),
driver);
return (FWFLASH_FAILURE);
}
== NULL) {
gettext("%s: Unable to allocate space to store a "
"driver name\n"), driver);
return (FWFLASH_FAILURE);
}
== NULL) {
gettext("%s: Unable to allocate space for a class "
"name\n"), drivername);
return (FWFLASH_FAILURE);
}
/* Get the access name for current node */
gettext("%s: Unable to allocate space for a devfs "
"name\n"), driver);
return (FWFLASH_FAILURE);
}
/* The slice number may be 2 or 0, we will try 2 first */
/* try 0 for EFI label */
"%s: unable to open device %s\n",
continue;
}
}
return (FWFLASH_FAILURE);
}
/*
* Only alloc as much as we truly need, and DON'T forget
* that libdevinfo manages the memory!
*/
gettext("%s: Unable to allocate space for SCSI "
"INQUIRY data\n"), driver);
return (FWFLASH_FAILURE);
}
/* We don't use new->ident->encap_ident currently */
/* Retrive information by using libscsi */
/* Vendor ID */
/* We need to do customize the output for SATA disks */
fw_sata_disk = 1;
} else {
fw_sata_disk = 0;
if (!sp_temp) {
"to get vendor id of %s\n"),
} else {
"allocation failure\n"));
}
return (FWFLASH_FAILURE);
}
}
/* Product ID */
if (fw_sata_disk) {
if (!sp_temp_cut) {
/*
* There is no SPACE character in the PID field
* Customize strings for special SATA disks
*/
!= FWFLASH_SUCCESS) {
return (FWFLASH_FAILURE);
}
} else {
/* The first string is vendor id */
"to get sata vendor id of %s\n"),
return (FWFLASH_FAILURE);
}
/* The second string is product id */
"to get sata product id of %s\n"),
return (FWFLASH_FAILURE);
}
}
} else {
return (FWFLASH_FAILURE);
}
}
/* Revision ID */
return (FWFLASH_FAILURE);
}
/* Finish using libscsi */
"%s: no inquiry-serial-no property for %s\n",
}
"%s: no client-guid property "
"for device %s\n",
/* try fallback */
"%s: no guid property for device %s\n",
}
} else {
"client-guid property: %s\n",
}
++idx;
}
/* Check if sd targets presented are all unflashable. */
return (FWFLASH_FAILURE);
if (fwflash_debug != 0) {
struct devicelist *tempdev;
driver);
"\ttempdev @ 0x%lx\n"
"\t\taccess_devname: %s\n"
"\t\tdrvname: %s\tclassname: %s\n"
"\t\tident->vid: %s\n"
"\t\tident->pid: %s\n"
"\t\tident->revid: %s\n"
"\t\tindex: %d\n"
"\t\taddress[0]: %s\n"
"\t\taddress[1]: %s\n"
"\t\taddress[2]: %s\n"
"\t\tplugin @ 0x%lx\n\n",
&tempdev,
"(not supported)"),
"(not supported)"),
}
}
return (FWFLASH_SUCCESS);
}
int
{
" Class [%s]\t\t\t%s\n"),
"\tVendor\t\t\t: %s\n"
"\tProduct\t\t\t: %s\n"
"\tFirmware revision\t: %-s\n"
"\tInquiry Serial Number : %-s\n"
"\tGUID\t\t\t: %s\n"),
"(not supported)"),
"(not supported)"));
return (FWFLASH_SUCCESS);
}
void
{
/*
* Function to clean up all the memory allocated
* by this plugin, for thisdev.
*/
/*
* Note that we DO NOT free addresses[1,2] because _IF_
* these elements are valid, they are managed by libdevinfo
* and we didn't allocate any space for them.
*/
/* what this points to is freed in common code */
}
/*
* Helper functions
*/
static int
{
const char *result;
arg = (void *)"(null)";
} else {
}
return (DI_WALK_CONTINUE);
}
static char *
{
char linkname[] = "^rdsk/\0";
if (bnode == DI_NODE_NIL) {
gettext("find_link must be called with non-null "
"di_node_t\n"));
return (NULL);
}
"link\n"));
return (NULL);
}
errno = 0;
gettext("%s: You must be super-user to use this "
"plugin.\n"), drivername);
} else {
gettext("unable to take devlink snapshot: %s\n"),
}
return (NULL);
}
errno = 0;
gettext("Unable to walk devlink snapshot for %s: %s\n"),
return (NULL);
}
if (di_devlink_fini(&hdl) < 0) {
gettext("Unable to close devlink snapshot: %s\n"),
}
return (cbresult);
}
static int
{
/* vid customization */
/* Customize retail Seagate disks */
return (FWFLASH_FAILURE);
}
/* Customize retail INTEL disks */
return (FWFLASH_FAILURE);
}
} else {
/* disks to do in the furture, fill 'ATA' first */
return (FWFLASH_FAILURE);
}
}
/* pid customization */
"product id\n"));
return (FWFLASH_FAILURE);
}
return (FWFLASH_SUCCESS);
}