[U-Boot] [RFC,v2 2/2] NVMe: add nvme commands
Zhikang Zhang
zhikang.zhang at nxp.com
Fri Apr 21 03:01:29 UTC 2017
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.zhang at nxp.com>
Signed-off-by: Wenbin Song <wenbin.song at 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
More information about the U-Boot
mailing list