Add nvme commands in U-Boot command line.

1. "nvme list" - show all available NVMe blk devices
2. "nvme info" - show current or a specific NVMe blk device
3. "nvme device" - show or set current device
4. "nvme part" - print partition table
5. "nvme read" - read data from NVMe blk device
6. "nvme write" - write data to NVMe blk device

Signed-off-by: Zhikang Zhang <zhikang.zh...@nxp.com>
Signed-off-by: Wenbin Song <wenbin.s...@nxp.com>
---
Changes for v2:
        - remove the calling of "initialie" in fuction "do_nvmecops"
        - change the function "do_nvme_info" to support BLK uclass
---
 cmd/Kconfig     |   9 +++
 cmd/Makefile    |   1 +
 cmd/nvme.c      | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 disk/part.c     |   6 ++
 doc/README.nvme |  54 ++++++++++++++++++
 5 files changed, 243 insertions(+)
 create mode 100644 cmd/nvme.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 13dc46a..e30814b 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -502,6 +502,15 @@ config CMD_USB
        help
          USB support.
 
+config CMD_NVME
+       bool "NVMe"
+       depends on NVME
+       help
+         NVMe support.
+         This enables nvme commands in command line
+         You can use comamnd "nvme" to show what commands it supports
+         such as "nvme info" "nvme list".
+
 config CMD_DFU
        bool "dfu"
        select USB_FUNCTION_DFU
diff --git a/cmd/Makefile b/cmd/Makefile
index 97c862f..941100e 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -111,6 +111,7 @@ obj-$(CONFIG_CMD_REISER) += reiser.o
 obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
 obj-$(CONFIG_SANDBOX) += host.o
 obj-$(CONFIG_CMD_SATA) += sata.o
+obj-$(CONFIG_CMD_NVME) += nvme.o
 obj-$(CONFIG_CMD_SF) += sf.o
 obj-$(CONFIG_SCSI) += scsi.o disk.o
 obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
