diff options
author | Ajit Khaparde <ajitk@serverengines.com> | 2009-09-03 08:33:08 +0530 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-11-25 09:42:47 -0500 |
commit | 9efed0a996f30e1f2d2d33611b209fee6faabc2c (patch) | |
tree | 6c733c529a510aff40c5648de56c489e7e49857d /ethtool.c | |
parent | 0bae92474a3d96070c1235928d0ce821c051583c (diff) | |
download | ethtool-9efed0a996f30e1f2d2d33611b209fee6faabc2c.tar.gz |
ethtool: Add option to flash firmware image from specified file, to a device.
This patch adds a new "-f" option to the ethtool utility to flash a
firmware image specified by a file, to a network device. The filename
is passed to the network driver which will flash the image on the
chip using the request_firmware path.
The region "on the chip" to be flashed can be specified by an option.
It is up to the device driver to enumerate the region number passed
by ethtool, to the region to be flashed.
The default behavior is to flash all the regions on the chip.
Usage:
ethtool -f <interface name> <filename of firmware image>
ethtool -f <interface name> <filename of firmware image> [ REGION-NUMBER-TO-FLASH ]
Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'ethtool.c')
-rw-r--r-- | ethtool.c | 55 |
1 files changed, 54 insertions, 1 deletions
@@ -77,6 +77,7 @@ static char *unparse_rxfhashopts(u64 opts); static int dump_rxfhash(int fhash, u64 val); static int do_srxclass(int fd, struct ifreq *ifr); static int do_grxclass(int fd, struct ifreq *ifr); +static int do_flash(int fd, struct ifreq *ifr); static int send_ioctl(int fd, struct ifreq *ifr); static enum { @@ -101,6 +102,7 @@ static enum { MODE_GSTATS, MODE_GNFC, MODE_SNFC, + MODE_FLASHDEV, } mode = MODE_GSET; static struct option { @@ -188,6 +190,9 @@ static struct option { "options", " [ rx-flow-hash tcp4|udp4|ah4|sctp4|" "tcp6|udp6|ah6|sctp6 ]\n" }, + { "-f", "--flash", MODE_FLASHDEV, "FILENAME " "Flash firmware image " + "from the specified file to a region on the device", + " [ REGION-NUMBER-TO-FLASH ]\n" }, { "-N", "--config-nfc", MODE_SNFC, "Configure Rx network flow " "classification options", " [ rx-flow-hash tcp4|udp4|ah4|sctp4|" @@ -304,6 +309,9 @@ static int rx_fhash_get = 0; static int rx_fhash_set = 0; static u32 rx_fhash_val = 0; static int rx_fhash_changed = 0; +static char *flash_file = NULL; +static int flash = -1; +static int flash_region = -1; static enum { ONLINE=0, OFFLINE, @@ -496,7 +504,8 @@ static void parse_cmdline(int argc, char **argp) (mode == MODE_GSTATS) || (mode == MODE_GNFC) || (mode == MODE_SNFC) || - (mode == MODE_PHYS_ID)) { + (mode == MODE_PHYS_ID) || + (mode == MODE_FLASHDEV)) { devname = argp[i]; break; } @@ -516,6 +525,10 @@ static void parse_cmdline(int argc, char **argp) if (phys_id_time < 0) show_usage(1); break; + } else if (mode == MODE_FLASHDEV) { + flash_file = argp[i]; + flash = 1; + break; } /* fallthrough */ default: @@ -590,6 +603,12 @@ static void parse_cmdline(int argc, char **argp) show_usage(1); break; } + if (mode == MODE_FLASHDEV) { + flash_region = strtol(argp[i], NULL, 0); + if ((flash_region < 0)) + show_usage(1); + break; + } if (mode == MODE_SNFC) { if (!strcmp(argp[i], "rx-flow-hash")) { i += 1; @@ -1516,6 +1535,8 @@ static int doit(void) return do_grxclass(fd, &ifr); } else if (mode == MODE_SNFC) { return do_srxclass(fd, &ifr); + } else if (mode == MODE_FLASHDEV) { + return do_flash(fd, &ifr); } return 69; @@ -2410,6 +2431,38 @@ static int do_grxclass(int fd, struct ifreq *ifr) return 0; } +static int do_flash(int fd, struct ifreq *ifr) +{ + struct ethtool_flash efl; + int err; + + if (flash < 0) { + fprintf(stdout, "Missing filename argument\n"); + show_usage(1); + return 98; + } + + if (strlen(flash_file) > ETHTOOL_FLASH_MAX_FILENAME - 1) { + fprintf(stdout, "Filename too long\n"); + return 99; + } + + efl.cmd = ETHTOOL_FLASHDEV; + strcpy(efl.data, flash_file); + + if (flash_region < 0) + efl.region = ETHTOOL_FLASH_ALL_REGIONS; + else + efl.region = flash_region; + + ifr->ifr_data = (caddr_t)&efl; + err = send_ioctl(fd, ifr); + if (err < 0) + perror("Flashing failed"); + + return err; +} + static int send_ioctl(int fd, struct ifreq *ifr) { return ioctl(fd, SIOCETHTOOL, ifr); |