diff options
author | XinChen <Xin.Chen@Sun.COM> | 2009-05-21 12:23:08 +0800 |
---|---|---|
committer | XinChen <Xin.Chen@Sun.COM> | 2009-05-21 12:23:08 +0800 |
commit | d65b419ea7828ceaecc8f2ed7188237add6b14dc (patch) | |
tree | fb36c5aef955ecaa631de1fdca3c6afeb45235b8 /usr | |
parent | f1956ffef55a0f859d3974677c90c728e3fc32f5 (diff) | |
download | illumos-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.c | 165 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/common/fwflash.h | 13 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/plugins/i386/Makefile | 5 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/plugins/sparc/Makefile | 5 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/plugins/transport/common/sd.c | 745 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/plugins/transport/common/ses.c | 64 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/plugins/transport/i386/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/plugins/transport/sparc/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/fwflash/plugins/vendor/sd-GENERIC.c | 89 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWfwflash/prototype_com | 4 |
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 |