diff --git a/cmd/nvme.c b/cmd/nvme.c
new file mode 100644
index 0000000..8dc1f14
--- /dev/null
+++ b/cmd/nvme.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <part.h>
+#include <nvme.h>
+#include <linux/math64.h>
+
+static int nvme_curr_device;
+
+static int do_nvme_list(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       blk_list_devices(IF_TYPE_NVME);
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_info(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       int devnum;
+       struct udevice *udev;
+       int ret;
+       if (argc > 1)
+               devnum = (int)simple_strtoul(argv[1], NULL, 10);
+       else
+               devnum = nvme_curr_device;
+       ret = blk_get_device(IF_TYPE_NVME, devnum, &udev);
+       if (ret < 0)
+               return ret;
+
+       nvme_print_info(udev);
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_device(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       if (argc > 1) {
+               int devnum = (int)simple_strtoul(argv[1], NULL, 10);
+               if (!blk_show_device(IF_TYPE_NVME, devnum)) {
+                       nvme_curr_device = devnum;
+                       printf("... is now current device\n");
+               } else {
+                       return CMD_RET_FAILURE;
+               }
+       } else {
+               blk_show_device(IF_TYPE_NVME, nvme_curr_device);
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_part(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       if (argc > 1) {
+               int devnum = (int)simple_strtoul(argv[2], NULL, 10);
+               if (blk_print_part_devnum(IF_TYPE_NVME, devnum)) {
+                       printf("\nNVME device %d not available\n", devnum);
+                       return CMD_RET_FAILURE;
+               }
+       } else {
+               blk_print_part_devnum(IF_TYPE_NVME, nvme_curr_device);
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_read(cmd_tbl_t *cmdtp, int flag, int argc,
+               char * const argv[])
+{
+       unsigned long time;
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+       ulong addr = simple_strtoul(argv[1], NULL, 16);
+       ulong cnt = simple_strtoul(argv[3], NULL, 16);
+       ulong n;
+       lbaint_t blk = simple_strtoul(argv[2], NULL, 16);
+
+       printf("\nNVME read: device %d block # %ld, count %ld ... ",
+              nvme_curr_device, blk, cnt);
+
+       time = get_timer(0);
+       n = blk_read_devnum(IF_TYPE_NVME, nvme_curr_device, blk,
+                           cnt, (ulong *)addr);
+       time = get_timer(time);
+
+       printf("read: %s\n", (n == cnt) ? "OK" : "ERROR");
+       printf("%lu bytes read in %lu ms", cnt * 512, time);
+       if (time > 0) {
+               puts(" (");
+               print_size(div_u64(cnt * 512, time) * 1000, "/s");
+               puts(")");
+       }
+       puts("\n");
+       return (n == cnt) ? 0 : 1;
+}
+
+static int do_nvme_write(cmd_tbl_t *cmdtp, int flag, int argc,
+               char * const argv[])
+{
+       unsigned long time;
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+       ulong addr = simple_strtoul(argv[1], NULL, 16);
+       ulong cnt = simple_strtoul(argv[3], NULL, 16);
+       ulong n;
+       lbaint_t blk = simple_strtoul(argv[2], NULL, 16);
+
+       printf("\nNVME write: device %d block # %ld, count %ld ... ",
+              nvme_curr_device, blk, cnt);
+
+       time = get_timer(0);
+       n = blk_write_devnum(IF_TYPE_NVME, nvme_curr_device, blk,
+                           cnt, (ulong *)addr);
+       time = get_timer(time);
+
+       printf("write: %s\n", (n == cnt) ? "OK" : "ERROR");
+       printf("%lu bytes read in %lu ms", cnt * 512, time);
+       if (time > 0) {
+               puts(" (");
+               print_size(div_u64(cnt * 512, time) * 1000, "/s");
+               puts(")");
+       }
+       puts("\n");
+       return (n == cnt) ? 0 : 1;
+}
+
+static cmd_tbl_t cmd_nvme[] = {
+       U_BOOT_CMD_MKENT(list, 1, 1, do_nvme_list, "", ""),
+       U_BOOT_CMD_MKENT(info, 2, 1, do_nvme_info, "", ""),
+       U_BOOT_CMD_MKENT(device, 2, 1, do_nvme_device, "", ""),
+       U_BOOT_CMD_MKENT(part, 2, 1, do_nvme_part, "", ""),
+       U_BOOT_CMD_MKENT(write, 4, 0, do_nvme_write, "", ""),
+       U_BOOT_CMD_MKENT(read, 4, 0, do_nvme_read, "", "")
+};
+
+static int do_nvmecops(cmd_tbl_t *cmdtp, int flag, int argc,
+               char * const argv[])
+{
+       cmd_tbl_t *cp;
+
+       cp = find_cmd_tbl(argv[1], cmd_nvme, ARRAY_SIZE(cmd_nvme));
+
+       argc--;
+       argv++;
+
+       if (cp == NULL || argc > cp->maxargs)
+               return CMD_RET_USAGE;
+
+       if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+               return CMD_RET_SUCCESS;
+
+       return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+       nvme, 8, 1, do_nvmecops,
+       "NVME sub system",
+       "\nnvme list - show all available NVME blk devices\n"
+       "nvme info [dev]- show current or a specific NVME blk device\n"
+       "nvme device [dev] - show or set current device\n"
+       "nvme part [dev] - print partition table\n"
+       "nvme read  addr blk# cnt\n"
+       "nvme write addr blk# cnt"
+);
diff --git a/disk/part.c b/disk/part.c
index cd44702..983104e 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -140,6 +140,12 @@ void dev_print (struct blk_desc *dev_desc)
        case IF_TYPE_DOC:
                puts("device type DOC\n");
                return;
+       case IF_TYPE_NVME:
+               printf("Vendor: %s Rev: %s Prod: %s\n",
+                      dev_desc->vendor,
+                      dev_desc->revision,
+                      dev_desc->product);
+       break;
        case IF_TYPE_UNKNOWN:
                puts("device type unknown\n");
                return;
diff --git a/doc/README.nvme b/doc/README.nvme
index b429715..9ecb314 100644
--- a/doc/README.nvme
+++ b/doc/README.nvme
@@ -28,3 +28,57 @@ You can also get/set other features through standard 
commands.
 NVMe Config Switches:
 ---------------------
 CONFIG_NVME            enables basic NVMe device support
+CONFIG_CMD_NVME                enables basic NVMe command
+
+
+NVMe usage in U-boot:
+---------------------
+
+Two ways to operate the hard disk
+
+* Raw read/write block from/to NVMe hard disk;
+* load read file from ext2/fat/ext4 filesytems in hard disk
+
+1 How to know the information of all the NVMe hard disk?
+
+       => nvme info
+
+2 How to list all of the NVMe hard disks?
+
+       => nvme list
+
+Device 0: Vendor: 0x8086 Rev: 8DV10131 Prod: CVFT535600LS400BGN
+           Type: Hard Disk
+           Capacity: 381554.0 MB = 372.6 GB (781422768 x 512)
+
+3 How to raw write the kernel.itb to a NVMe hard disk?
+
+       Notes: Hard disk sectors are normally 512 bytes, so
+               0x1000 sectors = 2 MBytes
+
+       wirte kernel.itb
+       => tftp 80000000 /tftpboot/kernel.itb
+       => nvme write 80000000 0 11000
+
+4 How to raw read the kernel.itb from a NVMe hard disk?
+
+       load kernel.itb
+       => nvme read a0000000 0 11000
+
+       boot
+       => bootm a0000000
+
+5 How to load image from fat filesystem in U-boot?
+
+       U-boot doesn't support fat write to hard disk, so
+       the files must be written by other means (e.g. linux).
+
+       => fatls nvme 0:1
+        32376967   kernel.itb
+        22929408   100m
+
+       2 file(s), 0 dir(s)
+
+       => fatload nvme 0:1 a0000000 /kernel.itb
+
+       => bootm a0000000
-- 
2.1.0.27.g96db324

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to