40 """Walk the image the way the ROM loader does, to find where it really ends.
42 We do not trust the file's length: a .bin can carry padding past the end of
43 the image, and then the appended digest is not the last 32 bytes of the file.
45 if len(data) < HEADER_LEN:
46 raise ImageError(f
"too short to be an image ({len(data)} bytes)")
47 if data[0] != IMAGE_MAGIC:
48 raise ImageError(f
"bad magic {data[0]:#04x}, expected {IMAGE_MAGIC:#04x}")
50 segment_count = data[1]
51 hash_appended = bool(data[23])
54 for i
in range(segment_count):
55 if off + SEGMENT_HEADER_LEN > len(data):
56 raise ImageError(f
"segment {i} header runs past end of file")
57 _load_addr, data_len = struct.unpack_from(
"<II", data, off)
58 off += SEGMENT_HEADER_LEN + data_len
60 raise ImageError(f
"segment {i} data runs past end of file")
65 off += (16 - (off % 16)) % 16
69 raise ImageError(f
"image length {off} exceeds file length {len(data)}")
72 "segment_count": segment_count,
73 "hash_appended": hash_appended,
75 "trailing_bytes": len(data) - off,
80 """Return (digest, info) -- the 32 bytes a board running this image reports."""
81 data = Path(path).read_bytes()
83 end = info[
"image_len"]
85 if info[
"hash_appended"]:
86 digest = data[end - HASH_LEN : end]
90 recomputed = hashlib.sha256(data[: end - HASH_LEN]).digest()
91 if digest != recomputed:
93 "appended digest does not match the image content it covers "
94 f
"(appended {digest.hex()}, recomputed {recomputed.hex()}); "
95 "the image is corrupt or the format has changed"
99 digest = hashlib.sha256(data[:end]).digest()
101 info[
"file_len"] = len(data)
102 info[
"file_sha256"] = hashlib.sha256(data).hexdigest()
110def _record(path: str, digest: bytes, info: dict, board: str, pio_env: str) -> dict:
111 repo = Path(__file__).resolve().parents[2]
113 "image_digest": digest.hex(),
114 "file_sha256": info[
"file_sha256"],
117 "image_len": info[
"image_len"],
121 rec[
"commits"] = [
_git(
"rev-parse",
"HEAD", cwd=str(repo))]
122 rec[
"first_seen_commit_at"] =
_git(
123 "log",
"-1",
"--format=%cI",
"HEAD", cwd=str(repo)
125 rec[
"subject"] =
_git(
"log",
"-1",
"--format=%s",
"HEAD", cwd=str(repo))
126 except (subprocess.CalledProcessError, OSError)
as exc:
127 rec[
"git_error"] = str(exc)
129 (
"run_id",
"GITHUB_RUN_ID"),
130 (
"run_attempt",
"GITHUB_RUN_ATTEMPT"),
132 if os.environ.get(env):
133 rec[key] = os.environ[env]
134 if os.environ.get(
"GITHUB_REPOSITORY")
and os.environ.get(
"GITHUB_RUN_ID"):
136 f
"https://github.com/{os.environ['GITHUB_REPOSITORY']}"
137 f
"/actions/runs/{os.environ['GITHUB_RUN_ID']}"
139 rec[
"built_by"] =
"ci" if os.environ.get(
"GITHUB_ACTIONS")
else "local"
147 (
"platform",
"STAR_PIO_PLATFORM"),
148 (
"framework",
"STAR_PIO_FRAMEWORK"),
149 (
"toolchains",
"STAR_PIO_TOOLCHAINS"),
150 (
"esptool",
"STAR_PIO_ESPTOOL"),
152 if os.environ.get(env):
153 rec[key] = os.environ[env]