1use crate::{SMBiosStruct, UndefinedStruct};
2use serde::{ser::SerializeStruct, Serialize, Serializer};
3use std::fmt;
4
5pub struct SMBiosSystemReset<'a> {
19 parts: &'a UndefinedStruct,
20}
21
22impl<'a> SMBiosStruct<'a> for SMBiosSystemReset<'a> {
23 const STRUCT_TYPE: u8 = 23u8;
24
25 fn new(parts: &'a UndefinedStruct) -> Self {
26 Self { parts }
27 }
28
29 fn parts(&self) -> &'a UndefinedStruct {
30 self.parts
31 }
32}
33
34impl<'a> SMBiosSystemReset<'a> {
35 pub fn capabilities(&self) -> Option<SystemResetCapabilities> {
39 self.parts
40 .get_field_byte(0x04)
41 .map(|raw| SystemResetCapabilities::from(raw))
42 }
43
44 pub fn reset_count(&self) -> Option<ResetCount> {
49 self.parts
50 .get_field_word(0x05)
51 .map(|raw| ResetCount::from(raw))
52 }
53
54 pub fn reset_limit(&self) -> Option<ResetLimit> {
58 self.parts
59 .get_field_word(0x07)
60 .map(|raw| ResetLimit::from(raw))
61 }
62
63 pub fn timer_interval(&self) -> Option<TimerInterval> {
70 self.parts
71 .get_field_word(0x09)
72 .map(|raw| TimerInterval::from(raw))
73 }
74
75 pub fn timeout(&self) -> Option<Timeout> {
82 self.parts
83 .get_field_word(0x0B)
84 .map(|raw| Timeout::from(raw))
85 }
86}
87
88impl fmt::Debug for SMBiosSystemReset<'_> {
89 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
90 fmt.debug_struct(std::any::type_name::<SMBiosSystemReset<'_>>())
91 .field("header", &self.parts.header)
92 .field("capabilities", &self.capabilities())
93 .field("reset_count", &self.reset_count())
94 .field("reset_limit", &self.reset_limit())
95 .field("timer_interval", &self.timer_interval())
96 .field("timeout", &self.timeout())
97 .finish()
98 }
99}
100
101impl Serialize for SMBiosSystemReset<'_> {
102 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103 where
104 S: Serializer,
105 {
106 let mut state = serializer.serialize_struct("SMBiosSystemReset", 6)?;
107 state.serialize_field("header", &self.parts.header)?;
108 state.serialize_field("capabilities", &self.capabilities())?;
109 state.serialize_field("reset_count", &self.reset_count())?;
110 state.serialize_field("reset_limit", &self.reset_limit())?;
111 state.serialize_field("timer_interval", &self.timer_interval())?;
112 state.serialize_field("timeout", &self.timeout())?;
113 state.end()
114 }
115}
116
117#[derive(PartialEq, Eq)]
119pub struct SystemResetCapabilities {
120 pub raw: u8,
122}
123
124impl From<u8> for SystemResetCapabilities {
125 fn from(raw: u8) -> Self {
126 SystemResetCapabilities { raw }
127 }
128}
129
130impl SystemResetCapabilities {
131 pub fn has_watchdog_timer(&self) -> bool {
134 self.raw & 0b0010_0000 == 0b0010_0000
135 }
136
137 pub fn boot_option_on_limit(&self) -> BootOptionOnLimit {
142 BootOptionOnLimit::from(self.raw)
143 }
144
145 pub fn boot_option(&self) -> BootOption {
150 BootOption::from(self.raw)
151 }
152
153 pub fn reset_enabled(&self) -> bool {
158 self.raw & 0b0000_0001 == 0b0000_0001
159 }
160}
161
162impl fmt::Debug for SystemResetCapabilities {
163 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
164 fmt.debug_struct(std::any::type_name::<SystemResetCapabilities>())
165 .field("raw", &self.raw)
166 .field("has_watchdog_timer", &self.has_watchdog_timer())
167 .field("boot_option_on_limit", &self.boot_option_on_limit())
168 .field("boot_option", &self.boot_option())
169 .field("reset_enabled", &self.reset_enabled())
170 .finish()
171 }
172}
173
174impl Serialize for SystemResetCapabilities {
175 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
176 where
177 S: Serializer,
178 {
179 let mut state = serializer.serialize_struct("SystemResetCapabilities", 5)?;
180 state.serialize_field("raw", &self.raw)?;
181 state.serialize_field("has_watchdog_timer", &self.has_watchdog_timer())?;
182 state.serialize_field("boot_option_on_limit", &self.boot_option_on_limit())?;
183 state.serialize_field("boot_option", &self.boot_option())?;
184 state.serialize_field("reset_enabled", &self.reset_enabled())?;
185 state.end()
186 }
187}
188
189#[derive(Serialize, Debug, PartialEq, Eq)]
194pub enum BootOptionOnLimit {
195 Reserved,
197 OperatingSystem,
199 SystemUtilities,
201 DoNotReboot,
203}
204
205impl From<u8> for BootOptionOnLimit {
206 fn from(raw: u8) -> Self {
207 match raw & 0b0001_1000 {
208 0b0000_0000 => BootOptionOnLimit::Reserved,
209 0b0000_1000 => BootOptionOnLimit::OperatingSystem,
210 0b0001_0000 => BootOptionOnLimit::SystemUtilities,
211 0b0001_1000 => BootOptionOnLimit::DoNotReboot,
212 _ => panic!("impossible value"),
213 }
214 }
215}
216
217#[derive(Serialize, Debug, PartialEq, Eq)]
222pub enum BootOption {
223 Reserved,
225 OperatingSystem,
227 SystemUtilities,
229 DoNotReboot,
231}
232
233impl From<u8> for BootOption {
234 fn from(raw: u8) -> Self {
235 match raw & 0b0000_0110 {
236 0b0000_0000 => BootOption::Reserved,
237 0b0000_0010 => BootOption::OperatingSystem,
238 0b0000_0100 => BootOption::SystemUtilities,
239 0b0000_0110 => BootOption::DoNotReboot,
240 _ => panic!("impossible value"),
241 }
242 }
243}
244
245#[derive(Serialize, Debug)]
247pub enum ResetCount {
248 Count(u16),
250 Unknown,
252}
253
254impl From<u16> for ResetCount {
255 fn from(raw: u16) -> Self {
256 match raw {
257 0xFFFF => ResetCount::Unknown,
258 _ => ResetCount::Count(raw),
259 }
260 }
261}
262
263#[derive(Serialize, Debug)]
265pub enum ResetLimit {
266 Count(u16),
268 Unknown,
270}
271
272impl From<u16> for ResetLimit {
273 fn from(raw: u16) -> Self {
274 match raw {
275 0xFFFF => ResetLimit::Unknown,
276 _ => ResetLimit::Count(raw),
277 }
278 }
279}
280
281#[derive(Serialize, Debug)]
283pub enum TimerInterval {
284 Minutes(u16),
289 Unknown,
291}
292
293impl From<u16> for TimerInterval {
294 fn from(raw: u16) -> Self {
295 match raw {
296 0xFFFF => TimerInterval::Unknown,
297 _ => TimerInterval::Minutes(raw),
298 }
299 }
300}
301
302#[derive(Serialize, Debug)]
304pub enum Timeout {
305 Minutes(u16),
310 Unknown,
312}
313
314impl From<u16> for Timeout {
315 fn from(raw: u16) -> Self {
316 match raw {
317 0xFFFF => Timeout::Unknown,
318 _ => Timeout::Minutes(raw),
319 }
320 }
321}
322
323#[cfg(test)]
324mod tests {
325 use super::*;
326
327 #[test]
328 fn unit_test() {
329 let struct_type23 = vec![
330 0x17, 0x0D, 0x4F, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
331 0x00,
332 ];
333
334 let parts = UndefinedStruct::new(&struct_type23);
335 let test_struct = SMBiosSystemReset::new(&parts);
336
337 assert_eq!(
338 test_struct.capabilities(),
339 Some(SystemResetCapabilities::from(0))
340 );
341 match test_struct.reset_count().unwrap() {
342 ResetCount::Count(_) => panic!("expected unknown"),
343 ResetCount::Unknown => (),
344 }
345 match test_struct.reset_limit().unwrap() {
346 ResetLimit::Count(_) => panic!("expected unknown"),
347 ResetLimit::Unknown => (),
348 }
349 match test_struct.timer_interval().unwrap() {
350 TimerInterval::Minutes(_) => panic!("expected unknown"),
351 TimerInterval::Unknown => (),
352 }
353 match test_struct.timeout().unwrap() {
354 Timeout::Minutes(_) => panic!("expected unknown"),
355 Timeout::Unknown => (),
356 }
357 }
358}