1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! System Configuration Options (Type 12)
//!
//! This SMBIOS structure contains information required to configure the baseboard’s Jumpers and
//! Switches.


use crate::{
    InfoType,
    MalformedStructureError::{
        self,
        InvalidStringIndex,
    },
    RawStructure,
    StructureStrings,
};


/// Contains an iterator through configuration strings
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SystemConfigurationOptions<'a> {
    /// Specifies the structure’s handle
    pub handle: u16,
    /// Configuration strings
    pub strings: StructureStrings<'a>
}


impl<'a> SystemConfigurationOptions<'a> {
    pub(crate) fn try_from(structure: RawStructure<'a>) -> Result<Self, MalformedStructureError> {
        let count: u8 = structure.get::<u8>(0x04)?;
        let strings = structure.strings();
        if count as usize != strings.count() {
            Err(InvalidStringIndex(InfoType::SystemConfigurationOptions, structure.handle, count))
        } else {
            Ok(SystemConfigurationOptions {
                handle: structure.handle,
                strings,
            })
        }
    }
}


#[cfg(test)]
mod tests {
    use std::prelude::v1::*;
    use pretty_assertions::{assert_eq,};

    #[test]
    fn system_configuration_options() {
        use crate::{InfoType, RawStructure};
        use super::*;

        let sample = vec!["ConfigOptions1","ConfigOptions2","ConfigOptions3"];
        let structure = RawStructure {
            version: (3, 4).into(),
            info: InfoType::SystemConfigurationOptions,
            length: 0x05,
            handle: 0x001F,
            // Remove 4 bytes from `dmidecode -H 8 -u` 'Header and Data'
            data: &[ 
                0x03, // Strings count
            ],
            strings: &[
                // ConfigOptions1
                0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x31, 0x00,
                // ConfigOptions2
                0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x32, 0x00,
                // ConfigOptions3
                0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x33, 0x00,
            ],
        };
        let result = SystemConfigurationOptions::try_from(structure)
            .unwrap();

        assert_eq!(sample, result.strings.collect::<Vec<_>>());
    }

    #[test]
    fn dmi_bin() {
        use crate::{Structure, EntryPoint, StructureStrings};
        use super::*;
        const DMIDECODE_BIN: &'static [u8] = include_bytes!("../../tests/data/dmi.0.bin");
        let entry_point = EntryPoint::search(DMIDECODE_BIN).unwrap();
        let oem_strings = entry_point
            .structures(&DMIDECODE_BIN[(entry_point.smbios_address() as usize)..])
            .filter_map(|s| {
                if let Err(ref s) = s {
                    println!("{}", s);
                }
                s.ok().filter(|s| matches!(s, Structure::SystemConfigurationOptions(_)))
            })
        .collect::<Vec<_>>();

        let sample = SystemConfigurationOptions {
            handle: 0x0C00,
            strings: StructureStrings::new(&[
                // NVRAM_CLR: Clear user settable NVRAM areas and set defaults
                0x4E, 0x56, 0x52, 0x41, 0x4D, 0x5F, 0x43, 0x4C, 0x52, 0x3A, 0x20, 0x43, 0x6C, 0x65,
                0x61, 0x72,  0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x73, 0x65, 0x74, 0x74, 0x61, 0x62,
                0x6C, 0x65, 0x20, 0x4E, 0x56, 0x52, 0x41, 0x4D, 0x20, 0x61, 0x72, 0x65, 0x61, 0x73,
                0x20, 0x61, 0x6E, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75,
                0x6C, 0x74, 0x73, 0x00,
                // PWRD_EN: Close to enable password
                0x50, 0x57, 0x52, 0x44, 0x5F, 0x45, 0x4E, 0x3A, 0x20, 0x43, 0x6C, 0x6F, 0x73, 0x65,
                0x20, 0x74, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x70, 0x61, 0x73,
                0x73, 0x77, 0x6F, 0x72, 0x64, 0x00,
                0x00
            ]), 
        };
        let result = oem_strings.iter()
            .find_map(|s| {
                match s {
                    Structure::SystemConfigurationOptions(os) => Some(os),
                    _ => None,
                }
            }).unwrap();
        assert_eq!(&sample, result, "Sample\n{:?}\nResult\n{:?}", sample, result);

        let string_sample = vec![
            "NVRAM_CLR: Clear user settable NVRAM areas and set defaults",
            "PWRD_EN: Close to enable password",
        ];
        assert_eq!(string_sample, result.strings.collect::<Vec<_>>(), "Strings"); 
    }
}