From: Gollu Appalanaidu Date: Fri, 13 Aug 2021 16:54:00 +0000 (+0530) Subject: nvme: add boot partition log support X-Git-Tag: v2.0-rc0~53^2~22 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=079afcdd46606a081b450389e8d08c9307524af3;p=users%2Fsagi%2Fnvme-cli.git nvme: add boot partition log support Signed-off-by: Gollu Appalanaidu [dwagner: ported from monolithic, droped nvme-ioctl changes, part of libnvme] Signed-off-by: Daniel Wagner --- diff --git a/Documentation/nvme-boot-part-log.1 b/Documentation/nvme-boot-part-log.1 new file mode 100644 index 00000000..4b6d8eb7 --- /dev/null +++ b/Documentation/nvme-boot-part-log.1 @@ -0,0 +1,89 @@ +'\" t +.\" Title: nvme-boot-part-log +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.79.1 +.\" Date: 08/13/2021 +.\" Manual: NVMe Manual +.\" Source: NVMe +.\" Language: English +.\" +.TH "NVME\-BOOT\-PART\-LO" "1" "08/13/2021" "NVMe" "NVMe Manual" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +nvme-boot-part-log \- Retrieves a Boot Partition log page from an NVMe device +.SH "SYNOPSIS" +.sp +.nf +\fInvme boot\-part\-log\fR [\-\-lsp= | \-s ] + [\-\-output\-file= | \-o ] + [\-\-output\-format= | \-o ] +.fi +.SH "DESCRIPTION" +.sp +Retrieves an Boot Partition log page from an NVMe device and provides the returned structure\&. +.sp +The parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&. +.sp +On success, the returned log structure will be in raw binary format \fIonly\fR with \-\-output\-file option which is mandatory\&. +.SH "OPTIONS" +.PP +\-s , \-\-lsp= +.RS 4 +The log specified field of LID\&. +.RE +.PP +\-o , \-\-output\-file= +.RS 4 +File name to which raw binary data will be saved to\&. +.RE +.PP +\-o , \-\-output\-format= +.RS 4 +Set the reporting format to +\fInormal\fR, +\fIjson\fR, or +\fIbinary\fR\&. Only one output format can be used at a time\&. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +Retrieve Boot Partition data to boot_part_log\&.bin +.sp +.if n \{\ +.RS 4 +.\} +.nf +# nvme boot\-part\-log /dev/nvme0 \-\-output\-file=boot_part_log\&.bin +.fi +.if n \{\ +.RE +.\} +.RE +.SH "NVME" +.sp +Part of the nvme\-user suite diff --git a/Documentation/nvme-boot-part-log.html b/Documentation/nvme-boot-part-log.html new file mode 100644 index 00000000..7c93c532 --- /dev/null +++ b/Documentation/nvme-boot-part-log.html @@ -0,0 +1,842 @@ + + + + + + +nvme-boot-part-log(1) + + + + + +
+
+

SYNOPSIS

+
+
+
nvme boot-part-log <device> [--lsp=<field> | -s <field>]
+                    [--output-file=<file> | -o <file>]
+                    [--output-format=<fmt> | -o <fmt>]
+
+
+
+
+
+

DESCRIPTION

+
+

Retrieves an Boot Partition log page from an NVMe device and provides +the returned structure.

+

The <device> parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).

+

On success, the returned log structure will be in raw binary format only with +--output-file option which is mandatory.

+
+
+
+

OPTIONS

+
+
+
+-s <field> +
+
+--lsp=<field> +
+
+

+ The log specified field of LID. +

+
+
+-o <file> +
+
+--output-file=<file> +
+
+

+ File name to which raw binary data will be saved to. +

+
+
+-o <format> +
+
+--output-format=<format> +
+
+

+ Set the reporting format to normal, json, or + binary. Only one output format can be used at a time. +

+
+
+
+
+
+

EXAMPLES

+
+
    +
  • +

    +Retrieve Boot Partition data to boot_part_log.bin +

    +
    +
    +
    # nvme boot-part-log /dev/nvme0 --output-file=boot_part_log.bin
    +
    +
  • +
+
+
+
+

NVME

+
+

Part of the nvme-user suite

+
+
+
+

