blob: fdc738dc58ee83be906c850f13138ce897fb356a [file] [log] [blame]
Marti Bolivard1780aa2019-01-30 20:30:42 -07001# Copyright (c) 2018 Foundries.io
2#
3# SPDX-License-Identifier: Apache-2.0
4
5import abc
6import argparse
7import os
Marti Bolivar2f839da2019-06-12 11:25:23 -06008import pathlib
Martí Bolívar9c92baa2020-07-08 14:43:07 -07009import pickle
Martí Bolívar698db692021-02-02 12:20:47 -080010import platform
Marti Bolivar4a0f1f22019-02-14 14:49:03 -070011import shutil
Marti Bolivard1780aa2019-01-30 20:30:42 -070012import subprocess
Martí Bolívard8f459a2019-11-12 14:55:03 -080013import sys
Marti Bolivard1780aa2019-01-30 20:30:42 -070014
Marti Bolivard1780aa2019-01-30 20:30:42 -070015from west import log
Marti Bolivard1780aa2019-01-30 20:30:42 -070016from west.util import quote_sh_list
17
Martí Bolívard8f459a2019-11-12 14:55:03 -080018from build_helpers import find_build_dir, is_zephyr_build, \
Marti Bolivar3bd07a22019-06-12 11:48:50 -060019 FIND_BUILD_DIR_DESCRIPTION
Martí Bolívard8f459a2019-11-12 14:55:03 -080020from runners.core import BuildConfiguration
21from zcmake import CMakeCache
Dominik Ermel09980d62021-01-19 18:19:36 +000022from zephyr_ext_common import Forceable, ZEPHYR_SCRIPTS
Jun Li2d5fb6d2019-05-07 02:00:20 -070023
Martí Bolívar9c92baa2020-07-08 14:43:07 -070024# This is needed to load edt.pickle files.
Mikkel Jakobsen3fe785d2021-04-06 15:05:23 +020025sys.path.append(str(ZEPHYR_SCRIPTS / 'dts' / 'python-devicetree' / 'src'))
Martí Bolívar6dab1632020-02-10 16:53:06 -080026
Marti Bolivard1780aa2019-01-30 20:30:42 -070027SIGN_DESCRIPTION = '''\
28This command automates some of the drudgery of creating signed Zephyr
29binaries for chain-loading by a bootloader.
30
31In the simplest usage, run this from your build directory:
32
33 west sign -t your_tool -- ARGS_FOR_YOUR_TOOL
34
Andrei Emeltchenkofb441882020-07-07 11:57:51 +030035The "ARGS_FOR_YOUR_TOOL" value can be any additional
Marti Bolivard1780aa2019-01-30 20:30:42 -070036arguments you want to pass to the tool, such as the location of a
37signing key, a version identifier, etc.
38
39See tool-specific help below for details.'''
40
41SIGN_EPILOG = '''\
42imgtool
43-------
44
Andrei Emeltchenko51182ab2020-07-06 15:37:00 +030045To build a signed binary you can load with MCUboot using imgtool,
46run this from your build directory:
Marti Bolivard1780aa2019-01-30 20:30:42 -070047
48 west sign -t imgtool -- --key YOUR_SIGNING_KEY.pem
49
Marti Bolivar4a0f1f22019-02-14 14:49:03 -070050For this to work, either imgtool must be installed (e.g. using pip3),
51or you must pass the path to imgtool.py using the -p option.
52
Andrei Emeltchenkofb441882020-07-07 11:57:51 +030053Assuming your binary was properly built for processing and handling by
54imgtool, this creates zephyr.signed.bin and zephyr.signed.hex
55files which are ready for use by your bootloader.
56
Marti Bolivard1780aa2019-01-30 20:30:42 -070057The image header size, alignment, and slot sizes are determined from
Marti Bolivar4a0f1f22019-02-14 14:49:03 -070058the build directory using .config and the device tree. A default
59version number of 0.0.0+0 is used (which can be overridden by passing
60"--version x.y.z+w" after "--key"). As shown above, extra arguments
Andrei Emeltchenko51182ab2020-07-06 15:37:00 +030061after a '--' are passed to imgtool directly.
62
63rimage
64------
65
66To create a signed binary with the rimage tool, run this from your build
67directory:
68
69 west sign -t rimage -- -k YOUR_SIGNING_KEY.pem
70
71For this to work, either rimage must be installed or you must pass
72the path to rimage using the -p option.'''
Marti Bolivard1780aa2019-01-30 20:30:42 -070073
74
75class ToggleAction(argparse.Action):
76
77 def __call__(self, parser, args, ignored, option):
78 setattr(args, self.dest, not option.startswith('--no-'))
79
80
81class Sign(Forceable):
82 def __init__(self):
83 super(Sign, self).__init__(
84 'sign',
85 # Keep this in sync with the string in west-commands.yml.
86 'sign a Zephyr binary for bootloader chain-loading',
87 SIGN_DESCRIPTION,
88 accepts_unknown_args=False)
89
90 def do_add_parser(self, parser_adder):
91 parser = parser_adder.add_parser(
92 self.name,
93 epilog=SIGN_EPILOG,
94 help=self.help,
95 formatter_class=argparse.RawDescriptionHelpFormatter,
96 description=self.description)
97
Marti Bolivar3bd07a22019-06-12 11:48:50 -060098 parser.add_argument('-d', '--build-dir',
99 help=FIND_BUILD_DIR_DESCRIPTION)
Martí Bolívar9b673672020-08-19 15:29:37 -0700100 parser.add_argument('-q', '--quiet', action='store_true',
101 help='suppress non-error output')
Marti Bolivard1780aa2019-01-30 20:30:42 -0700102 self.add_force_arg(parser)
103
104 # general options
105 group = parser.add_argument_group('tool control options')
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200106 group.add_argument('-t', '--tool', choices=['imgtool', 'rimage'],
107 required=True,
108 help='''image signing tool name; imgtool and rimage
109 are currently supported''')
Marti Bolivar4a0f1f22019-02-14 14:49:03 -0700110 group.add_argument('-p', '--tool-path', default=None,
Marti Bolivard1780aa2019-01-30 20:30:42 -0700111 help='''path to the tool itself, if needed''')
Anas Nashifb5531662021-01-25 13:57:20 -0500112 group.add_argument('-D', '--tool-data', default=None,
113 help='''path to tool data/configuration directory, if needed''')
Marti Bolivard1780aa2019-01-30 20:30:42 -0700114 group.add_argument('tool_args', nargs='*', metavar='tool_opt',
115 help='extra option(s) to pass to the signing tool')
116
117 # bin file options
118 group = parser.add_argument_group('binary (.bin) file options')
119 group.add_argument('--bin', '--no-bin', dest='gen_bin', nargs=0,
120 action=ToggleAction,
121 help='''produce a signed .bin file?
Marti Bolivard371c542019-06-12 11:39:09 -0600122 (default: yes, if supported and unsigned bin
123 exists)''')
Marti Bolivard1780aa2019-01-30 20:30:42 -0700124 group.add_argument('-B', '--sbin', metavar='BIN',
Marti Bolivard1780aa2019-01-30 20:30:42 -0700125 help='''signed .bin file name
Marti Bolivar33cbba32019-06-12 10:29:01 -0600126 (default: zephyr.signed.bin in the build
127 directory, next to zephyr.bin)''')
Marti Bolivard1780aa2019-01-30 20:30:42 -0700128
129 # hex file options
130 group = parser.add_argument_group('Intel HEX (.hex) file options')
131 group.add_argument('--hex', '--no-hex', dest='gen_hex', nargs=0,
132 action=ToggleAction,
133 help='''produce a signed .hex file?
Marti Bolivard371c542019-06-12 11:39:09 -0600134 (default: yes, if supported and unsigned hex
135 exists)''')
Marti Bolivard1780aa2019-01-30 20:30:42 -0700136 group.add_argument('-H', '--shex', metavar='HEX',
Marti Bolivard1780aa2019-01-30 20:30:42 -0700137 help='''signed .hex file name
Marti Bolivar33cbba32019-06-12 10:29:01 -0600138 (default: zephyr.signed.hex in the build
139 directory, next to zephyr.hex)''')
Marti Bolivard1780aa2019-01-30 20:30:42 -0700140
Marti Bolivard1780aa2019-01-30 20:30:42 -0700141 return parser
142
143 def do_run(self, args, ignored):
Marti Bolivarf13fa532019-02-14 10:01:00 -0700144 self.args = args # for check_force
Marti Bolivard371c542019-06-12 11:39:09 -0600145
146 # Find the build directory and parse .config and DT.
147 build_dir = find_build_dir(args.build_dir)
Marti Bolivar06c9f8e2019-06-12 11:49:02 -0600148 self.check_force(os.path.isdir(build_dir),
149 'no such build directory {}'.format(build_dir))
150 self.check_force(is_zephyr_build(build_dir),
Marti Bolivard1780aa2019-01-30 20:30:42 -0700151 "build directory {} doesn't look like a Zephyr build "
Marti Bolivar06c9f8e2019-06-12 11:49:02 -0600152 'directory'.format(build_dir))
Martí Bolívar250b2132021-04-28 16:20:38 -0700153 build_conf = BuildConfiguration(build_dir)
Marti Bolivard1780aa2019-01-30 20:30:42 -0700154
Marti Bolivard371c542019-06-12 11:39:09 -0600155 # Decide on output formats.
156 formats = []
Martí Bolívar250b2132021-04-28 16:20:38 -0700157 bin_exists = build_conf.getboolean('CONFIG_BUILD_OUTPUT_BIN')
Marti Bolivard371c542019-06-12 11:39:09 -0600158 if args.gen_bin:
159 self.check_force(bin_exists,
160 '--bin given but CONFIG_BUILD_OUTPUT_BIN not set '
161 "in build directory's ({}) .config".
162 format(build_dir))
163 formats.append('bin')
164 elif args.gen_bin is None and bin_exists:
165 formats.append('bin')
166
Martí Bolívar250b2132021-04-28 16:20:38 -0700167 hex_exists = build_conf.getboolean('CONFIG_BUILD_OUTPUT_HEX')
Marti Bolivard371c542019-06-12 11:39:09 -0600168 if args.gen_hex:
169 self.check_force(hex_exists,
Marti Bolivard371c542019-06-12 11:39:09 -0600170 '--hex given but CONFIG_BUILD_OUTPUT_HEX not set '
171 "in build directory's ({}) .config".
172 format(build_dir))
173 formats.append('hex')
174 elif args.gen_hex is None and hex_exists:
175 formats.append('hex')
176
Marti Bolivard371c542019-06-12 11:39:09 -0600177 # Delegate to the signer.
Marti Bolivard1780aa2019-01-30 20:30:42 -0700178 if args.tool == 'imgtool':
179 signer = ImgtoolSigner()
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200180 elif args.tool == 'rimage':
181 signer = RimageSigner()
Marti Bolivard1780aa2019-01-30 20:30:42 -0700182 # (Add support for other signers here in elif blocks)
183 else:
184 raise RuntimeError("can't happen")
185
Martí Bolívar250b2132021-04-28 16:20:38 -0700186 signer.sign(self, build_dir, build_conf, formats)
Marti Bolivard1780aa2019-01-30 20:30:42 -0700187
188
189class Signer(abc.ABC):
190 '''Common abstract superclass for signers.
191
192 To add support for a new tool, subclass this and add support for
193 it in the Sign.do_run() method.'''
194
195 @abc.abstractmethod
Martí Bolívar250b2132021-04-28 16:20:38 -0700196 def sign(self, command, build_dir, build_conf, formats):
Marti Bolivard1780aa2019-01-30 20:30:42 -0700197 '''Abstract method to perform a signature; subclasses must implement.
198
Marti Bolivar4a0f1f22019-02-14 14:49:03 -0700199 :param command: the Sign instance
Marti Bolivar06c9f8e2019-06-12 11:49:02 -0600200 :param build_dir: the build directory
Martí Bolívar250b2132021-04-28 16:20:38 -0700201 :param build_conf: BuildConfiguration for build directory
Marti Bolivard371c542019-06-12 11:39:09 -0600202 :param formats: list of formats to generate ('bin', 'hex')
Marti Bolivard1780aa2019-01-30 20:30:42 -0700203 '''
204
205
206class ImgtoolSigner(Signer):
207
Martí Bolívar250b2132021-04-28 16:20:38 -0700208 def sign(self, command, build_dir, build_conf, formats):
Martí Bolívard8f459a2019-11-12 14:55:03 -0800209 if not formats:
210 return
Marti Bolivar4a0f1f22019-02-14 14:49:03 -0700211
Martí Bolívard8f459a2019-11-12 14:55:03 -0800212 args = command.args
213 b = pathlib.Path(build_dir)
Martí Bolívard8f459a2019-11-12 14:55:03 -0800214
Martí Bolívarb4903d42021-02-02 12:05:58 -0800215 imgtool = self.find_imgtool(command, args)
Martí Bolívard8f459a2019-11-12 14:55:03 -0800216 # The vector table offset is set in Kconfig:
Martí Bolívar250b2132021-04-28 16:20:38 -0700217 vtoff = self.get_cfg(command, build_conf, 'CONFIG_ROM_START_OFFSET')
Martí Bolívard8f459a2019-11-12 14:55:03 -0800218 # Flash device write alignment and the partition's slot size
219 # come from devicetree:
Martí Bolívar9b673672020-08-19 15:29:37 -0700220 flash = self.edt_flash_node(b, args.quiet)
Martí Bolívard8f459a2019-11-12 14:55:03 -0800221 align, addr, size = self.edt_flash_params(flash)
222
Arvin Farahmand2de6bf92021-05-06 14:49:07 -0400223 if not build_conf.getboolean('CONFIG_BOOTLOADER_MCUBOOT'):
Martí Bolívar74929972020-08-07 15:40:05 -0700224 log.wrn("CONFIG_BOOTLOADER_MCUBOOT is not set to y in "
Martí Bolívar250b2132021-04-28 16:20:38 -0700225 f"{build_conf.path}; this probably won't work")
Martí Bolívar74929972020-08-07 15:40:05 -0700226
Martí Bolívar250b2132021-04-28 16:20:38 -0700227 kernel = build_conf.get('CONFIG_KERNEL_BIN_NAME', 'zephyr')
Martí Bolívar74929972020-08-07 15:40:05 -0700228
Martí Bolívard8f459a2019-11-12 14:55:03 -0800229 if 'bin' in formats:
Martí Bolívar74929972020-08-07 15:40:05 -0700230 in_bin = b / 'zephyr' / f'{kernel}.bin'
231 if not in_bin.is_file():
232 log.die(f"no unsigned .bin found at {in_bin}")
233 in_bin = os.fspath(in_bin)
Martí Bolívard8f459a2019-11-12 14:55:03 -0800234 else:
235 in_bin = None
236 if 'hex' in formats:
Martí Bolívar74929972020-08-07 15:40:05 -0700237 in_hex = b / 'zephyr' / f'{kernel}.hex'
238 if not in_hex.is_file():
239 log.die(f"no unsigned .hex found at {in_hex}")
240 in_hex = os.fspath(in_hex)
Martí Bolívard8f459a2019-11-12 14:55:03 -0800241 else:
242 in_hex = None
243
Martí Bolívar9b673672020-08-19 15:29:37 -0700244 if not args.quiet:
245 log.banner('image configuration:')
246 log.inf('partition offset: {0} (0x{0:x})'.format(addr))
247 log.inf('partition size: {0} (0x{0:x})'.format(size))
248 log.inf('rom start offset: {0} (0x{0:x})'.format(vtoff))
Martí Bolívard8f459a2019-11-12 14:55:03 -0800249
250 # Base sign command.
251 #
252 # We provide a default --version in case the user is just
253 # messing around and doesn't want to set one. It will be
254 # overridden if there is a --version in args.tool_args.
Martí Bolívarb4903d42021-02-02 12:05:58 -0800255 sign_base = imgtool + ['sign',
256 '--version', '0.0.0+0',
257 '--align', str(align),
258 '--header-size', str(vtoff),
259 '--slot-size', str(size)]
Martí Bolívard8f459a2019-11-12 14:55:03 -0800260 sign_base.extend(args.tool_args)
261
Martí Bolívar9b673672020-08-19 15:29:37 -0700262 if not args.quiet:
263 log.banner('signing binaries')
Martí Bolívard8f459a2019-11-12 14:55:03 -0800264 if in_bin:
265 out_bin = args.sbin or str(b / 'zephyr' / 'zephyr.signed.bin')
266 sign_bin = sign_base + [in_bin, out_bin]
Martí Bolívar9b673672020-08-19 15:29:37 -0700267 if not args.quiet:
268 log.inf(f'unsigned bin: {in_bin}')
269 log.inf(f'signed bin: {out_bin}')
270 log.dbg(quote_sh_list(sign_bin))
Martí Bolívard8f459a2019-11-12 14:55:03 -0800271 subprocess.check_call(sign_bin)
272 if in_hex:
273 out_hex = args.shex or str(b / 'zephyr' / 'zephyr.signed.hex')
274 sign_hex = sign_base + [in_hex, out_hex]
Martí Bolívar9b673672020-08-19 15:29:37 -0700275 if not args.quiet:
276 log.inf(f'unsigned hex: {in_hex}')
277 log.inf(f'signed hex: {out_hex}')
278 log.dbg(quote_sh_list(sign_hex))
Martí Bolívard8f459a2019-11-12 14:55:03 -0800279 subprocess.check_call(sign_hex)
280
281 @staticmethod
282 def find_imgtool(command, args):
Marti Bolivar4a0f1f22019-02-14 14:49:03 -0700283 if args.tool_path:
Martí Bolívar698db692021-02-02 12:20:47 -0800284 imgtool = args.tool_path
285 if not os.path.isfile(imgtool):
286 log.die(f'--tool-path {imgtool}: no such file')
287 else:
288 imgtool = shutil.which('imgtool') or shutil.which('imgtool.py')
289 if not imgtool:
290 log.die('imgtool not found; either install it',
291 '(e.g. "pip3 install imgtool") or provide --tool-path')
Martí Bolívarb4903d42021-02-02 12:05:58 -0800292
Martí Bolívar698db692021-02-02 12:20:47 -0800293 if platform.system() == 'Windows' and imgtool.endswith('.py'):
294 # Windows users may not be able to run .py files
295 # as executables in subprocesses, regardless of
296 # what the mode says. Always run imgtool as
297 # 'python path/to/imgtool.py' instead of
298 # 'path/to/imgtool.py' in these cases.
299 # https://github.com/zephyrproject-rtos/zephyr/issues/31876
300 return [sys.executable, imgtool]
301
Martí Bolívarb4903d42021-02-02 12:05:58 -0800302 return [imgtool]
Marti Bolivar2f839da2019-06-12 11:25:23 -0600303
Ulf Magnussonbb634162019-09-04 16:28:50 +0200304 @staticmethod
Martí Bolívar250b2132021-04-28 16:20:38 -0700305 def get_cfg(command, build_conf, item):
Marti Bolivar4a0f1f22019-02-14 14:49:03 -0700306 try:
Martí Bolívar250b2132021-04-28 16:20:38 -0700307 return build_conf[item]
Marti Bolivar4a0f1f22019-02-14 14:49:03 -0700308 except KeyError:
309 command.check_force(
Martí Bolívard8f459a2019-11-12 14:55:03 -0800310 False, "build .config is missing a {} value".format(item))
Marti Bolivar4a0f1f22019-02-14 14:49:03 -0700311 return None
Martí Bolívard8f459a2019-11-12 14:55:03 -0800312
313 @staticmethod
Martí Bolívar9b673672020-08-19 15:29:37 -0700314 def edt_flash_node(b, quiet=False):
Martí Bolívard8f459a2019-11-12 14:55:03 -0800315 # Get the EDT Node corresponding to the zephyr,flash chosen DT
Martí Bolívar9c92baa2020-07-08 14:43:07 -0700316 # node; 'b' is the build directory as a pathlib object.
Martí Bolívard8f459a2019-11-12 14:55:03 -0800317
318 # Ensure the build directory has a compiled DTS file
319 # where we expect it to be.
Martí Bolívar9c92baa2020-07-08 14:43:07 -0700320 dts = b / 'zephyr' / 'zephyr.dts'
Martí Bolívar9b673672020-08-19 15:29:37 -0700321 if not quiet:
322 log.dbg('DTS file:', dts, level=log.VERBOSE_VERY)
Martí Bolívar9c92baa2020-07-08 14:43:07 -0700323 edt_pickle = b / 'zephyr' / 'edt.pickle'
324 if not edt_pickle.is_file():
325 log.die("can't load devicetree; expected to find:", edt_pickle)
Martí Bolívard8f459a2019-11-12 14:55:03 -0800326
Martí Bolívar9c92baa2020-07-08 14:43:07 -0700327 # Load the devicetree.
328 with open(edt_pickle, 'rb') as f:
329 edt = pickle.load(f)
Martí Bolívard8f459a2019-11-12 14:55:03 -0800330
331 # By convention, the zephyr,flash chosen node contains the
332 # partition information about the zephyr image to sign.
333 flash = edt.chosen_node('zephyr,flash')
334 if not flash:
335 log.die('devicetree has no chosen zephyr,flash node;',
336 "can't infer flash write block or image-0 slot sizes")
337
338 return flash
339
340 @staticmethod
341 def edt_flash_params(flash):
Fabio Utzig716ab472020-08-17 08:59:36 -0300342 # Get the flash device's write alignment and offset from the
343 # image-0 partition and the size from image-1 partition, out of the
344 # build directory's devicetree. image-1 partition size is used,
345 # when available, because in swap-move mode it can be one sector
346 # smaller. When not available, fallback to image-0 (single image dfu).
Martí Bolívard8f459a2019-11-12 14:55:03 -0800347
348 # The node must have a "partitions" child node, which in turn
Fabio Utzig716ab472020-08-17 08:59:36 -0300349 # must have child node labeled "image-0" and may have a child node
350 # named "image-1". By convention, the slots for consumption by
351 # imgtool are linked into these partitions.
Martí Bolívard8f459a2019-11-12 14:55:03 -0800352 if 'partitions' not in flash.children:
353 log.die("DT zephyr,flash chosen node has no partitions,",
Fabio Utzig716ab472020-08-17 08:59:36 -0300354 "can't find partitions for MCUboot slots")
Martí Bolívard8f459a2019-11-12 14:55:03 -0800355
Fabio Utzig716ab472020-08-17 08:59:36 -0300356 partitions = flash.children['partitions']
357 images = {
358 node.label: node for node in partitions.children.values()
359 if node.label in set(['image-0', 'image-1'])
360 }
361
362 if 'image-0' not in images:
363 log.die("DT zephyr,flash chosen node has no image-0 partition,",
364 "can't determine its address")
Martí Bolívard8f459a2019-11-12 14:55:03 -0800365
366 # Die on missing or zero alignment or slot_size.
367 if "write-block-size" not in flash.props:
368 log.die('DT zephyr,flash node has no write-block-size;',
369 "can't determine imgtool write alignment")
370 align = flash.props['write-block-size'].val
371 if align == 0:
372 log.die('expected nonzero flash alignment, but got '
373 'DT flash device write-block-size {}'.format(align))
Martí Bolívard8f459a2019-11-12 14:55:03 -0800374
Fabio Utzig716ab472020-08-17 08:59:36 -0300375 # The partitions node, and its subnode, must provide
376 # the size of image-1 or image-0 partition via the regs property.
377 image_key = 'image-1' if 'image-1' in images else 'image-0'
378 if not images[image_key].regs:
379 log.die(f'{image_key} flash partition has no regs property;',
380 "can't determine size of image")
381
382 # always use addr of image-0, which is where images are run
383 addr = images['image-0'].regs[0].addr
384
385 size = images[image_key].regs[0].size
386 if size == 0:
387 log.die('expected nonzero slot size for {}'.format(image_key))
388
389 return (align, addr, size)
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200390
391class RimageSigner(Signer):
392
Martí Bolívar250b2132021-04-28 16:20:38 -0700393 def sign(self, command, build_dir, build_conf, formats):
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200394 args = command.args
395
396 if args.tool_path:
397 command.check_force(shutil.which(args.tool_path),
398 '--tool-path {}: not an executable'.
399 format(args.tool_path))
400 tool_path = args.tool_path
401 else:
402 tool_path = shutil.which('rimage')
403 if not tool_path:
404 log.die('rimage not found; either install it',
405 'or provide --tool-path')
406
Marc Herbert2fdc5512022-02-19 07:29:03 +0000407 #### -c sof/rimage/config/signing_schema.toml ####
408
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200409 b = pathlib.Path(build_dir)
410 cache = CMakeCache.from_build_dir(build_dir)
411
Marc Herbert2fdc5512022-02-19 07:29:03 +0000412 # warning: RIMAGE_TARGET is a duplicate of CONFIG_RIMAGE_SIGNING_SCHEMA
Maureen Helm525fa762021-11-17 08:05:25 -0600413 target = cache.get('RIMAGE_TARGET')
414 if not target:
415 log.die('rimage target not defined')
416
Marc Herbert2fdc5512022-02-19 07:29:03 +0000417 cmake_toml = target + '.toml'
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200418
Martí Bolívar9b673672020-08-19 15:29:37 -0700419 if not args.quiet:
420 log.inf('Signing with tool {}'.format(tool_path))
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200421
Iuliana Prodan602e6752021-10-01 19:10:57 +0300422 if target in ('imx8', 'imx8m'):
Iuliana Prodan82304212021-06-30 03:15:21 +0300423 kernel = str(b / 'zephyr' / 'zephyr.elf')
424 out_bin = str(b / 'zephyr' / 'zephyr.ri')
425 out_xman = str(b / 'zephyr' / 'zephyr.ri.xman')
426 out_tmp = str(b / 'zephyr' / 'zephyr.rix')
427 else:
Andy Ross2906d1a2021-12-10 15:37:17 -0800428 bootloader = str(b / 'zephyr' / 'boot.mod')
429 kernel = str(b / 'zephyr' / 'main.mod')
Iuliana Prodan82304212021-06-30 03:15:21 +0300430 out_bin = str(b / 'zephyr' / 'zephyr.ri')
431 out_xman = str(b / 'zephyr' / 'zephyr.ri.xman')
432 out_tmp = str(b / 'zephyr' / 'zephyr.rix')
Marc Herbert2fdc5512022-02-19 07:29:03 +0000433
Anas Nashiffee9af22021-01-25 13:59:57 -0500434 conf_path_cmd = []
Marc Herbert2fdc5512022-02-19 07:29:03 +0000435
436 if '-c' in args.tool_args:
437 # Precedence to the -- rimage command line
438 conf_path_cmd = []
439 if args.tool_data:
440 log.wrn('--tool-data ' + args.tool_data + ' ignored, overridden by -c')
441 # For logging only
442 conf_path = args.tool_args[args.tool_args.index('-c') + 1]
Anas Nashiffee9af22021-01-25 13:59:57 -0500443 elif args.tool_data:
444 conf_dir = pathlib.Path(args.tool_data)
Marc Herbert2fdc5512022-02-19 07:29:03 +0000445 conf_path = str(conf_dir / cmake_toml)
446 conf_path_cmd = ['-c', conf_path]
447 elif cache.get('RIMAGE_CONFIG_PATH'):
448 rimage_conf = pathlib.Path(cache['RIMAGE_CONFIG_PATH'])
449 conf_path = str(rimage_conf / cmake_toml)
Anas Nashiffee9af22021-01-25 13:59:57 -0500450 conf_path_cmd = ['-c', conf_path]
451 else:
Marc Herbert2fdc5512022-02-19 07:29:03 +0000452 log.die('-c configuration not found')
453
454 log.inf('Signing for SOC target ' + target + ' using ' + conf_path)
455
Jian Kang8c9b06a2021-02-03 17:05:24 +0800456 if '--no-manifest' in args.tool_args:
457 no_manifest = True
458 args.tool_args.remove('--no-manifest')
459 else:
460 no_manifest = False
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200461
Daniel Leung10eab232021-09-21 13:37:33 -0700462 if no_manifest:
463 extra_ri_args = ['-i', '3']
464 else:
465 extra_ri_args = ['-i', '3', '-e']
466
Iuliana Prodan602e6752021-10-01 19:10:57 +0300467 components = [ ] if (target in ('imx8', 'imx8m')) else [ bootloader ]
468 components += [ kernel ]
469 sign_base = ([tool_path] + args.tool_args +
470 ['-o', out_bin] + conf_path_cmd + extra_ri_args +
471 components)
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200472
Martí Bolívar9b673672020-08-19 15:29:37 -0700473 if not args.quiet:
474 log.inf(quote_sh_list(sign_base))
Andrei Emeltchenkod44d9862019-11-19 12:35:49 +0200475 subprocess.check_call(sign_base)
Guennadi Liakhovetski3de40b42020-10-27 12:48:36 +0100476
Jian Kang8c9b06a2021-02-03 17:05:24 +0800477 if no_manifest:
478 filenames = [out_bin]
479 else:
480 filenames = [out_xman, out_bin]
Marc Herbert2fdc5512022-02-19 07:29:03 +0000481 if not args.quiet:
482 log.inf('Prefixing ' + out_bin + ' with manifest ' + out_xman)
Guennadi Liakhovetski3de40b42020-10-27 12:48:36 +0100483 with open(out_tmp, 'wb') as outfile:
484 for fname in filenames:
485 with open(fname, 'rb') as infile:
486 outfile.write(infile.read())
487
488 os.remove(out_bin)
489 os.rename(out_tmp, out_bin)