Skip to content

Detect zen_generation for single-generation EPYC BIOSes#85

Open
vringar wants to merge 1 commit intoPSPReverse:masterfrom
vringar:zen-generation-epyc-backfill
Open

Detect zen_generation for single-generation EPYC BIOSes#85
vringar wants to merge 1 commit intoPSPReverse:masterfrom
vringar:zen-generation-epyc-backfill

Conversation

@vringar
Copy link
Copy Markdown

@vringar vringar commented May 7, 2026

Summary

EPYC server BIOSes (Naples through Turin) currently come back from PSPTool.from_file() with zen_generation = None on every directory and entry — silently. Neither of the two existing detection paths (combo_dir, tertiary self-tag) fires on a single-FET → single $PSP + $BHD layout, and no warning is emitted, so downstream tooling that bins or groups by Zen generation just drops these rows.

This adds a third detection path that runs after FET parsing: scan the PSP_FW_BOOT_LOADER (entry type 0x01) of any ROM whose directories were uniformly left unclassified, read the version major byte, and look it up in a new Directory.BOOTLOADER_VERSION_TO_ZEN map (Naples server through Turin). Apply the result to all directories in that ROM, including the $BHD/$BL2 BIOS directories that don't carry a boot loader of their own.

The back-fill is deliberately conservative:

  • Only fires when every directory in the ROM is currently None. In a multi-generation combo BIOS the boot loader belongs to one of several $PSP directories and cannot be safely associated with the sibling $BHD directories — combo_dir / tertiary remain the source of truth for those.
  • Emits a warning when a boot loader exists but its version major isn't in the table (replaces one silent-failure mode with a visible one).

Implementation note

The major byte lives at version[1], not version[2]. HeaderFile.version is reverse-sliced from header[0x63:0x5f:-1], so for a Rome boot loader printed as 0.C.0.86 we have v[0]=0x00, v[1]=0x0C, v[2]=0x00, v[3]=0x86. v[2] would silently always read 0x00 and never match.

What's in the PR

A single commit: back-fill code in psptool/directory.py + psptool/psptool.py, a small refactor in psptool/blob.py to expose POSSIBLE_FET_OFFSETS as a class constant (so the synthetic builder can derive its offsets instead of hardcoding them), a synthetic-ROM builder under tests/unit/, and a unit test that exercises the full mapping table without needing fixtures.

Test plan

  • Unit tests (no submodule needed): python -m unittest tests.unit.test_zen_generation_backfill -v — 3 tests pass. Covers known majors per BOOTLOADER_VERSION_TO_ZEN, the unrecognized-major warning path, and the no-overwrite-of-pre-classified guarantee.
  • Manual end-to-end against the real corpus (locally, before the fixture additions): Naples server (Supermicro H11DSI8, Gigabyte MZ31-AR, Tyan S8026) → Zen 1; Rome → Zen 2; Milan → Zen 3; Genoa → Zen 4; Siena → Zen 4; Turin → Zen 4 + Zen 5 (multi-ROM file). All SHA-256-verified against vendor downloads.

Companion work

The submodule URL cwerling/PSPTool-fixtures is dead and the test corpus needs to move to PSPReverse/Test-PSPTool, plus the new TestZenGenerationBackfill class in tests/integration/test_rom_files.py that exercises this fix on the real corpus. That's deliberately split out as #86 so this PR is self-contained: review the fix here, review the test-infrastructure cleanup separately. Both are individually mergeable in either order.

Out of scope / follow-ups

  • Distinguishing Zen 4 from Zen 4c (Bergamo / Siena share Zen 4 boot-loader major byte 0x29 with Genoa).
  • Detecting Zen generation for non-PSP ROMs (very old AMD platforms with no PSP). They legitimately stay None.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Metrics

psptool command line interface metrics

Metric Value
Files Processed 68
Stdout Lines 14,965
Stderr Lines 164
Total Lines 15,129
Error Ratio 1.08%

PSPTool python library metrics

Status Count Percentage
✓ Successful 68 100.0%
✗ Failed 0 0.0%
Total 68 100%

All files parsed successfully!

@vringar vringar force-pushed the zen-generation-epyc-backfill branch 2 times, most recently from d6e5506 to ec0d48a Compare May 7, 2026 20:45
EPYC server BIOSes use neither the 2PSP combo directory (AM4/AM5
combos) nor the tertiary self-tag (Zen 4 consumer), so neither of
the two existing zen_generation detection paths fires for them.
Every directory and entry comes back with zen_generation=None,
silently — no warning is emitted, so downstream tools that bin or
group by Zen generation just drop these rows.

Add a third detection path that runs after FET parsing: scan the
PSP_FW_BOOT_LOADER (entry type 0x01) for any ROM whose directories
were uniformly left unclassified, read the version major byte
(version[1] in the reverse-sliced HeaderFile.version), and look it
up in a new BOOTLOADER_VERSION_TO_ZEN map (Naples through Turin).
Apply the result to all directories in that ROM, including the
$BHD/$BL2 BIOS directories that don't carry a boot loader of their
own.

The back-fill is deliberately conservative:

  - Only fires when *every* directory in the ROM is currently None.
    In a multi-generation combo BIOS, the boot loader belongs to
    one of several $PSP directories and cannot be safely associated
    with the sibling $BHD directories — so we leave classification
    to combo_dir / tertiary in that case.
  - Emits a warning when a boot loader exists but its version major
    is not in the table (replaces one silent-failure mode with a
    visible one).

Verified against the issue's empirical corpus (Rome 4501, Milan
1002, Genoa 2305, Siena 0903, Turin V3.04 — the latter is a
multi-ROM file shipping a Genoa fallback alongside Turin); each
EPYC ROM goes from None across all directories to the expected
Zen N. AM4 combo positive controls (X470D4U2-2T 3.40) keep their
existing combo_dir output unchanged.

Also adds a synthetic-ROM builder under tests/unit/ that produces
8 MB ROM-shaped binaries with controlled boot-loader version
bytes, plus a unit test that exercises the back-fill across the
full mapping table without needing the fixtures submodule.
@vringar vringar force-pushed the zen-generation-epyc-backfill branch from ec0d48a to cb93fd0 Compare May 7, 2026 21:00
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