dmi/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(not(feature = "std"))]
4#[macro_use]
5extern crate alloc;
6
7#[cfg(not(feature = "std"))]
8use alloc::{string::String, vec::Vec};
9use plain::Plain;
10use core::num::Wrapping;
11
12pub trait TableKind: Plain {
13    const KIND: u8;
14}
15
16#[repr(packed)]
17#[derive(Clone, Copy, Default, Debug)]
18pub struct Smbios {
19    pub anchor: [u8; 4],
20    pub checksum: u8,
21    pub length: u8,
22    pub major_version: u8,
23    pub minor_version: u8,
24    pub max_structure_size: u16,
25    pub revision: u8,
26    pub formatted: [u8; 5],
27    pub inter_anchor: [u8; 5],
28    pub inter_checksum: u8,
29    pub table_length: u16,
30    pub table_address: u32,
31    pub structure_count: u16,
32    pub bcd_revision: u8
33}
34
35unsafe impl Plain for Smbios {}
36
37impl Smbios {
38    pub fn is_valid(&self) -> bool {
39        let mut sum: Wrapping<u8> = self.anchor.iter().map(|x| Wrapping(*x)).sum();
40        sum += self.checksum;
41        sum += self.length;
42        sum += self.major_version;
43        sum += self.minor_version;
44        sum += self.max_structure_size as u8;
45        sum += self.revision;
46        sum += self.formatted.iter().sum::<u8>();
47        sum.0 == 0
48    }
49}
50
51#[repr(packed)]
52#[derive(Clone, Copy, Default, Debug)]
53pub struct Smbios3 {
54    pub anchor: [u8; 5],
55    pub checksum: u8,
56    pub length: u8,
57    pub major_version: u8,
58    pub minor_version: u8,
59    pub docrev: u8,
60    pub revision: u8,
61    _reserved: u8,
62    pub table_length: u32,
63    pub table_address: u64,
64}
65
66unsafe impl Plain for Smbios3 {}
67
68impl Smbios3 {
69    pub fn is_valid(&self) -> bool {
70        //TODO: Checksum
71        self.anchor == *b"_SM3_"
72    }
73}
74
75#[repr(packed)]
76#[derive(Clone, Copy, Default, Debug)]
77pub struct Header {
78    pub kind: u8,
79    pub len: u8,
80    pub handle: u16
81}
82
83unsafe impl Plain for Header {}
84
85#[derive(Clone)]
86pub struct Table {
87    pub header: Header,
88    pub data: Vec<u8>,
89    pub strings: Vec<String>
90}
91
92impl Table {
93    pub fn get<T: TableKind>(&self) -> Option<&T> {
94        if self.header.kind == T::KIND {
95            T::from_bytes(&self.data).ok()
96        } else {
97            None
98        }
99    }
100
101    pub fn get_str(&self, index: u8) -> Option<&String> {
102        if index > 0 {
103            self.strings.get((index - 1) as usize)
104        } else {
105            None
106        }
107    }
108}
109
110#[repr(packed)]
111#[derive(Clone, Copy, Default, Debug)]
112pub struct BiosInfo {
113    pub vendor: u8,
114    pub version: u8,
115    pub address: u16,
116    pub date: u8,
117    pub size: u8,
118    pub characteristics: u64,
119}
120
121unsafe impl Plain for BiosInfo {}
122
123impl TableKind for BiosInfo {
124    const KIND: u8 = 0;
125}
126
127#[repr(packed)]
128#[derive(Default, Debug)]
129pub struct SystemInfo {
130    pub manufacturer: u8,
131    pub name: u8,
132    pub version: u8,
133    pub serial: u8,
134}
135
136unsafe impl Plain for SystemInfo {}
137
138impl TableKind for SystemInfo {
139    const KIND: u8 = 1;
140}
141
142#[repr(packed)]
143#[derive(Default, Debug)]
144pub struct BaseBoardInfo {
145    pub manufacturer: u8,
146    pub product: u8,
147    pub version: u8,
148    pub serial: u8,
149    pub asset_tag: u8,
150}
151
152unsafe impl Plain for BaseBoardInfo {}
153
154impl TableKind for BaseBoardInfo {
155    const KIND: u8 = 2;
156}
157
158#[repr(packed)]
159#[derive(Default, Debug)]
160pub struct ChassisInfo {
161    pub manufacturer: u8,
162    pub kind: u8,
163    pub version: u8,
164    pub serial: u8,
165    pub asset_tag: u8,
166}
167
168unsafe impl Plain for ChassisInfo {}
169
170impl TableKind for ChassisInfo {
171    const KIND: u8 = 3;
172}
173
174#[repr(packed)]
175#[derive(Clone, Copy, Default, Debug)]
176pub struct ProcessorInfo {
177    pub socket_designation: u8,
178    pub processor_kind: u8,
179    pub processor_family: u8,
180    pub processor_manufacturer: u8,
181    pub processor_id: u64,
182    pub processor_version: u8,
183    pub voltage: u8,
184    pub external_clock: u16,
185    pub max_speed: u16,
186    pub current_speed: u16,
187    pub status: u8,
188    pub processor_upgrade: u8,
189    pub l1_cache_handle: u16,
190    pub l2_cache_handle: u16,
191    pub l3_cache_handle: u16,
192    pub serial_number: u8,
193    pub asset_tag: u8,
194    pub part_number: u8,
195    pub core_count: u8,
196    pub core_enabled: u8,
197    pub thread_count: u8,
198    pub processor_characteristics: u16,
199    pub processor_family_2: u16,
200}
201
202unsafe impl Plain for ProcessorInfo {}
203
204impl TableKind for ProcessorInfo {
205    const KIND: u8 = 4;
206}
207
208#[repr(packed)]
209#[derive(Clone, Copy, Default, Debug)]
210pub struct MemoryDevice {
211    pub array_handle: u16,
212    pub error_information_handle: u16,
213    pub total_width: u16,
214    pub data_width: u16,
215    pub size: u16,
216    pub form_factor: u8,
217    pub device_set: u8,
218    pub device_locator: u8,
219    pub bank_locator: u8,
220    pub memory_kind: u8,
221    pub kind_detail: u16,
222    pub speed: u16,
223    pub manufacturer: u8,
224    pub serial_number: u8,
225    pub asset_tag: u8,
226    pub part_number: u8,
227    pub attributes: u8,
228    pub extended_size: u32,
229    pub configured_speed: u16,
230    pub minimum_voltage: u16,
231    pub maximum_voltage: u16,
232    pub configured_voltage: u16,
233}
234
235unsafe impl Plain for MemoryDevice {}
236
237impl TableKind for MemoryDevice {
238    const KIND: u8 = 17;
239}
240
241pub fn tables(data: &[u8]) -> Vec<Table> {
242    let mut tables = Vec::new();
243
244    let mut i = 0;
245    while i < data.len() {
246        // Read header
247        let mut header = Header::default();
248        {
249            let bytes = unsafe { plain::as_mut_bytes(&mut header) };
250
251            let mut j = 0;
252            while i < data.len() && j < bytes.len() {
253                bytes[j] = data[i];
254                i += 1;
255                j += 1;
256            }
257        }
258
259        if header.kind == 127 {
260            //println!("End header");
261            break;
262        }
263
264        //println!("{:?}", header);
265
266        // Read data
267        let mut table = vec![0; header.len as usize - unsafe { plain::as_bytes(&header) }.len()];
268
269        {
270            let mut j = 0;
271            while i < data.len() && j < table.len() {
272                table[j] = data[i];
273                i += 1;
274                j += 1;
275            }
276        }
277
278        // Read strings
279        let mut strings = Vec::new();
280        while i < data.len() {
281            let mut string = String::new();
282            while i < data.len() {
283                let b = data[i];
284                i += 1;
285
286                if b == 0 {
287                    break;
288                } else {
289                    string.push(b as char);
290                }
291            }
292
293            if string.is_empty() && ! strings.is_empty() {
294                break;
295            } else {
296                //println!("{}: {}", strings.len(), string);
297                strings.push(string);
298            }
299        }
300
301        tables.push(Table {
302            header: header,
303            data: table,
304            strings: strings
305        });
306    }
307
308    tables
309}