use crate::error::*;
use dmidecode::{Structure, processor::ProcessorType};
use serde::Serialize;
use std::fs;
#[derive(Serialize, Debug)]
pub struct DmiInformation {
pub system_information: SystemInformation,
pub chassis_information: ChassisInformation,
pub cpu_information: CpuInformation,
}
#[derive(Serialize, Debug)]
pub struct SystemInformation {
pub hostname: String,
pub vendor: String,
pub model: String,
pub uuid: String,
pub serial: String,
pub is_virtual: bool,
}
#[derive(Serialize, Debug)]
pub struct ChassisInformation {
pub chassis_type: String,
pub asset: String,
pub chassis_serial: String,
}
#[derive(Serialize, Debug)]
pub struct CpuInformation {
pub version: String,
pub core_count: String,
pub cores_enabled: String,
pub thread_count: String,
pub max_speed: String,
pub voltage: String,
pub status: String,
}
pub fn construct_dmi_information() -> NazaraResult<DmiInformation> {
status!("Collecting DMI Information...");
let hostname = fs::read_to_string("/proc/sys/kernel/hostname")
.map(|s| s.trim_end().to_string())
.unwrap_or_else(|_| "unknown".to_string());
let buf = fs::read("/sys/firmware/dmi/tables/smbios_entry_point")?;
let dmi = fs::read("/sys/firmware/dmi/tables/DMI")?;
let entry = dmidecode::EntryPoint::search(&buf)?;
let mut system_information = None;
let mut chassis_information = None;
let mut cpu_information = None;
for table in entry.structures(&dmi) {
let Ok(t) = table else {
warn!("DMI tables contain malformed structure: {table:?}");
continue;
};
match t {
Structure::System(x) => {
system_information = Some(SystemInformation {
hostname: hostname.to_owned(),
vendor: x.manufacturer.to_owned(),
model: x.product.to_owned(),
uuid: x.uuid.map_or_else(String::new, |u| u.to_string()),
serial: x.serial.to_owned(),
is_virtual: false,
})
}
Structure::Enclosure(x) => {
chassis_information = Some(ChassisInformation {
chassis_type: x.enclosure_type.to_string(),
asset: x.asset_tag_number.to_owned(),
chassis_serial: x.serial_number.to_owned(),
})
}
Structure::Processor(x) => {
if x.processor_type != ProcessorType::CentralProcessor {
continue;
}
cpu_information = Some(CpuInformation {
version: String::new(),
core_count: x.core_count.unwrap_or_default().to_string(),
cores_enabled: x.core_enabled.unwrap_or_default().to_string(),
thread_count: x.thread_count.unwrap_or_default().to_string(),
max_speed: x.max_speed.to_string(),
voltage: x.voltage.to_string(),
status: format!("{:?}", x.status),
});
}
_ => continue,
}
}
Ok(DmiInformation {
system_information: system_information.ok_or(NazaraError::UnableToCollectData(
"Couldn't collect system information".to_owned(),
))?,
chassis_information: chassis_information.ok_or(NazaraError::UnableToCollectData(
"Couldn't collect chassis information".to_owned(),
))?,
cpu_information: cpu_information.ok_or(NazaraError::UnableToCollectData(
"Couldn't collect CPU information".to_owned(),
))?,
})
}