linsysfs: expose raw SMBIOS tables - #521
Conversation
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>
Reviewer's GuideThe 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 exportsequenceDiagram
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
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
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>| eps_data = malloc(eps_len, M_DEVBUF, M_WAITOK); | ||
| memcpy(eps_data, RES2EPS(sc->res), eps_len); |
There was a problem hiding this comment.
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.
| 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); |
Summary
/sys/firmware/dmi/tables/smbios_entry_pointand/sys/firmware/dmi/tables/DMIthrough linsysfs as binary mode-0400 files with their actual sizesValidation
make -j4 buildkernel KERNCONF=GENERICmake -C sys/modules/bios/smbios clean allmake -C sys/modules/linsysfs clean allmake -C tests/sys/fs/linsysfs clean allsh -n tests/sys/fs/linsysfs/dmi_id_test.sh tests/sys/fs/linsysfs/raw_dmi_test.shtools/build/checkstyle9.pl --patchgit diff --check_SM_entry point and 4087-byte DMI table with correct stat sizes and offset readsGeekbench note
Geekbench 6.4 still prefers
/dev/memwhen run as root even with these interfaces present. Under Linux emulation it maps physical0xe0000for0x20000bytes and then faults eight bytes beyond the mapping. The same--sysinfocommand succeeds as an unprivileged user. This PR provides the Linux raw SMBIOS ABI, but the root-only Geekbench crash will require separate/dev/memcompatibility handling.Summary by Sourcery
Expose validated raw SMBIOS tables through linsysfs for Linux-compatible consumers.
New Features:
Bug Fixes:
Enhancements:
Build:
Tests: