1use core::{mem, slice};
2
3use super::{Record, RecordKind};
4
5unsafe fn text<'a>(ptr: *const u8, max: usize) -> &'a [u8] {
6 let mut i = 0;
7 while i < max {
8 if *ptr.add(i) == 0 {
9 break;
10 }
11 i += 1;
12 }
13 slice::from_raw_parts(
14 ptr,
15 i
16 )
17}
18
19#[derive(Debug)]
20#[repr(packed)]
21pub struct CmosEntry {
22 pub record: Record,
23 pub bit: u32,
24 pub length: u32,
25 pub config: u32,
26 pub config_id: u32,
27 }
29
30impl CmosEntry {
31 pub fn name(&self) -> &[u8] {
32 unsafe {
33 text(
34 (self as *const CmosEntry as usize + mem::size_of::<CmosEntry>()) as *const u8,
35 self.record.size as usize - mem::size_of::<CmosEntry>()
36 )
37 }
38 }
39}
40
41#[derive(Debug)]
42#[repr(packed)]
43pub struct CmosEnum {
44 pub record: Record,
45 pub config_id: u32,
46 pub value: u32,
47 }
49
50impl CmosEnum {
51 pub fn text(&self) -> &[u8] {
52 unsafe {
53 text(
54 (self as *const CmosEnum as usize + mem::size_of::<CmosEnum>()) as *const u8,
55 self.record.size as usize - mem::size_of::<CmosEnum>()
56 )
57 }
58 }
59}
60
61#[derive(Debug)]
62pub enum CmosRecord<'a> {
63 Entry(&'a CmosEntry),
64 Enum(&'a CmosEnum),
65 Other(&'a Record),
66}
67
68#[derive(Debug)]
69#[repr(packed)]
70pub struct Cmos {
71 pub record: Record,
72 pub header_length: u32,
73}
74
75impl Cmos {
76 pub fn records(&self) -> CmosRecords {
77 CmosRecords {
78 table: self,
79 i: self.header_length as usize,
80 }
81 }
82}
83
84pub struct CmosRecords<'a> {
85 table: &'a Cmos,
86 i: usize,
87}
88
89impl<'a> Iterator for CmosRecords<'a> {
90 type Item = CmosRecord<'a>;
91 fn next(&mut self) -> Option<CmosRecord<'a>> {
92 if self.i + mem::size_of::<Record>() <= self.table.record.size as usize {
93 let address = (self.table as *const Cmos as usize) + self.i;
94 let record = unsafe { &*(address as *const Record) };
95 self.i += record.size as usize;
96 Some(match record.kind {
97 RecordKind::Option => CmosRecord::Entry(unsafe {
98 &*(address as *const CmosEntry)
99 }),
100 RecordKind::OptionEnum => CmosRecord::Enum(unsafe {
101 &*(address as *const CmosEnum)
102 }),
103 _ => CmosRecord::Other(record),
104 })
105 } else {
106 None
107 }
108 }
109}