Skip to content

Commit 69c55d8

Browse files
Michael Eskowitzozersa
authored andcommitted
scripts: imgtool: Add script to combine multiple image as single
MCUBoot multi image support mode requires each image be procedded individually that requires multiple signature check during boot. If there be 4 imageis it requires 4 times signature validatation. This feature increase boot time. Depend on the project requirement long boot time may not be accepted. To provide a solution for this case we propose to - Generate each image as regular mcuboot format - Concatanate them and re generate a main mcuboot image. As below ------------------------- | Header | ------------------------- | Image-1 | | (Header+Data+Footer) | ------------------------- | Image-2 | | (Header+Data+Footer) | ------------------------- | ..... | ------------------------- | Footer | ------------------------- During boot time if top level image be validated sub image can be just copied to the target location without to recheck them. There will be two commit to implement this feature 1- Add a script that combine images 2- Update mcuboot source code to process subimages This commit is for #1, it adds a script which called as combine_images.py. Any imgtool parameters can be passed to the script It will directly pass them to the imgtool. Usage: python combine_images.py --config combine_images.yaml --imgtool imgtool --output <outfolder> combine_images.yaml file is added as reference file it need to be updated as per of the project need. Signed-off-by: Sadik Ozer <sadik.ozer@analog.com> Signed-off-by: Michael Eskowitz <Michael.Eskowitz@analog.com>
1 parent 3c8e571 commit 69c55d8

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

scripts/combine_images.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#! /usr/bin/env python3
2+
#
3+
# Copyright (C) 2025 Analog Devices, Inc.
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
import argparse
20+
import os
21+
import pathlib
22+
import subprocess
23+
import sys
24+
25+
import yaml
26+
import shutil
27+
28+
29+
def main():
30+
global img_tool
31+
global output_dir
32+
global config_path
33+
34+
parser = argparse.ArgumentParser(description="Create application package", allow_abbrev=False)
35+
parser.add_argument('--config', help="The path to config yaml file", required=True)
36+
parser.add_argument('--imgtool', help="The path to ImgTool", required=True)
37+
parser.add_argument('--output', help="Output directory", required=True)
38+
39+
args = parser.parse_args()
40+
41+
if not os.path.isfile(args.config):
42+
print(f"Error: The config file '{args.config}' does not exist")
43+
return
44+
45+
config_path = os.path.dirname(os.path.abspath(args.config))
46+
print(f"config_path: {config_path}")
47+
48+
with open(args.config) as config_file:
49+
config = yaml.safe_load(config_file)
50+
51+
img_tool = args.imgtool
52+
if img_tool.endswith('.py'):
53+
if not os.path.exists(img_tool): # Is python file exist?
54+
print(f"Error: The '{img_tool}' not found")
55+
return
56+
else:
57+
if not shutil.which(img_tool): # Is binary file exist?
58+
print(f"Error: The '{img_tool}' not found in the path")
59+
return
60+
61+
62+
output_dir = args.output
63+
os.makedirs(output_dir, exist_ok=True)
64+
65+
parse_app_pack(config, None)
66+
67+
print(f"\nCreated {package_name}")
68+
69+
70+
def verify_file_exists(filename):
71+
filepath = pathlib.Path(filename)
72+
73+
if not filepath.exists():
74+
print("ERROR: File " + filename + " not found")
75+
sys.exit(1)
76+
77+
78+
def parse_app_pack(app_pack, name):
79+
params = None
80+
image = []
81+
global package_name
82+
83+
for key in app_pack:
84+
if key.endswith("_pack"):
85+
imagename = parse_app_pack(app_pack[key], name)
86+
image += [imagename]
87+
if key.lower() == "params":
88+
params = app_pack[key]
89+
if key.lower() == "infile":
90+
if app_pack[key] != "":
91+
image_path = os.path.join(config_path, app_pack[key])
92+
verify_file_exists(image_path)
93+
image += [image_path]
94+
if key.lower() == "outfile":
95+
name = app_pack[key]
96+
97+
# Exit if params or image are not specified
98+
if (params is None) or (image is None):
99+
return None
100+
101+
cmd = []
102+
if img_tool.endswith('.py'):
103+
cmd += [sys.executable]
104+
105+
cmd += [img_tool]
106+
cmd += ["sign"]
107+
cmd += params.split()
108+
109+
# Combine images for parent package (top level package)
110+
if len(image) > 1:
111+
combined_images = os.path.join(output_dir, "combined.bin")
112+
113+
with open(combined_images, 'wb') as outfile:
114+
for fname in image:
115+
with open(fname, 'rb') as infile:
116+
outfile.write(infile.read())
117+
infile.close()
118+
outfile.close()
119+
120+
image_input = combined_images
121+
else:
122+
image_input = image[0]
123+
124+
image_output = os.path.join(output_dir, name)
125+
126+
cmd += [image_input]
127+
cmd += [image_output]
128+
129+
print(f'Calling imgtool to generate file {image_output}')
130+
package_name = image_output
131+
subprocess.run(cmd)
132+
133+
return image_output
134+
135+
136+
if __name__ == "__main__":
137+
main()

scripts/combine_images.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#
2+
# Copyright (C) 2025 Analog Devices, Inc.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
19+
img0_pack:
20+
outfile: combined_signed.bin
21+
params: "--key ../root-rsa-2048.pem --header-size 0x20 --align 4 --load-addr 0x20080000 --pad-header --version 1.0.0 --slot-size 0x100000"
22+
23+
img1_pack:
24+
infile: img1.bin
25+
outfile: img1_signed.bin
26+
params: "--key ../root-rsa-2048.pem --header-size 0x20 --align 4 --load-addr 0x20010000 --pad-header --version 1.0.0 --slot-size 0x10000"
27+
28+
img2_pack:
29+
infile: img2.bin
30+
outfile: img2_signed.bin
31+
params: "--key ../root-rsa-2048.pem --header-size 0x20 --align 4 --load-addr 0x20020000 --pad-header --version 1.0.0 --slot-size 0x10000"
32+
33+
img3_pack:
34+
infile: img3.bin
35+
outfile: img3_signed.bin
36+
params: "--key ../root-rsa-2048.pem --header-size 0x20 --align 4 --load-addr 0x20030000 --pad-header --version 1.0.0 --slot-size 0x10000"

0 commit comments

Comments
 (0)