Skip to content

Commit 2b6c318

Browse files
committed
transport: storage: add nvme support
Using the DSP0286, this patch adds support for communicating with an NVMe device with the NVME admin SECURITY SEND/RECEIVE commands for SPDM. `libnvme` is used to interact with the device specified. Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
1 parent 82db8d4 commit 2b6c318

File tree

10 files changed

+766
-25
lines changed

10 files changed

+766
-25
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Install dependencies
2424
run: |
2525
sudo apt-get update; \
26-
sudo apt-get install -y cmake libclang-dev libpci-dev libssl-dev python3-dev gem; \
26+
sudo apt-get install -y cmake libclang-dev libpci-dev libssl-dev python3-dev gem libnvme-dev; \
2727
sudo gem install cbor-diag;
2828
2929
- name: Build libspdm

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ std = [
3535
"inquire",
3636
"page_size",
3737
]
38-
page_size = ["dep:page_size"]
3938

4039
[lib]
4140
name = "libspdm"
@@ -75,7 +74,7 @@ minicbor-derive = { version = "0.15", features = [
7574
], optional = true }
7675
async-std = { version = "1.12", features = ["attributes"], optional = true }
7776
futures = { version = "0.3", optional = true }
78-
nix = { version = "0.29", features = ["user"], optional = true }
77+
nix = { version = "0.29", features = ["user", "fs", "ioctl"], optional = true }
7978
libmctp = { version = "0.2" }
8079
inquire = { version = "0.7.5", optional = true}
8180

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ Note: `dnf` commands are for Fedora, and `apt` is used for Debian/Ubuntu based
5757
distributions.
5858

5959
```shell
60-
$ sudo dnf install cmake clang-libs clang-devel pciutils-devel openssl openssl-devel python3-devel systemd-devel
60+
$ sudo dnf install cmake clang-libs clang-devel pciutils-devel openssl openssl-devel python3-devel systemd-devel libnvme
6161

6262
or
6363

64-
$ sudo apt install cmake clang libclang-dev pciutils libpci-dev openssl libssl-dev libsystemd-dev python3-dev pkg-config
64+
$ sudo apt install cmake clang libclang-dev pciutils libpci-dev openssl libssl-dev libsystemd-dev python3-dev pkg-config libnvme
6565
```
6666

6767
### Ruby
@@ -298,6 +298,14 @@ invoked as below:
298298
```shell
299299
./target/debug/spdm_utils --pcie-vid <VendorID> --pcie-devid <DeviceID> --doe-pci-cfg request get-digests
300300
```
301+
### SPDM for NVMe over the SPDM Storage Transport
302+
303+
SPDM-utils supports the SPDM over storage transport as defined by the DMTF DSP0286.
304+
For example, the following command can be used to interact with an NVMe device.
305+
306+
```shell
307+
$ ./target/debug/spdm_utils --blk-dev-path /dev/nvme0 --nvme --no-session request get-version,get-capabilities
308+
```
301309

302310
## Retrieving Certificates
303311

build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fn main() {
2222
println!("cargo:rustc-link-arg=-Wl,--start-group");
2323

2424
println!("cargo:rustc-link-arg=-lpci");
25+
println!("cargo:rustc-link-arg=-lnvme");
2526

2627
println!("cargo:rustc-link-arg=-lmemlib");
2728
println!("cargo:rustc-link-arg=-lmalloclib");
@@ -41,6 +42,7 @@ fn main() {
4142
println!("cargo:rustc-link-arg=-lspdm_crypt_ext_lib");
4243
println!("cargo:rustc-link-arg=-lspdm_transport_pcidoe_lib");
4344
println!("cargo:rustc-link-arg=-lspdm_transport_mctp_lib");
45+
println!("cargo:rustc-link-arg=-lspdm_transport_storage_lib");
4446

4547
// Link SPDM Test Libraries
4648
let mut builder = if cfg!(feature = "libspdm_tests") {

src/libspdm/spdm.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ pub enum TransportLayer {
277277
Doe,
278278
/// DMTF Management Component Transport Protocol
279279
Mctp,
280+
/// SCSI Security Protocol In/Out commands
281+
Storage,
280282
}
281283

282284
#[cfg(feature = "no_std")]
@@ -506,6 +508,18 @@ pub unsafe fn setup_transport_layer(
506508
)
507509
};
508510
}
511+
TransportLayer::Storage => {
512+
unsafe {
513+
libspdm_register_transport_layer_func(
514+
context,
515+
libspdm_max_spdm_msg_size,
516+
LIBSPDM_STORAGE_TRANSPORT_HEADER_SIZE,
517+
LIBSPDM_STORAGE_TRANSPORT_TAIL_SIZE,
518+
Some(libspdm_transport_storage_encode_message),
519+
Some(libspdm_transport_storage_decode_message),
520+
)
521+
};
522+
}
509523
}
510524

