fwflash.c revision 3b136daba8fa33f4c5101eb6f6146fc10b8984e4
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <locale.h>
#include <fcntl.h>
#include "fwflash.h"
#include "fwflash_ib.h"
/* FWflash functions */
static char *fwflash_name_from_class(int class);
static int fwflash_class_from_name(char *class_name);
static int fwflash_device_class_from_path(char *dev_name);
static int fwflash_list_fw(int dev_class);
static void fwflash_intr(int sig);
static void fwflash_handle_signals(void);
static void fwflash_usage();
static void fwflash_help(void);
static void fwflash_version(void);
/* IB Specific functions */
static int fwflash_list_fw_ib(int device);
static int fwflash_update_ib(char *device);
static int fwflash_read_file_ib(char *device);
#if !defined(lint)
/* embedded software license agreement */
static char *sla [] = { "Copyright 2007 Sun Microsystems, Inc., 4150 Network "
"Circle, Santa Clara, California 95054, U.S.A. All rights reserved. U.S. "
"Government Rights - Commercial software. Government users are subject to the "
"Sun Microsystems, Inc. standard license agreement and applicable provisions "
"of the FAR and its supplements. Use is subject to license terms. Parts of "
"the product may be derived from Berkeley BSD systems, licensed from the "
"University of California. UNIX is a registered trademark in the U.S. and in "
"Microsystems, the Sun logo and Solaris are trademarks or registered "
"trademarks of Sun Microsystems, Inc. in the U.S. and other countries. This "
"product is covered and controlled by U.S. Export Control laws and may be "
"subject to the export or import laws in other countries. Nuclear, missile, "
"chemical biological weapons or nuclear maritime end uses or end users, "
"whether direct or indirect, are strictly prohibited. Export or reexport "
"to countries subject to U.S. embargo or to entities identified on U.S. export "
"exclusion lists, including, but not limited to, the denied persons and "
"specially designated nationals lists is strictly prohibited." };
#endif /* lint */
/* global arg list */
int fwflash_arg_list = 0;
/* global state */
/* are we writing to flash? */
static int fwflash_in_write = 0;
/*
* Define the types of devices we support. The order matters, add appropriate
* values to the below #defines as well when updating this information.
*/
char *fwflash_classes [] =
{
"ALL",
"IB",
""
};
#define FWFLASH_DEVCLASS_ALL 0
#define FWFLASH_DEVCLASS_IB 1
/*
* FWFlash main code
*/
int
{
int rv;
char ch;
char *fw_file;
char *read_file;
int dev_class = FWFLASH_DEVCLASS_ALL;
extern char *optarg;
/* gather list of available devices to flash */
return (FWFLASH_FAILURE);
}
switch (ch) {
case 'h':
break;
case 'v':
break;
case 'y':
break;
case 'l':
break;
case 'c':
while (*optarg == ' ') {
optarg++;
}
if (dev_class == -1) {
gettext("Invalid device class"));
return (FWFLASH_FAILURE);
}
break;
case 'd':
while (*optarg == ' ') {
optarg++;
}
"Unknown device specification"));
": %s\n", optarg);
return (FWFLASH_FAILURE);
}
} else {
}
break;
case 'f':
while (*optarg == ' ') {
optarg++;
}
break;
case 'r':
while (*optarg == ' ') {
optarg++;
}
break;
/* illegal options */
default:
return (FWFLASH_FAILURE);
}
}
/* Do Help */
if (fwflash_arg_list & FWFLASH_HELP_FLAG) {
fwflash_help();
return (FWFLASH_SUCCESS);
}
/* Do Version */
if (fwflash_arg_list == FWFLASH_VER_FLAG) {
return (FWFLASH_SUCCESS);
}
/* Do list */
if (fwflash_arg_list == (FWFLASH_LIST_FLAG) ||
if (rv != FWFLASH_SUCCESS) {
"Unable to generate list of available devices"));
}
return (FWFLASH_SUCCESS);
}
/* Do flash update */
FWFLASH_YES_FLAG)) {
if (rv != FWFLASH_SUCCESS) {
gettext("Failed to (re)write firmware"));
return (FWFLASH_FAILURE);
}
return (FWFLASH_SUCCESS);
} else {
gettext("Write filename invalid"));
return (FWFLASH_FAILURE);
}
}
/* Do flash read */
FWFLASH_YES_FLAG)) {
if (rv == 0) {
gettext("Failed to read out firmware"));
return (FWFLASH_FAILURE);
}
return (FWFLASH_SUCCESS);
} else {
gettext("Read filename invalid"));
return (FWFLASH_FAILURE);
}
}
if (fwflash_arg_list == 0) {
} else {
}
return (FWFLASH_FAILURE);
}
static fwflash_device_info_t *
fwflash_device_list(int *count)
{
int i;
sizeof (fwflash_device_info_t));
/* Probe out all the supported devices */
/*
* First find all IB devices
*/
if (count == 0) {
} else {
for (i = 0; i < *count; i++) {
}
}
return (devices);
}
static char *
{
return (fwflash_classes[dev_class]);
}
static int
{
int class;
while (*class_name == ' ') {
class_name++;
}
break;
}
return (-1);
} else {
return (class);
}
}
static int
{
int entry;
break;
}
return (-1);
} else {
}
}
static int
fwflash_list_fw(int dev_class)
{
int rv = FWFLASH_FAILURE;
int i;
if (dev_class == FWFLASH_DEVCLASS_ALL ||
case FWFLASH_DEVCLASS_IB:
rv = fwflash_list_fw_ib(i);
if (rv != 0) {
/*
* flash type not yet supported
* move on to the next device
*/
rv = 0;
}
break;
default:
gettext("Unknown class for device"));
break;
}
}
}
out:
return (rv);
}
static int
{
int class;
int rv = 0;
/* new firmware filename and device desc */
if (class == -1) {
return (FWFLASH_FAILURE);
}
switch (class) {
case FWFLASH_DEVCLASS_IB:
if (rv != 0) {
gettext("Flash update IB failed."));
return (rv);
}
break;
default:
break;
}
return (rv);
}
static int
{
int class;
int rv;
/* new firmware filename and device desc */
if (class == -1) {
return (FWFLASH_FAILURE);
}
switch (class) {
case FWFLASH_DEVCLASS_IB:
if (rv == 0) {
gettext("Flash read file failed."));
return (rv);
}
break;
default:
break;
}
return (rv);
}
static void
{
"fwflash [-l [-c <device_class> | ALL]] | [-v] | [-h]"));
"fwflash [-f <file>] | -r <file>] [-y] -d <dev_spec]"));
}
static void
fwflash_version(void)
{
}
static void
fwflash_help(void)
{
}
/* ARGSUSED */
static void
fwflash_intr(int sig)
{
if (fwflash_in_write) {
gettext("WARNING: firmware image may be corrupted"));
gettext("Reflash firmware before rebooting!"));
}
switch (state.device_class) {
case FWFLASH_DEVCLASS_IB:
break;
default:
break;
}
}
static void
fwflash_handle_signals(void)
{
perror("signal");
}
perror("signal");
}
}
/*
* IB (InfiniBand) specific functions. Add additional functions following
* these for otherclass types.
*/
static int
fwflash_list_fw_ib(int device)
{
int rv;
char *dev_name;
/* open device and read some stuff */
return (FWFLASH_FAILURE);
}
/*
* Flash read GUIDs
* - First try the primary image GUIDs. If this exists, then
* we have booted the primary image.
*
* - If primary doesn't work, fallback to the secondary GUIDs,
* assuming we have booted from the secondary firmware image.
*
* - If both fail, something is wrong here, and we must print
* out an error.
*/
if (rv != 0) {
"Trying secondary..\n"));
if (rv != 0) {
gettext("WARNING: HCA FIRMWARE MAY BE CORRUPT"));
gettext("Unable to read GUID values"));
return (FWFLASH_FAILURE);
}
}
/* print the guids */
/* print firmware revision */
} else {
gettext("WARNING: HCA FIRMWARE MAY BE CORRUPT"));
gettext("Unable to read firmware version"));
return (FWFLASH_FAILURE);
}
/* print the HW product name, PSID, and part number */
} else {
}
/* close the device */
return (FWFLASH_SUCCESS);
}
static void
{
}
static int
fwflash_update_ib(char *device)
{
char ans;
int rv;
int i;
/* flash devices we're working on */
return (FWFLASH_FAILURE);
}
/* read in and verify the new firmware */
if (rv != 0) {
goto out;
}
/*
* Ask the user if he would like to continue.
*/
if (!(fwflash_arg_list & FWFLASH_YES_FLAG)) {
goto out;
}
}
/* write both the primary and secondary images */
fwflash_in_write = 1;
/*
* Try to read existing GUIDs from the device. We will use these, if
* we are able to read them, when updating each image. We try the
* primary first, and then the secondary. To the end user, there
* should be no distinction between primary and secondary images, so
* the GUID values are expected to be the same between both sets of
* images.
*/
if (rv != 0) {
"from secondary image.\n"));
if (rv != 0) {
gettext("Failed to read any valid GUIDs."));
gettext("Using default GUIDs from file."));
}
}
/*
* If we were able to read some valid GUIDs from either primary or
* secondary images, then we set them here to our local image. This
* allows us to use the existing GUIDs in the firmware. However, if
* both attempts to read GUIDs failed, then we do not set any of the
* GUIDs in our local image, and will use the values that are in the
* firmware file itself instead.
*/
if (rv == 0) {
if (rv != 0) {
}
if (rv != 0) {
}
}
/*
* Update both Primary and Secondary images
*/
for (i = FWFLASH_FLASH_IMAGES; i > 0; i--) {
if (rv != 0) {
goto out;
}
if (rv != 0) {
goto out;
}
}
gettext("New image will be active after the system is rebooted."));
out:
fwflash_in_write = 0;
return (rv);
}
static int
fwflash_read_file_ib(char *device)
{
char ans;
int rv;
int i;
/* flash devices we're working on */
return (FWFLASH_FAILURE);
}
/*
* Ask the user if he would like to continue.
*/
if (!(fwflash_arg_list & FWFLASH_YES_FLAG)) {
goto out;
}
}
/* read both the primary and secondary images */
for (i = FWFLASH_FLASH_IMAGES; i > 0; i--) {
(void) printf(" .");
if (rv != 0) {
goto out;
}
}
(void) printf(" .");
out:
fwflash_in_write = 0;
return (rv);
}