coreboot_table/
cmos.rs

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    // name: [u8; 32]
28}
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    // text: [u8; 32]
48}
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}