#![warn(missing_docs)]
#![deny(rust_2018_idioms)]
#[cfg_attr(any(target_os = "linux", target_os = "freebsd"), path = "unix.rs")]
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(target_os = "macos", path = "macos.rs")]
mod platform;
mod default_out;
mod dmifn;
mod dmiopt;
mod error;
use default_out::default_dump;
use dmiopt::{BiosType, Keyword, Opt};
use enum_iterator::all;
use smbioslib::*;
use std::fmt::Write;
use structopt::StructOpt;
pub fn print_dmidecode_version() {
println!("# {} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let opt: Opt = Opt::from_args();
let smbios_data = if let Some(path) = opt.input.as_ref() {
let mut output = String::new();
writeln!(
&mut output,
"Getting SMBIOS data from {}.",
path.to_string_lossy()
)
.unwrap();
let data = load_smbios_data_from_file(path)?;
(data, output)
} else {
platform::table_load(&opt)?
};
match (
opt.keyword.as_ref(),
opt.output.as_ref(),
opt.bios_types.as_ref(),
opt.handle.as_ref(),
opt.oem_string.as_ref(),
opt.undefined_dump,
opt.list,
opt.json_pretty,
opt.json,
) {
(Some(keyword), None, None, None, None, false, false, false, false) => {
let output = keyword.parse(&smbios_data.0)?;
println!("{}", output);
}
(None, Some(output), None, None, None, false, false, false, false) => {
print_dmidecode_version();
dump_raw(raw_smbios_from_device()?, &output.as_path())?
}
(None, None, Some(bios_types), None, None, false, false, false, false) => {
print_dmidecode_version();
println!("{}", smbios_data.1);
BiosType::parse_and_display(bios_types, &smbios_data.0, opt.quiet);
}
(None, None, None, Some(handle), None, false, false, false, false) => {
print_dmidecode_version();
println!("{}", smbios_data.1);
let found_struct = smbios_data
.0
.find_by_handle(&handle)
.ok_or(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Handle not found: {}", *handle),
))?;
println!("{:#X?}", &found_struct.defined_struct())
}
(None, None, None, None, Some(oem), false, false, false, false) => {
fn invalid_num(s: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid OEM string number {}", s),
)))
}
let oem_val = oem.trim().parse::<u8>();
let mut index = 0;
match oem_val {
Ok(n) => {
if n == 0 {
invalid_num(oem.as_str())?
}
index = n
}
Err(_) => {
if oem != "count" {
invalid_num(oem.as_str())?
}
}
}
match smbios_data.0.first::<SMBiosOemStrings<'_>>() {
Some(v) => {
match v.oem_strings().get_string(index).to_utf8_lossy() {
Some(s) => println!("{}", s),
None => {
if index != 0 {
invalid_num(oem.as_str())?
}
println!("{}", v.count().unwrap());
}
}
}
None => {
if index != 0 {
invalid_num(oem.as_str())?
} else {
println!("0")
}
}
}
}
(None, None, None, None, None, true, false, false, false) => {
print_dmidecode_version();
println!("{}", smbios_data.1);
for undefined_struct in smbios_data.0 {
println!();
println!(
"Handle {:#06X}, DMI type {}, {} bytes",
*undefined_struct.header.handle(),
undefined_struct.header.struct_type(),
undefined_struct.fields.len()
);
print!("\tHeader and Data:");
for item in undefined_struct.fields.iter().enumerate() {
if item.0 % 16 == 0 {
println!();
print!("\t\t");
}
print!("{:02X} ", item.1);
}
println!();
print!("\tStrings:");
for string_item in undefined_struct.strings.iter() {
for item in string_item.iter().chain([0].iter()).enumerate() {
if item.0 % 16 == 0 {
println!();
print!("\t\t");
}
print!("{:02X} ", item.1);
}
println!();
let as_string: String = string_item.iter().map(|x| *x as char).collect();
print!("\t\t\"{}\"", as_string);
}
println!();
}
}
(None, None, None, None, None, false, true, false, false) => {
let keywords = all::<Keyword>().collect::<Vec<_>>();
for keyword in keywords {
let kstr = format!("{}", &keyword);
println!("{}", kstr);
}
}
(None, None, None, None, None, false, false, true, false) => {
if let Ok(output) = serde_json::to_string_pretty(&smbios_data.0) {
println!("{}", output)
}
}
(None, None, None, None, None, false, false, false, true) => {
if let Ok(output) = serde_json::to_string(&smbios_data.0) {
println!("{}", output)
}
}
_ => {
print_dmidecode_version();
let smbios_data = platform::table_load(&opt)?;
print!("{}", smbios_data.1);
default_dump(&smbios_data.0, opt.quiet);
}
}
Ok(())
}