Skip to content

Commit 683fe50

Browse files
committed
feat: Enhance firmware manifest generation with optional gzip-compressed app binary and improved SHA256 handling
1 parent 1bc72ce commit 683fe50

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

fw/scripts/ci/generate_firmware_manifest.py

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import argparse
77
import hashlib
88
import datetime
9+
import gzip
910

1011
def main():
1112
parser = argparse.ArgumentParser(description='Generate firmware manifest and copy binary')
@@ -93,24 +94,50 @@ def main():
9394
sys.exit(1)
9495

9596
# Destination binary name
96-
bin_name = f"{product_id.replace('/', '-')}_firmware_ce_v{version}.bin"
97-
dest_bin = os.path.join(output_dir, bin_name)
97+
merged_bin_name = f"{product_id.replace('/', '-')}_firmware_ce_v{version}.bin"
98+
merged_dest_bin = os.path.join(output_dir, merged_bin_name)
9899

99100
# Copy the binary
100-
shutil.copy2(source_bin, dest_bin)
101-
print(f"Copied {source_bin} to {dest_bin}")
101+
shutil.copy2(source_bin, merged_dest_bin)
102+
print(f"Copied {source_bin} to {merged_dest_bin}")
102103

103104
# Calculate sha256 of the copied binary
104105
sha256_hash = hashlib.sha256()
105-
with open(dest_bin, "rb") as f:
106+
with open(merged_dest_bin, "rb") as f:
106107
for chunk in iter(lambda: f.read(4096), b""):
107108
sha256_hash.update(chunk)
108-
binary_sha256 = sha256_hash.hexdigest()
109-
print(f"SHA256 of {dest_bin}: {binary_sha256}")
109+
merged_binary_sha256 = sha256_hash.hexdigest()
110+
print(f"SHA256 of {merged_dest_bin}: {merged_binary_sha256}")
111+
112+
# Handle optional "app" binary which should be compressed and hashed
113+
app_source = os.path.join(
114+
base_dir, 'build', f"{product_id.replace('/', '_')}.bin")
115+
if not os.path.exists(app_source):
116+
print(f"App binary {app_source} does not exist")
117+
sys.exit(1)
118+
119+
ota_filename = f"{product_id.replace('/', '-')}_ota_ce_v{version}.bin.gz"
120+
ota_dest = os.path.join(output_dir, ota_filename)
121+
122+
# gzip-compress the app binary
123+
with open(app_source, "rb") as src, gzip.open(ota_dest, "wb") as dst:
124+
shutil.copyfileobj(src, dst)
125+
print(f"Compressed {app_source} to {ota_dest}")
126+
127+
# Calculate sha256 of the compressed app
128+
ota_sha256 = hashlib.sha256()
129+
with open(ota_dest, "rb") as f:
130+
for chunk in iter(lambda: f.read(4096), b""):
131+
ota_sha256.update(chunk)
132+
ota_hash = ota_sha256.hexdigest()
133+
print(f"SHA256 of {ota_dest}: {ota_hash}")
110134

111135
# Generate manifest
112136
# timestamp in milliseconds since epoch
113137
timestamp_ms = int(datetime.datetime.utcnow().timestamp() * 1000)
138+
# The manifest now includes an optional gzip-compressed "app" binary
139+
# alongside the merged firmware. app_path is the filename (relative to
140+
# output_dir) and app_hash is the SHA256 of the compressed file.
114141

115142
manifest = {
116143
"name": device_name,
@@ -119,7 +146,10 @@ def main():
119146
"manufacturer": manufacturer,
120147
"compatible": compatible,
121148
"version": version,
122-
"sha256": binary_sha256,
149+
"sha256": merged_binary_sha256,
150+
"ota_filename": ota_filename,
151+
"ota_sha256": ota_hash,
152+
"merged_filename": merged_bin_name,
123153
"timestamp": timestamp_ms,
124154
"new_install_prompt_erase": True,
125155
"new_install_improv_wait_time": 0,
@@ -128,7 +158,7 @@ def main():
128158
"chipFamily": chip_family,
129159
"parts": [
130160
{
131-
"path": "/firmware/" + bin_name,
161+
"path": "/firmware/" + merged_bin_name,
132162
"offset": 0
133163
}
134164
]

fw/scripts/ci/merge_manifest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ def main():
3838

3939
try:
4040
with open(args.output, 'w', encoding='utf-8') as f:
41-
json.dump(merged_data, f, separators=(
42-
',', ':'), ensure_ascii=False)
41+
json.dump(merged_data, f, indent=4)
4342
print(f"Successfully merged {len(merged_data)} manifest files into '{args.output}'.")
4443
except Exception as e:
4544
print(f"Error writing to output file '{args.output}': {e}")

0 commit comments

Comments
 (0)