use crate::core::{Handle, UndefinedStruct};
use crate::SMBiosStruct;
use std::fmt;
use std::ops::Deref;
pub struct SMBiosMemoryDevice<'a> {
parts: &'a UndefinedStruct,
}
impl<'a> SMBiosStruct<'a> for SMBiosMemoryDevice<'a> {
const STRUCT_TYPE: u8 = 17u8;
fn new(parts: &'a UndefinedStruct) -> Self {
Self { parts }
}
fn parts(&self) -> &'a UndefinedStruct {
self.parts
}
}
impl<'a> SMBiosMemoryDevice<'a> {
pub fn physical_memory_array_handle(&self) -> Option<Handle> {
self.parts.get_field_handle(0x04)
}
pub fn memory_error_information_handle(&self) -> Option<Handle> {
self.parts.get_field_handle(0x06)
}
pub fn total_width(&self) -> Option<u16> {
self.parts.get_field_word(0x08)
}
pub fn data_width(&self) -> Option<u16> {
self.parts.get_field_word(0x0A)
}
pub fn size(&self) -> Option<MemorySize> {
self.parts
.get_field_word(0x0C)
.map(|raw| MemorySize::from(raw))
}
pub fn form_factor(&self) -> Option<MemoryFormFactorData> {
self.parts
.get_field_byte(0x0E)
.map(|raw| MemoryFormFactorData::from(raw))
}
pub fn device_set(&self) -> Option<u8> {
self.parts.get_field_byte(0x0F)
}
pub fn device_locator(&self) -> Option<String> {
self.parts.get_field_string(0x10)
}
pub fn bank_locator(&self) -> Option<String> {
self.parts.get_field_string(0x11)
}
pub fn memory_type(&self) -> Option<MemoryDeviceTypeData> {
self.parts
.get_field_byte(0x12)
.map(|raw| MemoryDeviceTypeData::from(raw))
}
pub fn type_detail(&self) -> Option<MemoryTypeDetails> {
self.parts
.get_field_word(0x13)
.map(|raw| MemoryTypeDetails::from(raw))
}
pub fn speed(&self) -> Option<MemorySpeed> {
self.parts
.get_field_word(0x15)
.map(|raw| MemorySpeed::from(raw))
}
pub fn manufacturer(&self) -> Option<String> {
self.parts.get_field_string(0x17)
}
pub fn serial_number(&self) -> Option<String> {
self.parts.get_field_string(0x18)
}
pub fn asset_tag(&self) -> Option<String> {
self.parts.get_field_string(0x19)
}
pub fn part_number(&self) -> Option<String> {
self.parts.get_field_string(0x1A)
}
pub fn attributes(&self) -> Option<u8> {
self.parts.get_field_byte(0x1B)
}
pub fn extended_size(&self) -> Option<u32> {
self.parts.get_field_dword(0x1C)
}
pub fn configured_memory_speed(&self) -> Option<MemorySpeed> {
self.parts
.get_field_word(0x20)
.map(|raw| MemorySpeed::from(raw))
}
pub fn minimum_voltage(&self) -> Option<u16> {
self.parts.get_field_word(0x22)
}
pub fn maximum_voltage(&self) -> Option<u16> {
self.parts.get_field_word(0x24)
}
pub fn configured_voltage(&self) -> Option<u16> {
self.parts.get_field_word(0x26)
}
pub fn memory_technology(&self) -> Option<MemoryDeviceTechnologyData> {
self.parts
.get_field_byte(0x28)
.map(|raw| MemoryDeviceTechnologyData::from(raw))
}
pub fn memory_operating_mode_capability(&self) -> Option<MemoryOperatingModeCapabilities> {
self.parts
.get_field_word(0x29)
.map(|raw| MemoryOperatingModeCapabilities::from(raw))
}
pub fn firmware_version(&self) -> Option<String> {
self.parts.get_field_string(0x2B)
}
pub fn module_manufacturer_id(&self) -> Option<u16> {
self.parts.get_field_word(0x2C)
}
pub fn module_product_id(&self) -> Option<u16> {
self.parts.get_field_word(0x2E)
}
pub fn memory_subsystem_controller_manufacturer_id(&self) -> Option<u16> {
self.parts.get_field_word(0x30)
}
pub fn memory_subsystem_controller_product_id(&self) -> Option<u16> {
self.parts.get_field_word(0x32)
}
pub fn non_volatile_size(&self) -> Option<MemoryIndicatedSize> {
self.parts
.get_field_qword(0x34)
.map(|raw| MemoryIndicatedSize::from(raw))
}
pub fn volatile_size(&self) -> Option<MemoryIndicatedSize> {
self.parts
.get_field_qword(0x3C)
.map(|raw| MemoryIndicatedSize::from(raw))
}
pub fn cache_size(&self) -> Option<MemoryIndicatedSize> {
self.parts
.get_field_qword(0x44)
.map(|raw| MemoryIndicatedSize::from(raw))
}
pub fn logical_size(&self) -> Option<MemoryIndicatedSize> {
self.parts
.get_field_qword(0x4C)
.map(|raw| MemoryIndicatedSize::from(raw))
}
pub fn extended_speed(&self) -> Option<u32> {
self.parts.get_field_dword(0x54)
}
pub fn extended_configured_memory_speed(&self) -> Option<u32> {
self.parts.get_field_dword(0x58)
}
}
impl fmt::Debug for SMBiosMemoryDevice<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SMBiosMemoryDevice<'_>>())
.field("header", &self.parts.header)
.field(
"physical_memory_array_handle",
&self.physical_memory_array_handle(),
)
.field(
"memory_error_information_handle",
&self.memory_error_information_handle(),
)
.field("total_width", &self.total_width())
.field("data_width", &self.data_width())
.field("size", &self.size())
.field("form_factor", &self.form_factor())
.field("device_set", &self.device_set())
.field("device_locator", &self.device_locator())
.field("bank_locator", &self.bank_locator())
.field("memory_type", &self.memory_type())
.field("type_detail", &self.type_detail())
.field("speed", &self.speed())
.field("manufacturer", &self.manufacturer())
.field("serial_number", &self.serial_number())
.field("asset_tag", &self.asset_tag())
.field("part_number", &self.part_number())
.field("attributes", &self.attributes())
.field("extended_size", &self.extended_size())
.field("configured_memory_speed", &self.configured_memory_speed())
.field("minimum_voltage", &self.minimum_voltage())
.field("maximum_voltage", &self.maximum_voltage())
.field("configured_voltage", &self.configured_voltage())
.field("memory_technology", &self.memory_technology())
.field(
"memory_operating_mode_capability",
&self.memory_operating_mode_capability(),
)
.field("firmware_version", &self.firmware_version())
.field("module_manufacturer_id", &self.module_manufacturer_id())
.field("module_product_id", &self.module_product_id())
.field(
"memory_subsystem_controller_manufacturer_id",
&self.memory_subsystem_controller_manufacturer_id(),
)
.field(
"memory_subsystem_controller_product_id",
&self.memory_subsystem_controller_product_id(),
)
.field("non_volatile_size", &self.non_volatile_size())
.field("volatile_size", &self.volatile_size())
.field("cache_size", &self.cache_size())
.field("logical_size", &self.logical_size())
.field("extended_speed", &self.extended_speed())
.field(
"extended_configured_memory_speed",
&self.extended_configured_memory_speed(),
)
.finish()
}
}
#[derive(PartialEq, Eq)]
pub struct MemoryDeviceTypeData {
pub raw: u8,
pub value: MemoryDeviceType,
}
impl fmt::Debug for MemoryDeviceTypeData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<MemoryDeviceTypeData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Deref for MemoryDeviceTypeData {
type Target = MemoryDeviceType;
fn deref(&self) -> &Self::Target {
&self.value
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum MemoryDeviceType {
Other,
Unknown,
Dram,
Edram,
Vram,
Sram,
Ram,
Rom,
Flash,
Eeprom,
Feprom,
Eprom,
Cdram,
ThreeDram,
Sdram,
Sgram,
Rdram,
Ddr,
Ddr2,
Ddr2Fbdimm,
Ddr3,
Fbd2,
Ddr4,
Lpddr,
Lpddr2,
Lpddr3,
Lpddr4,
LogicalNonVolatileDevice,
Hbm,
Hbm2,
Ddr5,
Lpddr5,
None,
}
impl From<u8> for MemoryDeviceTypeData {
fn from(raw: u8) -> Self {
MemoryDeviceTypeData {
value: match raw {
0x01 => MemoryDeviceType::Other,
0x02 => MemoryDeviceType::Unknown,
0x03 => MemoryDeviceType::Dram,
0x04 => MemoryDeviceType::Edram,
0x05 => MemoryDeviceType::Vram,
0x06 => MemoryDeviceType::Sram,
0x07 => MemoryDeviceType::Ram,
0x08 => MemoryDeviceType::Rom,
0x09 => MemoryDeviceType::Flash,
0x0A => MemoryDeviceType::Eeprom,
0x0B => MemoryDeviceType::Feprom,
0x0C => MemoryDeviceType::Eprom,
0x0D => MemoryDeviceType::Cdram,
0x0E => MemoryDeviceType::ThreeDram,
0x0F => MemoryDeviceType::Sdram,
0x10 => MemoryDeviceType::Sgram,
0x11 => MemoryDeviceType::Rdram,
0x12 => MemoryDeviceType::Ddr,
0x13 => MemoryDeviceType::Ddr2,
0x14 => MemoryDeviceType::Ddr2Fbdimm,
0x18 => MemoryDeviceType::Ddr3,
0x19 => MemoryDeviceType::Fbd2,
0x1A => MemoryDeviceType::Ddr4,
0x1B => MemoryDeviceType::Lpddr,
0x1C => MemoryDeviceType::Lpddr2,
0x1D => MemoryDeviceType::Lpddr3,
0x1E => MemoryDeviceType::Lpddr4,
0x1F => MemoryDeviceType::LogicalNonVolatileDevice,
0x20 => MemoryDeviceType::Hbm,
0x21 => MemoryDeviceType::Hbm2,
0x22 => MemoryDeviceType::Ddr5,
0x23 => MemoryDeviceType::Lpddr5,
_ => MemoryDeviceType::None,
},
raw,
}
}
}
pub struct MemoryFormFactorData {
pub raw: u8,
pub value: MemoryFormFactor,
}
impl fmt::Debug for MemoryFormFactorData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<MemoryFormFactorData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Deref for MemoryFormFactorData {
type Target = MemoryFormFactor;
fn deref(&self) -> &Self::Target {
&self.value
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum MemoryFormFactor {
Other,
Unknown,
Simm,
Sip,
Chip,
Dip,
Zip,
ProprietaryCard,
Dimm,
Tsop,
RowOfChips,
Rimm,
Sodimm,
Srimm,
Fbdimm,
Die,
None,
}
impl From<u8> for MemoryFormFactorData {
fn from(raw: u8) -> Self {
MemoryFormFactorData {
value: match raw {
0x01 => MemoryFormFactor::Other,
0x02 => MemoryFormFactor::Unknown,
0x03 => MemoryFormFactor::Simm,
0x04 => MemoryFormFactor::Sip,
0x05 => MemoryFormFactor::Chip,
0x06 => MemoryFormFactor::Dip,
0x07 => MemoryFormFactor::Zip,
0x08 => MemoryFormFactor::ProprietaryCard,
0x09 => MemoryFormFactor::Dimm,
0x0A => MemoryFormFactor::Tsop,
0x0B => MemoryFormFactor::RowOfChips,
0x0C => MemoryFormFactor::Rimm,
0x0D => MemoryFormFactor::Sodimm,
0x0E => MemoryFormFactor::Srimm,
0x0F => MemoryFormFactor::Fbdimm,
0x10 => MemoryFormFactor::Die,
_ => MemoryFormFactor::None,
},
raw,
}
}
}
#[derive(PartialEq, Eq)]
pub struct MemoryTypeDetails {
pub raw: u16,
}
impl Deref for MemoryTypeDetails {
type Target = u16;
fn deref(&self) -> &Self::Target {
&self.raw
}
}
impl From<u16> for MemoryTypeDetails {
fn from(raw: u16) -> Self {
MemoryTypeDetails { raw }
}
}
impl MemoryTypeDetails {
pub fn other(&self) -> bool {
self.raw & 0x0002 == 0x0002
}
pub fn unknown(&self) -> bool {
self.raw & 0x0004 == 0x0004
}
pub fn fast_paged(&self) -> bool {
self.raw & 0x0008 == 0x0008
}
pub fn static_column(&self) -> bool {
self.raw & 0x0010 == 0x0010
}
pub fn pseudo_static(&self) -> bool {
self.raw & 0x0020 == 0x0020
}
pub fn ram_bus(&self) -> bool {
self.raw & 0x0040 == 0x0040
}
pub fn synchronous(&self) -> bool {
self.raw & 0x0080 == 0x0080
}
pub fn cmos(&self) -> bool {
self.raw & 0x0100 == 0x0100
}
pub fn edo(&self) -> bool {
self.raw & 0x0200 == 0x0200
}
pub fn window_dram(&self) -> bool {
self.raw & 0x0400 == 0x0400
}
pub fn cache_dram(&self) -> bool {
self.raw & 0x0800 == 0x0800
}
pub fn non_volatile(&self) -> bool {
self.raw & 0x1000 == 0x1000
}
pub fn registered(&self) -> bool {
self.raw & 0x2000 == 0x2000
}
pub fn unbuffered(&self) -> bool {
self.raw & 0x4000 == 0x4000
}
pub fn lrdimm(&self) -> bool {
self.raw & 0x8000 == 0x8000
}
}
impl fmt::Debug for MemoryTypeDetails {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<MemoryTypeDetails>())
.field("raw", &self.raw)
.field("other", &self.other())
.field("unknown", &self.unknown())
.field("fast_paged", &self.fast_paged())
.field("static_column", &self.static_column())
.field("pseudo_static", &self.pseudo_static())
.field("ram_bus", &self.ram_bus())
.field("synchronous", &self.synchronous())
.field("cmos", &self.cmos())
.field("edo", &self.edo())
.field("window_dram", &self.window_dram())
.field("cache_dram", &self.cache_dram())
.field("non_volatile", &self.non_volatile())
.field("registered", &self.registered())
.field("unbuffered", &self.unbuffered())
.field("lrdimm", &self.lrdimm())
.finish()
}
}
pub struct MemoryDeviceTechnologyData {
pub raw: u8,
pub value: MemoryDeviceTechnology,
}
impl fmt::Debug for MemoryDeviceTechnologyData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<MemoryDeviceTechnologyData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Deref for MemoryDeviceTechnologyData {
type Target = MemoryDeviceTechnology;
fn deref(&self) -> &Self::Target {
&self.value
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum MemoryDeviceTechnology {
Other,
Unknown,
Dram,
NvdimmN,
NvdimmF,
NvdimmP,
IntelOptaneDcPersistentMemory,
None,
}
impl From<u8> for MemoryDeviceTechnologyData {
fn from(raw: u8) -> Self {
MemoryDeviceTechnologyData {
value: match raw {
0x01 => MemoryDeviceTechnology::Other,
0x02 => MemoryDeviceTechnology::Unknown,
0x03 => MemoryDeviceTechnology::Dram,
0x04 => MemoryDeviceTechnology::NvdimmN,
0x05 => MemoryDeviceTechnology::NvdimmF,
0x06 => MemoryDeviceTechnology::NvdimmP,
0x07 => MemoryDeviceTechnology::IntelOptaneDcPersistentMemory,
_ => MemoryDeviceTechnology::None,
},
raw,
}
}
}
#[derive(PartialEq, Eq)]
pub struct MemoryOperatingModeCapabilities {
pub raw: u16,
}
impl Deref for MemoryOperatingModeCapabilities {
type Target = u16;
fn deref(&self) -> &Self::Target {
&self.raw
}
}
impl From<u16> for MemoryOperatingModeCapabilities {
fn from(raw: u16) -> Self {
MemoryOperatingModeCapabilities { raw }
}
}
impl MemoryOperatingModeCapabilities {
pub fn other(&self) -> bool {
self.raw & 0x0002 == 0x0002
}
pub fn unknown(&self) -> bool {
self.raw & 0x0004 == 0x0004
}
pub fn volatile_memory(&self) -> bool {
self.raw & 0x0008 == 0x0008
}
pub fn byte_accessible_persistent_memory(&self) -> bool {
self.raw & 0x0010 == 0x0010
}
pub fn block_accessible_persistent_memory(&self) -> bool {
self.raw & 0x0020 == 0x0020
}
}
impl fmt::Debug for MemoryOperatingModeCapabilities {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<MemoryOperatingModeCapabilities>())
.field("raw", &self.raw)
.field("other", &self.other())
.field("unknown", &self.unknown())
.field("volatile_memory", &self.volatile_memory())
.field(
"byte_accessible_persistent_memory",
&self.byte_accessible_persistent_memory(),
)
.field(
"block_accessible_persistent_memory",
&self.block_accessible_persistent_memory(),
)
.finish()
}
}
#[derive(Debug)]
pub enum MemorySpeed {
Unknown,
SeeExtendedSpeed,
MTs(u16),
}
impl From<u16> for MemorySpeed {
fn from(raw: u16) -> Self {
match raw {
0 => MemorySpeed::Unknown,
0xFFFF => MemorySpeed::SeeExtendedSpeed,
_ => MemorySpeed::MTs(raw),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum MemorySize {
NotInstalled,
Unknown,
SeeExtendedSize,
Kilobytes(u16),
Megabytes(u16),
}
impl From<u16> for MemorySize {
fn from(raw: u16) -> Self {
match raw {
0 => MemorySize::NotInstalled,
0xFFFF => MemorySize::Unknown,
0x7FFF => MemorySize::SeeExtendedSize,
_ => match raw & 0x8000 {
0x8000 => MemorySize::Kilobytes(raw & 0x7FFF),
_ => MemorySize::Megabytes(raw),
},
}
}
}
#[derive(Debug)]
pub enum MemoryIndicatedSize {
Unknown,
Bytes(u64),
}
impl From<u64> for MemoryIndicatedSize {
fn from(raw: u64) -> Self {
match raw {
0xFFFFFFFFFFFFFFFF => MemoryIndicatedSize::Unknown,
_ => MemoryIndicatedSize::Bytes(raw),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let struct_type17 = vec![
0x11, 0x28, 0x40, 0x00, 0x3E, 0x00, 0xFE, 0xFF, 0x48, 0x00, 0x40, 0x00, 0x00, 0x20,
0x09, 0x00, 0x01, 0x02, 0x1A, 0x80, 0x00, 0x6A, 0x0A, 0x03, 0x04, 0x05, 0x06, 0x01,
0x00, 0x00, 0x00, 0x00, 0x6A, 0x0A, 0xB0, 0x04, 0xB0, 0x04, 0xB0, 0x04, 0x43, 0x50,
0x55, 0x31, 0x5F, 0x44, 0x49, 0x4D, 0x4D, 0x5F, 0x31, 0x00, 0x4E, 0x4F, 0x44, 0x45,
0x20, 0x31, 0x00, 0x48, 0x79, 0x6E, 0x69, 0x78, 0x00, 0x37, 0x32, 0x30, 0x39, 0x31,
0x30, 0x30, 0x33, 0x00, 0x20, 0x00, 0x48, 0x4D, 0x41, 0x38, 0x31, 0x47, 0x52, 0x37,
0x41, 0x46, 0x52, 0x38, 0x4E, 0x2D, 0x56, 0x4B, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00,
];
let parts = UndefinedStruct::new(&struct_type17);
let test_struct = SMBiosMemoryDevice::new(&parts);
assert_eq!(test_struct.physical_memory_array_handle(), Some(Handle(62)));
assert_eq!(
test_struct.memory_error_information_handle(),
Some(Handle(65534))
);
assert_eq!(test_struct.total_width(), Some(72));
assert_eq!(test_struct.data_width(), Some(64));
match test_struct.size().unwrap() {
MemorySize::Megabytes(size) => assert_eq!(size, 8192),
_ => panic!("incorrect size"),
}
assert_eq!(*test_struct.form_factor().unwrap(), MemoryFormFactor::Dimm);
assert_eq!(test_struct.device_set(), Some(0));
assert_eq!(
test_struct.device_locator(),
Some("CPU1_DIMM_1".to_string())
);
assert_eq!(test_struct.bank_locator(), Some("NODE 1".to_string()));
assert_eq!(
test_struct.memory_type(),
Some(MemoryDeviceTypeData::from(26))
);
assert_eq!(
test_struct.type_detail(),
Some(MemoryTypeDetails::from(128))
);
match test_struct.speed().unwrap() {
MemorySpeed::MTs(speed) => assert_eq!(speed, 2666),
MemorySpeed::Unknown => panic!("expected speed"),
MemorySpeed::SeeExtendedSpeed => panic!("expected speed"),
}
assert_eq!(test_struct.manufacturer(), Some("Hynix".to_string()));
assert_eq!(test_struct.serial_number(), Some("72091003".to_string()));
assert_eq!(test_struct.asset_tag(), Some(" ".to_string()));
assert_eq!(
test_struct.part_number(),
Some("HMA81GR7AFR8N-VK ".to_string())
);
assert_eq!(test_struct.attributes(), Some(1));
assert_eq!(test_struct.extended_size(), Some(0));
match test_struct.configured_memory_speed().unwrap() {
MemorySpeed::MTs(speed) => assert_eq!(speed, 2666),
MemorySpeed::Unknown => panic!("expected speed"),
MemorySpeed::SeeExtendedSpeed => panic!("expected speed"),
}
assert_eq!(test_struct.minimum_voltage(), Some(1200));
assert_eq!(test_struct.maximum_voltage(), Some(1200));
assert_eq!(test_struct.configured_voltage(), Some(1200));
assert!(test_struct.memory_technology().is_none());
let struct_type17 = vec![
0x11, 0x5C, 0x40, 0x00, 0x3E, 0x00, 0xFE, 0xFF, 0x48, 0x00, 0x40, 0x00, 0x00, 0x20,
0x09, 0x00, 0x01, 0x02, 0x1A, 0x80, 0x00, 0x6A, 0x0A, 0x03, 0x04, 0x05, 0x06, 0x01,
0x00, 0x00, 0x00, 0x00, 0x6A, 0x0A, 0xB0, 0x04, 0xB0, 0x04, 0xB0, 0x04,
0x07,
0x20, 0x00,
0x07,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x04, 0x03, 0x02, 0x01,
0x08, 0x07, 0x06, 0x05,
0x43, 0x50, 0x55, 0x31, 0x5F, 0x44, 0x49, 0x4D, 0x4D, 0x5F, 0x31, 0x00, 0x4E, 0x4F,
0x44, 0x45, 0x20, 0x31, 0x00, 0x48, 0x79, 0x6E, 0x69, 0x78, 0x00, 0x37, 0x32, 0x30,
0x39, 0x31, 0x30, 0x30, 0x33, 0x00, 0x20, 0x00, 0x48, 0x4D, 0x41, 0x38, 0x31, 0x47,
0x52, 0x37, 0x41, 0x46, 0x52, 0x38, 0x4E, 0x2D, 0x56, 0x4B, 0x20, 0x20, 0x20, 0x20,
0x00, 0x38, 0x00, 0x00,
];
let parts = UndefinedStruct::new(&struct_type17);
let test_struct = SMBiosMemoryDevice::new(&parts);
assert_eq!(
*test_struct.memory_technology().unwrap(),
MemoryDeviceTechnology::IntelOptaneDcPersistentMemory
);
assert!(test_struct
.memory_operating_mode_capability()
.unwrap()
.block_accessible_persistent_memory());
assert_eq!(test_struct.firmware_version(), Some("8".to_string()));
assert_eq!(test_struct.module_manufacturer_id(), Some(0));
assert_eq!(test_struct.module_product_id(), Some(0));
assert_eq!(
test_struct.memory_subsystem_controller_manufacturer_id(),
Some(0)
);
assert_eq!(
test_struct.memory_subsystem_controller_product_id(),
Some(0)
);
match test_struct.non_volatile_size().unwrap() {
MemoryIndicatedSize::Unknown => (),
MemoryIndicatedSize::Bytes(_) => panic!("expected unknown"),
}
match test_struct.volatile_size().unwrap() {
MemoryIndicatedSize::Unknown => (),
MemoryIndicatedSize::Bytes(_) => panic!("expected unknown"),
}
match test_struct.cache_size().unwrap() {
MemoryIndicatedSize::Unknown => (),
MemoryIndicatedSize::Bytes(_) => panic!("expected unknown"),
}
match test_struct.logical_size().unwrap() {
MemoryIndicatedSize::Unknown => (),
MemoryIndicatedSize::Bytes(_) => panic!("expected unknown"),
}
assert_eq!(test_struct.extended_speed(), Some(0x01020304));
assert_eq!(
test_struct.extended_configured_memory_speed(),
Some(0x05060708)
);
}
}