511525
let libspdm_scratch_buffer_size =

src/main.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,20 @@ use std::path::Path;
2222
extern crate log;
2323
use env_logger::Env;
2424
use libspdm::{responder, responder::CertModel, spdm};
25+
use nix::errno::Errno;
2526
use once_cell::sync::Lazy;
2627

2728
pub static SOCKET_PATH: &str = "SPDM-Utils-loopback-socket";
2829

2930
mod cli_helpers;
3031
mod doe_pci_cfg;
3132
mod io_buffers;
33+
mod nvme;
3234
mod qemu_server;
3335
mod request;
3436
mod socket_client;
3537
mod socket_server;
38+
mod storage_standards;
3639
mod tcg_concise_evidence_binding;
3740
mod test_suite;
3841
mod usb_i2c;
@@ -43,6 +46,18 @@ struct Args {
4346
#[command(subcommand)]
4447
command: Commands,
4548

49+
/// Use NVMe commands for the target device
50+
#[arg(short, long, requires_ifs([("true", "blk_dev_path")]))]
51+
nvme: bool,
52+
53+
/// NVME NameSpace Identifier
54+
#[arg(long, default_value_t = 1)]
55+
nsid: u32,
56+
57+
/// Path to the block device
58+
#[arg(long)]
59+
blk_dev_path: Option<String>,
60+
4661
/// Use the Linux PCIe extended configuration backend
4762
/// This is generally run on the Linux host machine
4863
#[arg(short, long)]
@@ -642,6 +657,10 @@ async fn main() -> Result<(), ()> {
642657

643658
let mut count = 0;
644659

660+
cli.nvme.then(|| {
661+
count += 1;
662+
});
663+
645664
cli.doe_pci_cfg.then(|| {
646665
count += 1;
647666
});
@@ -706,12 +725,21 @@ async fn main() -> Result<(), ()> {
706725
}
707726

708727
usb_i2c::register_device(cntx_ptr, cli.usb_i2c_dev, cli.usb_i2c_baud)?;
728+
} else if cli.nvme {
729+
if let Err(e) = nvme::nvme_get_sec_info(&cli.blk_dev_path.clone().unwrap(), cli.nsid) {
730+
if e == Errno::ENOTSUP {
731+
error!("SPDM is not supported by this NVMe device");
732+
}
733+
return Err(());
734+
}
735+
nvme::register_device(cntx_ptr, &cli.blk_dev_path.clone().unwrap(), cli.nsid).unwrap();
709736
} else if cli.qemu_server {
710737
if let Commands::Request { .. } = cli.command {
711738
error!("QEMU Server does not support running an SPDM requester");
712739
return Err(());
713740
}
714741
if let Some(proto) = cli.spdm_transport_protocol {
742+
info!("Using {:?} transport for QEMU", proto);
715743
qemu_server::register_device(cntx_ptr, cli.qemu_port, proto)?;
716744
} else {
717745
qemu_server::register_device(cntx_ptr, cli.qemu_port, spdm::TransportLayer::Doe)?;
@@ -723,13 +751,21 @@ async fn main() -> Result<(), ()> {
723751

724752
unsafe {
725753
if let Some(proto) = cli.spdm_transport_protocol {
754+
info!("Using {:?} transport", proto);
726755
spdm::setup_transport_layer(cntx_ptr, proto, spdm::LIBSPDM_MAX_SPDM_MSG_SIZE)?;
727756
} else if cli.usb_i2c {
728757
spdm::setup_transport_layer(
729758
cntx_ptr,
730759
spdm::TransportLayer::Mctp,
731760
spdm::LIBSPDM_MAX_SPDM_MSG_SIZE,
732761
)?;
762+
} else if cli.nvme {
763+
spdm::setup_transport_layer(
764+
cntx_ptr,
765+
spdm::TransportLayer::Storage,
766+
spdm::LIBSPDM_MAX_SPDM_MSG_SIZE,
767+
)
768+
.unwrap();
733769
} else {
734770
spdm::setup_transport_layer(
735771
cntx_ptr,

0 commit comments

Comments
 (0)