+ + + diff --git a/Documentation/nvme-boot-part-log.txt b/Documentation/nvme-boot-part-log.txt new file mode 100644 index 00000000..2dd32a67 --- /dev/null +++ b/Documentation/nvme-boot-part-log.txt @@ -0,0 +1,51 @@ +nvme-boot-part-log(1) +===================== + +NAME +---- +nvme-boot-part-log - Retrieves a Boot Partition log page from an NVMe device + +SYNOPSIS +-------- +[verse] +'nvme boot-part-log' [--lsp= | -s ] + [--output-file= | -o ] + [--output-format= | -o ] + +DESCRIPTION +----------- +Retrieves an Boot Partition log page from an NVMe device and provides +the returned structure. + +The parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1). + +On success, the returned log structure will be in raw binary format _only_ with +--output-file option which is mandatory. + +OPTIONS +------- +-s :: +--lsp=:: + The log specified field of LID. + +-o :: +--output-file=:: + File name to which raw binary data will be saved to. + +-o :: +--output-format=:: + Set the reporting format to 'normal', 'json', or + 'binary'. Only one output format can be used at a time. + +EXAMPLES +-------- +* Retrieve Boot Partition data to boot_part_log.bin ++ +------------ +# nvme boot-part-log /dev/nvme0 --output-file=boot_part_log.bin +------------ + +NVME +---- +Part of the nvme-user suite diff --git a/completions/_nvme b/completions/_nvme index 82a28b61..2cf6b30f 100644 --- a/completions/_nvme +++ b/completions/_nvme @@ -51,6 +51,7 @@ _nvme () { 'write:submit a write command' 'capacity-mgmt: submit capacity management command' 'show-regs:shows the controller registers; requires admin character device' + 'boot-part-log: retrieve boot partition log' 'help:print brief descriptions of all nvme commands' ) @@ -358,6 +359,18 @@ _nvme () { _arguments '*:: :->subcmds' _describe -t commands "nvme resv-notif-log options" _resvnotiflog ;; + (boot-part-log) + local _bootpartlog + _bootpartlog=( + /dev/nvme':supply a device to use (required)' + --lsp=': log specific field' + -s':alias to --lsp' + --output-file=': boot partition data output write' + -f':alias for --output-file' + ) + _arguments '*:: :->subcmds' + _describe -t commands "nvme boot-part-log options" _bootpartlog + ;; (get-feature) local _getf _getf=( @@ -837,7 +850,7 @@ _nvme () { security-send security-recv resv-acquire resv-register resv-release resv-report flush compare read write copy show-regs persistent-event-log pred-lat-event-agg-log nvm-id-ctrl endurance-event-agg-log lba-status-log - resv-notif-log capacity-mgmt id-domain + resv-notif-log capacity-mgmt id-domain boot-part-log ) _arguments '*:: :->subcmds' _describe -t commands "help: infos on a specific nvme command, or provide no option to see a synopsis of all nvme commands" _h diff --git a/completions/bash-nvme-completion.sh b/completions/bash-nvme-completion.sh index 4d3097aa..207c705b 100644 --- a/completions/bash-nvme-completion.sh +++ b/completions/bash-nvme-completion.sh @@ -100,7 +100,7 @@ _cmds="list list-subsys id-ctrl id-ns \ ns-rescan show-regs discover connect-all \ connect disconnect disconnect-all gen-hostnqn \ show-hostnqn dir-receive dir-send virt-mgmt \ - rpmb" + rpmb boot-part-log" # Add plugins: for plugin in "${!_plugin_subcmds[@]}"; do @@ -253,6 +253,10 @@ nvme_list_opts () { "resv-notif-log") opts+=" --output-format= -o" ;; + "boot-part-log") + opts+=" --lsp -s --output-file= -f \ + --output-format= -o" + ;; "get-feature") opts+=" --namespace-id= -n --feature-id= -f --sel= -s \ --data-len= -l --cdw11= --c -uuid-index= -U --raw-binary -b \ diff --git a/nvme-builtin.h b/nvme-builtin.h index 53cea348..a45b632f 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -43,6 +43,7 @@ COMMAND_LIST( ENTRY("endurance-event-agg-log", "Retrieve Endurance Group Event Aggregate Log, show it", get_endurance_event_agg_log) ENTRY("lba-status-log", "Retrieve LBA Status Information Log, show it", get_lba_status_log) ENTRY("resv-notif-log", "Retrieve Reservation Notification Log, show it", get_resv_notif_log) + ENTRY("boot-part-log", "Retrieve Boot Partition Log, show it", get_boot_part_log) ENTRY("get-feature", "Get feature and show the resulting value", get_feature) ENTRY("device-self-test", "Perform the necessary tests to observe the performance", device_self_test) ENTRY("self-test-log", "Retrieve the SELF-TEST Log, show it", self_test_log) diff --git a/nvme-print.c b/nvme-print.c index e89d2361..3580cd7c 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -1863,6 +1863,41 @@ void nvme_show_resv_notif_log(struct nvme_resv_notification_log *resv, le32_to_cpu(resv->nsid)); } +static void json_boot_part_log(void *bp_log) +{ + struct nvme_boot_partition *hdr; + struct json_object *root; + + hdr = bp_log; + root = json_create_object(); + + json_object_add_value_uint(root, "count", hdr->lid); + json_object_add_value_uint(root, "abpid", + (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); + json_object_add_value_uint(root, "bpsz", + le32_to_cpu(hdr->bpinfo) & 0x7fff); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_boot_part_log(void *bp_log, const char *devname, + __u32 size, enum nvme_print_flags flags) +{ + struct nvme_boot_partition *hdr; + if (flags & BINARY) + return d_raw((unsigned char *)bp_log, size); + if (flags & JSON) + return json_boot_part_log(bp_log); + + hdr = bp_log; + printf("Boot Partition Log for device: %s\n", devname); + printf("Log ID: %u\n", hdr->lid); + printf("Boot Partition Size: %u KiB\n", le32_to_cpu(hdr->bpinfo) & 0x7fff); + printf("Active BPID: %u\n", (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); +} + static void nvme_show_subsystem(nvme_root_t r) { nvme_host_t h; diff --git a/nvme-print.h b/nvme-print.h index ce1e81ce..05d992f7 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -78,6 +78,8 @@ void nvme_show_lba_status_log(void *lba_status, __u32 size, const char *devname, enum nvme_print_flags flags); void nvme_show_resv_notif_log(struct nvme_resv_notification_log *resv, const char *devname, enum nvme_print_flags flags); +void nvme_show_boot_part_log(void *bp_log, const char *devname, + __u32 size, enum nvme_print_flags flags); void nvme_show_ctrl_registers(void *bar, bool fabrics, enum nvme_print_flags flags); void nvme_show_single_property(int offset, uint64_t prop, int human); void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flags); diff --git a/nvme.c b/nvme.c index 66502ba4..5f94dbf5 100644 --- a/nvme.c +++ b/nvme.c @@ -1287,6 +1287,116 @@ ret: } +static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Retrieve Boot Partition " \ + "log page and prints it, for the given " \ + "device in either decoded format(default), " \ + "json or binary."; + const char *lsp = "log specific field"; + const char *fname = "boot partition data output file name"; + struct nvme_boot_partition boot; + __u8 *bp_log; + enum nvme_print_flags flags; + int err = -1, fd = 0, output = 0; + __u32 bpsz = 0; + + struct config { + __u8 lsp; + char *output_format; + char *file_name; + }; + + struct config cfg = { + .lsp = 0, + .file_name = NULL, + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_BYTE("lsp", 's', &cfg.lsp, lsp), + OPT_FILE("output-file", 'f', &cfg.file_name, fname), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_END() + }; + + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto close_fd; + + if (!cfg.file_name) { + fprintf(stderr, "Please provide an output file!\n"); + errno = EINVAL; + err = -1; + goto close_fd; + } + + if (cfg.lsp > 128) { + fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp); + errno = EINVAL; + err = -1; + goto close_fd; + } + + output = open(cfg.file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) { + fprintf(stderr, "Failed to open output file %s: %s!\n", + cfg.file_name, strerror(errno)); + err = output; + goto close_fd; + } + + err = nvme_get_log_boot_partition(fd, false, cfg.lsp, + sizeof(boot), &boot); + if (err < 0) { + perror("boot partition log"); + goto close_output; + } else if (err) { + nvme_show_status(err); + goto close_output; + } + + bpsz = (boot.bpinfo & 0x7fff) * 128 * 1024; + bp_log = calloc(sizeof(boot) + bpsz, 1); + if (!bp_log) { + perror("could not alloc buffer for boot partition log"); + errno = ENOMEM; + err = -1; + goto close_output; + } + + err = nvme_get_log_boot_partition(fd, false, cfg.lsp, + sizeof(boot) + bpsz, + (struct nvme_boot_partition *)bp_log); + if (!err) + nvme_show_boot_part_log(&bp_log, devicename, flags, sizeof(boot) + bpsz); + else if (err > 0) + nvme_show_status(err); + else + perror("boot partition log"); + + err = write(output, (void *) bp_log + sizeof(boot), bpsz); + if (err != bpsz) { + fprintf(stderr, "Failed to flush all data to file!\n"); + } else { + printf("Data flushed into file %s\n", cfg.file_name); + } + err = 0; + + free(bp_log); + +close_output: + close(output); +close_fd: + close(fd); +ret: + return nvme_status_to_errno(err, false); +} + static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve desired number of bytes "\