feat(flash): firmware pin + matches_pin detection + pm3flash CLI

Adds the 'is the device running the right firmware, and flash it if not'
layer on top of the flasher.

- _firmware.py: FirmwarePin (pinned to the firmware/ submodule commit) and
  matches() — a device version-string test against the pinned git SHA (or a
  release tag, once tagged releases exist).
- FirmwareInfo gains expected_firmware + matches_pin, computed on connect, so
  pm3.firmware.matches_pin tells you whether the fork build is present.
- pm3flash console-script: auto-detect, compare to the pin, resolve the image
  (--image / $PM3PY_FIRMWARE / local build), confirm, flash with progress,
  then reopen and verify the new version. Flashes only on mismatch unless
  --force; fullimage-only unless --allow-bootrom.

Detection + CLI are unit-tested; the auto-download layer (fetch the pinned
release asset) and hardware validation are still to come. Suite 1034 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
michael
2026-07-05 21:37:46 -07:00
parent 762e305dd9
commit b0b46b3919
5 changed files with 239 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ from .hf_iso15 import HF15Commands
from .hf_mfc import HFMFCommands
from .hf_mfu import HFMFUCommands
from .flash import Flasher
from .._firmware import FIRMWARE_PIN, matches as _fw_matches
log = logging.getLogger(__name__)
@@ -28,6 +29,8 @@ class FirmwareInfo:
section_size: int = 0
ng_protocol: bool = False
compatible: bool = False
expected_firmware: str = "" # the fork build this pm3py is pinned to
matches_pin: bool = False # device firmware == the pinned build?
warnings: list[str] = field(default_factory=list)
@@ -116,6 +119,10 @@ class Proxmark3:
except PM3Error:
fw.warnings.append("Could not read firmware version — device may be in bootloader mode")
# Step 2.5: Compare against the pinned fork firmware (for pm3flash / live-sim)
fw.expected_firmware = FIRMWARE_PIN.tag or FIRMWARE_PIN.sha
fw.matches_pin = _fw_matches(fw.version_string)
# Step 3: Assess compatibility
fw.compatible = fw.ng_protocol and len(fw.warnings) == 0