Skip to content

linsysfs: expose raw SMBIOS tables - #521

Merged
laffer1 merged 1 commit into
masterfrom
linux-smbios-tables
Sep 25, 2026
Merged

laffer1 merged 1 commit into
masterfrom
linux-smbios-tables

Conversation

@laffer1

@laffer1 laffer1 commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Summary

  • add SMBIOS 3 entry-point discovery and validate SMBIOS 2/3 checksums
  • snapshot the entry point and structure table for kernel consumers
  • expose /sys/firmware/dmi/tables/smbios_entry_point and /sys/firmware/dmi/tables/DMI through linsysfs as binary mode-0400 files with their actual sizes
  • add an ATF regression test for permissions, signatures, checksums, content, and offset reads

Validation

  • make -j4 buildkernel KERNCONF=GENERIC
  • make -C sys/modules/bios/smbios clean all
  • make -C sys/modules/linsysfs clean all
  • make -C tests/sys/fs/linsysfs clean all
  • sh -n tests/sys/fs/linsysfs/dmi_id_test.sh tests/sys/fs/linsysfs/raw_dmi_test.sh
  • C pre-commit cppcheck/clang-format skill (cppcheck clean; formatting churn discarded)
  • Splint pre-commit skill (kernel sources skipped as designed)
  • tools/build/checkstyle9.pl --patch
  • git diff --check
  • booted the resulting kernel and verified the raw files return a valid 31-byte _SM_ entry point and 4087-byte DMI table with correct stat sizes and offset reads

Geekbench note

Geekbench 6.4 still prefers /dev/mem when run as root even with these interfaces present. Under Linux emulation it maps physical 0xe0000 for 0x20000 bytes and then faults eight bytes beyond the mapping. The same --sysinfo command succeeds as an unprivileged user. This PR provides the Linux raw SMBIOS ABI, but the root-only Geekbench crash will require separate /dev/mem compatibility handling.

Summary by Sourcery

Expose validated raw SMBIOS tables through linsysfs for Linux-compatible consumers.

New Features:

  • Expose raw SMBIOS entry-point and DMI structure table data through Linux-compatible linsysfs paths.

Bug Fixes:

  • Validate SMBIOS 2 and SMBIOS 3 entry points and their checksums before use.

Enhancements:

  • Snapshot SMBIOS metadata and structure tables for safe kernel consumers and report their actual read-only file sizes.

Build:

  • Export the SMBIOS snapshot accessors and add the raw DMI regression test to the test build.

Tests:

  • Add ATF coverage for raw SMBIOS file permissions, signatures, checksums, sizes, contents, and offset reads.

Add Linux-compatible firmware/dmi/tables files backed by validated SMBIOS entry-point and structure-table snapshots. Support SMBIOS 3 entry points, preserve the SMBIOS 2.1 length workaround, and export the data accessors for linsysfs.

Expose the binary files as root-readable raw pseudofs nodes with their actual sizes and add an ATF regression test for permissions, signatures, checksums, and offset reads.

AI-Assisted-by: OpenAI Codex
Signed-off-by: Lucas Holt <luke@foolishgames.com>
@sourcery-ai

sourcery-ai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR discovers and validates SMBIOS 2.x/3.x entry points, snapshots the entry point and structure table into kernel-owned buffers, and exposes them as Linux-compatible binary linsysfs files with accurate metadata and offset reads. A root ATF regression test verifies the exported ABI and handles systems without available SMBIOS data.

Sequence diagram for SMBIOS discovery and raw table export

sequenceDiagram
    participant SMBIOS as SMBIOS driver
    participant Firmware as Firmware SMBIOS data
    participant Kernel as Kernel snapshot buffers
    participant Linsysfs as linsysfs
    participant Consumer as Linux consumer

    SMBIOS->>Firmware: smbios_validate_eps()
    Firmware-->>SMBIOS: Valid SMBIOS 2.x or 3.x entry point
    SMBIOS->>Firmware: pmap_mapbios()
    Firmware-->>SMBIOS: Structure table
    SMBIOS->>Kernel: Copy entry point and structure table
    Consumer->>Linsysfs: Read /sys/firmware/dmi/tables/smbios_entry_point
    Linsysfs->>Kernel: smbios_get_entry_point()
    Kernel-->>Linsysfs: Snapshot and actual length
    Linsysfs-->>Consumer: Binary data at requested offset
    Consumer->>Linsysfs: Read /sys/firmware/dmi/tables/DMI
    Linsysfs->>Kernel: smbios_get_structure_table()
    Kernel-->>Linsysfs: Snapshot and actual length
    Linsysfs-->>Consumer: Binary data at requested offset
