]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
[memblaze] add select-download command
author丁剑 <jian.ding@memblaze.com>
Tue, 12 May 2020 03:49:09 +0000 (11:49 +0800)
committerKeith Busch <kbusch@kernel.org>
Tue, 12 May 2020 14:38:34 +0000 (08:38 -0600)
1. This performs a selective firmware download;
2. Please power cycle for changes to take effect, after the update successful.

Signed-off-by: 丁剑 <jian.ding@memblaze.com>
plugins/memblaze/memblaze-nvme.c
plugins/memblaze/memblaze-nvme.h

index b54941437f2d36ea3b808a1a8f991c777a0ddf57..92b09ba15e9e42311fbc366e8b2d6045c36ab660 100644 (file)
@@ -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;
+}
+
index 528285ef40848496363b51f7106cd0aa289c79a0..8f7024dd81fd31dd3f998cd9e4d0d90fbae6cfe1 100644 (file)
@@ -5,15 +5,23 @@
 #define MEMBLAZE_NVME
 
 #include "cmd.h"
+#include "common.h"
+
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 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"
+