summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorXinChen <Xin.Chen@Sun.COM>2009-05-21 12:23:08 +0800
committerXinChen <Xin.Chen@Sun.COM>2009-05-21 12:23:08 +0800
commitd65b419ea7828ceaecc8f2ed7188237add6b14dc (patch)
treefb36c5aef955ecaa631de1fdca3c6afeb45235b8 /usr
parentf1956ffef55a0f859d3974677c90c728e3fc32f5 (diff)
downloadillumos-gate-d65b419ea7828ceaecc8f2ed7188237add6b14dc.tar.gz
PSARC 2009/163 Specification update for Pluggable fwflash
6771438 enhance fwflash to allow firmware download for disk drives 6808567 fwflash's ses plugin should use exit status codes consistently
Diffstat (limited to 'usr')
-rw-r--r--usr/src/cmd/fwflash/common/fwflash.c165
-rw-r--r--usr/src/cmd/fwflash/common/fwflash.h13
-rw-r--r--usr/src/cmd/fwflash/plugins/i386/Makefile5
-rw-r--r--usr/src/cmd/fwflash/plugins/sparc/Makefile5
-rw-r--r--usr/src/cmd/fwflash/plugins/transport/common/sd.c745
-rw-r--r--usr/src/cmd/fwflash/plugins/transport/common/ses.c64
-rw-r--r--usr/src/cmd/fwflash/plugins/transport/i386/Makefile3
-rw-r--r--usr/src/cmd/fwflash/plugins/transport/sparc/Makefile3
-rw-r--r--usr/src/cmd/fwflash/plugins/vendor/sd-GENERIC.c89
-rw-r--r--usr/src/pkgdefs/SUNWfwflash/prototype_com4
10 files changed, 1002 insertions, 94 deletions
diff --git a/usr/src/cmd/fwflash/common/fwflash.c b/usr/src/cmd/fwflash/common/fwflash.c
index 8514eaa07f..ead9c4f2ce 100644
--- a/usr/src/cmd/fwflash/common/fwflash.c
+++ b/usr/src/cmd/fwflash/common/fwflash.c
@@ -83,7 +83,7 @@ static int fwflash_in_write = 0;
* actually of any use - it doesn't line up with Mercurial's
* concept of the changeset.
*/
-#define FWFLASH_VERSION "v1.7"
+#define FWFLASH_VERSION "v1.8"
#define FWFLASH_PROG_NAME "fwflash"
static int get_fileopts(char *options);
@@ -323,7 +323,7 @@ flash_load_plugins()
logmsg(MSG_ERROR,
gettext("Unable to malloc %d bytes while "
"trying to load plugins: %s\n"),
- sizeof (struct fw_plugin) + 1, strerror(errno));
+ sizeof (struct fw_plugin), strerror(errno));
return (FWFLASH_FAILURE);
}
@@ -399,7 +399,8 @@ flash_load_plugins()
MAXMODCONFNAME) != 0) {
char *tempnm = calloc(1, MAXMODCONFNAME);
- memcpy(tempnm, plugdir->d_name, MAXMODCONFNAME);
+ (void) memcpy(tempnm, plugdir->d_name,
+ MAXMODCONFNAME);
(void) strlcpy(tmpplug->drvname,
strtok(tempnm, "."),
strlen(plugdir->d_name) + 1);
@@ -444,6 +445,28 @@ flash_load_plugins()
continue;
}
+ if ((sym = dlsym(tmpplug->handle, "plugin_version"))
+ != NULL) {
+ if ((*(int *)sym) >= FWPLUGIN_VERSION_2) {
+ if ((sym = dlsym(tmpplug->handle,
+ "fw_cleanup")) != NULL) {
+ tmpplug->fw_cleanup =
+ (void (*)(struct devicelist *))sym;
+ } else {
+ logmsg(MSG_ERROR,
+ gettext("ERROR: v2 plugin (%s) "
+ "has no fw_cleanup function\n"),
+ tmpplug->filename);
+ CLOSEFREE();
+ continue;
+ }
+ } else {
+ logmsg(MSG_INFO,
+ "Identification plugin %s defined "
+ "plugin_version < FWPLUGIN_VERSION_2 !");
+ }
+ }
+
if ((tmpelem->drvname = calloc(1, MAXMODCONFNAME))
== NULL) {
logmsg(MSG_ERROR,
@@ -482,12 +505,11 @@ flash_load_plugins()
logmsg(MSG_ERROR,
gettext("Error reading directory entry in %s\n"),
fwplugdirpath);
- (void) closedir(dirp);
rval = errno;
}
- (void) free(fwplugdirpath);
- (void) free(plugdir);
+ free(fwplugdirpath);
+ free(plugdir);
(void) closedir(dirp);
return (rval);
}
@@ -522,11 +544,15 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
verifier->imgsize = 0;
verifier->flashbuf = 0; /* set by the verifier function */
- if (verifier->imgfile != NULL)
- (void) free(verifier->imgfile);
+ if (verifier->imgfile != NULL) {
+ free(verifier->imgfile);
+ verifier->imgfile = NULL;
+ }
- if (verifier->fwimage != NULL)
- (void) free(verifier->fwimage);
+ if (verifier->fwimage != NULL) {
+ free(verifier->fwimage);
+ verifier->fwimage = NULL;
+ }
} else {
if ((fwvrfydirpath = calloc(1, MAXPATHLEN + 1)) == NULL) {
logmsg(MSG_ERROR,
@@ -539,20 +565,24 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
logmsg(MSG_ERROR,
gettext("Unable to allocate space "
"for a firmware verifier file(2)"));
+ free(fwvrfydirpath);
return (rv);
}
- /*
- * Since SCSI devices can have a vendor id of up to 8 left-aligned
- * and _space-padded_ characters, we first need to strip off any
- * space characters before we try to make a filename out of it
- */
+ /*
+ * Since SCSI devices can have a vendor id of up to 8
+ * left-aligned and _space-padded_ characters, we first need to
+ * strip off any space characters before we try to make a
+ * filename out of it
+ */
clean = strtok(vendorid, " ");
if (clean == NULL) {
/* invalid vendorid, something's really wrong */
logmsg(MSG_ERROR,
gettext("Invalid vendorid (null) specified for "
"device\n"));
+ free(filename);
+ free(fwvrfydirpath);
return (rv);
}
@@ -572,14 +602,39 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
"for a firmware verifier structure"));
free(filename);
free(fwvrfydirpath);
- return (FWFLASH_FAILURE);
+ return (rv);
}
errno = 0; /* false positive removal */
- (void) snprintf(filename, strlen(fwvrfydirpath) +
- strlen(drv) + 7 + strlen(clean), "%s/%s-%s.so\0",
+ (void) snprintf(filename, MAXPATHLEN, "%s/%s-%s.so",
fwvrfydirpath, drv, clean);
+ if ((vrfy->handle = dlopen(filename, RTLD_NOW)) == NULL) {
+ logmsg(MSG_INFO, gettext(dlerror()));
+ logmsg(MSG_INFO,
+ gettext("\nUnable to open verification plugin "
+ "%s. Looking for %s-GENERIC plugin instead.\n"),
+ filename, drv);
+
+ /* Try the drv-GENERIC.so form, _then_ die */
+ bzero(filename, strlen(filename) + 1);
+ (void) snprintf(filename, MAXPATHLEN,
+ "%s/%s-GENERIC.so", fwvrfydirpath, drv);
+
+ if ((vrfy->handle = dlopen(filename, RTLD_NOW))
+ == NULL) {
+ logmsg(MSG_INFO, gettext(dlerror()));
+ logmsg(MSG_ERROR,
+ gettext("\nUnable to open either "
+ "verification plugin %s/%s-%s.so or "
+ "generic plugin %s.\nUnable to verify "
+ "firmware image. Aborting.\n"),
+ fwvrfydirpath, drv, clean, filename);
+ free(filename);
+ free(fwvrfydirpath);
+ return (rv);
+ }
+ }
if ((vrfy->filename = calloc(1, strlen(filename) + 1))
== NULL) {
@@ -589,23 +644,10 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
free(filename);
free(fwvrfydirpath);
free(vrfy->handle);
- return (FWFLASH_FAILURE);
+ return (rv);
}
-
(void) strlcpy(vrfy->filename, filename, strlen(filename) + 1);
- if ((vrfy->handle = dlopen(filename, RTLD_NOW)) == NULL) {
- logmsg(MSG_ERROR, gettext(dlerror()));
- logmsg(MSG_ERROR,
- gettext("Unable to open verification plugin "
- "%s. Unable to verify firmware image. "
- "Aborting.\n"),
- filename);
- free(filename);
- free(fwvrfydirpath);
- return (FWFLASH_FAILURE);
- }
-
if ((vrfysym = dlsym(vrfy->handle, "vendorvrfy")) == NULL) {
logmsg(MSG_ERROR,
gettext("%s is an invalid firmware verification "
@@ -614,7 +656,7 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
free(filename);
free(fwvrfydirpath);
free(vrfy);
- return (FWFLASH_FAILURE);
+ return (rv);
} else {
vrfy->vendorvrfy =
(int (*)(struct devicelist *))vrfysym;
@@ -628,13 +670,13 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
"plugin %s\n"), filename);
(void) dlclose(vrfy->handle);
free(vrfy);
- return (NULL);
+ return (rv);
} else {
if (strncmp(vendorid, (char *)vrfysym,
strlen(vendorid)) != 0) {
logmsg(MSG_INFO,
"Using a sym-linked (%s -> %s) "
- "verification plugin",
+ "verification plugin\n",
vendorid, vrfysym);
vrfy->vendor = calloc(1, strlen(vendorid) + 1);
} else {
@@ -645,9 +687,10 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
}
verifier = vrfy; /* a convenience variable */
+ free(filename);
+ free(fwvrfydirpath);
}
-
/*
* We don't do any verification that the fw image file is in
* an approved location, but it's easy enough to modify this
@@ -694,7 +737,7 @@ fwflash_load_verifier(char *drv, char *vendorid, char *fwimg)
"(got %d bytes, expected %d bytes) from "
"firmware image file %s: %s\n"),
rv, verifier->imgsize,
- filename, strerror(errno));
+ verifier->filename, strerror(errno));
rv = FWFLASH_FAILURE;
} else {
rv = FWFLASH_SUCCESS;
@@ -714,7 +757,8 @@ cleanup:
free(verifier->filename);
free(verifier->vendor);
- if (!(fwflash_arg_list & FWFLASH_READ_FLAG))
+ if (!(fwflash_arg_list & FWFLASH_READ_FLAG) &&
+ verifier->fwimage)
free(verifier->fwimage);
verifier->filename = NULL;
@@ -753,7 +797,7 @@ flash_device_list()
struct pluginlist *plugins;
/* we open rootnode here, and close it in fwflash_intr */
- if ((rootnode = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
+ if ((rootnode = di_init("/", DINFOCPYALL|DINFOFORCE)) == DI_NODE_NIL) {
logmsg(MSG_ERROR,
gettext("Unable to take device tree snapshot: %s\n"),
strerror(errno));
@@ -898,7 +942,6 @@ fwflash_update(char *device, char *filename, int flags)
filename, device);
TAILQ_FOREACH(curdev, fw_devices, nextdev) {
-
if (strcmp(curdev->access_devname, realfile) == 0) {
found++;
rv = fwflash_load_verifier(curdev->drvname,
@@ -953,7 +996,7 @@ fwflash_update(char *device, char *filename, int flags)
gettext("Device %s does not appear "
"to be flashable\n"),
((strncmp(device, realfile, strlen(device)) == 0) ?
- device : realfile));
+ realfile : device));
if (needsfree)
free(realfile);
@@ -1060,10 +1103,10 @@ fwflash_intr(int sig)
struct devicelist *thisdev;
struct pluginlist *thisplug;
-
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGTERM, SIG_IGN);
(void) signal(SIGABRT, SIG_IGN);
+
if (fwflash_in_write) {
(void) fprintf(stderr,
gettext("WARNING: firmware image may be corrupted\n\t"));
@@ -1083,15 +1126,23 @@ fwflash_intr(int sig)
*/
if (fw_devices != NULL) {
TAILQ_FOREACH(thisdev, fw_devices, nextdev) {
- /* free the components first */
- free(thisdev->access_devname);
- free(thisdev->drvname);
- free(thisdev->classname);
- if (thisdev->ident != NULL)
- free(thisdev->ident);
-
- thisdev->ident = NULL;
- thisdev->plugin = NULL; /* we free this elsewhere */
+ if (thisdev->plugin->fw_cleanup != NULL) {
+ /*
+ * If we've got a cleanup routine, it
+ * cleans up _everything_ for thisdev
+ */
+ thisdev->plugin->fw_cleanup(thisdev);
+ } else {
+ /* free the components first */
+ free(thisdev->access_devname);
+ free(thisdev->drvname);
+ free(thisdev->classname);
+ if (thisdev->ident != NULL)
+ free(thisdev->ident);
+ /* We don't free address[] for old plugins */
+ thisdev->ident = NULL;
+ thisdev->plugin = NULL;
+ }
/* CONSTCOND */
TAILQ_REMOVE(fw_devices, thisdev, nextdev);
}
@@ -1111,6 +1162,7 @@ fwflash_intr(int sig)
thisplug->plugin->fw_writefw = NULL;
thisplug->plugin->fw_identify = NULL;
thisplug->plugin->fw_devinfo = NULL;
+ thisplug->plugin->fw_cleanup = NULL;
(void) dlclose(thisplug->plugin->handle);
thisplug->plugin->handle = NULL;
free(thisplug->plugin);
@@ -1135,6 +1187,9 @@ fwflash_intr(int sig)
free(verifier);
}
di_fini(rootnode);
+
+ if (sig > 0)
+ exit(FWFLASH_FAILURE);
}
static void
@@ -1159,8 +1214,8 @@ confirm_target(struct devicelist *thisdev, char *file)
(void) fflush(stdin);
(void) printf(gettext("About to update firmware on %s\n"),
thisdev->access_devname);
- (void) printf(gettext("with file %s. Do you want to continue? "
- "(Y/N): "), file);
+ (void) printf(gettext("with file %s.\n"
+ "Do you want to continue? (Y/N): "), file);
resp = getchar();
if (resp == 'Y' || resp == 'y') {
@@ -1227,8 +1282,8 @@ get_fileopts(char *options)
* code reuse - cheerfully borrowed from stmsboot_util.c
*/
void
-logmsg(int severity, const char *msg, ...) {
-
+logmsg(int severity, const char *msg, ...)
+{
va_list ap;
if ((severity > MSG_INFO) ||
diff --git a/usr/src/cmd/fwflash/common/fwflash.h b/usr/src/cmd/fwflash/common/fwflash.h
index ff7985d19c..54c140896d 100644
--- a/usr/src/cmd/fwflash/common/fwflash.h
+++ b/usr/src/cmd/fwflash/common/fwflash.h
@@ -57,6 +57,7 @@ int fwflash_debug;
*/
#define FWPLUGIN_VERSION_1 1
+#define FWPLUGIN_VERSION_2 2
struct devicelist;
@@ -120,6 +121,16 @@ struct fw_plugin {
* All identification plugins must support this operation.
*/
int (*fw_devinfo)(struct devicelist *thisdev);
+
+ /*
+ * Function entry point to allow the plugin to clean up its
+ * data structure use IF plugin_version == FWPLUGIN_VERSION_2.
+ *
+ * If this function is not defined in the plugin, that is not
+ * an error condition unless the plugin_version variable is
+ * defined.
+ */
+ void (*fw_cleanup)(struct devicelist *thisdev);
};
@@ -173,7 +184,7 @@ struct vpr {
struct fwfile {
/*
* The fully qualified filename. No default location for
- * for the firmware image file is mandated.
+ * the firmware image file is mandated.
*/
char *filename;
diff --git a/usr/src/cmd/fwflash/plugins/i386/Makefile b/usr/src/cmd/fwflash/plugins/i386/Makefile
index 66b1a29458..d359c556e6 100644
--- a/usr/src/cmd/fwflash/plugins/i386/Makefile
+++ b/usr/src/cmd/fwflash/plugins/i386/Makefile
@@ -24,7 +24,7 @@
# cmd/fwflash/plugins/i386
#
-SRCS= tavor-MELLANOX.c hermon-MELLANOX.c
+SRCS= tavor-MELLANOX.c hermon-MELLANOX.c sd-GENERIC.c
OBJECTS= $(SRCS:%.c=%.o)
PLUGINS= $(SRCS:%.c=%.so)
POFILES= $(SRCS:%.c=%.po)
@@ -82,7 +82,8 @@ $(VERIFYPOFILE): $(POFILES)
install: $(ROOTLIBFWFLASHVERIFY) \
$(ROOTLIBFWFLASHVERIFY)/tavor-MELLANOX.so \
- $(ROOTLIBFWFLASHVERIFY)/hermon-MELLANOX.so
+ $(ROOTLIBFWFLASHVERIFY)/hermon-MELLANOX.so \
+ $(ROOTLIBFWFLASHVERIFY)/sd-GENERIC.so
clean:
$(RM) $(OBJECTS)
diff --git a/usr/src/cmd/fwflash/plugins/sparc/Makefile b/usr/src/cmd/fwflash/plugins/sparc/Makefile
index cbc156b6e5..fedee291ee 100644
--- a/usr/src/cmd/fwflash/plugins/sparc/Makefile
+++ b/usr/src/cmd/fwflash/plugins/sparc/Makefile
@@ -24,7 +24,7 @@
# cmd/fwflash/plugins/sparc
#
-SRCS= tavor-MELLANOX.c hermon-MELLANOX.c
+SRCS= tavor-MELLANOX.c hermon-MELLANOX.c sd-GENERIC.c
OBJECTS= $(SRCS:%.c=%.o)
PLUGINS= $(SRCS:%.c=%.so)
POFILES= $(SRCS:%.c=%.po)
@@ -82,7 +82,8 @@ $(VERIFYPOFILE): $(POFILES)
install: $(ROOTLIBFWFLASHVERIFY) \
$(ROOTLIBFWFLASHVERIFY)/tavor-MELLANOX.so \
- $(ROOTLIBFWFLASHVERIFY)/hermon-MELLANOX.so
+ $(ROOTLIBFWFLASHVERIFY)/hermon-MELLANOX.so \
+ $(ROOTLIBFWFLASHVERIFY)/sd-GENERIC.so
clean:
$(RM) $(OBJECTS)
diff --git a/usr/src/cmd/fwflash/plugins/transport/common/sd.c b/usr/src/cmd/fwflash/plugins/transport/common/sd.c
new file mode 100644
index 0000000000..c1d32cf97b
--- /dev/null
+++ b/usr/src/cmd/fwflash/plugins/transport/common/sd.c
@@ -0,0 +1,745 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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/types.h>
+#include <sys/sysmacros.h>
+#include <sys/queue.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <scsi/libscsi.h>
+#include <libintl.h> /* for gettext(3c) */
+#include <fwflash/fwflash.h>
+
+typedef struct sam4_statdesc {
+ int status;
+ char *message;
+} sam4_statdesc_t;
+
+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" },
+ { SAM4_STATUS_TASK_SET_FULL,
+ "Status: TASK SET FULL (insufficient resources in command queue" },
+ { SAM4_STATUS_TASK_ABORTED, "Status: TASK ABORTED" },
+ { NULL, NULL }
+};
+
+#define NSAM4_STATUS \
+ (sizeof (sam4_status) / sizeof (sam4_status[0]))
+
+#define FW_SD_FREE_DEVPATH(devpath) { \
+ di_devfs_path_free((devpath)); \
+ }
+#define FW_SD_FREE_DEVICELIST(thisdev, devpath) { \
+ free((thisdev)); \
+ FW_SD_FREE_DEVPATH((devpath)) \
+ }
+#define FW_SD_FREE_ACC_NAME(thisdev, devpath) { \
+ free((thisdev)->access_devname); \
+ FW_SD_FREE_DEVICELIST(thisdev, devpath) \
+ }
+#define FW_SD_FREE_DRV_NAME(thisdev, devpath) { \
+ free((thisdev)->drvname); \
+ FW_SD_FREE_ACC_NAME((thisdev), (devpath)) \
+ }
+#define FW_SD_FREE_CLS_NAME(thisdev, devpath) { \
+ free((thisdev)->classname); \
+ FW_SD_FREE_DRV_NAME((thisdev), (devpath)) \
+ }
+#define FW_SD_FREE_IDENT(thisdev, devpath) { \
+ free((thisdev)->ident); \
+ FW_SD_FREE_CLS_NAME((thisdev), (devpath)) \
+ }
+#define FW_SD_FREE_IDENT_VID(thisdev, devpath) { \
+ free((thisdev)->ident->vid); \
+ FW_SD_FREE_IDENT((thisdev), (devpath)) \
+ }
+#define FW_SD_FREE_IDENT_PID(thisdev, devpath) { \
+ free((thisdev)->ident->pid); \
+ FW_SD_FREE_IDENT_VID((thisdev), (devpath)) \
+ }
+#define FW_SD_FREE_IDENT_ALL(thisdev, devpath) { \
+ free((thisdev)->ident->revid); \
+ FW_SD_FREE_IDENT_PID((thisdev), (devpath)) \
+ }
+
+int errno;
+char drivername[] = "sd\0";
+int plugin_version = FWPLUGIN_VERSION_2;
+
+static char *devprefix = "/devices";
+extern di_node_t rootnode;
+extern struct fw_plugin *self;
+extern struct vrfyplugin *verifier;
+extern int fwflash_debug;
+
+/* required functions for this plugin */
+int fw_readfw(struct devicelist *device, char *filename);
+int fw_writefw(struct devicelist *device);
+int fw_identify(int start);
+int fw_devinfo(struct devicelist *thisdev);
+void fw_cleanup(struct devicelist *thisdev);
+
+/* helper functions */
+static char *find_link(di_node_t bnode);
+static int link_cb(di_devlink_t devlink, void *arg);
+static int sd_idtfy_custmz(struct devicelist *device, char *sp);
+
+/*
+ * 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
+fw_readfw(struct devicelist *flashdev, char *filename)
+{
+
+ logmsg(MSG_INFO,
+ "%s: not writing firmware for device %s to file %s\n",
+ flashdev->drvname, flashdev->access_devname, filename);
+ logmsg(MSG_ERROR,
+ gettext("\n\nReading of firmware images from %s-attached "
+ "devices is not supported\n\n"),
+ flashdev->drvname);
+
+ return (FWFLASH_SUCCESS);
+}
+
+int
+fw_writefw(struct devicelist *flashdev)
+{
+ int rv;
+ int i = 0;
+ libscsi_hdl_t *handle;
+ libscsi_target_t *target;
+ libscsi_action_t *action;
+ libscsi_errno_t serr;
+ spc3_write_buffer_cdb_t *wb_cdb;
+ sam4_status_t samstatus;
+
+ if ((verifier == NULL) || (verifier->imgsize == 0) ||
+ (verifier->fwimage == NULL)) {
+ /* should _NOT_ happen */
+ logmsg(MSG_ERROR,
+ gettext("%s: Firmware image has not been verified\n"),
+ flashdev->drvname);
+ return (FWFLASH_FAILURE);
+ }
+
+ if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
+ logmsg(MSG_ERROR, gettext("%s: failed to initialize libscsi\n"),
+ flashdev->drvname);
+ return (FWFLASH_FAILURE);
+ }
+
+ if ((target = libscsi_open(handle, NULL, flashdev->access_devname))
+ == NULL) {
+ logmsg(MSG_ERROR,
+ gettext("%s: unable to open device %s\n"),
+ flashdev->drvname, flashdev->access_devname);
+ libscsi_fini(handle);
+ return (FWFLASH_FAILURE);
+ }
+
+ action = libscsi_action_alloc(handle, SPC3_CMD_WRITE_BUFFER,
+ LIBSCSI_AF_WRITE|LIBSCSI_AF_RQSENSE,
+ (void *)verifier->fwimage, (size_t)verifier->imgsize);
+
+ wb_cdb = (spc3_write_buffer_cdb_t *)libscsi_action_get_cdb(action);
+
+ wb_cdb->wbc_mode = SPC3_WB_MODE_DL_UCODE_SAVE;
+ wb_cdb->wbc_bufferid = verifier->flashbuf;
+
+ wb_cdb->wbc_buffer_offset[0] = 0;
+ wb_cdb->wbc_buffer_offset[1] = 0;
+ wb_cdb->wbc_buffer_offset[2] = 0;
+
+ wb_cdb->wbc_parameter_list_len[0] =
+ (verifier->imgsize & 0xff0000) >> 16;
+ wb_cdb->wbc_parameter_list_len[1] = (verifier->imgsize & 0xff00) >> 8;
+ wb_cdb->wbc_parameter_list_len[2] = (verifier->imgsize & 0xff);
+
+ rv = libscsi_exec(action, target);
+ samstatus = libscsi_action_get_status(action);
+
+ logmsg(MSG_INFO, "\nscsi_writebuffer: ret 0x%0x, samstatus 0x%0x\n",
+ rv, samstatus);
+
+ libscsi_action_free(action);
+ libscsi_close(handle, target);
+ libscsi_fini(handle);
+
+ if (rv != FWFLASH_SUCCESS)
+ return (FWFLASH_FAILURE);
+
+ for (i = 0; i < NSAM4_STATUS; i++) {
+ if (sam4_status[i].status == samstatus) {
+ logmsg(MSG_ERROR, gettext("RETURN STATUS: %s\n"),
+ (sam4_status[i].message));
+ break;
+ }
+ }
+ if (i == NSAM4_STATUS)
+ logmsg(MSG_ERROR, gettext("Status UNKNOWN\n"));
+
+ if (samstatus == SAM4_STATUS_GOOD) {
+ logmsg(MSG_ERROR, gettext("Note: For flash based disks "
+ "(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 idx = start;
+ int fw_sata_disk = 0;
+ int *exists;
+ di_node_t thisnode;
+ struct devicelist *newdev = NULL;
+ char *devpath = NULL;
+ char *driver = NULL;
+ char *sp_temp;
+ char *sp_temp_cut;
+
+ /* We need to inquiry information manually by sending probe command */
+ libscsi_hdl_t *handle;
+ libscsi_target_t *target;
+ libscsi_errno_t serr;
+
+ /* Just in case we've got an FC-attached device on sparc */
+ if (strcmp(self->drvname, "ssd") == 0) {
+ driver = self->drvname;
+ } else
+ driver = drivername;
+
+ thisnode = di_drv_first_node(driver, rootnode);
+
+ if (thisnode == DI_NODE_NIL) {
+ logmsg(MSG_INFO, "No %s nodes in this system\n", driver);
+ return (FWFLASH_FAILURE);
+ }
+
+ if ((devpath = calloc(1, MAXPATHLEN + 1)) == NULL) {
+ logmsg(MSG_ERROR,
+ gettext("%s: Unable to allocate space for a device node\n"),
+ driver);
+ return (FWFLASH_FAILURE);
+ }
+
+ if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
+ logmsg(MSG_ERROR, gettext("%s: failed to initialize "
+ "libscsi\n"), newdev->drvname);
+ FW_SD_FREE_DEVPATH(devpath)
+ return (FWFLASH_FAILURE);
+ }
+
+ /* we've found one, at least */
+ for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
+ devpath = di_devfs_path(thisnode);
+ /*
+ * We check if this is removable device, in which case
+ * we really aren't interested, so exit stage left
+ */
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, thisnode,
+ "removable-media", &exists) > -1) {
+ logmsg(MSG_INFO,
+ "%s: not interested in removable media device\n"
+ "%s\n", driver, devpath);
+ continue;
+ }
+
+ if ((newdev = calloc(1, sizeof (struct devicelist)))
+ == NULL) {
+ logmsg(MSG_ERROR,
+ gettext("%s: identification function unable "
+ "to allocate space for device entry\n"),
+ driver);
+ libscsi_fini(handle);
+ FW_SD_FREE_DEVPATH(devpath)
+ return (FWFLASH_FAILURE);
+ }
+
+ if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) {
+ logmsg(MSG_ERROR,
+ gettext("%s: Unable to allocate space for a devfs "
+ "name\n"), driver);
+ libscsi_fini(handle);
+ FW_SD_FREE_DEVICELIST(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+
+ /* save the /devices name */
+ (void) snprintf(newdev->access_devname, MAXPATHLEN,
+ "%s%s:c,raw", devprefix, devpath);
+
+ /* and the /dev/rdsk/ name */
+ newdev->addresses[0] = calloc(1, MAXPATHLEN);
+ if (newdev->addresses[0])
+ newdev->addresses[0] = find_link(thisnode);
+ if (newdev->addresses[0] == NULL) {
+ libscsi_fini(handle);
+ FW_SD_FREE_DEVICELIST(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+
+ if ((newdev->drvname = calloc(1, strlen(driver) + 1))
+ == NULL) {
+ logmsg(MSG_ERROR,
+ gettext("%s: Unable to allocate space to store a "
+ "driver name\n"), driver);
+ libscsi_fini(handle);
+ FW_SD_FREE_ACC_NAME(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+ (void) strlcpy(newdev->drvname, driver, strlen(driver) + 1);
+
+ if ((newdev->classname = calloc(1, strlen(driver) + 1))
+ == NULL) {
+ logmsg(MSG_ERROR,
+ gettext("%s: Unable to allocate space for a class "
+ "name\n"), drivername);
+ libscsi_fini(handle);
+ FW_SD_FREE_DRV_NAME(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+ (void) strlcpy(newdev->classname, driver, strlen(driver) + 1);
+
+ /*
+ * Only alloc as much as we truly need, and DON'T forget
+ * that libdevinfo manages the memory!
+ */
+ if ((newdev->ident = calloc(1, sizeof (struct vpr))) == NULL) {
+ logmsg(MSG_ERROR,
+ gettext("%s: Unable to allocate space for SCSI "
+ "INQUIRY data\n"), driver);
+ libscsi_fini(handle);
+ FW_SD_FREE_CLS_NAME(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+
+ /* We don't use new->ident->encap_ident currently */
+
+ /* Retrive information by using libscsi */
+ if ((target = libscsi_open(handle, NULL,
+ newdev->access_devname)) == NULL) {
+ logmsg(MSG_INFO, "%s: unable to open device %s\n",
+ newdev->drvname, newdev->access_devname);
+ FW_SD_FREE_IDENT(newdev, devpath)
+ continue;
+ }
+
+ /* Vendor ID */
+ sp_temp = (char *)libscsi_vendor(target);
+ if (strncmp(sp_temp, "ATA", 3) == 0) {
+ /* We need to do customize the output for SATA disks */
+ fw_sata_disk = 1;
+ } else {
+ fw_sata_disk = 0;
+ if ((newdev->ident->vid =
+ calloc(1, strlen(sp_temp) + 1)) == NULL ||
+ sp_temp == NULL) {
+ if (!sp_temp) {
+ logmsg(MSG_ERROR, gettext("%s: unable "
+ "to get vendor id of %s\n"),
+ newdev->drvname,
+ newdev->access_devname);
+ } else {
+ logmsg(MSG_ERROR, gettext("Memory "
+ "allocation failure\n"));
+ }
+
+ libscsi_close(handle, target);
+ libscsi_fini(handle);
+ FW_SD_FREE_IDENT(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+ strlcpy(newdev->ident->vid, sp_temp,
+ strlen(sp_temp) + 1);
+ }
+
+ /* Product ID */
+ sp_temp = (char *)libscsi_product(target);
+ if (fw_sata_disk) {
+ sp_temp_cut = strchr(sp_temp, ' ');
+ if (!sp_temp_cut) {
+ /* Customize strings for special SATA disks */
+ if (sd_idtfy_custmz(newdev, sp_temp)
+ != FWFLASH_SUCCESS) {
+ libscsi_close(handle, target);
+ libscsi_fini(handle);
+ FW_SD_FREE_IDENT(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+ } else {
+ /* The first string is vendor id */
+ if ((newdev->ident->vid = calloc(1,
+ (sp_temp_cut - sp_temp + 1))) == NULL) {
+ logmsg(MSG_ERROR, gettext("%s: unable "
+ "to get sata vendor id of %s\n"),
+ newdev->drvname,
+ newdev->access_devname);
+
+ libscsi_close(handle, target);
+ libscsi_fini(handle);
+ FW_SD_FREE_IDENT(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+ strlcpy(newdev->ident->vid, sp_temp,
+ sp_temp_cut - sp_temp + 1);
+
+ /* The second string is product id */
+ if ((newdev->ident->pid =
+ calloc(1, strlen(sp_temp) -
+ strlen(newdev->ident->vid))) == NULL) {
+ logmsg(MSG_ERROR, gettext("%s: unable "
+ "to get sata product id of %s\n"),
+ newdev->drvname,
+ newdev->access_devname);
+
+ libscsi_close(handle, target);
+ libscsi_fini(handle);
+ FW_SD_FREE_IDENT_VID(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+ strlcpy(newdev->ident->pid, sp_temp_cut + 1,
+ strlen(sp_temp) -
+ strlen(newdev->ident->vid));
+ }
+ } else {
+ if ((newdev->ident->pid =
+ calloc(1, strlen(sp_temp) + 1)) == NULL ||
+ sp_temp == NULL) {
+ logmsg(MSG_ERROR, gettext("%s: unable to get "
+ "product id of %s\n"), newdev->drvname,
+ newdev->access_devname);
+ FW_SD_FREE_IDENT_VID(newdev, devpath)
+ libscsi_close(handle, target);
+ libscsi_fini(handle);
+ return (FWFLASH_FAILURE);
+ }
+ strlcpy(newdev->ident->pid, sp_temp,
+ strlen(sp_temp) + 1);
+ }
+
+ /* Revision ID */
+ sp_temp = (char *)libscsi_revision(target);
+ if ((newdev->ident->revid = calloc(1, strlen(sp_temp) + 1))
+ == NULL || sp_temp == NULL) {
+ logmsg(MSG_ERROR, gettext("%s: unable to get revision "
+ "id of %s\n"), newdev->drvname,
+ newdev->access_devname);
+ libscsi_close(handle, target);
+ libscsi_fini(handle);
+ FW_SD_FREE_IDENT_PID(newdev, devpath)
+ return (FWFLASH_FAILURE);
+ }
+ strlcpy(newdev->ident->revid, sp_temp, strlen(sp_temp) + 1);
+
+ /* Finish using libscsi */
+ libscsi_close(handle, target);
+
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
+ "inquiry-serial-no", &newdev->addresses[1]) < 0) {
+ logmsg(MSG_INFO,
+ "%s: no inquiry-serial-no property for %s\n",
+ driver, newdev->access_devname);
+ logmsg(MSG_INFO, "The errno is %d\n", errno);
+ }
+
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
+ "client-guid", &newdev->addresses[2])) < 0) {
+ logmsg(MSG_INFO,
+ "%s: no client-guid property "
+ "for device %s\n",
+ driver, newdev->access_devname);
+ /* try fallback */
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, thisnode,
+ "guid", &newdev->addresses[2])) < 0) {
+ logmsg(MSG_INFO,
+ "%s: no guid property for device %s\n",
+ driver, newdev->access_devname);
+ }
+ } else {
+ logmsg(MSG_INFO,
+ "client-guid property: %s\n",
+ newdev->addresses[2]);
+ }
+
+ newdev->index = idx;
+ ++idx;
+ newdev->plugin = self;
+
+ TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
+ }
+ libscsi_fini(handle);
+ FW_SD_FREE_DEVPATH(devpath)
+
+ /* Check if sd targets presented are all unflashable. */
+ if (idx == start)
+ return (FWFLASH_FAILURE);
+
+ if (fwflash_debug != 0) {
+ struct devicelist *tempdev;
+
+ TAILQ_FOREACH(tempdev, fw_devices, nextdev) {
+ logmsg(MSG_INFO, "%s:fw_identify:\n",
+ driver);
+ logmsg(MSG_INFO,
+ "\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,
+ tempdev->access_devname,
+ tempdev->drvname, newdev->classname,
+ tempdev->ident->vid,
+ tempdev->ident->pid,
+ tempdev->ident->revid,
+ tempdev->index,
+ tempdev->addresses[0],
+ (tempdev->addresses[1] ? tempdev->addresses[1] :
+ "(not supported)"),
+ (tempdev->addresses[2] ? tempdev->addresses[2] :
+ "(not supported)"),
+ &tempdev->plugin);
+ }
+ }
+ return (FWFLASH_SUCCESS);
+}
+
+int
+fw_devinfo(struct devicelist *thisdev)
+{
+ fprintf(stdout, gettext("Device[%d]\t\t\t%s\n"
+ " Class [%s]\t\t\t%s\n"),
+ thisdev->index, thisdev->access_devname,
+ thisdev->classname, thisdev->addresses[0]);
+
+ fprintf(stdout,
+ gettext(
+ "\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"),
+ thisdev->ident->vid,
+ thisdev->ident->pid,
+ thisdev->ident->revid,
+ (thisdev->addresses[1] ? thisdev->addresses[1] :
+ "(not supported)"),
+ (thisdev->addresses[2] ? thisdev->addresses[2] :
+ "(not supported)"));
+
+ fprintf(stdout, "\n\n");
+
+ return (FWFLASH_SUCCESS);
+}
+
+void
+fw_cleanup(struct devicelist *thisdev)
+{
+ /*
+ * Function to clean up all the memory allocated
+ * by this plugin, for thisdev.
+ */
+ free(thisdev->access_devname);
+ free(thisdev->drvname);
+ free(thisdev->classname);
+
+ /*
+ * 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.
+ */
+ free(thisdev->addresses[0]);
+
+ /* what this points to is freed in common code */
+ thisdev->plugin = NULL;
+
+ free(thisdev->ident->vid);
+ free(thisdev->ident->pid);
+ free(thisdev->ident->revid);
+
+ thisdev->ident = NULL;
+}
+
+/*
+ * Helper functions
+ */
+static int
+link_cb(di_devlink_t devlink, void *arg)
+{
+ const char *result;
+
+ result = di_devlink_path(devlink);
+ if (result == NULL) {
+ arg = (void *)"(null)";
+ } else {
+ (void) strlcpy(arg, result, strlen(result) + 1);
+ }
+
+ logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n",
+ ((result != NULL) ? result : "(null)"));
+
+ return (DI_WALK_CONTINUE);
+}
+
+static char *
+find_link(di_node_t bnode)
+{
+ di_minor_t devminor = DI_MINOR_NIL;
+ di_devlink_handle_t hdl;
+ char *devfspath = NULL;
+ char *minorpath = NULL;
+ char *cbresult = NULL;
+ char linkname[] = "^rdsk/\0";
+
+ devfspath = di_devfs_path(bnode);
+ if (bnode == DI_NODE_NIL) {
+ logmsg(MSG_ERROR,
+ gettext("find_link must be called with non-null "
+ "di_node_t\n"));
+ FW_SD_FREE_DEVPATH(devfspath)
+ return (NULL);
+ }
+
+ logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath);
+
+ if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) ||
+ ((minorpath = calloc(1, MAXPATHLEN)) == NULL)) {
+ logmsg(MSG_ERROR, gettext("unable to allocate space for dev "
+ "link\n"));
+ FW_SD_FREE_DEVPATH(devfspath)
+ return (NULL);
+ }
+
+ devminor = di_minor_next(bnode, devminor);
+ errno = 0;
+ hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
+ if (hdl == NULL) {
+ if (errno == EPERM || errno == EACCES) {
+ logmsg(MSG_ERROR,
+ gettext("%s: You must be super-user to use this "
+ "plugin.\n"), drivername);
+ } else {
+ logmsg(MSG_ERROR,
+ gettext("unable to take devlink snapshot: %s\n"),
+ strerror(errno));
+ }
+ FW_SD_FREE_DEVPATH(devfspath)
+ return (NULL);
+ }
+
+ (void) snprintf(minorpath, MAXPATHLEN, "%s:c,raw", devfspath);
+
+ errno = 0;
+ if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK,
+ (void *)cbresult, link_cb) < 0) {
+ logmsg(MSG_ERROR,
+ gettext("Unable to walk devlink snapshot for %s: %s\n"),
+ minorpath, strerror(errno));
+ FW_SD_FREE_DEVPATH(devfspath)
+ return (NULL);
+ }
+
+ if (di_devlink_fini(&hdl) < 0) {
+ logmsg(MSG_ERROR,
+ gettext("Unable to close devlink snapshot: %s\n"),
+ strerror(errno));
+ }
+ free(minorpath); /* don't need this now */
+ FW_SD_FREE_DEVPATH(devfspath)
+
+ logmsg(MSG_INFO, "cbresult: %s\n", cbresult);
+ return (cbresult);
+}
+
+static int
+sd_idtfy_custmz(struct devicelist *device, char *sp)
+{
+ /* vid customization */
+ if (strncmp(sp, "ST", 2) == 0) {
+ /* Customize retail Seagate disks */
+ if ((device->ident->vid = strdup("SEAGATE")) == NULL) {
+ return (FWFLASH_FAILURE);
+ }
+ } else if (strncmp(sp, "SSD", 3) == 0) {
+ /* Customize retail INTEL disks */
+ if ((device->ident->vid = strdup("INTEL")) == NULL) {
+ return (FWFLASH_FAILURE);
+ }
+ } else {
+ /* disks to do in the furture, fill 'ATA' first */
+ if ((device->ident->vid = strdup("ATA")) == NULL) {
+ return (FWFLASH_FAILURE);
+ }
+ }
+
+ /* pid customization */
+ if ((device->ident->pid = calloc(1, strlen(sp) + 1)) == NULL) {
+ logmsg(MSG_ERROR, gettext("Unable to allocate space for "
+ "product id\n"));
+ free(device->ident->vid);
+ return (FWFLASH_FAILURE);
+ }
+ strlcpy(device->ident->pid, sp, strlen(sp) + 1);
+
+ return (FWFLASH_SUCCESS);
+}
diff --git a/usr/src/cmd/fwflash/plugins/transport/common/ses.c b/usr/src/cmd/fwflash/plugins/transport/common/ses.c
index 104dbec3e5..f8aeb042a0 100644
--- a/usr/src/cmd/fwflash/plugins/transport/common/ses.c
+++ b/usr/src/cmd/fwflash/plugins/transport/common/ses.c
@@ -133,7 +133,6 @@ static char *sgensuffix = ":ses";
static ses_target_t *ses_target;
-static int internalstatus;
extern di_node_t rootnode;
extern int errno;
@@ -150,7 +149,7 @@ int fw_devinfo(struct devicelist *thisdev);
/* helper functions */
-static void print_updated_status(ses_node_t *np, void *arg);
+static int print_updated_status(ses_node_t *np, void *arg);
static int get_status(nvlist_t *props, ucode_status_t *sp);
static int sendimg(ses_node_t *np, void *data);
static int scsi_writebuf();
@@ -191,7 +190,7 @@ fw_readfw(struct devicelist *flashdev, char *filename)
int
fw_writefw(struct devicelist *flashdev)
{
- int rv;
+ int rv = FWFLASH_FAILURE;
nvlist_t *nvl;
ses_snap_t *snapshot;
ses_node_t *targetnode;
@@ -244,7 +243,6 @@ fw_writefw(struct devicelist *flashdev)
}
snapshot = ses_snap_hold(ses_target);
- internalstatus = FWFLASH_FAILURE;
if ((targetnode = ses_snap_primary_enclosure(snapshot)) == NULL) {
logmsg(MSG_ERROR,
@@ -271,7 +269,7 @@ fw_writefw(struct devicelist *flashdev)
cancel:
nvlist_free(nvl);
- return (internalstatus);
+ return (rv);
}
@@ -555,7 +553,6 @@ int
fw_devinfo(struct devicelist *thisdev)
{
-
fprintf(stdout, gettext("Device[%d] %s\n Class [%s]\n"),
thisdev->index, thisdev->access_devname, thisdev->classname);
@@ -593,16 +590,14 @@ get_status(nvlist_t *props, ucode_status_t *sp)
sp->us_status = -1ULL;
(void) snprintf(sp->us_desc, sizeof (sp->us_desc),
"not supported");
- internalstatus = FWFLASH_FAILURE;
- return (-1);
+ return (FWFLASH_FAILURE);
}
if (nvlist_lookup_uint64(props, SES_EN_PROP_UCODE_A,
&astatus) != 0) {
logmsg(MSG_ERROR,
gettext("\nError: Unable to retrieve current status\n"));
- internalstatus = FWFLASH_FAILURE;
- return (-1);
+ return (FWFLASH_FAILURE);
}
for (i = 0; i < NUCODE_STATUS; i++) {
@@ -615,7 +610,8 @@ get_status(nvlist_t *props, ucode_status_t *sp)
if (i == NUCODE_STATUS) {
(void) snprintf(sp->us_desc, sizeof (sp->us_desc),
"unknown (0x%02x)", (int)status);
- sp->us_iserr = sp->us_pending = B_FALSE;
+ sp->us_iserr = sp->us_pending = B_TRUE;
+ return (FWFLASH_FAILURE);
} else {
/* LINTED */
(void) snprintf(sp->us_desc, sizeof (sp->us_desc),
@@ -624,11 +620,11 @@ get_status(nvlist_t *props, ucode_status_t *sp)
sp->us_pending = ucode_statdesc_table[i].us_pending;
}
- return (0);
+ return (FWFLASH_SUCCESS);
}
-static void
+static int
print_updated_status(ses_node_t *np, void *arg)
{
ucode_wait_t *uwp = arg;
@@ -637,13 +633,11 @@ print_updated_status(ses_node_t *np, void *arg)
if ((props = ses_node_props(np)) == NULL) {
- internalstatus = FWFLASH_FAILURE;
- return;
+ return (FWFLASH_FAILURE);
}
- if (get_status(props, &status) != 0)
- /* internalstatus is already set to FWFLASH_FAILURE */
- return;
+ if (get_status(props, &status) != FWFLASH_SUCCESS)
+ return (FWFLASH_FAILURE);
if (status.us_status != uwp->uw_prevstatus)
(void) printf("%30s: %s\n", "status", status.us_desc);
@@ -655,10 +649,9 @@ print_updated_status(ses_node_t *np, void *arg)
logmsg(MSG_INFO,
"libses: status.us_iserr: 0x%0x\n",
status.us_iserr);
- internalstatus = FWFLASH_FAILURE;
- } else
- internalstatus = FWFLASH_SUCCESS;
-
+ return (FWFLASH_FAILURE);
+ }
+ return (FWFLASH_SUCCESS);
}
/*ARGSUSED*/
@@ -699,7 +692,7 @@ sendimg(ses_node_t *np, void *data)
ret = get_status(props, &statdesc);
(void) printf("%30s: %s\n", "current status", statdesc.us_desc);
- if (ret != 0) {
+ if (ret != FWFLASH_SUCCESS) {
return (FWFLASH_FAILURE);
}
@@ -717,7 +710,7 @@ sendimg(ses_node_t *np, void *data)
return (scsi_writebuf());
- if (ses_node_ctl(np, SES_CTL_OP_DL_UCODE, arg) != 0) {
+ if (ses_node_ctl(np, SES_CTL_OP_DL_UCODE, arg) != FWFLASH_SUCCESS) {
(void) printf("failed!\n");
(void) printf("%s\n", ses_errmsg());
return (FWFLASH_FAILURE);
@@ -728,16 +721,18 @@ sendimg(ses_node_t *np, void *data)
wait.uw_prevstatus = -1ULL;
wait.uw_oldnp = np;
- if ((newsnap = ses_snap_new(ses_target)) == NULL)
+ if ((newsnap = ses_snap_new(ses_target)) == NULL) {
logmsg(MSG_ERROR,
"failed to update SES snapshot: %s",
ses_errmsg());
+ return (FWFLASH_FAILURE);
+ }
print_updated_status(ses_snap_primary_enclosure(newsnap),
&wait);
ses_snap_rele(newsnap);
- return (internalstatus);
+ return (FWFLASH_SUCCESS);
}
static int
@@ -759,10 +754,18 @@ scsi_writebuf()
(void *)verifier->fwimage, (size_t)verifier->imgsize);
wb_cdb = (spc3_write_buffer_cdb_t *)libscsi_action_get_cdb(action);
+
wb_cdb->wbc_mode = SPC3_WB_MODE_DATA;
wb_cdb->wbc_bufferid = verifier->flashbuf;
- SCSI_WRITE24(&wb_cdb->wbc_buffer_offset, 0);
- SCSI_WRITE24(&wb_cdb->wbc_parameter_list_len, verifier->imgsize);
+
+ wb_cdb->wbc_buffer_offset[0] = 0;
+ wb_cdb->wbc_buffer_offset[1] = 0;
+ wb_cdb->wbc_buffer_offset[2] = 0;
+
+ wb_cdb->wbc_parameter_list_len[0] =
+ (verifier->imgsize & 0xff0000) >> 16;
+ wb_cdb->wbc_parameter_list_len[1] = (verifier->imgsize & 0xff00) >> 8;
+ wb_cdb->wbc_parameter_list_len[2] = (verifier->imgsize & 0xff);
ret = libscsi_exec(action, target);
samstatus = libscsi_action_get_status(action);
@@ -771,9 +774,9 @@ scsi_writebuf()
"\nscsi_writebuffer: ret 0x%0x, samstatus 0x%0x\n",
ret, samstatus);
- if ((ret != 0) || samstatus != 0) {
+ if ((ret != FWFLASH_SUCCESS) || samstatus != SAM4_STATUS_GOOD) {
libscsi_action_free(action);
- return (ret);
+ return (FWFLASH_FAILURE);
} else {
(void) printf("ok\n");
}
@@ -789,7 +792,6 @@ scsi_writebuf()
(void) printf("Status: UNKNOWN\n");
if (samstatus == SAM4_STATUS_GOOD) {
- internalstatus = FWFLASH_SUCCESS;
return (FWFLASH_SUCCESS);
}
diff --git a/usr/src/cmd/fwflash/plugins/transport/i386/Makefile b/usr/src/cmd/fwflash/plugins/transport/i386/Makefile
index 260a39533d..25737381d7 100644
--- a/usr/src/cmd/fwflash/plugins/transport/i386/Makefile
+++ b/usr/src/cmd/fwflash/plugins/transport/i386/Makefile
@@ -24,7 +24,7 @@
# cmd/fwflash/plugins/transport/i386
#
-SRCS= ses.c tavor.c hermon.c
+SRCS= ses.c tavor.c hermon.c sd.c
OBJECTS= $(SRCS:%.c=%.o)
PLUGINS= $(SRCS:%.c=%.so)
@@ -63,6 +63,7 @@ install: all $(ROOTLIBFWFLASHPLUGINS) \
$(ROOTLIBFWFLASHPLUGINS)/ses.so \
$(ROOTLIBFWFLASHPLUGINS)/tavor.so \
$(ROOTLIBFWFLASHPLUGINS)/hermon.so \
+ $(ROOTLIBFWFLASHPLUGINS)/sd.so \
$(ROOTLIBFWFLASHPLUGINS)/$(SLINKS)
clobber clean:
diff --git a/usr/src/cmd/fwflash/plugins/transport/sparc/Makefile b/usr/src/cmd/fwflash/plugins/transport/sparc/Makefile
index 1d428ed093..3e413393e4 100644
--- a/usr/src/cmd/fwflash/plugins/transport/sparc/Makefile
+++ b/usr/src/cmd/fwflash/plugins/transport/sparc/Makefile
@@ -24,7 +24,7 @@
# cmd/fwflash/plugins/transport/sparc
#
-SRCS= ses.c tavor.c hermon.c
+SRCS= ses.c tavor.c hermon.c sd.c
OBJECTS= $(SRCS:%.c=%.o)
PLUGINS= $(SRCS:%.c=%.so)
@@ -63,6 +63,7 @@ install: all $(ROOTLIBFWFLASHPLUGINS) \
$(ROOTLIBFWFLASHPLUGINS)/ses.so \
$(ROOTLIBFWFLASHPLUGINS)/tavor.so \
$(ROOTLIBFWFLASHPLUGINS)/hermon.so \
+ $(ROOTLIBFWFLASHPLUGINS)/sd.so \
$(ROOTLIBFWFLASHPLUGINS)/$(SLINKS)
clobber clean:
diff --git a/usr/src/cmd/fwflash/plugins/vendor/sd-GENERIC.c b/usr/src/cmd/fwflash/plugins/vendor/sd-GENERIC.c
new file mode 100644
index 0000000000..d66339226f
--- /dev/null
+++ b/usr/src/cmd/fwflash/plugins/vendor/sd-GENERIC.c
@@ -0,0 +1,89 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <fcntl.h>
+#include <sys/condvar.h>
+#include <string.h>
+#include <strings.h>
+
+#include <sys/byteorder.h>
+
+#include <libintl.h> /* for gettext(3c) */
+#include <fwflash/fwflash.h>
+
+char vendor[] = "GENERIC \0";
+
+/* MAXIMGSIZE = 1.4 * 1024 * 1024 bytes */
+/* Currently the largest firmware image size is 1.4 MB */
+/* 1468006 = 1.4 * 1024 * 1024 */
+#define MAXIMGSIZE ((unsigned int)(1468006))
+
+extern struct vrfyplugin *verifier;
+
+/* required functions for this plugin */
+int vendorvrfy(struct devicelist *devicenode);
+
+/*
+ * Important information about how this verification plugin works
+ *
+ * Direct-attached disks (sd instances) which support firmware
+ * download accept image files up to 1.4 * 1024 * 1024 bytes in
+ * size, and do their own verification of the image, rejecting the
+ * file if it is not appropriate for them.
+ *
+ * All that we need to do here is set the various verifier fields
+ * correctly, and check that the filesize as read from the filesystem
+ * is less than 1.4 * 1024 * 1024 bytes.
+ */
+
+int
+vendorvrfy(struct devicelist *devicenode)
+{
+ if (verifier->imgsize > MAXIMGSIZE) {
+ logmsg(MSG_ERROR,
+ gettext("\nsd-GENERIC firmware image verifier: "
+ "supplied filename %s exceeds maximum allowable "
+ "size of %d bytes\n"),
+ verifier->imgfile, MAXIMGSIZE);
+ return (FWFLASH_FAILURE);
+ }
+
+ logmsg(MSG_INFO,
+ "sd-GENERIC verifier for device\n"
+ "vid %s, pid %s, rev %s\npath %s\n",
+ devicenode->ident->vid,
+ devicenode->ident->pid,
+ devicenode->ident->revid,
+ devicenode->addresses[0]);
+ verifier->flashbuf = 0;
+
+ return (FWFLASH_SUCCESS);
+}
diff --git a/usr/src/pkgdefs/SUNWfwflash/prototype_com b/usr/src/pkgdefs/SUNWfwflash/prototype_com
index 5e2ae2c53e..9ae0b8b40d 100644
--- a/usr/src/pkgdefs/SUNWfwflash/prototype_com
+++ b/usr/src/pkgdefs/SUNWfwflash/prototype_com
@@ -18,7 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# This required package information file contains a list of package contents.
@@ -51,10 +51,12 @@ s none usr/lib/fwflash/verify/sgen-SUN.so=ses-SUN.so
s none usr/lib/fwflash/verify/sgen-LSILOGIC.so=ses-SUN.so
f none usr/lib/fwflash/verify/tavor-MELLANOX.so 644 root bin
f none usr/lib/fwflash/verify/hermon-MELLANOX.so 644 root bin
+f none usr/lib/fwflash/verify/sd-GENERIC.so 644 root bin
f none usr/lib/fwflash/identify/ses.so 0644 root bin
s none usr/lib/fwflash/identify/sgen.so=ses.so 644 root bin
f none usr/lib/fwflash/identify/tavor.so 0644 root bin
f none usr/lib/fwflash/identify/hermon.so 0644 root bin
+f none usr/lib/fwflash/identify/sd.so 0644 root bin
d none usr/include 0755 root bin
d none usr/include/fwflash 0755 root bin
f none usr/include/fwflash/fwflash.h 0644 root bin