OpenDMI reads DMI/SMBIOS data and gives it back as structured data instead of text to parse: a C library, command line tools, machine-readable output and bindings for Go, Python and Rust. Every field has a code, a type and a unit, so the same data reads the same way in the terminal, in JSON and through the API.
The project is under active development, see ROADMAP and CHANGELOG for details.
Structures are decoded field by field, including the ones other tools leave as raw bytes:
$ opendmi show -t processor
Processor information
Socket Designation: U3E1
Type: Central processor
Family: Intel Core i5
Vendor: Intel(R) Corporation
ID: A4 06 09 00 FF FB EB BF
Signature:
Type: 0
Family: 6
Model: 154
Stepping: 4
Flags: 0xBFEBFBFF
FPU (floating-point unit on-chip): yes
VME (virtual mode extension): yes
...
The same structure in JSON, with stable codes instead of human-readable labels:
$ opendmi export -f json -t processor
{
"entry": {
"smbios-version": "3.0"
},
"table": [
{
"handle": "0x001a",
"type": 4,
"length": 185,
"level": "3.0",
"state": [
"decoded",
"linked"
],
"description": "Processor information",
"attributes": {
"socket-designation": "U3E1",
"type": "central",
"family": "intel-core-i5",
"vendor": "Intel(R) Corporation",
"id": "a4060900fffbebbf",
"signature": {
"type": "0",
"family": "6",
"model": "154",
"stepping": "4"
},
"flags": {
"fpu": true,
"vme": true
}
}
}
]
}
The same data from C, with decoded structures mapped to plain C types:
#include <opendmi/context.h>
#include <opendmi/entity/system.h>
dmi_context_t *context = dmi_create(DMI_CONTEXT_FLAG_LINK);
if (dmi_open(context, nullptr)) {
dmi_registry_t *registry = dmi_get_registry(context);
dmi_entity_t *entity = dmi_registry_lookup_first(registry, DMI_TYPE(SYSTEM), false);
dmi_system_t *system = dmi_entity_info(entity, DMI_TYPE(SYSTEM));
if (system != nullptr)
printf("%s %s\n", system->vendor, system->product);
}
dmi_destroy(context);
dmidecode parse its human-readable
output. OpenDMI provides a C library, bindings and JSON, XML and YAML output,
where every field is addressed by a stable code.decoded, incomplete, partial), errors are collected in a queue, and a
strict mode is available when correctness matters more than completeness.
Known firmware quirks, such as swapped processor ID words or reversed TPM
vendor identifiers, are handled.lint command checks a table
against the rules of the specification, from the checksum of the entry point
to the values of individual fields, and reports what it finds with the file
offset, the structure and the attribute it belongs to.dmidecode --dump-bin and --from-dump, in both directions.| Component | Description | Status |
|---|---|---|
libopendmi |
C/C++ library providing direct interface to DMI/SMBIOS | Usable, API not frozen until 1.0 |
opendmi |
Command line tool to query DMI/SMBIOS data | Usable, import command is on the way |
libopendmi-python |
Python bindings for libopendmi |
In progress |
opendmi-dbus |
D-Bus service providing access to DMI/SMBIOS data | In progress |
opendmi-sysfs |
Linux kernel module providing DMI/SMBIOS data via SysFS | Planned |
libopendmi-go |
Go bindings for libopendmi |
Planned |
libopendmi-rust |
Rust bindings for libopendmi |
Planned |
Everything is scheduled for 1.0, see ROADMAP for the order.
Build and install OpenDMI from sources:
$ ./build.sh configure --prefix /usr/local
$ ./build.sh build
$ ./build.sh install
Then read the data of the local system:
$ opendmi show
See Building from sources for configuration options, optional components and packaging.
The opendmi command line tool provides access to DMI/SMBIOS data. The general
usage pattern is:
$ opendmi [global options] <command> [command options]
| Option | Description |
|---|---|
-v, --version |
Print version information and exit |
-h, --help |
Print help and exit |
-i <path>, --file=<path> |
Read DMI data from a binary file instead of the system |
-d <path>, --device=<path> |
Set path to memory device (default: /dev/mem) |
-m <module>, --module=<module> |
Enable the specified module |
-O, --overlay |
Apply additional information entries (type 40) to structures |
-l, --log |
Enable logging to the terminal |
--log-file=<path> |
Enable logging to a file |
-L <level>, --log-level=<level> |
Set logging level |
Values of options are specified either as a separate argument (-i <path>,
--file <path>) or attached to the option (-i<path>, --file=<path>).
| Command | Description |
|---|---|
show |
Show SMBIOS structures data |
list |
List SMBIOS structures |
entry |
Show SMBIOS entry point data |
types |
List SMBIOS structure types |
explain |
Explain an SMBIOS structure type |
export |
Export SMBIOS data to external format (JSON, XML, YAML) |
dump |
Dump the entire SMBIOS table to a binary file |
import |
Import SMBIOS data from an external format * |
lint |
Check SMBIOS structures against the rules of the specification |
modules |
List available modules |
Use opendmi <command> --help for detailed information on a specific command.
Commands marked with an asterisk are on the way.
showShow SMBIOS structures data in human-readable form. Structures are selected with filter options.
| Option | Description |
|---|---|
-q, --quiet |
Hide meta-data and handle references |
-V, --verbose |
Show structure versions and states |
-D, --dump |
Show raw structure data instead of decoded fields |
listList SMBIOS structures with their handles and types. Structures are selected with filter options.
| Option | Description |
|---|---|
-r, --raw |
Raw output (default if standard output is a pipe) |
entryShow SMBIOS entry point data. The command has no options.
typesList SMBIOS structure types. Only standard types are listed by default.
| Option | Description |
|---|---|
-m <module>, --module=<module> |
List types provided by the specified module |
-M, --all-modules |
List types provided by all modules |
-a, --all |
List all available types |
-r, --raw |
Raw output (default if standard output is a pipe) |
explainExplain an SMBIOS structure type, given by its number or code:
opendmi explain [--] <type>. The command has no options.
exportExport SMBIOS data to external format. Structures are selected with filter options.
| Option | Description |
|---|---|
-o <path>, --output=<path> |
Set output file path (default: standard output) |
-f <format>, --format=<format> |
Set output format: text, json, xml or yaml (default: yaml) |
-D, --dump |
Export raw structure data instead of decoded fields |
-p, --pretty |
Write the values for a person (4 GiB) instead of by their codes (4294967296) |
-F, --force |
Overwrite existing files |
dumpDump the entire SMBIOS table to a binary file, compatible with
dmidecode --from-dump.
| Option | Description |
|---|---|
-o <path>, --output=<path> |
Set output file path (default: smbios.bin) |
-F, --force |
Overwrite existing files |
lintCheck SMBIOS data against the rules of the specification.
| Option | Description |
|---|---|
-A, --all-checks |
Enable the rules which are disabled by default |
-e <rule>, --enable=<rule> |
Check the given rule or group of rules only |
-d <rule>, --disable=<rule> |
Skip the given rule or group of rules |
-P, --producer |
Check the data as if it was produced, not read |
-S, --strict |
Treat warnings as errors |
-q, --quiet |
Report errors only |
-R, --list-rules |
List the rules and exit |
Each issue is reported the way a compiler reports a diagnostic, so that the output is readable by the tools that are used to that format:
$ opendmi -i smbios.bin lint
0x0009: warning: firmware@0x0000.rom-size (Platform firmware information): ROM size refers to the extended one, which the structure does not carry [firmware.rom-size]
0x00F3: note: baseboard@0x0002 (Baseboard or module information): string 4 holds whitespace only [string.blank]
0x103C: note: <table>: table has 290 bytes past the end-of-table structure [table.trailing-data]
9 issues: 0 errors, 1 warning, 8 notes
The location is the offset of the issue within the data, followed by the code
of the structure and its handle, and by the attribute the issue belongs to.
Issues of the entry point and of the table itself are located at <entry> and
<table> instead. The rule that has found the issue is named in brackets.
Rules are named <group>.<rule>, e.g. entry.checksum, and -e and -d take
either a full name or a group name standing for every rule in it. Naming rules
with -e leaves the rest of them out, and a rule named explicitly is checked
even if it is disabled by default. Use -R to list the rules along with their
severities.
Severity depends on the profile. By default the data is assumed to have been
read from a platform, where the defects of the firmware are nothing the reader
can fix; -P checks it as data being written, where the same defects are
errors.
The command exits with a non-zero status if any issue of the error severity has been found, or any warning in strict mode.
modulesList available modules.
| Option | Description |
|---|---|
-r, --raw |
Raw output (default if standard output is a pipe) |
The show, list and export commands show standard and OEM-specific
structures by default, excluding inactive and unknown ones. Filter options
select structures to show.
| Option | Description |
|---|---|
-H <handle>, --handle=<handle> |
Only show structures with the given handle(s) |
-t <type>, --type=<type> |
Only show structures of the given type(s), by number or code |
-s, --standard |
Show standard structures |
-S, --no-standard |
Don’t show standard structures |
-e, --oem |
Show OEM-specific structures |
-E, --no-oem |
Don’t show OEM-specific structures |
-i, --inactive |
Show inactive structures |
-I, --no-inactive |
Don’t show inactive structures |
-u, --unknown |
Show unknown structures |
-U, --no-unknown |
Don’t show unknown structures |
-m <module>, --module=<module> |
Show structures provided by the specified enabled module |
-M, --all-modules |
Show structures provided by all enabled modules |
-a, --all |
Show all structures |
Output of text commands (e.g. show or types) is shown through the pager set by
the PAGER environment variable, or less if it is not set. Unless the LESS
environment variable is set, less prints output that fits on one screen
directly. Set PAGER to an empty value to disable the pager.
Show all SMBIOS structures in human-readable format:
$ opendmi show
Show structures of a specific type only:
$ opendmi show -t processor
Show structure versions and decoding states (for example, incomplete for
structures, which do not match any specification version):
$ opendmi show -V
Enable the Dell extension module, so that its structures are decoded:
$ opendmi -m dell show
Show structures provided by the enabled module only, hiding the rest:
$ opendmi -m dell show -m dell
List all structures with their handles and types:
$ opendmi list
Show SMBIOS entry point information:
$ opendmi entry
Explain a specific structure type:
$ opendmi explain processor
Export SMBIOS data to YAML (default format):
$ opendmi export -o smbios.yaml
Export SMBIOS data to JSON:
$ opendmi export -f json -o smbios.json
Export to JSON with the values written for a person rather than for a program,
so that "memory-type": "ddr4" reads as "memory-type": "DDR4" and a size
carries its unit:
$ opendmi export -f json --pretty -o smbios.json
Dump the raw SMBIOS table to a binary file:
$ opendmi dump -o smbios.bin
Read SMBIOS data from a previously saved dump:
$ opendmi -i smbios.bin show
Check a dump against the rules of the specification:
$ opendmi -i smbios.bin lint
Check everything, reporting the peculiarities of the data along with its defects:
$ opendmi lint -A
Check the references between the structures only:
$ opendmi lint -e link -e overlay
libxml2 — optional, only when XML support is enabledlibyaml — optional, only when YAML support is enabledlibyajl — optional, only when JSON support is enabledUse the following command to configure OpenDMI build:
$ ./build.sh configure
This produces a release build by default. Pass --debug to configure a debug
build (optimization disabled, debug assertions included):
$ ./build.sh configure --debug
Debug and coverage builds use AddressSanitizer when the runtime of the
toolchain runs on the platform, which is checked while configuring, since a
runtime the system has outgrown hangs every program before it starts. Pass
--without-asan to build without it, or --with-asan to require it and fail
to configure instead of falling back.
To set the installation prefix:
$ ./build.sh configure --prefix /usr/local
To enable optional components:
$ ./build.sh configure --enable-dbus --enable-python
To enable all optional components at once:
$ ./build.sh configure --enable-all
To enable optional format support:
$ ./build.sh configure --with-json --with-xml --with-yaml
For all configuration options, see usage:
$ ./build.sh --help
To override defaults persistently without modifying build.conf.dist, create a
build.conf file in the project root — settings there take precedence.
Use the following command to build OpenDMI:
$ ./build.sh build
To build using a specific number of parallel jobs:
$ ./build.sh -j 4 build
To use a custom build directory:
$ ./build.sh -b /tmp/opendmi-build build
OpenDMI uses the CTest framework for testing. You can simply run it to ensure that build was successful:
$ ./build.sh test
To re-run only the failed tests:
$ ./build.sh test --failed
Use the following command to install OpenDMI to the configured prefix:
$ ./build.sh install
The installed library can be found with CMake:
find_package(OpenDMI 0.5 REQUIRED)
target_link_libraries(example PRIVATE OpenDMI::opendmi)
OpenDMI::opendmi and OpenDMI::shared refer to the shared library, and
OpenDMI::static refers to the static one. Binary compatibility is not
guaranteed between minor versions before 1.0, so the package is only
compatible with the same minor version.
The library can also be found with pkg-config:
$ cc example.c $(pkg-config --cflags --libs opendmi)
Use the following command to build distributable packages using CPack:
$ ./build.sh package
To remove build artifacts without removing the configuration:
$ ./build.sh clean
To remove the entire build directory including the configuration:
$ ./build.sh distclean
The project is open to contributions. Please feel free to test it and create bug reports, feature requests or pull requests on GitHub. You can also help the project by sending SMBIOS dumps to the authors. To get the dump you can use the following command:
$ dmidecode --dump-bin <filename>
Or, using OpenDMI itself:
$ opendmi dump -o <filename>
See CONTRIBUTING for more details. A full list of contributors who helped the project so far can be found in the CONTRIBUTORS.
OpenDMI is licensed under BSD 3-clause license. See LICENSE for details. It uses parts of some third-party libraries that are distributed under their own terms (see LICENSE-3RD-PARTY).
PVS-Studio - static analyzer for C, C++, C#, and Java code.