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 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 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 break;
262 }
263
264 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 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 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}