markqvist___RNode_Firmware/scripts/get_partition_hash.py
GlassOnTin 5a0a0df0ec Confirmed: T-Beam Supreme RX hardware failure, not firmware
Tested with both our fork AND upstream RNode firmware — neither
can receive LoRa packets on this T-Beam Supreme unit. TX works
(14KB transmitted via rnsd), noise floor measured (-86 dBm),
airtime detected from watch beacon, but RX_DONE interrupt never
fires. Decoded packets = 0 in all tests.

The watch beacon firmware is verified correct:
- IFAC crypto: all 4 tests PASS (Python round-trip verified)
- Packet format: byte-for-byte match with Python IFAC apply
- IFAC key: stored correctly in NVS, matches computed value

To verify the beacon end-to-end, a working RNode receiver is
needed (different T-Beam unit, Heltec, or the GL.inet's RNode
brought within range).
2026-03-29 16:20:51 +01:00

42 lines
1.3 KiB
Python

#!/usr/bin/env python3
"""Compute the ESP32 partition hash for an RNode firmware binary.
The ESP32 build toolchain appends a SHA256 hash to firmware binaries.
esp_partition_get_sha256() returns this embedded hash (the last 32 bytes).
This is different from sha256sum of the entire file.
Usage:
python3 get_partition_hash.py <firmware.bin>
# Flash and set hash:
python3 get_partition_hash.py build/esp32.esp32.esp32s3/RNode_Firmware.ino.bin
rnodeconf -H <output_hash> /dev/ttyACM0
"""
import hashlib
import sys
def get_partition_hash(firmware_path):
with open(firmware_path, "rb") as f:
fw = f.read()
embedded_hash = fw[-32:]
calc_hash = hashlib.sha256(fw[:-32]).digest()
if calc_hash != embedded_hash:
print(f"WARNING: Embedded hash doesn't match SHA256(fw[:-32])", file=sys.stderr)
print(f" Calculated: {calc_hash.hex()}", file=sys.stderr)
print(f" Embedded: {embedded_hash.hex()}", file=sys.stderr)
return None
return embedded_hash.hex()
if __name__ == "__main__":
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <firmware.bin>", file=sys.stderr)
sys.exit(1)
result = get_partition_hash(sys.argv[1])
if result:
print(result)
else:
sys.exit(1)