13 releases

0.9.2 Sep 17, 2024
0.9.1 Sep 22, 2023
0.9.0 Mar 29, 2022
0.8.0 Jun 12, 2021
0.7.1 Mar 29, 2021

#22 in Hardware support

Download history 2654/week @ 2024-08-18 3410/week @ 2024-08-25 2219/week @ 2024-09-01 2247/week @ 2024-09-08 1809/week @ 2024-09-15 2013/week @ 2024-09-22 5440/week @ 2024-09-29 8426/week @ 2024-10-06 8329/week @ 2024-10-13 6958/week @ 2024-10-20 7452/week @ 2024-10-27 5756/week @ 2024-11-03 6427/week @ 2024-11-10 4330/week @ 2024-11-17 3655/week @ 2024-11-24 7445/week @ 2024-12-01

21,988 downloads per month
Used in 5 crates (4 directly)

Custom license

1MB
18K SLoC

smbios-lib

An SMBIOS Library created in Rust that reads and parses raw BIOS data

crates.io smbioslib_ci LOC

Table of contents

General info

This project reads raw SMBIOS data from either a device or file and provides the data as an API.

For an example project using this library take a look at dmidecode-rs.

Supports

SMBIOS 3.7.0 contains 49 defined structure types, all of which are covered by this library (types 0-46, 126, and 127). Support via extensibility exists for types 128-255 (reserved for OEMs). Extensibility also applies in the case when this library has not been updated for the latest specification version or a pre-released specification and a new type is introduced.

Project Status

In early development.

The current development stage is to finalize the API design.

Dependencies

  • Windows
    • libc = "^0.2"
  • MacOS
    • libc = "^0.2"
    • mach2 = "^0.4.1"
    • core-foundation = "~0.9"
    • core-foundation-sys = "~0.8"
    • io-kit-sys = "^0.4.0"

Security

This library design follows a strict security mantra: "Never trust the input".

SMBIOS has been around for decades and has undergone many versions and revisions. Many OEM vendors have interpreted and implemented the specifications over the years. Known cases of incorrect firmware implementations exist. This presents a veritable labrynth of logic for both the known and the unknown. Rather than creating such a complex state machine, we take advantage of Rust's Option<> trait and assert that the act of retrieval for any and all information may fail. The burden of proof thus shifts from the library to the library consumer who is required to implement the failing condition arm.

Examples

Retrieve a Field of a Single Instance Structure

Some structures are required and are a single instance. (e.g. SMBiosSystemInformation)

#[test]
/// Retrieves the System UUID from a device.
/// UUID is found in the System Information (type 1) structure
fn retrieve_system_uuid() {
    match table_load_from_device() {
        Ok(data) => match data.find_map(|sys_info: SMBiosSystemInformation| sys_info.uuid()) {
            Some(uuid) => println!("System Information UUID == {:?}", uuid),
            None => println!("No System Information (Type 1) structure found with a UUID field"),
        },
        Err(err) => println!("failure: {:?}", err),
    }
}

Output:

running 1 test
System Information UUID == Uuid(4ee6523f-d56a-f3ea-8e2a-891cf96286ea)
test retrieve_system_uuid ... ok

Retrieve All Instances of a Structure - collect()

Some structures are allowed to have more than one instance. (e.g. SMBiosMemoryDevice)

#[test]
/// Prints information for all memory devices within a device.
fn print_all_memory_devices() {
    match table_load_from_device() {
        Ok(data) => {
            for memory_device in data.collect::<SMBiosMemoryDevice>() {
                println!("{:#?}", memory_device);
            }
        }
        Err(err) => println!("failure: {:?}", err),
    }
}

Output:

running 1 test
smbioslib::structs::types::memory_device::SMBiosMemoryDevice {
    header: smbioslib::core::header::Header {
        struct_type: 17,
        length: 40,
        handle: smbioslib::structs::structure::Handle {
            handle: 8,
        },
    },
    physical_memory_array_handle: Some(
        smbioslib::structs::structure::Handle {
            handle: 1,
        },
    ),
[...elided...]

Retrieve a Structure Given a Handle - find_by_handle()

Some structures point to other structures via handles. (e.g. SMBiosMemoryDevice points to SMBiosPhysicalMemoryArray)

/// Finds an associated struct by handle
#[test]
fn struct_struct_association() {
    match table_load_from_device() {
        Ok(data) => match data.first::<SMBiosMemoryDevice>() {
            Some(first_memory_device) => {
                let handle = first_memory_device.physical_memory_array_handle().unwrap();
                match data.find_by_handle(&handle) {
                    Some(undefined_struct) => {
                        let physical_memory_array = undefined_struct.defined_struct();
                        println!("{:#?}", physical_memory_array)
                    }
                    None => println!("No Physical Memory Array (Type 16) structure found"),
                }
            }
            None => println!("No Memory Device (Type 17) structure found"),
        },
        Err(err) => println!("failure: {:?}", err),
    }
}

Output:

running 1 test
PhysicalMemoryArray(
    smbioslib::structs::types::physical_memory_array::SMBiosPhysicalMemoryArray {
        header: smbioslib::core::header::Header {
            struct_type: 16,
            length: 23,
            handle: smbioslib::structs::structure::Handle {
                handle: 1,
            },
        },
        location: Some(
            smbioslib::structs::types::physical_memory_array::MemoryArrayLocationData {
                raw: 3,
                value: SystemBoardOrMotherboard,
            },
        ),
[...elided...]

Dependencies

~1.8–3MB
~57K SLoC