diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59606b8..3d577f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: path: target/debug/framework_tool - name: Build Linux tool (Release) - run: cargo build -p framework_tool --release --features nvidia + run: cargo build -p framework_tool --release --features nvidia,smartmontools - name: Upload Linux App uses: actions/upload-artifact@v6 @@ -143,10 +143,10 @@ jobs: - name: Build Windows tool run: | cargo build -p framework_tool - cargo build -p framework_tool --release --features nvidia + cargo build -p framework_tool --release --features nvidia,smartmontools - name: Check if Windows tool can start - run: cargo run -- --help --release + run: target/release/framework_tool.exe --help # Upload release build so that vcruntime is statically linked - name: Upload Windows App diff --git a/Cargo.lock b/Cargo.lock index abd1418..00ca45a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -435,6 +435,7 @@ dependencies = [ "rusb", "sha1", "sha2", + "smartmon", "spin 0.10.0", "uefi", "uefi-raw", @@ -1202,6 +1203,15 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +[[package]] +name = "smartmon" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1356952f6fc09d25032f6f811a454b7a7c4b9ff24d5505f88b0a4cb4f6847cd" +dependencies = [ + "cc", +] + [[package]] name = "spin" version = "0.9.8" diff --git a/EXAMPLES.md b/EXAMPLES.md index 5e24685..391bc33 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -240,6 +240,28 @@ Touchpad Firmware Version: v0E07 ``` +### Disks (needs `smartmontools` feature) + +Shows model, serial and firmware version of all ATA, NVMe and SCSI disks, +including NVMe drives behind USB bridges, like the Storage Expansion Card. + +``` +> framework_tool --versions +[...] +NVMe Device: /dev/sda (sntasmedia) + Model Number: 250GB Expansion Card + Serial Number: 071C4BE9098A2D57 + Firmware Version: UHFM00.7 +NVMe Device: /dev/sdb (sntasmedia) + Model Number: USB DISK 3.2 + Serial Number: 07001A60B3A20F79 + Firmware Version: UHFM10.0 +NVMe Device: /dev/nvme0 (nvme) + Model Number: WD PC SN8000S SDEPNRG-2T00 + Serial Number: 24434D800023 + Firmware Version: 63100000 +``` + ### Input modules (Laptop 16) Shows firmware version and location of the modules. diff --git a/README.md b/README.md index 3cb74e0..59103dd 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,8 @@ On UEFI and FreeBSD raw port I/O is used - on Linux this can also be used as a f - [x] Retimer - [x] Touchpad (Linux, Windows, FreeBSD, not UEFI) - [x] Touchscreen (Linux, Windows, FreeBSD, not UEFI) + - [x] NVMe SSD (Linux only) + - [x] Storage Expansion Card, NVMe/SATA/SCSI disks (Needs `smartmontools` feature) - [x] Get Expansion Card Firmware (Not on UEFI so far) - [x] HDMI Expansion Card (`--dp-hdmi-info`) - [x] DisplayPort Expansion Card (`--dp-hdmi-info`) @@ -293,6 +295,23 @@ make -C framework_uefi ls -l framework_uefi/build/x86_64-unknown-uefi/boot.efi ``` +#### Optional: smartmontools + +With the `smartmontools` feature, `--versions` uses libsmartmon to show model, +serial and firmware version of all disks, including the Storage Expansion Card +and other NVMe drives behind USB bridges. + +The library is built from source by the +[`smartmon`](https://crates.io/crates/smartmon) crate, only a C++ compiler is +needed. + +Note: smartmontools is licensed GPL-2.0-or-later, so a binary built with this +feature must be distributed under the GPL. + +``` +cargo build --features smartmontools +``` + ## Install local package ``` diff --git a/framework_lib/Cargo.toml b/framework_lib/Cargo.toml index 512d7b3..2e03874 100644 --- a/framework_lib/Cargo.toml +++ b/framework_lib/Cargo.toml @@ -19,6 +19,8 @@ rusb = ["dep:rusb"] hidapi = ["dep:hidapi"] uefi = [ "lazy_static/spin_no_std" ] nvidia = ["dep:nvml-wrapper"] +# Needs libsmartmon (GPL-2.0-or-later), see README +smartmontools = ["dep:smartmon"] [build-dependencies] built = { version = "0.8", features = ["chrono", "git2"] } @@ -39,6 +41,7 @@ hidapi = { version = "2.6.3", features = [ "windows-native" ], optional = true } rusb = { version = "0.9.4", optional = true } guid-create = { version = "0.5.0", default-features = false } zerocopy = { version = "0.8", default-features = false, features = ["derive"] } +smartmon = { version = "0.1", optional = true } [target.'cfg(target_os = "uefi")'.dependencies] uefi = { version = "0.36.1", features = ["alloc", "global_allocator", "panic_handler", "logger"] } diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 9d4d005..49dce62 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -54,7 +54,7 @@ use crate::esrt::{self, ResourceType}; use crate::fw_uefi::enable_page_break; #[cfg(feature = "rusb")] use crate::inputmodule::check_inputmodule_version; -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", not(feature = "smartmontools")))] use crate::nvme; use crate::os_specific; use crate::parade_retimer; @@ -843,7 +843,10 @@ fn print_versions(ec: &CrosEc) { #[cfg(feature = "hidapi")] print_dp_hdmi_details(false); - #[cfg(target_os = "linux")] + #[cfg(feature = "smartmontools")] + print_disk_versions(); + + #[cfg(all(target_os = "linux", not(feature = "smartmontools")))] for i in 0..4 { let device = format!("/dev/nvme{i}"); match nvme::get_nvme_firmware_version(&device) { @@ -863,6 +866,26 @@ fn print_versions(ec: &CrosEc) { print_nvidia_details(); } +#[cfg(feature = "smartmontools")] +fn print_disk_versions() { + match smartmon::scan_disks() { + Ok(disks) => { + for disk in disks { + println!( + "{} Device: {} ({})", + disk.protocol, disk.name, disk.dev_type + ); + println!(" Model Number: {}", disk.model); + if !disk.serial.is_empty() { + println!(" Serial Number: {}", disk.serial); + } + println!(" Firmware Version: {}", disk.firmware); + } + } + Err(err) => error!("{}", err), + } +} + #[cfg(feature = "nvidia")] fn probably_has_nvidia() -> bool { match smbios::get_platform().and_then(Platform::which_family) { diff --git a/framework_tool/Cargo.toml b/framework_tool/Cargo.toml index a7f4f91..d4fc4ea 100644 --- a/framework_tool/Cargo.toml +++ b/framework_tool/Cargo.toml @@ -17,6 +17,7 @@ path = "src/main.rs" default = [ ] readonly = [ "framework_lib/readonly" ] nvidia = [ "framework_lib/nvidia" ] +smartmontools = [ "framework_lib/smartmontools" ] [dependencies.framework_lib] path = "../framework_lib"