use crate::{SMBiosStruct, UndefinedStruct};
use std::fmt;
use std::ops::Deref;
pub struct SMBiosCacheInformation<'a> {
parts: &'a UndefinedStruct,
}
impl<'a> SMBiosStruct<'a> for SMBiosCacheInformation<'a> {
const STRUCT_TYPE: u8 = 7u8;
fn new(parts: &'a UndefinedStruct) -> Self {
Self { parts }
}
fn parts(&self) -> &'a UndefinedStruct {
self.parts
}
}
impl<'a> SMBiosCacheInformation<'a> {
pub fn socket_designation(&self) -> Option<String> {
self.parts.get_field_string(0x04)
}
pub fn cache_configuration(&self) -> Option<CacheConfiguaration> {
self.parts
.get_field_word(0x05)
.map(|raw| CacheConfiguaration::from(raw))
}
pub fn maximum_cache_size(&self) -> Option<u16> {
self.parts.get_field_word(0x07)
}
pub fn installed_size(&self) -> Option<u16> {
self.parts.get_field_word(0x09)
}
pub fn supported_sram_type(&self) -> Option<SramTypes> {
self.parts
.get_field_word(0x0B)
.map(|raw| SramTypes::from(raw))
}
pub fn current_sram_type(&self) -> Option<SramTypes> {
self.parts
.get_field_word(0x0D)
.map(|raw| SramTypes::from(raw))
}
pub fn cache_speed(&self) -> Option<u8> {
self.parts.get_field_byte(0x0F)
}
pub fn error_correction_type(&self) -> Option<ErrorCorrectionTypeData> {
self.parts
.get_field_byte(0x10)
.map(|raw| ErrorCorrectionTypeData::from(raw))
}
pub fn system_cache_type(&self) -> Option<SystemCacheTypeData> {
self.parts
.get_field_byte(0x11)
.map(|raw| SystemCacheTypeData::from(raw))
}
pub fn associativity(&self) -> Option<CacheAssociativityData> {
self.parts
.get_field_byte(0x12)
.map(|raw| CacheAssociativityData::from(raw))
}
pub fn maximum_cache_size_2(&self) -> Option<u32> {
self.parts.get_field_dword(0x13)
}
pub fn installed_cache_size_2(&self) -> Option<u32> {
self.parts.get_field_dword(0x17)
}
}
impl fmt::Debug for SMBiosCacheInformation<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SMBiosCacheInformation<'_>>())
.field("header", &self.parts.header)
.field("socket_designation", &self.socket_designation())
.field("cache_configuration", &self.cache_configuration())
.field("maximum_cache_size", &self.maximum_cache_size())
.field("installed_size", &self.installed_size())
.field("supported_sram_type", &self.supported_sram_type())
.field("current_sram_type", &self.current_sram_type())
.field("cache_speed", &self.cache_speed())
.field("error_correction_type", &self.error_correction_type())
.field("system_cache_type", &self.system_cache_type())
.field("associativity", &self.associativity())
.field("maximum_cache_size_2", &self.maximum_cache_size_2())
.field("installed_cache_size_2", &self.installed_cache_size_2())
.finish()
}
}
pub struct CacheAssociativityData {
pub raw: u8,
pub value: CacheAssociativity,
}
impl fmt::Debug for CacheAssociativityData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<CacheAssociativityData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Deref for CacheAssociativityData {
type Target = CacheAssociativity;
fn deref(&self) -> &Self::Target {
&self.value
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum CacheAssociativity {
Other = 0x01,
Unknown = 0x02,
DirectMapped = 0x03,
SetAssociative2Way = 0x04,
SetAssociative4Way = 0x05,
FullyAssociative = 0x06,
SetAssociative8Way = 0x07,
SetAssociative16Way = 0x08,
SetAssociative12Way = 0x09,
SetAssociative24Way = 0x0A,
SetAssociative32Way = 0x0B,
SetAssociative48Way = 0x0C,
SetAssociative64Way = 0x0D,
SetAssociative20Way = 0x0E,
None,
}
impl From<u8> for CacheAssociativityData {
fn from(raw: u8) -> Self {
CacheAssociativityData {
value: match raw {
0x01 => CacheAssociativity::Other,
0x02 => CacheAssociativity::Unknown,
0x03 => CacheAssociativity::DirectMapped,
0x04 => CacheAssociativity::SetAssociative2Way,
0x05 => CacheAssociativity::SetAssociative4Way,
0x06 => CacheAssociativity::FullyAssociative,
0x07 => CacheAssociativity::SetAssociative8Way,
0x08 => CacheAssociativity::SetAssociative16Way,
0x09 => CacheAssociativity::SetAssociative12Way,
0x0A => CacheAssociativity::SetAssociative24Way,
0x0B => CacheAssociativity::SetAssociative32Way,
0x0C => CacheAssociativity::SetAssociative48Way,
0x0D => CacheAssociativity::SetAssociative64Way,
0x0E => CacheAssociativity::SetAssociative20Way,
_ => CacheAssociativity::None,
},
raw,
}
}
}
pub struct SystemCacheTypeData {
pub raw: u8,
pub value: SystemCacheType,
}
impl fmt::Debug for SystemCacheTypeData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SystemCacheTypeData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Deref for SystemCacheTypeData {
type Target = SystemCacheType;
fn deref(&self) -> &Self::Target {
&self.value
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum SystemCacheType {
Other,
Unknown,
Instruction,
Data,
Unified,
None,
}
impl From<u8> for SystemCacheTypeData {
fn from(raw: u8) -> Self {
SystemCacheTypeData {
value: match raw {
0x01 => SystemCacheType::Other,
0x02 => SystemCacheType::Unknown,
0x03 => SystemCacheType::Instruction,
0x04 => SystemCacheType::Data,
0x05 => SystemCacheType::Unified,
_ => SystemCacheType::None,
},
raw,
}
}
}
pub struct ErrorCorrectionTypeData {
pub raw: u8,
pub value: ErrorCorrectionType,
}
impl fmt::Debug for ErrorCorrectionTypeData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<ErrorCorrectionTypeData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Deref for ErrorCorrectionTypeData {
type Target = ErrorCorrectionType;
fn deref(&self) -> &Self::Target {
&self.value
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum ErrorCorrectionType {
Other = 0x01,
Unknown = 0x02,
NoCorrection = 0x03,
Parity = 0x04,
SingleBitEcc = 0x05,
MultiBitEcc = 0x06,
None,
}
impl From<u8> for ErrorCorrectionTypeData {
fn from(raw: u8) -> Self {
ErrorCorrectionTypeData {
value: match raw {
0x01 => ErrorCorrectionType::Other,
0x02 => ErrorCorrectionType::Unknown,
0x03 => ErrorCorrectionType::NoCorrection,
0x04 => ErrorCorrectionType::Parity,
0x05 => ErrorCorrectionType::SingleBitEcc,
0x06 => ErrorCorrectionType::MultiBitEcc,
_ => ErrorCorrectionType::None,
},
raw,
}
}
}
#[derive(PartialEq, Eq)]
pub struct SramTypes {
pub raw: u16,
}
impl Deref for SramTypes {
type Target = u16;
fn deref(&self) -> &Self::Target {
&self.raw
}
}
impl From<u16> for SramTypes {
fn from(raw: u16) -> Self {
SramTypes { raw }
}
}
impl SramTypes {
pub fn other(&self) -> bool {
self.raw & 0x0001 == 0x0001
}
pub fn unknown(&self) -> bool {
self.raw & 0x0002 == 0x0002
}
pub fn non_burst(&self) -> bool {
self.raw & 0x0004 == 0x0004
}
pub fn burst(&self) -> bool {
self.raw & 0x0008 == 0x0008
}
pub fn pipeline_burst(&self) -> bool {
self.raw & 0x0010 == 0x0010
}
pub fn synchronous(&self) -> bool {
self.raw & 0x0020 == 0x0020
}
pub fn asynchronous(&self) -> bool {
self.raw & 0x0040 == 0x0040
}
}
impl fmt::Debug for SramTypes {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SramTypes>())
.field("raw", &self.raw)
.field("other", &self.other())
.field("unknown", &self.unknown())
.field("non_burst", &self.non_burst())
.field("burst", &self.burst())
.field("pipeline_burst", &self.pipeline_burst())
.field("synchronous", &self.synchronous())
.field("asynchronous", &self.asynchronous())
.finish()
}
}
#[derive(PartialEq, Eq)]
pub struct CacheConfiguaration {
pub raw: u16,
}
impl Deref for CacheConfiguaration {
type Target = u16;
fn deref(&self) -> &Self::Target {
&self.raw
}
}
impl From<u16> for CacheConfiguaration {
fn from(raw: u16) -> Self {
CacheConfiguaration { raw }
}
}
impl CacheConfiguaration {
pub fn cache_level(&self) -> u8 {
(self.raw & 0x0007) as u8 + 1
}
pub fn cache_socketed(&self) -> bool {
self.raw & 0x0008 == 0x0008
}
pub fn location(&self) -> CacheLocation {
match self.raw & 0x0060 {
0x0000 => CacheLocation::Internal,
0x0020 => CacheLocation::External,
0x0040 => CacheLocation::Reserved,
0x0060 => CacheLocation::Unknown,
_ => panic!("Impossible condition"),
}
}
pub fn enabled_at_boot(&self) -> bool {
self.raw & 0x0080 == 0x0080
}
pub fn operational_mode(&self) -> CacheOperationalMode {
match self.raw & 0x0300 {
0x0000 => CacheOperationalMode::WriteThrough,
0x0100 => CacheOperationalMode::WriteBack,
0x0200 => CacheOperationalMode::VariesWithMemoryAddress,
0x0300 => CacheOperationalMode::Unknown,
_ => panic!("Impossible condition"),
}
}
}
impl fmt::Debug for CacheConfiguaration {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<CacheConfiguaration>())
.field("raw", &self.raw)
.field("cache_level", &self.cache_level())
.field("cache_socketed", &self.cache_socketed())
.field("location", &self.location())
.field("enabled_at_boot", &self.enabled_at_boot())
.field("operational_mode", &self.operational_mode())
.finish()
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum CacheLocation {
Internal,
External,
Reserved,
Unknown,
}
#[derive(Debug, PartialEq, Eq)]
pub enum CacheOperationalMode {
WriteThrough = 0x00,
WriteBack = 0x01,
VariesWithMemoryAddress = 0x02,
Unknown = 0x03,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unit_test() {
let struct_type7 = vec![
0x07, 0x1B, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x10, 0x00, 0x10,
0x00, 0x01, 0x06, 0x05, 0x07, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x4C,
0x31, 0x20, 0x2D, 0x20, 0x43, 0x61, 0x63, 0x68, 0x65, 0x00, 0x00,
];
let parts = UndefinedStruct::new(&struct_type7);
let test_struct = SMBiosCacheInformation::new(&parts);
let cache_configuration = test_struct.cache_configuration().unwrap();
assert_eq!(cache_configuration.cache_level(), 1);
assert!(!cache_configuration.cache_socketed());
assert_eq!(cache_configuration.location(), CacheLocation::Internal);
assert!(cache_configuration.enabled_at_boot());
assert_eq!(
cache_configuration.operational_mode(),
CacheOperationalMode::WriteBack
);
println!("{:?}", test_struct);
}
}