Loading

File-Level Changes

Change Details Files
Add SMBIOS 2.x and 3.x discovery, validation, and bounded table handling.
  • Prefer the SMBIOS 3 EFI entry point, with SMBIOS 2 fallback.
  • Validate entry-point signatures, lengths, primary and intermediate checksums.
  • Map and snapshot validated entry-point and structure-table data with a maximum table-size bound.
  • Export accessor APIs and module symbols for consumers.
sys/dev/smbios/smbios.c
sys/dev/smbios/smbios.h
sys/modules/bios/smbios/Makefile
Expose snapshotted SMBIOS data through Linux-compatible linsysfs files.
  • Create the firmware/dmi/tables hierarchy when both snapshots are available.
  • Provide binary, read-only mode-0400 files with actual sizes.
  • Implement bounded offset and short-read handling for both raw files.
  • Add the SMBIOS module dependency on supported architectures.
sys/compat/linsysfs/linsysfs.c
Add regression coverage for the raw SMBIOS linsysfs ABI.
  • Register an ATF shell test covering permissions, nonzero sizes, signatures, checksums, full reads, and offset reads.
  • Load and mount linsysfs as needed and skip systems without SMBIOS data.
  • Clean up dynamically loaded modules and mounts.
tests/sys/fs/linsysfs/Makefile
tests/sys/fs/linsysfs/raw_dmi_test.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@laffer1
laffer1 merged commit fbe1eed into master Sep 25, 2026
5 of 10 checks passed
@laffer1
laffer1 deleted the linux-smbios-tables branch September 25, 2026 04:23

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="sys/dev/smbios/smbios.c" line_range="197-198" />
<code_context>
+		error = ENXIO;
+		goto bad;
+	}
+	eps_data = malloc(eps_len, M_DEVBUF, M_WAITOK);
+	memcpy(eps_data, RES2EPS(sc->res), eps_len);
+
+	if (memcmp(eps_data, SMBIOS3_SIG, 5) == 0) {
</code_context>
<issue_to_address>
**issue (bug_risk):** A legacy SMBIOS 2.1 entry point with length `0x1e` is copied into a 30-byte allocation, but `struct smbios_eps` is 31 bytes and the subsequent `eps->BCD_revision` access reads one byte past that allocation. The preserved 2.1 resource-length workaround is applied only to the bus resource, not to `eps_len` used for the snapshot.

**Triggers:** When firmware provides the SMBIOS 2.1 length workaround entry point with `length == 0x1e`.

**Suggested fix:** Normalize the SMBIOS 2.1 length to `sizeof(struct smbios_eps)` before allocating and copying the snapshot, while preserving the checksum length separately if necessary.

```suggestion
	if (memcmp(RES2EPS(sc->res), SMBIOS_SIG, 4) == 0 &&
	    eps_len == 0x1e)
		eps_len = sizeof(struct smbios_eps);
	eps_data = malloc(eps_len, M_DEVBUF, M_WAITOK);
	memcpy(eps_data, RES2EPS(sc->res), eps_len);
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread sys/dev/smbios/smbios.c
Comment on lines +197 to +198
eps_data = malloc(eps_len, M_DEVBUF, M_WAITOK);
memcpy(eps_data, RES2EPS(sc->res), eps_len);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): A legacy SMBIOS 2.1 entry point with length 0x1e is copied into a 30-byte allocation, but struct smbios_eps is 31 bytes and the subsequent eps->BCD_revision access reads one byte past that allocation. The preserved 2.1 resource-length workaround is applied only to the bus resource, not to eps_len used for the snapshot.

Triggers: When firmware provides the SMBIOS 2.1 length workaround entry point with length == 0x1e.

Suggested fix: Normalize the SMBIOS 2.1 length to sizeof(struct smbios_eps) before allocating and copying the snapshot, while preserving the checksum length separately if necessary.

Suggested change
eps_data = malloc(eps_len, M_DEVBUF, M_WAITOK);
memcpy(eps_data, RES2EPS(sc->res), eps_len);
if (memcmp(RES2EPS(sc->res), SMBIOS_SIG, 4) == 0 &&
eps_len == 0x1e)
eps_len = sizeof(struct smbios_eps);
eps_data = malloc(eps_len, M_DEVBUF, M_WAITOK);
memcpy(eps_data, RES2EPS(sc->res), eps_len);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant