4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
33 #include <sys/queue.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
42 #include <sys/varargs.h>
43 #include <libintl.h> /* for gettext(3c) */
44 #include <libdevinfo.h>
45 #include <libscf_priv.h>
46 #include <fwflash/fwflash.h>
47 #include <sys/modctl.h> /* for MAXMODCONFNAME */
50 int fwflash_arg_list
= 0;
53 /* exposed global args */
55 struct PLUGINLIST
*fw_pluginlist
;
56 struct DEVICELIST
*fw_devices
;
57 struct vrfyplugin
*verifier
;
58 struct fw_plugin
*self
;
59 int fwflash_debug
= 0;
61 /* are we writing to flash? */
62 static int fwflash_in_write
= 0;
65 * If we *must* track the version string for fwflash, then
66 * we should do so in this common file rather than the header
67 * file since it will then be in sync with what the customer
68 * sees. We should deprecate the "-v" option since it is not
69 * actually of any use - it doesn't line up with Mercurial's
70 * concept of the changeset.
72 #define FWFLASH_VERSION "v1.9"
73 #define FWFLASH_PROG_NAME "fwflash"
75 static int get_fileopts(char *options
);
76 static int flash_device_list();
77 static int flash_load_plugins();
78 static int fwflash_update(char *device
, char *filename
, int flags
);
79 static int fwflash_read_file(char *device
, char *filename
);
80 static int fwflash_list_fw(char *class);
81 static int fwflash_load_verifier(char *drv
, char *vendorid
, char *fwimg
);
82 static void fwflash_intr(int sig
);
83 static void fwflash_handle_signals(void);
84 static void fwflash_usage(char *arg
);
85 static void fwflash_version(void);
86 static int confirm_target(struct devicelist
*thisdev
, char *file
);
92 main(int argc
, char **argv
)
94 int rv
= FWFLASH_SUCCESS
;
99 char *devclass
= NULL
;
100 char *devpath
= NULL
;
102 /* local variables from env */
103 (void) setlocale(LC_ALL
, "");
105 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
106 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */
109 (void) textdomain(TEXT_DOMAIN
);
114 /* no args supplied */
116 return (FWFLASH_FAILURE
);
119 while ((ch
= getopt(argc
, argv
, "hvylc:f:r:Qd:")) != EOF
) {
122 fwflash_arg_list
|= FWFLASH_HELP_FLAG
;
125 fwflash_arg_list
|= FWFLASH_VER_FLAG
;
128 fwflash_arg_list
|= FWFLASH_YES_FLAG
;
131 fwflash_arg_list
|= FWFLASH_LIST_FLAG
;
134 fwflash_arg_list
|= FWFLASH_CLASS_FLAG
;
135 /* we validate later */
136 devclass
= strdup(optarg
);
139 fwflash_arg_list
|= FWFLASH_DEVICE_FLAG
;
140 devpath
= strdup(optarg
);
143 fwflash_arg_list
|= FWFLASH_FW_FLAG
;
144 if ((rv
= get_fileopts(optarg
)) != FWFLASH_SUCCESS
) {
146 return (FWFLASH_FAILURE
);
150 fwflash_arg_list
|= FWFLASH_READ_FLAG
;
151 read_file
= strdup(optarg
);
154 /* NOT in the manpage */
157 /* illegal options */
159 fwflash_usage(optarg
);
160 return (FWFLASH_FAILURE
);
165 if ((fwflash_arg_list
& FWFLASH_HELP_FLAG
) ||
166 ((fwflash_arg_list
& FWFLASH_DEVICE_FLAG
) &&
167 !((fwflash_arg_list
& FWFLASH_FW_FLAG
) ||
168 (fwflash_arg_list
& FWFLASH_READ_FLAG
)))) {
170 return (FWFLASH_SUCCESS
);
174 if (fwflash_arg_list
== FWFLASH_VER_FLAG
) {
176 return (FWFLASH_SUCCESS
);
179 /* generate global list of devices */
180 if ((rv
= flash_load_plugins()) != FWFLASH_SUCCESS
) {
182 gettext("Unable to load fwflash plugins\n"));
187 if ((rv
= flash_device_list()) != FWFLASH_SUCCESS
) {
189 gettext("No flashable devices in this system\n"));
195 if (fwflash_arg_list
== (FWFLASH_LIST_FLAG
) ||
196 fwflash_arg_list
== (FWFLASH_LIST_FLAG
| FWFLASH_CLASS_FLAG
)) {
197 rv
= fwflash_list_fw(devclass
);
202 fwflash_handle_signals();
204 /* Do flash update (write) */
205 if ((fwflash_arg_list
== (FWFLASH_FW_FLAG
| FWFLASH_DEVICE_FLAG
)) ||
206 (fwflash_arg_list
== (FWFLASH_FW_FLAG
| FWFLASH_DEVICE_FLAG
|
207 FWFLASH_YES_FLAG
))) {
208 int fastreboot_disabled
= 0;
209 /* the update function handles the real arg parsing */
211 while (filelist
[i
] != NULL
) {
212 if ((rv
= fwflash_update(devpath
, filelist
[i
],
213 fwflash_arg_list
)) == FWFLASH_SUCCESS
) {
214 /* failed ops have already been noted */
215 if (!fastreboot_disabled
&&
216 scf_fastreboot_default_set_transient(
217 B_FALSE
) != SCF_SUCCESS
)
218 logmsg(MSG_ERROR
, gettext(
219 "Failed to disable fast "
222 fastreboot_disabled
= 1;
224 gettext("New firmware will be activated "
225 "after you reboot\n\n"));
235 if ((fwflash_arg_list
== (FWFLASH_READ_FLAG
| FWFLASH_DEVICE_FLAG
)) ||
236 (fwflash_arg_list
== (FWFLASH_READ_FLAG
| FWFLASH_DEVICE_FLAG
|
237 FWFLASH_YES_FLAG
))) {
238 rv
= fwflash_read_file(devpath
, read_file
);
245 return (FWFLASH_FAILURE
);
253 int rval
= FWFLASH_SUCCESS
;
255 struct dirent
*plugdir
;
257 struct fw_plugin
*tmpplug
;
258 struct pluginlist
*tmpelem
;
260 char *fwplugdirpath
, *tempdirpath
;
263 #define CLOSEFREE() { \
264 (void) dlclose(tmpplug->handle); \
270 * cd /usr/lib/fwflash/identify
271 * open each .so file found therein
273 * if it's one of our plugins, add it to fw_pluginlist;
275 * functions we need here include dlopen and dlsym.
277 * If we get to the end and fw_pluginlist struct is empty,
278 * return FWFLASH_FAILURE so we return to the shell.
281 if ((fwplugdirpath
= calloc(1, MAXPATHLEN
+ 1)) == NULL
) {
283 gettext("Unable to malloc %d bytes while "
284 "trying to load plugins: %s\n"),
285 MAXPATHLEN
+ 1, strerror(errno
));
286 return (FWFLASH_FAILURE
);
289 tempdirpath
= getenv("FWPLUGINDIR");
291 if ((fwflash_debug
> 0) && (tempdirpath
!= NULL
)) {
292 (void) strlcpy(fwplugdirpath
, tempdirpath
,
293 strlen(tempdirpath
) + 1);
295 (void) strlcpy(fwplugdirpath
, FWPLUGINDIR
,
296 strlen(FWPLUGINDIR
) + 1);
299 if ((dirp
= opendir(fwplugdirpath
)) == NULL
) {
301 gettext("Unable to open %s\n"),
306 if ((plugdir
= calloc(1, sizeof (struct dirent
) + MAXPATHLEN
+ 1))
309 gettext("Unable to malloc %d bytes while "
310 "trying to load plugins: %s\n"),
311 MAXPATHLEN
+ 1 + sizeof (struct dirent
),
313 return (FWFLASH_FAILURE
);
316 if ((fw_pluginlist
= calloc(1, sizeof (struct fw_plugin
)))
319 gettext("Unable to malloc %d bytes while "
320 "trying to load plugins: %s\n"),
321 sizeof (struct fw_plugin
), strerror(errno
));
322 return (FWFLASH_FAILURE
);
325 TAILQ_INIT(fw_pluginlist
);
327 while ((readdir_r(dirp
, plugdir
, &plugdir
) == 0) && (plugdir
!= NULL
)) {
329 errno
= 0; /* remove chance of false results */
331 if ((plugdir
->d_name
[0] == '.') ||
332 (strstr(plugdir
->d_name
, ".so") == NULL
)) {
336 if ((plugname
= calloc(1, MAXPATHLEN
+ 1)) == NULL
) {
338 gettext("Unable to malloc %d bytes while "
339 "trying to load plugins: %s\n"),
340 MAXPATHLEN
+ 1, strerror(errno
));
341 return (FWFLASH_FAILURE
);
344 (void) snprintf(plugname
, MAXPATHLEN
, "%s/%s",
345 fwplugdirpath
, plugdir
->d_name
);
347 /* start allocating storage */
348 if ((tmpelem
= calloc(1, sizeof (struct pluginlist
)))
351 gettext("Unable to malloc %d bytes while "
352 "trying to load plugins: %s\n"),
353 sizeof (struct pluginlist
), strerror(errno
));
354 return (FWFLASH_FAILURE
);
357 if ((tmpplug
= calloc(1, sizeof (struct fw_plugin
)))
360 gettext("Unable to malloc %d bytes while "
361 "trying to load plugins: %s\n"),
362 sizeof (struct fw_plugin
), strerror(errno
));
363 return (FWFLASH_FAILURE
);
367 tmpplug
->handle
= dlopen(plugname
, RTLD_NOW
);
368 if (tmpplug
->handle
== NULL
) {
370 continue; /* assume there are other plugins */
373 if ((tmpplug
->filename
= calloc(1, strlen(plugname
) + 1))
376 gettext("Unable to allocate %d bytes for plugin "
378 strlen(plugname
) + 1, plugname
,
383 (void) strlcpy(tmpplug
->filename
, plugname
,
384 strlen(plugname
) + 1);
386 /* now sanity check the file */
387 if ((sym
= dlsym(tmpplug
->handle
, "drivername"))
389 /* max length of drivername */
390 tmpplug
->drvname
= calloc(1, MAXMODCONFNAME
);
392 /* are we doing double-time? */
393 if (strncmp((char *)sym
, plugdir
->d_name
,
394 MAXMODCONFNAME
) != 0) {
395 char *tempnm
= calloc(1, MAXMODCONFNAME
);
397 (void) memcpy(tempnm
, plugdir
->d_name
,
399 (void) strlcpy(tmpplug
->drvname
,
401 strlen(plugdir
->d_name
) + 1);
404 (void) strlcpy(tmpplug
->drvname
,
405 (char *)sym
, strlen(sym
) + 1);
411 if ((sym
= dlsym(tmpplug
->handle
, "fw_readfw"))
413 tmpplug
->fw_readfw
= (int (*)())sym
;
418 if ((sym
= dlsym(tmpplug
->handle
, "fw_writefw"))
420 tmpplug
->fw_writefw
= (int (*)())sym
;
426 if ((sym
= dlsym(tmpplug
->handle
, "fw_identify"))
428 tmpplug
->fw_identify
=
434 if ((sym
= dlsym(tmpplug
->handle
, "fw_devinfo"))
436 tmpplug
->fw_devinfo
=
437 (int (*)(struct devicelist
*))sym
;
443 if ((sym
= dlsym(tmpplug
->handle
, "plugin_version"))
445 if ((*(int *)sym
) >= FWPLUGIN_VERSION_2
) {
446 if ((sym
= dlsym(tmpplug
->handle
,
447 "fw_cleanup")) != NULL
) {
448 tmpplug
->fw_cleanup
=
449 (void (*)(struct devicelist
*))sym
;
452 gettext("ERROR: v2 plugin (%s) "
453 "has no fw_cleanup function\n"),
460 "Identification plugin %s defined "
461 "plugin_version < FWPLUGIN_VERSION_2 !");
465 if ((tmpelem
->drvname
= calloc(1, MAXMODCONFNAME
))
468 gettext("Unable to allocate space for a"
471 return (FWFLASH_FAILURE
);
474 (void) strlcpy(tmpelem
->drvname
, tmpplug
->drvname
,
475 strlen(tmpplug
->drvname
) + 1);
477 if ((tmpelem
->filename
= calloc(1,
478 strlen(tmpplug
->filename
) + 1)) == NULL
) {
480 gettext("Unable to allocate %d bytes for "
482 strlen(tmpplug
->filename
) + 1,
484 return (FWFLASH_FAILURE
);
487 (void) strlcpy(tmpelem
->filename
, plugname
,
488 strlen(plugname
) + 1);
489 tmpelem
->plugin
= tmpplug
;
492 TAILQ_INSERT_TAIL(fw_pluginlist
, tmpelem
, nextplugin
);
495 if ((plugdir
== NULL
) && TAILQ_EMPTY(fw_pluginlist
)) {
496 return (FWFLASH_FAILURE
);
501 gettext("Error reading directory entry in %s\n"),
508 (void) closedir(dirp
);
513 * fwflash_load_verifier dlload()s the appropriate firmware image
514 * verification plugin, and attaches the designated fwimg's fd to
515 * the vrfyplugin structure so we only have to load the image in
519 fwflash_load_verifier(char *drv
, char *vendorid
, char *fwimg
)
522 int rv
= FWFLASH_FAILURE
;
524 char *fwvrfydirpath
, *tempdirpath
, *filename
;
525 char *clean
; /* for the space-removed vid */
527 struct vrfyplugin
*vrfy
;
531 * To make flashing multiple firmware images somewhat more
532 * efficient, we start this function by checking whether a
533 * verifier for this device has already been loaded. If it
534 * has been loaded, we replace the imgfile information, and
535 * then continue as if we were loading for the first time.
538 if (verifier
!= NULL
) {
539 verifier
->imgsize
= 0;
540 verifier
->flashbuf
= 0; /* set by the verifier function */
542 if (verifier
->imgfile
!= NULL
) {
543 free(verifier
->imgfile
);
544 verifier
->imgfile
= NULL
;
547 if (verifier
->fwimage
!= NULL
) {
548 free(verifier
->fwimage
);
549 verifier
->fwimage
= NULL
;
552 if ((fwvrfydirpath
= calloc(1, MAXPATHLEN
+ 1)) == NULL
) {
554 gettext("Unable to allocate space for a firmware "
555 "verifier file(1)"));
559 if ((filename
= calloc(1, MAXPATHLEN
+ 1)) == NULL
) {
561 gettext("Unable to allocate space "
562 "for a firmware verifier file(2)"));
568 * Since SCSI devices can have a vendor id of up to 8
569 * left-aligned and _space-padded_ characters, we first need to
570 * strip off any space characters before we try to make a
573 clean
= strtok(vendorid
, " ");
575 /* invalid vendorid, something's really wrong */
577 gettext("Invalid vendorid (null) specified for "
584 tempdirpath
= getenv("FWVERIFYPLUGINDIR");
586 if ((fwflash_debug
> 0) && (tempdirpath
!= NULL
)) {
587 (void) strlcpy(fwvrfydirpath
, tempdirpath
,
588 strlen(tempdirpath
) + 1);
590 (void) strlcpy(fwvrfydirpath
, FWVERIFYPLUGINDIR
,
591 strlen(FWVERIFYPLUGINDIR
) + 1);
594 if ((vrfy
= calloc(1, sizeof (struct vrfyplugin
))) == NULL
) {
596 gettext("Unable to allocate space "
597 "for a firmware verifier structure"));
603 errno
= 0; /* false positive removal */
605 (void) snprintf(filename
, MAXPATHLEN
, "%s/%s-%s.so",
606 fwvrfydirpath
, drv
, clean
);
607 if ((vrfy
->handle
= dlopen(filename
, RTLD_NOW
)) == NULL
) {
608 logmsg(MSG_INFO
, gettext(dlerror()));
610 gettext("\nUnable to open verification plugin "
611 "%s. Looking for %s-GENERIC plugin instead.\n"),
614 /* Try the drv-GENERIC.so form, _then_ die */
615 bzero(filename
, strlen(filename
) + 1);
616 (void) snprintf(filename
, MAXPATHLEN
,
617 "%s/%s-GENERIC.so", fwvrfydirpath
, drv
);
619 if ((vrfy
->handle
= dlopen(filename
, RTLD_NOW
))
621 logmsg(MSG_INFO
, gettext(dlerror()));
623 gettext("\nUnable to open either "
624 "verification plugin %s/%s-%s.so or "
625 "generic plugin %s.\nUnable to verify "
626 "firmware image. Aborting.\n"),
627 fwvrfydirpath
, drv
, clean
, filename
);
634 if ((vrfy
->filename
= calloc(1, strlen(filename
) + 1))
637 gettext("Unable to allocate space to store "
638 "a verifier filename\n"));
644 (void) strlcpy(vrfy
->filename
, filename
, strlen(filename
) + 1);
646 if ((vrfysym
= dlsym(vrfy
->handle
, "vendorvrfy")) == NULL
) {
648 gettext("%s is an invalid firmware verification "
649 "plugin."), filename
);
650 (void) dlclose(vrfy
->handle
);
657 (int (*)(struct devicelist
*))vrfysym
;
660 vrfysym
= dlsym(vrfy
->handle
, "vendor");
662 if (vrfysym
== NULL
) {
664 gettext("Invalid vendor (null) in verification "
665 "plugin %s\n"), filename
);
666 (void) dlclose(vrfy
->handle
);
670 if (strncmp(vendorid
, (char *)vrfysym
,
671 strlen(vendorid
)) != 0) {
673 "Using a sym-linked (%s -> %s) "
674 "verification plugin\n",
676 vrfy
->vendor
= calloc(1, strlen(vendorid
) + 1);
678 vrfy
->vendor
= calloc(1, strlen(vrfysym
) + 1);
680 (void) strlcpy(vrfy
->vendor
, (char *)vrfysym
,
681 strlen(vendorid
) + 1);
684 verifier
= vrfy
; /* a convenience variable */
690 * We don't do any verification that the fw image file is in
691 * an approved location, but it's easy enough to modify this
692 * function to do so. The verification plugin should provide
693 * sufficient protection.
696 if ((imgfd
= open(fwimg
, O_RDONLY
)) < 0) {
698 gettext("Unable to open designated firmware "
699 "image file %s: %s\n"),
700 (fwimg
!= NULL
) ? fwimg
: "(null)",
702 rv
= FWFLASH_FAILURE
;
706 if (stat(fwimg
, &fwstat
) == -1) {
708 gettext("Unable to stat() firmware image file "
710 fwimg
, strerror(errno
));
711 rv
= FWFLASH_FAILURE
;
714 verifier
->imgsize
= fwstat
.st_size
;
715 if ((verifier
->fwimage
= calloc(1, verifier
->imgsize
))
718 gettext("Unable to load firmware image "
720 fwimg
, strerror(errno
));
721 rv
= FWFLASH_FAILURE
;
727 if ((rv
= read(imgfd
, verifier
->fwimage
,
728 (size_t)verifier
->imgsize
)) < verifier
->imgsize
) {
729 /* we haven't read enough data, bail */
731 gettext("Failed to read sufficient data "
732 "(got %d bytes, expected %d bytes) from "
733 "firmware image file %s: %s\n"),
734 rv
, verifier
->imgsize
,
735 verifier
->filename
, strerror(errno
));
736 rv
= FWFLASH_FAILURE
;
738 rv
= FWFLASH_SUCCESS
;
741 if ((verifier
->imgfile
= calloc(1, strlen(fwimg
) + 1)) == NULL
) {
743 gettext("Unable to save name of firmware image\n"));
744 rv
= FWFLASH_FAILURE
;
746 (void) strlcpy(verifier
->imgfile
, fwimg
, strlen(fwimg
) + 1);
749 if (rv
!= FWFLASH_SUCCESS
) {
750 /* cleanup and let's get outta here */
752 free(verifier
->filename
);
753 free(verifier
->vendor
);
755 if (!(fwflash_arg_list
& FWFLASH_READ_FLAG
) &&
757 free(verifier
->fwimage
);
759 verifier
->filename
= NULL
;
760 verifier
->vendor
= NULL
;
761 verifier
->vendorvrfy
= NULL
;
762 verifier
->fwimage
= NULL
;
763 (void) dlclose(verifier
->handle
);
764 verifier
->handle
= NULL
;
776 * cycles through the global list of plugins to find
777 * each flashable device, which is added to fw_devices
779 * Each plugin's identify routine must allocated storage
782 * Each plugin's identify routine must return
783 * FWFLASH_FAILURE if it cannot find any devices
789 int rv
= FWFLASH_FAILURE
;
792 struct pluginlist
*plugins
;
794 /* we open rootnode here, and close it in fwflash_intr */
795 if ((rootnode
= di_init("/", DINFOCPYALL
|DINFOFORCE
)) == DI_NODE_NIL
) {
797 gettext("Unable to take device tree snapshot: %s\n"),
802 if ((fw_devices
= calloc(1, sizeof (struct devicelist
))) == NULL
) {
804 gettext("Unable to malloc %d bytes while "
805 "trying to find devices: %s\n"),
806 sizeof (struct devicelist
), strerror(errno
));
807 return (FWFLASH_FAILURE
);
811 TAILQ_INIT(fw_devices
);
813 TAILQ_FOREACH(plugins
, fw_pluginlist
, nextplugin
) {
814 self
= plugins
->plugin
;
815 rv
= plugins
->plugin
->fw_identify(startidx
);
818 gettext("fwflash:flash_device_list() got %d from "
819 "identify routine\n"), rv
);
821 /* only bump startidx if we've found at least one device */
822 if (rv
== FWFLASH_SUCCESS
) {
827 gettext("No flashable devices attached with "
828 "the %s driver in this system\n"),
834 rv
= FWFLASH_SUCCESS
;
840 fwflash_list_fw(char *class)
843 struct devicelist
*curdev
;
846 TAILQ_FOREACH(curdev
, fw_devices
, nextdev
) {
848 /* we're either class-conscious, or we're not */
849 if (((class != NULL
) &&
850 ((strncmp(curdev
->classname
, "ALL", 3) == 0) ||
851 (strcmp(curdev
->classname
, class) == 0))) ||
855 (void) fprintf(stdout
,
856 gettext("List of available devices:\n"));
860 * If any plugin's fw_devinfo() function returns
861 * FWFLASH_FAILURE then we want to keep track of
862 * it. _Most_ plugins should always return
863 * FWFLASH_SUCCESS from this function. The only
864 * exception known at this point is the tavor plugin.
866 rv
+= curdev
->plugin
->fw_devinfo(curdev
);
873 fwflash_update(char *device
, char *filename
, int flags
)
876 int rv
= FWFLASH_FAILURE
;
879 struct devicelist
*curdev
;
883 * Here's how we operate:
885 * We perform some basic checks on the args, then walk
886 * through the device list looking for the device which
887 * matches. We then load the appropriate verifier for the
888 * image file and device, verify the image, then call the
889 * fw_writefw() function of the appropriate plugin.
891 * There is no "force" flag to enable you to flash a firmware
892 * image onto an incompatible device because the verifier
893 * will return FWFLASH_FAILURE if the image doesn't match.
896 /* new firmware filename and device desc */
897 if (filename
== NULL
) {
899 gettext("Invalid firmware filename (null)\n"));
900 return (FWFLASH_FAILURE
);
903 if (device
== NULL
) {
905 gettext("Invalid device requested (null)\n"));
906 return (FWFLASH_FAILURE
);
909 if ((realfile
= calloc(1, PATH_MAX
+ 1)) == NULL
) {
911 gettext("Unable to allocate space for device "
912 "filename, operation might fail if %s is"
913 "a symbolic link\n"),
918 * If realpath() succeeds, then we have a valid
919 * device filename in realfile.
921 if (realpath(device
, realfile
) == NULL
) {
923 gettext("Unable to resolve device filename"
928 /* realpath didn't succeed, use fallback */
936 gettext("fwflash_update: fw_filename (%s) device (%s)\n"),
939 TAILQ_FOREACH(curdev
, fw_devices
, nextdev
) {
940 if (strcmp(curdev
->access_devname
, realfile
) == 0) {
942 rv
= fwflash_load_verifier(curdev
->drvname
,
943 curdev
->ident
->vid
, filename
);
944 if (rv
== FWFLASH_FAILURE
) {
946 gettext("Unable to load verifier "
948 curdev
->access_devname
);
949 return (FWFLASH_FAILURE
);
951 rv
= verifier
->vendorvrfy(curdev
);
952 if (rv
== FWFLASH_FAILURE
) {
953 /* the verifier prints a message */
955 "verifier (%s) for %s :: %s returned "
958 filename
, curdev
->access_devname
);
962 if (((flags
& FWFLASH_YES_FLAG
) == FWFLASH_YES_FLAG
) ||
963 (rv
= confirm_target(curdev
, filename
)) ==
966 "about to flash using plugin %s\n",
967 curdev
->plugin
->filename
);
968 rv
= curdev
->plugin
->fw_writefw(curdev
,
970 if (rv
== FWFLASH_FAILURE
) {
972 gettext("Failed to flash "
973 "firmware file %s on "
976 curdev
->access_devname
, rv
);
980 gettext("Flash operation not confirmed "
982 curdev
->access_devname
);
983 rv
= FWFLASH_FAILURE
;
989 /* report the same device that the user passed in */
991 gettext("Device %s does not appear "
992 "to be flashable\n"),
993 ((strncmp(device
, realfile
, strlen(device
)) == 0) ?
1003 * We validate that the device path is in our global device list and
1004 * that the filename exists, then palm things off to the relevant plugin.
1007 fwflash_read_file(char *device
, char *filename
)
1009 struct devicelist
*curdev
;
1013 /* new firmware filename and device desc */
1015 TAILQ_FOREACH(curdev
, fw_devices
, nextdev
) {
1016 if (strncmp(curdev
->access_devname
, device
,
1018 rv
= curdev
->plugin
->fw_readfw(curdev
, filename
);
1020 if (rv
!= FWFLASH_SUCCESS
)
1022 gettext("Unable to write out firmware "
1023 "image for %s to file %s\n"),
1024 curdev
->access_devname
, filename
);
1032 gettext("No device matching %s was found.\n"),
1034 rv
= FWFLASH_FAILURE
;
1041 fwflash_usage(char *arg
)
1044 (void) fprintf(stderr
, "\n");
1047 gettext("Invalid argument (%s) supplied\n"), arg
);
1050 (void) fprintf(stderr
, "\n");
1052 (void) fprintf(stdout
, gettext("Usage:\n\t"));
1053 (void) fprintf(stdout
, gettext("fwflash [-l [-c device_class "
1054 "| ALL]] | [-v] | [-h]\n\t"));
1055 (void) fprintf(stdout
, gettext("fwflash [-f file1,file2,file3"
1056 ",... | -r file] [-y] -d device_path\n\n"));
1057 (void) fprintf(stdout
, "\n"); /* workaround for xgettext */
1059 (void) fprintf(stdout
,
1060 gettext("\t-l\t\tlist flashable devices in this system\n"
1061 "\t-c device_class limit search to a specific class\n"
1062 "\t\t\teg IB for InfiniBand, ses for SCSI Enclosures\n"
1063 "\t-v\t\tprint version number of fwflash utility\n"
1064 "\t-h\t\tprint this usage message\n\n"));
1065 (void) fprintf(stdout
,
1066 gettext("\t-f file1,file2,file3,...\n"
1067 "\t\t\tfirmware image file list to flash\n"
1068 "\t-r file\t\tfile to dump device firmware to\n"
1069 "\t-y\t\tanswer Yes/Y/y to prompts\n"
1070 "\t-d device_path\tpathname of device to be flashed\n\n"));
1072 (void) fprintf(stdout
,
1073 gettext("\tIf -d device_path is specified, then one of -f "
1075 "\tor -r <file> must also be specified\n\n"));
1077 (void) fprintf(stdout
,
1078 gettext("\tIf multiple firmware images are required to be "
1080 "\tthey must be listed together, separated by commas. The\n"
1081 "\timages will be flashed in the order specified.\n\n"));
1083 (void) fprintf(stdout
, "\n");
1087 fwflash_version(void)
1089 (void) fprintf(stdout
, gettext("\n%s: "), FWFLASH_PROG_NAME
);
1090 (void) fprintf(stdout
, gettext("version %s\n"),
1095 fwflash_intr(int sig
)
1098 struct devicelist
*thisdev
;
1099 struct pluginlist
*thisplug
;
1101 (void) signal(SIGINT
, SIG_IGN
);
1102 (void) signal(SIGTERM
, SIG_IGN
);
1103 (void) signal(SIGABRT
, SIG_IGN
);
1105 if (fwflash_in_write
) {
1106 (void) fprintf(stderr
,
1107 gettext("WARNING: firmware image may be corrupted\n\t"));
1108 (void) fprintf(stderr
,
1109 gettext("Reflash firmware before rebooting!\n"));
1113 (void) logmsg(MSG_ERROR
, gettext("\n"));
1114 (void) logmsg(MSG_ERROR
,
1115 gettext("fwflash exiting due to signal (%d)\n"), sig
);
1119 * we need to close everything down properly, so
1120 * call the plugin closure routines
1122 if (fw_devices
!= NULL
) {
1123 TAILQ_FOREACH(thisdev
, fw_devices
, nextdev
) {
1124 if (thisdev
->plugin
->fw_cleanup
!= NULL
) {
1126 * If we've got a cleanup routine, it
1127 * cleans up _everything_ for thisdev
1129 thisdev
->plugin
->fw_cleanup(thisdev
);
1131 /* free the components first */
1132 free(thisdev
->access_devname
);
1133 free(thisdev
->drvname
);
1134 free(thisdev
->classname
);
1135 if (thisdev
->ident
!= NULL
)
1136 free(thisdev
->ident
);
1137 /* We don't free address[] for old plugins */
1138 thisdev
->ident
= NULL
;
1139 thisdev
->plugin
= NULL
;
1142 TAILQ_REMOVE(fw_devices
, thisdev
, nextdev
);
1146 if (fw_pluginlist
!= NULL
) {
1147 TAILQ_FOREACH(thisplug
, fw_pluginlist
, nextplugin
) {
1148 free(thisplug
->filename
);
1149 free(thisplug
->drvname
);
1150 free(thisplug
->plugin
->filename
);
1151 free(thisplug
->plugin
->drvname
);
1152 thisplug
->filename
= NULL
;
1153 thisplug
->drvname
= NULL
;
1154 thisplug
->plugin
->filename
= NULL
;
1155 thisplug
->plugin
->drvname
= NULL
;
1156 thisplug
->plugin
->fw_readfw
= NULL
;
1157 thisplug
->plugin
->fw_writefw
= NULL
;
1158 thisplug
->plugin
->fw_identify
= NULL
;
1159 thisplug
->plugin
->fw_devinfo
= NULL
;
1160 thisplug
->plugin
->fw_cleanup
= NULL
;
1161 (void) dlclose(thisplug
->plugin
->handle
);
1162 thisplug
->plugin
->handle
= NULL
;
1163 free(thisplug
->plugin
);
1164 thisplug
->plugin
= NULL
;
1166 TAILQ_REMOVE(fw_pluginlist
, thisplug
, nextplugin
);
1170 if (verifier
!= NULL
) {
1171 free(verifier
->filename
);
1172 free(verifier
->vendor
);
1173 free(verifier
->imgfile
);
1174 free(verifier
->fwimage
);
1175 verifier
->filename
= NULL
;
1176 verifier
->vendor
= NULL
;
1177 verifier
->vendorvrfy
= NULL
;
1178 verifier
->imgfile
= NULL
;
1179 verifier
->fwimage
= NULL
;
1180 (void) dlclose(verifier
->handle
);
1181 verifier
->handle
= NULL
;
1187 exit(FWFLASH_FAILURE
);
1191 fwflash_handle_signals(void)
1193 if (signal(SIGINT
, fwflash_intr
) == SIG_ERR
) {
1195 exit(FWFLASH_FAILURE
);
1198 if (signal(SIGTERM
, fwflash_intr
) == SIG_ERR
) {
1200 exit(FWFLASH_FAILURE
);
1205 confirm_target(struct devicelist
*thisdev
, char *file
)
1209 (void) fflush(stdin
);
1210 (void) printf(gettext("About to update firmware on %s\n"),
1211 thisdev
->access_devname
);
1212 (void) printf(gettext("with file %s.\n"
1213 "Do you want to continue? (Y/N): "), file
);
1216 if (resp
== 'Y' || resp
== 'y') {
1217 return (FWFLASH_YES_FLAG
);
1219 logmsg(MSG_INFO
, "flash operation NOT confirmed.\n");
1222 (void) fflush(stdin
);
1223 return (FWFLASH_FAILURE
);
1227 get_fileopts(char *options
)
1233 if (files
= strtok(options
, ",")) {
1234 /* we have more than one */
1235 if ((filelist
[0] = calloc(1, MAXPATHLEN
+ 1)) == NULL
) {
1237 gettext("Unable to allocate space for "
1238 "a firmware image filename\n"));
1239 return (FWFLASH_FAILURE
);
1241 (void) strlcpy(filelist
[0], files
, strlen(files
) + 1);
1244 logmsg(MSG_INFO
, "fwflash: filelist[0]: %s\n",
1248 while (files
= strtok(NULL
, ",")) {
1249 if ((filelist
[i
] = calloc(1, MAXPATHLEN
+ 1))
1252 gettext("Unable to allocate space for "
1253 "a firmware image filename\n"));
1254 return (FWFLASH_FAILURE
);
1256 (void) strlcpy(filelist
[i
], files
,
1258 logmsg(MSG_INFO
, "fwflash: filelist[%d]: %s\n",
1263 if ((filelist
[0] = calloc(1, MAXPATHLEN
+ 1)) == NULL
) {
1265 gettext("Unable to allocate space for "
1266 "a firmware image filename\n"));
1267 return (FWFLASH_FAILURE
);
1269 (void) strlcpy(filelist
[0], options
, strlen(files
) + 1);
1270 logmsg(MSG_INFO
, "fwflash: filelist[0]: %s\n",
1273 return (FWFLASH_SUCCESS
);
1277 * code reuse - cheerfully borrowed from stmsboot_util.c
1280 logmsg(int severity
, const char *msg
, ...)
1284 if ((severity
> MSG_INFO
) ||
1285 ((severity
== MSG_INFO
) && (fwflash_debug
> 0))) {
1286 (void) fprintf(stderr
, "%s: ", FWFLASH_PROG_NAME
);
1288 (void) vfprintf(stderr
, msg
, ap
);