summaryrefslogtreecommitdiff
path: root/zephyr/zmake/zmake/output_packers.py
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/zmake/zmake/output_packers.py')
-rw-r--r--zephyr/zmake/zmake/output_packers.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/zephyr/zmake/zmake/output_packers.py b/zephyr/zmake/zmake/output_packers.py
new file mode 100644
index 0000000000..d8c1a8db43
--- /dev/null
+++ b/zephyr/zmake/zmake/output_packers.py
@@ -0,0 +1,163 @@
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Types which provide many builds and composite them into a single binary."""
+import logging
+import pathlib
+import subprocess
+
+import zmake.build_config as build_config
+import zmake.multiproc
+import zmake.util as util
+
+
+def _write_dts_file(dts_file, config_header, output_bin, ro_filename, rw_filename):
+ """Generate the .dts file used for binman.
+
+ Args:
+ dts_file: The dts file to write to.
+ config_header: The full path to the generated autoconf.h header.
+ output_bin: The full path to the binary that binman should output.
+ ro_filename: The RO image file name.
+ rw_filename: The RW image file name.
+
+ Returns:
+ The path to the .dts file that was generated.
+ """
+ dts_file.write("""
+ /dts-v1/;
+ #include "{config_header}"
+ / {{
+ #address-cells = <1>;
+ #size-cells = <1>;
+ binman {{
+ filename = "{output_bin}";
+ pad-byte = <0x1d>;
+ section@0 {{
+ read-only;
+ offset = <CONFIG_CROS_EC_RO_MEM_OFF>;
+ size = <CONFIG_CROS_EC_RO_SIZE>;
+ blob {{
+ filename = "{ro_filename}";
+ }};
+ }};
+ section@1 {{
+ offset = <CONFIG_CROS_EC_RW_MEM_OFF>;
+ size = <CONFIG_CROS_EC_RW_SIZE>;
+ blob {{
+ filename = "{rw_filename}";
+ }};
+ }};
+ }};
+ }};""".format(
+ output_bin=output_bin,
+ config_header=config_header,
+ ro_filename=ro_filename,
+ rw_filename=rw_filename
+ ))
+
+
+class BasePacker:
+ """Abstract base for all packers."""
+ def __init__(self, project):
+ self.project = project
+
+ def configs(self):
+ """Get all of the build configurations necessary.
+
+ Yields:
+ 2-tuples of config name and a BuildConfig.
+ """
+ yield 'singleimage', build_config.BuildConfig()
+
+ def pack_firmware(self, work_dir, jobclient):
+ """Pack a firmware image.
+
+ Config names from the configs generator are passed as keyword
+ arguments, with each argument being set to the path of the
+ build directory.
+
+ Args:
+ work_dir: A directory to write outputs and temporary files
+ into.
+ jobclient: A JobClient object to use.
+
+ Yields:
+ 2-tuples of the path of each file in the work_dir (or any
+ other directory) which should be copied into the output
+ directory, and the output filename.
+ """
+ raise NotImplementedError('Abstract method not implemented')
+
+
+class ElfPacker(BasePacker):
+ """Raw proxy for ELF output of a single build."""
+ def pack_firmware(self, work_dir, jobclient, singleimage):
+ yield singleimage / 'zephyr' / 'zephyr.elf', 'zephyr.elf'
+
+
+class RawBinPacker(BasePacker):
+ """Packer for RO/RW image to generate a .bin build using FMAP."""
+ def __init__(self, project):
+ self.logger = logging.getLogger(self.__class__.__name__)
+ super().__init__(project)
+
+ def configs(self):
+ yield 'ro', build_config.BuildConfig(kconfig_defs={'CONFIG_CROS_EC_RO': 'y'})
+ yield 'rw', build_config.BuildConfig(kconfig_defs={'CONFIG_CROS_EC_RW': 'y'})
+
+ def pack_firmware(self, work_dir, jobclient, ro, rw):
+ """Pack the 'raw' binary.
+
+ This combines the RO and RW images as specified in the Kconfig file for
+ the project. For this function to work, the following config values must
+ be defined:
+ * CONFIG_CROS_EC_RO_MEM_OFF - The offset in bytes of the RO image from
+ the start of the resulting binary.
+ * CONFIG_CROS_EC_RO_SIZE - The maximum allowed size (in bytes) of the RO
+ image.
+ * CONFIG_CROS_EC_RW_MEM_OFF - The offset in bytes of the RW image from
+ the start of the resulting binary (must be >= RO_MEM_OFF + RO_SIZE).
+ * CONFIG_CROS_EC_RW_SIZE - The maximum allowed size (in bytes) of the RW
+ image.
+
+ Args:
+ work_dir: The directory used for packing.
+ jobclient: The client used to run subprocesses.
+ ro: Directory containing the RO image build.
+ rw: Directory containing the RW image build.
+
+ Returns:
+ Tuple mapping the resulting .bin file to the output filename.
+ """
+ work_dir = pathlib.Path(work_dir).resolve()
+ ro = pathlib.Path(ro).resolve()
+ rw = pathlib.Path(rw).resolve()
+ dts_file_path = work_dir / 'project.dts'
+ with open(dts_file_path, 'w+') as dts_file:
+ _write_dts_file(
+ dts_file=dts_file,
+ config_header=ro / 'zephyr' / 'include' / 'generated' / 'autoconf.h',
+ output_bin=work_dir / 'zephyr.bin',
+ ro_filename=ro / 'zephyr' / 'zephyr.bin',
+ rw_filename=rw / 'zephyr' / 'zephyr.bin')
+
+ proc = jobclient.popen(
+ ['binman', '-v', '5', 'build', '-d', dts_file_path, '-m'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ encoding='utf-8')
+
+ zmake.multiproc.log_output(self.logger, logging.DEBUG, proc.stdout)
+ zmake.multiproc.log_output(self.logger, logging.ERROR, proc.stderr)
+ if proc.wait(timeout=5):
+ raise OSError('Failed to run binman')
+
+ yield work_dir / 'zephyr.bin', 'zephyr.bin'
+
+
+# A dictionary mapping packer config names to classes.
+packer_registry = {
+ 'elf': ElfPacker,
+ 'raw': RawBinPacker,
+}