1. Today's topic
We learn to establish:
which firmware is running;
which commit it was built from;
which toolchain was used;
which sdkconfig was used;
the binary's SHA-256;
which ELF is required for the coredump.The main idea: version=1.8.0 is not enough. Complete firmware identity consists of source, configuration, dependencies, toolchain and the hash of the specific artifact.
2. Why this matters
For postmortem analysis, an address cannot be symbolicated based on the version alone:
version=1.8.0
PC=0x40091a42The same version may have been built with different sdkconfig, stack sizes, patches and component versions. You need:
Git commit;
dirty state;
ESP-IDF version;
sdkconfig hash;
dependencies.lock hash;
ELF SHA-256;
firmware.bin SHA-256.For EC25, complete device identity also includes:
EC25 firmware;
MBN profile;
hardware revision;
config generation.3. Theory
Version, build identity, reproducibility, authenticity
- Version: 1.8.0 — convenient for a person.
- Build identity: commit, configuration, dependencies and toolchain.
- Reproducibility: two independent builds produce identical bytes.
- Authenticity: the release manifest is signed with a trusted key.
A Git commit is not enough
If the working tree is dirty, the commit does not describe the binary. A release must require:
git_dirty=falseESP-IDF reproducible build
In sdkconfig.defaults:
CONFIG_APP_REPRODUCIBLE_BUILD=yDo not use:
__DATE__
__TIME__Toolchain pinning
Poor approach:
image: espressif/idf:latestBetter approach:
image: espressif/idf:v6.0.2@sha256:<digest>esp_app_desc_t
ESP-IDF includes esp_app_desc_t in the image:
project name;
version;
ESP-IDF version;
secure version;
app_elf_sha256.The runtime CLI version command must display these fields.
Release manifest
The manifest links:
source -> environment -> configuration -> artifacts -> validationExample fields:
{
"project": "traffic-controller",
"version": "1.8.0",
"git_commit": "9ac04be12f91",
"dirty": false,
"idf": "v6.0.2",
"sdkconfig_sha256": "...",
"app_bin_sha256": "...",
"app_elf_sha256": "...",
"hil_result": "passed"
}Do not try to embed the binary's SHA-256 inside the binary itself: that is a self-reference. Store the final binary's hash in an external manifest.
STM32
For STM32, preserve:
firmware.elf;
firmware.map;
firmware.hex/bin;
.ioc;
startup;
linker script;
HAL/LL/CMSIS versions;
STM32CubeMX version;
compiler version;
build flags.It is better to keep generated code in Git and check in CI that regenerating the .ioc produces no diff.
4. Common mistakes
- The version contains only 1.8.0.
- The release is built from a dirty tree.
- Using __DATE__/__TIME__.
- CI uses latest.
- Managed components are not pinned.
- The .bin is saved, but the .elf is deleted.
- An ELF from a different build is used for a coredump.
- sdkconfig is not preserved.
- STM32 .ioc and CubeMX version are not preserved.
- Production rebuilds firmware locally instead of using the CI artifact.
5. A practical task for 30–60 minutes
Create RELEASE_POLICY.md:
# Firmware release policy
1. Release builds are created only by CI.
2. Release source trees must be clean.
3. Every release has a semantic version and Git commit.
4. ESP-IDF and toolchain are pinned by container digest.
5. sdkconfig and dependency lock are archived.
6. Reproducible build mode is enabled.
7. Application ELF and BIN must reproduce bit-for-bit.
8. ELF, map, binaries and flash metadata are retained.
9. All artifacts have SHA-256 hashes.
10. Release manifest is signed.
11. Production flashes only immutable release artifacts.
12. Field diagnostics report firmware and modem identities.Check two builds in different directories:
cmp /tmp/repro-a/build/traffic_controller.bin /tmp/repro-b/build/traffic_controller.bin
cmp /tmp/repro-a/build/traffic_controller.elf /tmp/repro-b/build/traffic_controller.elfAssemble a release bundle:
.bin
.elf
.map
bootloader.bin
partition-table.bin
partition CSV
flasher_args.json
sdkconfig
dependencies.lock
version.txt
manifest
HIL report6. What to read or try next
- ESP-IDF Reproducible Builds.
- esp_app_desc_t and App Image Format.
- IDF Component Manager dependencies.lock.
- STM32CubeMX command-line generation and user code sections.
Criteria: Use complete build identity rather than a version label alone.
Exercise
Review a release bundle containing only firmware.bin and version.txt. Name the evidence missing for reproducibility and postmortem analysis, without rebuilding anything.
Self-check criteria: Distinguish saved artifacts from demonstrated reproducibility. Keep the binary hash external to avoid self-reference.
Show the supplied answer
Preserve the exact ELF, configuration/sdkconfig and dependency lock, source commit and clean-tree status, pinned toolchain, relevant map/flash metadata, artifact SHA-256 values and the external release manifest. Reproducibility is checked with independent builds, not inferred from version.txt.