From: 丁剑 Date: Tue, 12 May 2020 03:49:09 +0000 (+0800) Subject: [memblaze] add select-download command X-Git-Tag: v1.12~21 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=6555f936f3e07a6a87384c7752b8b231aa5c38b3;p=users%2Fhch%2Fnvme-cli.git [memblaze] add select-download command 1. This performs a selective firmware download; 2. Please power cycle for changes to take effect, after the update successful. Signed-off-by: 丁剑 --- diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index b549414..92b09ba 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -593,3 +593,130 @@ free: return err; } +static int memblaze_fw_commit(int fd, int select) +{ + struct nvme_admin_cmd cmd = { + .opcode = nvme_admin_activate_fw, + .cdw10 = 8, + .cdw12 = select, + }; + + return nvme_submit_admin_passthru(fd, &cmd); +} + +static int memblaze_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = + "This performs a selective firmware download, which allows the user to " + "select which firmware binary to update for 9200 devices. This requires a power cycle once the " + "update completes. The options available are: \n\n" + "OOB - This updates the OOB and main firmware\n" + "EEP - This updates the eeprom and main firmware\n" + "ALL - This updates the eeprom, OOB, and main firmware"; + const char *fw = "firmware file (required)"; + const char *select = "FW Select (e.g., --select=OOB, EEP, ALL)"; + int xfer = 4096; + void *fw_buf; + int fd, selectNo,fw_fd,fw_size,err,offset = 0; + struct stat sb; + int i; + + struct config { + char *fw; + char *select; + }; + + struct config cfg = { + .fw = "", + .select = "\0", + }; + + OPT_ARGS(opts) = { + OPT_STRING("fw", 'f', "FILE", &cfg.fw, fw), + OPT_STRING("select", 's', "flag", &cfg.select, select), + OPT_END() + }; + + fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + return fd; + + if (strlen(cfg.select) != 3) { + fprintf(stderr, "Invalid select flag\n"); + err = EINVAL; + goto out; + } + + for (i = 0; i < 3; i++) { + cfg.select[i] = toupper(cfg.select[i]); + } + + if (strncmp(cfg.select,"OOB", 3) == 0) { + selectNo = 18; + } else if (strncmp(cfg.select,"EEP", 3) == 0) { + selectNo = 10; + } else if (strncmp(cfg.select,"ALL", 3) == 0) { + selectNo = 26; + } else { + fprintf(stderr, "Invalid select flag\n"); + err = EINVAL; + goto out; + } + + fw_fd = open(cfg.fw, O_RDONLY); + if (fw_fd < 0) { + fprintf(stderr, "no firmware file provided\n"); + err = EINVAL; + goto out; + } + + err = fstat(fw_fd, &sb); + if (err < 0) { + perror("fstat"); + err = errno; + } + + fw_size = sb.st_size; + if (fw_size & 0x3) { + fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size); + err = EINVAL; + goto out; + } + + if (posix_memalign(&fw_buf, getpagesize(), fw_size)) { + fprintf(stderr, "No memory for f/w size:%d\n", fw_size); + err = ENOMEM; + goto out; + } + + if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size))) + return EIO; + + while (fw_size > 0) { + xfer = min(xfer, fw_size); + + err = nvme_fw_download(fd, offset, xfer, fw_buf); + if (err < 0) { + perror("fw-download"); + goto out; + } else if (err != 0) { + fprintf(stderr, "NVME Admin command error:%s(%x)\n", + nvme_status_to_string(err), err); + goto out; + } + fw_buf += xfer; + fw_size -= xfer; + offset += xfer; + } + + err = memblaze_fw_commit(fd,selectNo); + + if(err == 0x10B || err == 0x20B) { + err = 0; + fprintf(stderr, "Update successful! Please power cycle for changes to take effect\n"); + } + +out: + return err; +} + diff --git a/plugins/memblaze/memblaze-nvme.h b/plugins/memblaze/memblaze-nvme.h index 528285e..8f7024d 100644 --- a/plugins/memblaze/memblaze-nvme.h +++ b/plugins/memblaze/memblaze-nvme.h @@ -5,15 +5,23 @@ #define MEMBLAZE_NVME #include "cmd.h" +#include "common.h" + +#include +#include +#include +#include PLUGIN(NAME("memblaze", "Memblaze vendor specific extensions"), COMMAND_LIST( ENTRY("smart-log-add", "Retrieve Memblaze SMART Log, show it", get_additional_smart_log) ENTRY("get-feature-add", "Get Memblaze feature and show the resulting value", get_additional_feature) ENTRY("set-feature-add", "Set a Memblaze feature and show the resulting value", set_additional_feature) + ENTRY("select-download", "Selective Firmware Download", memblaze_selective_download) ) ); #endif #include "define_cmd.h" +