1use crate::core::{Handle, UndefinedStruct};
2use crate::SMBiosStruct;
3use serde::{ser::SerializeStruct, Serialize, Serializer};
4use std::fmt;
5use std::ops::Deref;
6
7pub struct SMBiosProcessorAdditionalInformation<'a> {
23 parts: &'a UndefinedStruct,
24}
25
26impl<'a> SMBiosStruct<'a> for SMBiosProcessorAdditionalInformation<'a> {
27 const STRUCT_TYPE: u8 = 44u8;
28
29 fn new(parts: &'a UndefinedStruct) -> Self {
30 Self { parts }
31 }
32
33 fn parts(&self) -> &'a UndefinedStruct {
34 self.parts
35 }
36}
37
38impl<'a> SMBiosProcessorAdditionalInformation<'a> {
39 const PROCESSOR_SPECIFIC_BLOCK_OFFSET: usize = 0x06usize;
41
42 pub fn referenced_handle(&self) -> Option<Handle> {
46 self.parts.get_field_handle(0x04)
47 }
48
49 pub fn processor_specific_block(&self) -> Option<ProcessorSpecificBlock<'_>> {
51 ProcessorSpecificBlock::new(self)
52 }
53}
54
55impl fmt::Debug for SMBiosProcessorAdditionalInformation<'_> {
56 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
57 fmt.debug_struct(std::any::type_name::<
58 SMBiosProcessorAdditionalInformation<'_>,
59 >())
60 .field("header", &self.parts.header)
61 .field("referenced_handle", &self.referenced_handle())
62 .field("processor_specific_block", &self.processor_specific_block())
63 .finish()
64 }
65}
66
67impl Serialize for SMBiosProcessorAdditionalInformation<'_> {
68 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
69 where
70 S: Serializer,
71 {
72 let mut state = serializer.serialize_struct("SMBiosProcessorAdditionalInformation", 3)?;
73 state.serialize_field("header", &self.parts.header)?;
74 state.serialize_field("referenced_handle", &self.referenced_handle())?;
75 state.serialize_field("processor_specific_block", &self.processor_specific_block())?;
76 state.end()
77 }
78}
79
80pub struct ProcessorSpecificBlock<'a> {
82 pub raw: &'a [u8],
84}
85
86impl<'a> ProcessorSpecificBlock<'a> {
87 const BLOCK_LENGTH_OFFSET: usize = 0x00usize;
89 const PROCESSOR_TYPE_OFFSET: usize = 0x01usize;
91 const PROCESSOR_SPECIFIC_DATA_OFFSET: usize = 0x02usize;
93
94 fn new(additional_information: &'a SMBiosProcessorAdditionalInformation<'a>) -> Option<Self> {
95 additional_information
96 .parts()
97 .get_field_byte(
98 SMBiosProcessorAdditionalInformation::PROCESSOR_SPECIFIC_BLOCK_OFFSET
99 + Self::BLOCK_LENGTH_OFFSET,
100 )
101 .and_then(|block_length| {
102 additional_information
103 .parts()
104 .get_field_data(
105 SMBiosProcessorAdditionalInformation::PROCESSOR_SPECIFIC_BLOCK_OFFSET
106 + Self::BLOCK_LENGTH_OFFSET,
107 block_length as usize
108 + SMBiosProcessorAdditionalInformation::PROCESSOR_SPECIFIC_BLOCK_OFFSET
109 + Self::PROCESSOR_SPECIFIC_DATA_OFFSET,
110 )
111 .map(|raw| Self { raw })
112 })
113 }
114
115 pub fn block_length(&self) -> u8 {
117 self.raw[Self::BLOCK_LENGTH_OFFSET]
118 }
119
120 pub fn processor_type(&self) -> ProcessorArchitectureTypeData {
122 ProcessorArchitectureTypeData::from(self.raw[Self::PROCESSOR_TYPE_OFFSET])
123 }
124
125 pub fn processor_specific_data(&self) -> &'a [u8] {
128 &self.raw[Self::PROCESSOR_SPECIFIC_DATA_OFFSET..]
129 }
130}
131
132impl fmt::Debug for ProcessorSpecificBlock<'_> {
133 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
134 fmt.debug_struct(std::any::type_name::<ProcessorSpecificBlock<'_>>())
135 .field("block_length", &self.block_length())
136 .field("processor_type", &self.processor_type())
137 .field("processor_specific_data", &self.processor_specific_data())
138 .finish()
139 }
140}
141
142impl Serialize for ProcessorSpecificBlock<'_> {
143 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
144 where
145 S: Serializer,
146 {
147 let mut state = serializer.serialize_struct("ProcessorSpecificBlock", 3)?;
148 state.serialize_field("block_length", &self.block_length())?;
149 state.serialize_field("processor_type", &self.processor_type())?;
150 state.serialize_field("processor_specific_data", &self.processor_specific_data())?;
151 state.end()
152 }
153}
154
155pub struct ProcessorArchitectureTypeData {
157 pub raw: u8,
164 pub value: ProcessorArchitectureType,
166}
167
168impl fmt::Debug for ProcessorArchitectureTypeData {
169 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
170 fmt.debug_struct(std::any::type_name::<ProcessorArchitectureTypeData>())
171 .field("raw", &self.raw)
172 .field("value", &self.value)
173 .finish()
174 }
175}
176
177impl Serialize for ProcessorArchitectureTypeData {
178 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
179 where
180 S: Serializer,
181 {
182 let mut state = serializer.serialize_struct("ProcessorArchitectureTypeData", 2)?;
183 state.serialize_field("raw", &self.raw)?;
184 state.serialize_field("value", &self.value)?;
185 state.end()
186 }
187}
188
189impl fmt::Display for ProcessorArchitectureTypeData {
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 match &self.value {
192 ProcessorArchitectureType::None => write!(f, "{}", &self.raw),
193 _ => write!(f, "{:?}", &self.value),
194 }
195 }
196}
197
198impl Deref for ProcessorArchitectureTypeData {
199 type Target = ProcessorArchitectureType;
200
201 fn deref(&self) -> &Self::Target {
202 &self.value
203 }
204}
205
206#[derive(Serialize, Debug, PartialEq, Eq)]
208pub enum ProcessorArchitectureType {
209 IA32,
211 X64,
213 IntelItanium,
215 Arm32Bit,
217 Arm64Bit,
219 RiscV32Bit,
221 RiscV64Bit,
223 RiscV128Bit,
225 LoongArch32,
227 LoongArch64,
229 None,
231}
232
233impl From<u8> for ProcessorArchitectureTypeData {
234 fn from(raw: u8) -> Self {
235 ProcessorArchitectureTypeData {
236 value: match raw {
237 0x01 => ProcessorArchitectureType::IA32,
238 0x02 => ProcessorArchitectureType::X64,
239 0x03 => ProcessorArchitectureType::IntelItanium,
240 0x04 => ProcessorArchitectureType::Arm32Bit,
241 0x05 => ProcessorArchitectureType::Arm64Bit,
242 0x06 => ProcessorArchitectureType::RiscV32Bit,
243 0x07 => ProcessorArchitectureType::RiscV64Bit,
244 0x08 => ProcessorArchitectureType::RiscV128Bit,
245 0x09 => ProcessorArchitectureType::LoongArch32,
246 0x10 => ProcessorArchitectureType::LoongArch64,
247 _ => ProcessorArchitectureType::None,
248 },
249 raw,
250 }
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257
258 #[test]
259 fn unit_test() {
260 let block_length = 3u8;
261 let processor_type = 0x07u8; let struct_type44 = vec![
264 44u8,
265 6 + block_length + 2,
266 0x2E,
267 0x00, 0x08,
269 0x09, block_length,
271 processor_type,
272 0x03,
273 0x02,
274 0x01,
275 0x00,
276 0x00,
277 ];
278
279 let parts = UndefinedStruct::new(&struct_type44);
280 let test_struct = SMBiosProcessorAdditionalInformation::new(&parts);
281
282 assert_eq!(*test_struct.referenced_handle().unwrap(), 0x0908);
283 let processor_specific_block = test_struct.processor_specific_block().unwrap();
284 assert_eq!(processor_specific_block.block_length(), 3);
285 assert_eq!(
286 *processor_specific_block.processor_type(),
287 ProcessorArchitectureType::RiscV64Bit
288 );
289 assert_eq!(
290 processor_specific_block.processor_specific_data(),
291 &[0x03, 0x02, 0x01]
292 );
293 }
294}