Index: head/sbin/nvmecontrol/Makefile =================================================================== --- head/sbin/nvmecontrol/Makefile (revision 350562) +++ head/sbin/nvmecontrol/Makefile (revision 350563) @@ -1,18 +1,18 @@ # $FreeBSD$ PACKAGE=runtime PROG= nvmecontrol SRCS= comnd.c nvmecontrol.c SRCS+= devlist.c firmware.c format.c identify.c logpage.c ns.c nsid.c -SRCS+= perftest.c power.c reset.c +SRCS+= perftest.c power.c reset.c sanitize.c #SRCS+= passthru.c SRCS+= identify_ext.c nvme_util.c nc_util.c MAN= nvmecontrol.8 LDFLAGS+= -rdynamic LIBADD+= util SUBDIR= modules .PATH: ${SRCTOP}/sys/dev/nvme .include .include Index: head/sbin/nvmecontrol/identify_ext.c =================================================================== --- head/sbin/nvmecontrol/identify_ext.c (revision 350562) +++ head/sbin/nvmecontrol/identify_ext.c (revision 350563) @@ -1,247 +1,247 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (C) 2012-2013 Intel Corporation * All rights reserved. * Copyright (C) 2018-2019 Alexander Motin * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "nvmecontrol.h" #include "nvmecontrol_ext.h" void nvme_print_controller(struct nvme_controller_data *cdata) { uint8_t str[128]; char cbuf[UINT128_DIG + 1]; uint16_t oncs, oacs; uint8_t compare, write_unc, dsm, t; uint8_t security, fmt, fw, nsmgmt; uint8_t fw_slot1_ro, fw_num_slots; uint8_t ns_smart; uint8_t sqes_max, sqes_min; uint8_t cqes_max, cqes_min; oncs = cdata->oncs; compare = (oncs >> NVME_CTRLR_DATA_ONCS_COMPARE_SHIFT) & NVME_CTRLR_DATA_ONCS_COMPARE_MASK; write_unc = (oncs >> NVME_CTRLR_DATA_ONCS_WRITE_UNC_SHIFT) & NVME_CTRLR_DATA_ONCS_WRITE_UNC_MASK; dsm = (oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) & NVME_CTRLR_DATA_ONCS_DSM_MASK; oacs = cdata->oacs; security = (oacs >> NVME_CTRLR_DATA_OACS_SECURITY_SHIFT) & NVME_CTRLR_DATA_OACS_SECURITY_MASK; fmt = (oacs >> NVME_CTRLR_DATA_OACS_FORMAT_SHIFT) & NVME_CTRLR_DATA_OACS_FORMAT_MASK; fw = (oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) & NVME_CTRLR_DATA_OACS_FIRMWARE_MASK; nsmgmt = (oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & NVME_CTRLR_DATA_OACS_NSMGMT_MASK; fw_num_slots = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) & NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK; fw_slot1_ro = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) & NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK; ns_smart = (cdata->lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) & NVME_CTRLR_DATA_LPA_NS_SMART_MASK; sqes_min = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MIN_SHIFT) & NVME_CTRLR_DATA_SQES_MIN_MASK; sqes_max = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MAX_SHIFT) & NVME_CTRLR_DATA_SQES_MAX_MASK; cqes_min = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MIN_SHIFT) & NVME_CTRLR_DATA_CQES_MIN_MASK; cqes_max = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MAX_SHIFT) & NVME_CTRLR_DATA_CQES_MAX_MASK; printf("Controller Capabilities/Features\n"); printf("================================\n"); printf("Vendor ID: %04x\n", cdata->vid); printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); nvme_strvis(str, cdata->sn, sizeof(str), NVME_SERIAL_NUMBER_LENGTH); printf("Serial Number: %s\n", str); nvme_strvis(str, cdata->mn, sizeof(str), NVME_MODEL_NUMBER_LENGTH); printf("Model Number: %s\n", str); nvme_strvis(str, cdata->fr, sizeof(str), NVME_FIRMWARE_REVISION_LENGTH); printf("Firmware Version: %s\n", str); printf("Recommended Arb Burst: %d\n", cdata->rab); printf("IEEE OUI Identifier: %02x %02x %02x\n", cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); printf("Multi-Path I/O Capabilities: %s%s%s%s%s\n", (cdata->mic == 0) ? "Not Supported" : "", ((cdata->mic >> NVME_CTRLR_DATA_MIC_ANAR_SHIFT) & NVME_CTRLR_DATA_MIC_SRIOVVF_MASK) ? "Asymmetric, " : "", ((cdata->mic >> NVME_CTRLR_DATA_MIC_SRIOVVF_SHIFT) & NVME_CTRLR_DATA_MIC_SRIOVVF_MASK) ? "SR-IOV VF, " : "", ((cdata->mic >> NVME_CTRLR_DATA_MIC_MCTRLRS_SHIFT) & NVME_CTRLR_DATA_MIC_MCTRLRS_MASK) ? "Multiple controllers, " : "", ((cdata->mic >> NVME_CTRLR_DATA_MIC_MPORTS_SHIFT) & NVME_CTRLR_DATA_MIC_MPORTS_MASK) ? "Multiple ports" : ""); /* TODO: Use CAP.MPSMIN to determine true memory page size. */ printf("Max Data Transfer Size: "); if (cdata->mdts == 0) printf("Unlimited\n"); else printf("%ld\n", PAGE_SIZE * (1L << cdata->mdts)); printf("Controller ID: 0x%04x\n", cdata->ctrlr_id); printf("Version: %d.%d.%d\n", (cdata->ver >> 16) & 0xffff, (cdata->ver >> 8) & 0xff, cdata->ver & 0xff); printf("\n"); printf("Admin Command Set Attributes\n"); printf("============================\n"); printf("Security Send/Receive: %s\n", security ? "Supported" : "Not Supported"); printf("Format NVM: %s\n", fmt ? "Supported" : "Not Supported"); printf("Firmware Activate/Download: %s\n", fw ? "Supported" : "Not Supported"); printf("Namespace Managment: %s\n", nsmgmt ? "Supported" : "Not Supported"); printf("Device Self-test: %sSupported\n", ((oacs >> NVME_CTRLR_DATA_OACS_SELFTEST_SHIFT) & NVME_CTRLR_DATA_OACS_SELFTEST_MASK) ? "" : "Not "); printf("Directives: %sSupported\n", ((oacs >> NVME_CTRLR_DATA_OACS_DIRECTIVES_SHIFT) & NVME_CTRLR_DATA_OACS_DIRECTIVES_MASK) ? "" : "Not "); printf("NVMe-MI Send/Receive: %sSupported\n", ((oacs >> NVME_CTRLR_DATA_OACS_NVMEMI_SHIFT) & NVME_CTRLR_DATA_OACS_NVMEMI_MASK) ? "" : "Not "); printf("Virtualization Management: %sSupported\n", ((oacs >> NVME_CTRLR_DATA_OACS_VM_SHIFT) & NVME_CTRLR_DATA_OACS_VM_MASK) ? "" : "Not "); printf("Doorbell Buffer Config: %sSupported\n", ((oacs >> NVME_CTRLR_DATA_OACS_DBBUFFER_SHIFT) & NVME_CTRLR_DATA_OACS_DBBUFFER_MASK) ? "" : "Not "); printf("Get LBA Status: %sSupported\n", ((oacs >> NVME_CTRLR_DATA_OACS_GETLBA_SHIFT) & NVME_CTRLR_DATA_OACS_GETLBA_MASK) ? "" : "Not "); printf("Sanitize: "); if (cdata->sanicap != 0) { printf("%s%s%s\n", ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_CES_SHIFT) & - NVME_CTRLR_DATA_SANICAP_CES_SHIFT) ? "crypto, " : "", + NVME_CTRLR_DATA_SANICAP_CES_MASK) ? "crypto, " : "", ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_BES_SHIFT) & - NVME_CTRLR_DATA_SANICAP_BES_SHIFT) ? "block, " : "", + NVME_CTRLR_DATA_SANICAP_BES_MASK) ? "block, " : "", ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_OWS_SHIFT) & - NVME_CTRLR_DATA_SANICAP_OWS_SHIFT) ? "overwrite" : ""); + NVME_CTRLR_DATA_SANICAP_OWS_MASK) ? "overwrite" : ""); } else { printf("Not Supported\n"); } printf("Abort Command Limit: %d\n", cdata->acl+1); printf("Async Event Request Limit: %d\n", cdata->aerl+1); printf("Number of Firmware Slots: "); if (fw != 0) printf("%d\n", fw_num_slots); else printf("N/A\n"); printf("Firmware Slot 1 Read-Only: "); if (fw != 0) printf("%s\n", fw_slot1_ro ? "Yes" : "No"); else printf("N/A\n"); printf("Per-Namespace SMART Log: %s\n", ns_smart ? "Yes" : "No"); printf("Error Log Page Entries: %d\n", cdata->elpe+1); printf("Number of Power States: %d\n", cdata->npss+1); printf("\n"); printf("NVM Command Set Attributes\n"); printf("==========================\n"); printf("Submission Queue Entry Size\n"); printf(" Max: %d\n", 1 << sqes_max); printf(" Min: %d\n", 1 << sqes_min); printf("Completion Queue Entry Size\n"); printf(" Max: %d\n", 1 << cqes_max); printf(" Min: %d\n", 1 << cqes_min); printf("Number of Namespaces: %d\n", cdata->nn); printf("Compare Command: %s\n", compare ? "Supported" : "Not Supported"); printf("Write Uncorrectable Command: %s\n", write_unc ? "Supported" : "Not Supported"); printf("Dataset Management Command: %s\n", dsm ? "Supported" : "Not Supported"); printf("Write Zeroes Command: %sSupported\n", ((oncs >> NVME_CTRLR_DATA_ONCS_WRZERO_SHIFT) & NVME_CTRLR_DATA_ONCS_WRZERO_MASK) ? "" : "Not "); printf("Save Features: %sSupported\n", ((oncs >> NVME_CTRLR_DATA_ONCS_SAVEFEAT_SHIFT) & NVME_CTRLR_DATA_ONCS_SAVEFEAT_MASK) ? "" : "Not "); printf("Reservations: %sSupported\n", ((oncs >> NVME_CTRLR_DATA_ONCS_RESERV_SHIFT) & NVME_CTRLR_DATA_ONCS_RESERV_MASK) ? "" : "Not "); printf("Timestamp feature: %sSupported\n", ((oncs >> NVME_CTRLR_DATA_ONCS_TIMESTAMP_SHIFT) & NVME_CTRLR_DATA_ONCS_TIMESTAMP_MASK) ? "" : "Not "); printf("Verify feature: %sSupported\n", ((oncs >> NVME_CTRLR_DATA_ONCS_VERIFY_SHIFT) & NVME_CTRLR_DATA_ONCS_VERIFY_MASK) ? "" : "Not "); printf("Fused Operation Support: %s%s\n", (cdata->fuses == 0) ? "Not Supported" : "", ((cdata->fuses >> NVME_CTRLR_DATA_FUSES_CNW_SHIFT) & NVME_CTRLR_DATA_FUSES_CNW_MASK) ? "Compare and Write" : ""); printf("Format NVM Attributes: %s%s Erase, %s Format\n", ((cdata->fna >> NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_SHIFT) & NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_MASK) ? "Crypto Erase, " : "", ((cdata->fna >> NVME_CTRLR_DATA_FNA_ERASE_ALL_SHIFT) & NVME_CTRLR_DATA_FNA_ERASE_ALL_MASK) ? "All-NVM" : "Per-NS", ((cdata->fna >> NVME_CTRLR_DATA_FNA_FORMAT_ALL_SHIFT) & NVME_CTRLR_DATA_FNA_FORMAT_ALL_MASK) ? "All-NVM" : "Per-NS"); t = (cdata->vwc >> NVME_CTRLR_DATA_VWC_ALL_SHIFT) & NVME_CTRLR_DATA_VWC_ALL_MASK; printf("Volatile Write Cache: %s%s\n", ((cdata->vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) & NVME_CTRLR_DATA_VWC_PRESENT_MASK) ? "Present" : "Not Present", (t == NVME_CTRLR_DATA_VWC_ALL_NO) ? ", no flush all" : (t == NVME_CTRLR_DATA_VWC_ALL_YES) ? ", flush all" : ""); if (nsmgmt) { printf("\n"); printf("Namespace Drive Attributes\n"); printf("==========================\n"); printf("NVM total cap: %s\n", uint128_to_str(to128(cdata->untncap.tnvmcap), cbuf, sizeof(cbuf))); printf("NVM unallocated cap: %s\n", uint128_to_str(to128(cdata->untncap.unvmcap), cbuf, sizeof(cbuf))); } } Index: head/sbin/nvmecontrol/nvmecontrol.8 =================================================================== --- head/sbin/nvmecontrol/nvmecontrol.8 (revision 350562) +++ head/sbin/nvmecontrol/nvmecontrol.8 (revision 350563) @@ -1,342 +1,411 @@ .\" .\" Copyright (c) 2018-2019 Alexander Motin .\" Copyright (c) 2012 Intel Corporation .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions, and the following disclaimer, .\" without modification. .\" 2. Redistributions in binary form must reproduce at minimum a disclaimer .\" substantially similar to the "NO WARRANTY" disclaimer below .\" ("Disclaimer") and any redistribution must be conditioned upon .\" including a substantially similar Disclaimer requirement for further .\" binary redistribution. .\" .\" NO WARRANTY .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR .\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT .\" HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGES. .\" .\" nvmecontrol man page. .\" .\" Author: Jim Harris .\" .\" $FreeBSD$ .\" -.Dd August 2, 2019 +.Dd August 3, 2019 .Dt NVMECONTROL 8 .Os .Sh NAME .Nm nvmecontrol .Nd NVM Express control utility .Sh SYNOPSIS .Nm .Ic devlist .Nm .Ic identify .Op Fl v .Op Fl x .Aq device id .Aq namespace id .Nm .Ic perftest .Aq Fl n Ar num_threads .Aq Fl o Ar read|write .Op Fl p .Aq Fl s Ar size_in_bytes .Aq Fl t Ar time_in_sec .Aq namespace id .Nm .Ic reset .Aq controller id .Nm .Ic logpage .Aq Fl p Ar page_id .Op Fl x .Op Fl v Ar vendor-string .Op Fl b .Op Fl f Ar LSP .Op Fl i Ar LSI .Op Fl r .Aq device id .Aq namespace id .Nm .Ic ns active .Aq device id .Nm .Ic ns allocated .Aq device id .Nm .Ic ns attach .Aq Fl n Ar nsid .Aq Fl c Ar cntid .Aq device id .Nm .Ic ns attached .Aq Fl n Ar nsid .Aq device id .Nm .Ic ns controllers .Aq device id .Nm .Ic ns create .Aq Fl s Ar nsze .Op Fl c Ar ncap .Op Fl f Ar lbaf .Op Fl m Ar mset .Op Fl n Ar nmic .Op Fl p Ar pi .Op Fl l Ar pil .Op Fl L Ar flbas .Op Fl d Ar dps .Aq device id .Nm .Ic ns delete .Aq Fl n Ar nsid .Aq device id .Nm .Ic ns detach .Aq Fl n Ar nsid .Aq Fl c Ar cntid .Aq device id .Nm .Ic ns identify .Op Fl v .Op Fl x .Aq Fl n Ar nsid .Aq device id .Nm .Ic nsid .Aq device id .Aq namespace id .Nm .Ic firmware .Op Fl s Ar slot .Op Fl f Ar path_to_firmware .Op Fl a .Aq device id .Nm .Ic format .Op Fl f Ar fmt .Op Fl m Ar mset .Op Fl o Ar pi .Op Fl l Ar pil .Op Fl E .Op Fl C .Aq device id .Aq namespace id .Nm +.Ic sanitize +.Aq Fl a Ar sanact +.Op Fl c Ar owpass +.Op Fl p Ar ovrpat +.Op Fl r +.Op Fl D +.Op Fl I +.Op Fl U +.Aq device id +.Nm .Ic power .Op Fl l .Op Fl p power_state .Op Fl w workload_hint .Nm .Ic wdc cap-diag .Op Fl o path_template .Aq device id .Nm .Ic wdc drive-log .Op Fl o path_template .Aq device id .Nm .Ic wdc get-crash-dump .Op Fl o path_template .Aq device id .\" .Nm .\" .Ic wdc purge .\" .Aq device id .\" .Nm .\" .Ic wdc purge-monitor .\" .Aq device id .Sh DESCRIPTION NVM Express (NVMe) is a storage protocol standard, for SSDs and other high-speed storage devices over PCI Express. .Pp .Ss logpage The logpage command knows how to print log pages of various types. It also knows about vendor specific log pages from hgst/wdc and intel. Note that some vendors use the same log page numbers for different data. .Pp .Bl -tag -compact -width "Page 0x00" .It Dv Page 0x01 Drive Error Log .It Dv Page 0x02 Health/SMART Data .It Dv Page 0x03 Firmware Information .It Dv Page 0x04 Changed Namespace List .It Dv Page 0x05 Commands Supported and Effects .It Dv Page 0x80 Reservation Notification .It Dv Page 0x81 Sanitize Status .It Dv Page 0xc1 Advanced SMART information (WDC/HGST) .It Dv Page 0xc1 Read latency stats (Intel) .It Dv Page 0xc2 Wite latency stats (Intel) .It Dv Page 0xc5 Temperature stats (Intel) .It Dv Page 0xca Advanced SMART information (Intel) .El .Pp Specifying .Fl v .Ic help will list all valid vendors and pages. .Fl x will print the page as hex. .Fl b will print the binary data for the page. .Fl s will set Log Specific Field. .Fl i will set Log Specific Identifier. .Fl r will set Retain Asynchronous Event. .Ss ns Various namespace management commands. If namespace management is supported by device, allow list, create and delete namespaces, list, attach and detach controllers to namespaces. .Ss format Format either specified namespace, or all namespaces of specified controller, using specified parameters: .Ar fmt LBA Format, .Ar mset Metadata Settings, .Ar pi Protection Information, .Ar pil Protection Information Location. When formatting specific namespace, existing values are used as defaults. When formatting all namespaces, all parameters should be specified. Some controllers may not support formatting or erasing specific or all namespaces. Option .Fl E enables User Data Erase during format. Option .Fl C enables Cryptographic Erase during format. +.Ss sanitize +Sanitize NVM subsystem of specified controller, +using specified parameters: +.Bl -tag -width 6n +.It Fl a Ar operation +Specify the sanitize operation to perform. +.Bl -tag -width 16n +.It overwrite +Perform an overwrite operation by writing a user supplied +data pattern to the device one or more times. +The pattern is given by the +.Fl p +argument. +The number of times is given by the +.Fl c +argument. +.It block +Perform a block erase operation. +All the device's blocks are set to a vendor defined +value, typically zero. +.It crypto +Perform a cryptographic erase operation. +The encryption keys are changed to prevent the decryption +of the data. +.It exitfailure +Exits a previously failed sanitize operation. +A failed sanitize operation can only be exited if it was +run in the unrestricted completion mode, as provided by the +.Fl U +argument. +.El +.It Fl c Ar passes +The number of passes when performing an +.Sq overwrite +operation. +Valid values are between 1 and 16. +The default is 1. +.It Fl D +No Deallocate After Sanitize. +.It Fl I +When performing an +.Sq overwrite +operation, the pattern is inverted between consecutive passes. +.It Fl p Ar pattern +32 bits of pattern to use when performing an +.Sq overwrite +operation. +The pattern is repeated as needed to fill each block. +.It Fl U +Perform the sanitize in the unrestricted completion mode. +If the operation fails, it can later be exited with the +.Sq exitfailure +operation. +.It Fl r +Run in +.Dq report only +mode. +This will report status on a sanitize that is already running on the drive. +.El .Ss wdc The various wdc command retrieve log data from the wdc/hgst drives. The .Fl o flag specifies a path template to use to output the files. Each file takes the path template (which defaults to nothing), appends the drive's serial number and the type of dump it is followed by .bin. These logs must be sent to the vendor for analysis. This tool only provides a way to extract them. .Sh EXAMPLES .Dl nvmecontrol devlist .Pp Display a list of NVMe controllers and namespaces along with their device nodes. .Pp .Dl nvmecontrol identify nvme0 .Pp Display a human-readable summary of the nvme0 IDENTIFY_CONTROLLER data. .Pp .Dl nvmecontrol identify -x -v nvme0ns1 .Pp Display an hexadecimal dump of the nvme0 IDENTIFY_NAMESPACE data for namespace 1. .Pp .Dl nvmecontrol perftest -n 32 -o read -s 512 -t 30 nvme0ns1 .Pp Run a performance test on nvme0ns1 using 32 kernel threads for 30 seconds. Each thread will issue a single 512 byte read command. Results are printed to stdout when 30 seconds expires. .Pp .Dl nvmecontrol reset nvme0 .Pp Perform a controller-level reset of the nvme0 controller. .Pp .Dl nvmecontrol logpage -p 1 nvme0 .Pp Display a human-readable summary of the nvme0 controller's Error Information Log. Log pages defined by the NVMe specification include Error Information Log (ID=1), SMART/Health Information Log (ID=2), and Firmware Slot Log (ID=3). .Pp .Dl nvmecontrol logpage -p 0xc1 -v wdc nvme0 .Pp Display a human-readable summary of the nvme0's wdc-specific advanced SMART data. .Pp .Dl nvmecontrol logpage -p 1 -x nvme0 .Pp Display a hexadecimal dump of the nvme0 controller's Error Information Log. .Pp .Dl nvmecontrol logpage -p 0xcb -b nvme0 > /tmp/page-cb.bin .Pp Print the contents of vendor specific page 0xcb as binary data on standard out. Redirect it to a temporary file. .Pp .Dl nvmecontrol firmware -s 2 -f /tmp/nvme_firmware nvme0 .Pp Download the firmware image contained in "/tmp/nvme_firmware" to slot 2 of the nvme0 controller, but do not activate the image. .Pp .Dl nvmecontrol firmware -s 4 -a nvme0 .Pp Activate the firmware in slot 4 of the nvme0 controller on the next reset. .Pp .Dl nvmecontrol firmware -s 7 -f /tmp/nvme_firmware -a nvme0 .Pp Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the nvme0 controller and activate it on the next reset. .Pp .Dl nvmecontrol power -l nvme0 .Pp List all the current power modes. .Pp .Dl nvmecontrol power -p 3 nvme0 .Pp Set the current power mode. .Pp .Dl nvmecontrol power nvme0 .Pp Get the current power mode. .Sh DYNAMIC LOADING The directories .Pa /lib/nvmecontrol and .Pa /usr/local/lib/nvmecontrol are scanned for any .so files. These files are loaded. The members of the .Va top linker set are added to the top-level commands. The members of the .Va logpage linker set are added to the logpage parsers. .Sh HISTORY The .Nm utility appeared in .Fx 9.2 . .Sh AUTHORS .An -nosplit .Nm was developed by Intel and originally written by .An Jim Harris Aq Mt jimharris@FreeBSD.org . .Pp This man page was written by .An Jim Harris Aq Mt jimharris@FreeBSD.org . Index: head/sbin/nvmecontrol/sanitize.c =================================================================== --- head/sbin/nvmecontrol/sanitize.c (nonexistent) +++ head/sbin/nvmecontrol/sanitize.c (revision 350563) @@ -0,0 +1,222 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (C) 2019 Alexander Motin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +/* Tables for command line parsing */ + +static cmd_fn_t sanitize; + +static struct options { + bool ause; + bool ndas; + bool oipbp; + bool reportonly; + uint8_t owpass; + uint32_t ovrpat; + const char *sanact; + const char *dev; +} opt = { + .ause = false, + .ndas = false, + .oipbp = false, + .reportonly = false, + .owpass = 1, + .ovrpat = 0, + .sanact = NULL, + .dev = NULL, +}; + +static const struct opts sanitize_opts[] = { +#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc } + OPT("ause", 'U', arg_none, opt, ause, + "Allow Unrestricted Sanitize Exit"), + OPT("ndas", 'D', arg_none, opt, ndas, + "No Deallocate After Sanitize"), + OPT("oipbp", 'I', arg_none, opt, oipbp, + "Overwrite Invert Pattern Between Passes"), + OPT("reportonly", 'r', arg_none, opt, reportonly, + "Report previous sanitize status"), + OPT("owpass", 'c', arg_uint8, opt, owpass, + "Overwrite Pass Count"), + OPT("ovrpat", 'p', arg_uint32, opt, ovrpat, + "Overwrite Pattern"), + OPT("sanact", 'a', arg_string, opt, sanact, + "Sanitize Action (block, overwrite, crypto)"), + { NULL, 0, arg_none, NULL, NULL } +}; +#undef OPT + +static const struct args sanitize_args[] = { + { arg_string, &opt.dev, "controller-id" }, + { arg_none, NULL, NULL }, +}; + +static struct cmd sanitize_cmd = { + .name = "sanitize", + .fn = sanitize, + .descr = "Sanitize NVM subsystem", + .ctx_size = sizeof(opt), + .opts = sanitize_opts, + .args = sanitize_args, +}; + +CMD_COMMAND(sanitize_cmd); + +/* End of tables for command line parsing */ + +static void +sanitize(const struct cmd *f, int argc, char *argv[]) +{ + struct nvme_controller_data cd; + struct nvme_pt_command pt; + struct nvme_sanitize_status_page ss; + char *path; + uint32_t nsid; + int sanact = 0, fd, delay = 1; + + if (arg_parse(argc, argv, f)) + return; + + if (opt.sanact == NULL) { + if (!opt.reportonly) { + fprintf(stderr, "Sanitize Action is not specified\n"); + arg_help(argc, argv, f); + } + } else { + if (strcmp(opt.sanact, "exitfailure") == 0) + sanact = 1; + else if (strcmp(opt.sanact, "block") == 0) + sanact = 2; + else if (strcmp(opt.sanact, "overwrite") == 0) + sanact = 3; + else if (strcmp(opt.sanact, "crypto") == 0) + sanact = 4; + else { + fprintf(stderr, "Incorrect Sanitize Action value\n"); + arg_help(argc, argv, f); + } + } + if (opt.owpass == 0 || opt.owpass > 16) { + fprintf(stderr, "Incorrect Overwrite Pass Count value\n"); + arg_help(argc, argv, f); + } + + open_dev(opt.dev, &fd, 1, 1); + get_nsid(fd, &path, &nsid); + if (nsid != 0) { + close(fd); + open_dev(path, &fd, 1, 1); + } + free(path); + + if (opt.reportonly) + goto wait; + + /* Check that controller can execute this command. */ + read_controller_data(fd, &cd); + if (((cd.sanicap >> NVME_CTRLR_DATA_SANICAP_BES_SHIFT) & + NVME_CTRLR_DATA_SANICAP_BES_MASK) == 0 && sanact == 2) + errx(1, "controller does not support Block Erase"); + if (((cd.sanicap >> NVME_CTRLR_DATA_SANICAP_OWS_SHIFT) & + NVME_CTRLR_DATA_SANICAP_OWS_MASK) == 0 && sanact == 3) + errx(1, "controller does not support Overwrite"); + if (((cd.sanicap >> NVME_CTRLR_DATA_SANICAP_CES_SHIFT) & + NVME_CTRLR_DATA_SANICAP_CES_MASK) == 0 && sanact == 4) + errx(1, "controller does not support Crypto Erase"); + + /* + * If controller supports only one namespace, we may sanitize it. + * If there can be more, make user explicit in his commands. + */ + if (nsid != 0 && cd.nn > 1) + errx(1, "can't sanitize one of namespaces, specify controller"); + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_SANITIZE; + pt.cmd.cdw10 = htole32((opt.ndas << 9) | (opt.oipbp << 8) | + ((opt.owpass & 0xf) << 4) | (opt.ause << 3) | sanact); + pt.cmd.cdw11 = htole32(opt.ovrpat); + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "sanitize request failed"); + + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "sanitize request returned error"); + +wait: + read_logpage(fd, NVME_LOG_SANITIZE_STATUS, + NVME_GLOBAL_NAMESPACE_TAG, 0, 0, 0, &ss, sizeof(ss)); + switch ((ss.sstat >> NVME_SS_PAGE_SSTAT_STATUS_SHIFT) & + NVME_SS_PAGE_SSTAT_STATUS_MASK) { + case NVME_SS_PAGE_SSTAT_STATUS_NEVER: + printf("Never sanitized"); + break; + case NVME_SS_PAGE_SSTAT_STATUS_COMPLETED: + printf("Sanitize completed"); + break; + case NVME_SS_PAGE_SSTAT_STATUS_INPROG: + printf("Sanitize in progress: %u%% (%u/65535)\r", + (ss.sprog * 100 + 32768) / 65536, ss.sprog); + fflush(stdout); + if (delay < 16) + delay++; + sleep(delay); + goto wait; + case NVME_SS_PAGE_SSTAT_STATUS_FAILED: + printf("Sanitize failed"); + break; + case NVME_SS_PAGE_SSTAT_STATUS_COMPLETEDWD: + printf("Sanitize completed with deallocation"); + break; + default: + printf("Sanitize status unknown"); + break; + } + if (delay > 1) + printf(" "); + printf("\n"); + + close(fd); + exit(0); +} Property changes on: head/sbin/nvmecontrol/sanitize.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property