Skip to content

Update stale Build HAT firmware and make version/signature reads timing-independent#2554

Closed
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-build-hat-firmware-error
Closed

Update stale Build HAT firmware and make version/signature reads timing-independent#2554
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-build-hat-firmware-error

Conversation

Copilot AI commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Instantiating a Brick throws IOException: BuildHat firmware signture error from GetBuildHatInformation(), even when the Python library has already flashed firmware. Two causes: the firmware bundled with the binding is stale (2021), and version/signature parsing depends on serial timing that breaks on faster boards (e.g. Raspberry Pi 5).

Changes

  • Refreshed bundled firmware (src/devices/BuildHat/data/{firmware.bin,signature.bin,version}) to the current official build 1737564117 (2025-01-22), matching the binaries shipped by RaspberryPiFoundation/python-build-hat (md5sums verified identical).
  • Made GetRawVersion/GetRawSignature timing-independent. They previously used ReadExisting / a fixed count of ReadLine calls, which races against the device on fast hosts. They now read whole lines (blocking on the \r\n terminator) until the expected marker appears, skipping interleaved echo, prompt, and asynchronous port lines — the same strategy the Python library uses.
private string GetRawSignature()
{
    PortWrite("signature\r");
    return PortReadUntil(FirmwareSignature);
}

// Reads lines until one contains the marker, tolerating echo/prompt/async lines.
private string PortReadUntil(string marker)
{
    const int MaximumLines = 10;
    string line = string.Empty;
    for (int i = 0; i < MaximumLines; i++)
    {
        line = PortReadLine();
        if (line.Contains(marker))
        {
            break;
        }
    }

    return line;
}

Notes

  • Contains (not StartsWith) is kept deliberately, consistent with the existing marker checks in this file and safe if the firmware prepends a prompt to the answer line.
  • Build HAT firmware is only auto-flashed from the bootloader; a device already running older firmware is not re-flashed (matches current behavior). Version-mismatch re-flashing is out of scope here.

@dotnet-policy-service dotnet-policy-service Bot added the area-device-bindings Device Bindings for audio, sensor, motor, and display hardware that can used with System.Device.Gpio label Jun 2, 2026
Copilot AI changed the title [WIP] Fix Build HAT firmware signature error on initialization Update stale Build HAT firmware and make version/signature reads timing-independent Jun 2, 2026
Copilot AI requested a review from raffaeler June 2, 2026 15:12
@joperezr

Copy link
Copy Markdown
Member

Following up on @raffaeler's request to document the firmware/signature/version consistency validation here. (The original write-up had landed in the description of #2555, which I've now closed; I re-verified everything below independently before posting.)

Firmware/signature/version consistency check ✅

This PR replaces the full firmware triple atomically — not just the version file:

File Status Change
data/firmware.bin modified Binary content replaced (51,456 bytes)
data/signature.bin modified Old signature (1E B0 13 3B 10 0D 83 3E 67 …) replaced (64 bytes)
data/version modified 16361096361737564117
Brick.cs modified GetRawVersion/GetRawSignature now read via PortReadUntil(marker) (line-by-line, timing-independent)

Upstream provenance — confirmed byte-for-byte against RaspberryPiFoundation/python-build-hat buildhat/data/:

File dotnet/iot (this PR) upstream match
firmware.bin sha256 639eb14b…5ad3fec7 (51,456 B) identical
signature.bin sha256 c162d0a7…2ab3d7b6 (64 B) identical
version 1737564117 1737564117

So the firmware, its signature, and the version string are a single matching set from the same official Raspberry Pi Build HAT release — we are not mixing a new firmware with a stale signature. The old signature bytes in the diff also match the documented value in Brick.cs (// … Firmware signature: 1E B0 13 3B 10 0D 83 3E 67 …), confirming the previous set was fully replaced rather than partially edited. Only one set may be embedded: the upload path's assembly.GetManifestResourceNames().Single(str => str.EndsWith("signature.bin")) lookup (and the bootloader's cryptographic verification) would otherwise fail with BuildHat firmware signture error.

Residual verification (not provable from source alone):

  • Hardware smoke test — a clean init on a real Build HAT (no firmware signture error) is the definitive proof, since the bootloader performs the actual cryptographic validation at upload time.

@joperezr

Copy link
Copy Markdown
Member

Closing in favor of consolidating these changes alongside the ActiveMotor pid fix (#2556). Both pieces from this PR are being carried over verbatim: the firmware refresh to build 1737564117 (firmware.bin/signature.bin are byte-identical) and the timing-independent GetRawVersion/GetRawSignature reads via PortReadUntil. Nothing is lost by closing here.

@joperezr joperezr closed this Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-device-bindings Device Bindings for audio, sensor, motor, and display hardware that can used with System.Device.Gpio

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Is the Raspberry Pi Build HAT firmware in this repository stale?

3 participants