diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/binman/btool/mkimage.py | 8 | ||||
-rw-r--r-- | tools/binman/control.py | 9 | ||||
-rw-r--r-- | tools/binman/entries.rst | 44 | ||||
-rw-r--r-- | tools/binman/etype/fit.py | 47 | ||||
-rw-r--r-- | tools/binman/ftest.py | 111 | ||||
-rw-r--r-- | tools/binman/test/343_fit_encrypt_data.dts | 53 | ||||
-rw-r--r-- | tools/binman/test/344_fit_encrypt_data_no_key.dts | 53 | ||||
-rw-r--r-- | tools/binman/test/345_fit_fdt_name.dts | 58 | ||||
-rw-r--r-- | tools/binman/test/aes256.bin | 1 | ||||
-rw-r--r-- | tools/buildman/boards.py | 25 | ||||
-rw-r--r-- | tools/buildman/buildman.rst | 63 | ||||
-rw-r--r-- | tools/buildman/func_test.py | 85 | ||||
-rwxr-xr-x | tools/buildman/main.py | 9 | ||||
-rw-r--r-- | tools/buildman/test.py | 50 | ||||
-rw-r--r-- | tools/buildman/toolchain.py | 47 | ||||
-rw-r--r-- | tools/docker/Dockerfile | 146 | ||||
-rw-r--r-- | tools/dtoc/fdt_util.py | 5 | ||||
-rw-r--r-- | tools/image-host.c | 2 | ||||
-rw-r--r-- | tools/imx8image.c | 2 | ||||
-rwxr-xr-x | tools/imx_cntr_image.sh | 4 | ||||
-rw-r--r-- | tools/u_boot_pylib/tools.py | 16 |
21 files changed, 707 insertions, 131 deletions
diff --git a/tools/binman/btool/mkimage.py b/tools/binman/btool/mkimage.py index 78d3301bc10..3f84220fb1a 100644 --- a/tools/binman/btool/mkimage.py +++ b/tools/binman/btool/mkimage.py @@ -22,7 +22,7 @@ class Bintoolmkimage(bintool.Bintool): # pylint: disable=R0913 def run(self, reset_timestamp=False, output_fname=None, external=False, - pad=None, align=None, priv_keys_dir=None): + pad=None, align=None, keys_dir=None): """Run mkimage Args: @@ -34,7 +34,7 @@ class Bintoolmkimage(bintool.Bintool): other things to be easily added later, if required, such as signatures align: Bytes to use for alignment of the FIT and its external data - priv_keys_dir: Path to directory containing private keys + keys_dir: Path to directory containing private and encryption keys version: True to get the mkimage version """ args = [] @@ -46,8 +46,8 @@ class Bintoolmkimage(bintool.Bintool): args += ['-B', f'{align:x}'] if reset_timestamp: args.append('-t') - if priv_keys_dir: - args += ['-k', f'{priv_keys_dir}'] + if keys_dir: + args += ['-k', f'{keys_dir}'] if output_fname: args += ['-F', output_fname] return self.run_cmd(*args) diff --git a/tools/binman/control.py b/tools/binman/control.py index 542c2b45644..e73c598298c 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -526,7 +526,7 @@ def _RemoveTemplates(parent): if node.name.startswith('template'): node.Delete() -def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded): +def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded, indir): """Prepare the images to be processed and select the device tree This function: @@ -543,6 +543,7 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded): use_expanded: True to use expanded versions of entries, if available. So if 'u-boot' is called for, we use 'u-boot-expanded' instead. This is needed if update_fdt is True (although tests may disable it) + indir: List of directories where input files can be found Returns: OrderedDict of images: @@ -558,7 +559,9 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded): # Get the device tree ready by compiling it and copying the compiled # output into a file in our output directly. Then scan it for use # in binman. - dtb_fname = fdt_util.EnsureCompiled(dtb_fname) + if indir is None: + indir = [] + dtb_fname = fdt_util.EnsureCompiled(dtb_fname, indir=indir) fname = tools.get_output_filename('u-boot.dtb.out') tools.write_file(fname, tools.read_file(dtb_fname)) dtb = fdt.FdtScan(fname) @@ -846,7 +849,7 @@ def Binman(args): state.SetThreads(args.threads) images = PrepareImagesAndDtbs(dtb_fname, args.image, - args.update_fdt, use_expanded) + args.update_fdt, use_expanded, args.indir) if args.test_section_timeout: # Set the first image to timeout, used in testThreadTimeout() diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index e918162fb48..780e9817fb6 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -197,7 +197,7 @@ source files that the tool examples: To run the tool:: - $ tools/binman/fip_util.py -s /path/to/trusted-firmware-a + $ tools/binman/fip_util.py -s /path/to/arm-trusted-firmware Warning: UUID 'UUID_NON_TRUSTED_WORLD_KEY_CERT' is not mentioned in tbbr_config.c file Existing code in 'tools/binman/fip_util.py' is up-to-date @@ -862,14 +862,25 @@ The top-level 'fit' node supports the following special properties: can be provided as a directory. Each .dtb file in the directory is processed, , e.g.:: - fit,fdt-list-dir = "arch/arm/dts + fit,fdt-list-dir = "arch/arm/dts"; + + In this case the input directories are ignored and all devicetree + files must be in that directory. fit,sign Enable signing FIT images via mkimage as described in - verified-boot.rst. If the property is found, the private keys path is - detected among binman include directories and passed to mkimage via - -k flag. All the keys required for signing FIT must be available at - time of signing and must be located in single include directory. + verified-boot.rst. If the property is found, the private keys path + is detected among binman include directories and passed to mkimage + via -k flag. All the keys required for signing FIT must be + available at time of signing and must be located in single include + directory. + + fit,encrypt + Enable data encryption in FIT images via mkimage. If the property + is found, the keys path is detected among binman include + directories and passed to mkimage via -k flag. All the keys + required for encrypting the FIT must be available at the time of + encrypting and must be located in a single include directory. Substitutions ~~~~~~~~~~~~~ @@ -892,6 +903,9 @@ DEFAULT-SEQ: Sequence number of the default fdt, as provided by the 'default-dt' entry argument +DEFAULT-NAME: + Name of the default fdt, as provided by the 'default-dt' entry argument + Available operations ~~~~~~~~~~~~~~~~~~~~ @@ -953,6 +967,21 @@ You can create config nodes in a similar way:: This tells binman to create nodes `config-1` and `config-2`, i.e. a config for each of your two files. +It is also possible to use NAME in the node names so that the FDT files name +will be used instead of the sequence number. This can be useful to identify +easily at runtime in U-Boot, the config to be used:: + + configurations { + default = "@config-DEFAULT-NAME"; + @config-NAME { + description = "NAME"; + firmware = "atf"; + loadables = "uboot"; + fdt = "fdt-NAME"; + fit,compatible; // optional + }; + }; + Note that if no devicetree files are provided (with '-a of-list' as above) then no nodes will be generated. @@ -985,7 +1014,8 @@ same approach can of course be used for SPL images. Note that the `of-spl-remove-props` entryarg can be used to indicate additional properties to remove. It is often used to remove properties like -`clock-names` and `pinctrl-names` which are not needed in SPL builds. +`clock-names` and `pinctrl-names` which are not needed in SPL builds. This +value is automatically passed to binman by the U-Boot build. See :ref:`fdtgrep_filter` for more information. diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py index b5afbda41b5..803fb66ea83 100644 --- a/tools/binman/etype/fit.py +++ b/tools/binman/etype/fit.py @@ -110,6 +110,13 @@ class Entry_fit(Entry_section): available at time of signing and must be located in single include directory. + fit,encrypt + Enable data encryption in FIT images via mkimage. If the property + is found, the keys path is detected among binman include + directories and passed to mkimage via -k flag. All the keys + required for encrypting the FIT must be available at the time of + encrypting and must be located in a single include directory. + Substitutions ~~~~~~~~~~~~~ @@ -131,6 +138,9 @@ class Entry_fit(Entry_section): Sequence number of the default fdt, as provided by the 'default-dt' entry argument + DEFAULT-NAME: + Name of the default fdt, as provided by the 'default-dt' entry argument + Available operations ~~~~~~~~~~~~~~~~~~~~ @@ -192,6 +202,21 @@ class Entry_fit(Entry_section): This tells binman to create nodes `config-1` and `config-2`, i.e. a config for each of your two files. + It is also possible to use NAME in the node names so that the FDT files name + will be used instead of the sequence number. This can be useful to identify + easily at runtime in U-Boot, the config to be used:: + + configurations { + default = "@config-DEFAULT-NAME"; + @config-NAME { + description = "NAME"; + firmware = "atf"; + loadables = "uboot"; + fdt = "fdt-NAME"; + fit,compatible; // optional + }; + }; + Note that if no devicetree files are provided (with '-a of-list' as above) then no nodes will be generated. @@ -452,6 +477,8 @@ class Entry_fit(Entry_section): self._fdt_dir = fdt_util.GetString(self._node, 'fit,fdt-list-dir') if self._fdt_dir: indir = tools.get_input_filename(self._fdt_dir) + if indir: + tools.append_input_dirs(indir) fdts = glob.glob('*.dtb', root_dir=indir) self._fdts = [os.path.splitext(f)[0] for f in sorted(fdts)] else: @@ -518,14 +545,14 @@ class Entry_fit(Entry_section): # are removed from self._entries later. self._priv_entries = dict(self._entries) - def _get_priv_keys_dir(self, data): - """Detect private keys path among binman include directories + def _get_keys_dir(self, data): + """Detect private and encryption keys path among binman include directories Args: data: FIT image in binary format Returns: - str: Single path containing all private keys found or None + str: Single path containing all keys found or None Raises: ValueError: Filename 'rsa2048.key' not found in input path @@ -533,11 +560,14 @@ class Entry_fit(Entry_section): """ def _find_keys_dir(node): for subnode in node.subnodes: - if subnode.name.startswith('signature'): + if (subnode.name.startswith('signature') or + subnode.name.startswith('cipher')): if subnode.props.get('key-name-hint') is None: continue hint = subnode.props['key-name-hint'].value - name = tools.get_input_filename(f"{hint}.key") + name = tools.get_input_filename( + f"{hint}.key" if subnode.name.startswith('signature') + else f"{hint}.bin") path = os.path.dirname(name) if path not in paths: paths.append(path) @@ -587,8 +617,9 @@ class Entry_fit(Entry_section): align = self._fit_props.get('fit,align') if align is not None: args.update({'align': fdt_util.fdt32_to_cpu(align.value)}) - if self._fit_props.get('fit,sign') is not None: - args.update({'priv_keys_dir': self._get_priv_keys_dir(data)}) + if (self._fit_props.get('fit,sign') is not None or + self._fit_props.get('fit,encrypt') is not None): + args.update({'keys_dir': self._get_keys_dir(data)}) if self.mkimage.run(reset_timestamp=True, output_fname=output_fname, **args) is None: if not self.GetAllowMissing(): @@ -663,6 +694,7 @@ class Entry_fit(Entry_section): f"not found in fdt list: {', '.join(self._fdts)}") seq = self._fdts.index(default_dt) val = val[1:].replace('DEFAULT-SEQ', str(seq + 1)) + val = val.replace('DEFAULT-NAME', self._fit_default_dt) fsw.property_string(pname, val) return elif pname.startswith('fit,'): @@ -729,6 +761,7 @@ class Entry_fit(Entry_section): # Generate nodes for each FDT for seq, fdt_fname in enumerate(self._fdts): node_name = node.name[1:].replace('SEQ', str(seq + 1)) + node_name = node_name.replace('NAME', fdt_fname) if self._fdt_dir: fname = os.path.join(self._fdt_dir, fdt_fname + '.dtb') else: diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 156567ace77..a553ca9e564 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -4233,56 +4233,69 @@ class TestFunctional(unittest.TestCase): self.assertEqual(SCP_DATA, data[:len(SCP_DATA)]) def CheckFitFdt(self, dts='170_fit_fdt.dts', use_fdt_list=True, - default_dt=None): + default_dt=None, use_seq_num=True): """Check an image with an FIT with multiple FDT images""" - def _CheckFdt(seq, expected_data): + def _CheckFdt(val, expected_data): """Check the FDT nodes Args: - seq: Sequence number to check (0 or 1) + val: Sequence number to check (0 or 1) or fdt name expected_data: Expected contents of 'data' property """ - name = 'fdt-%d' % seq + name = 'fdt-%s' % val fnode = dtb.GetNode('/images/%s' % name) self.assertIsNotNone(fnode) self.assertEqual({'description','type', 'compression', 'data'}, set(fnode.props.keys())) self.assertEqual(expected_data, fnode.props['data'].bytes) - self.assertEqual('fdt-test-fdt%d.dtb' % seq, - fnode.props['description'].value) + description = ( + 'fdt-test-fdt%s.dtb' % val if len(val) == 1 else + 'fdt-%s.dtb' % val + ) + self.assertEqual(description, fnode.props['description'].value) self.assertEqual(fnode.subnodes[0].name, 'hash') - def _CheckConfig(seq, expected_data): + def _CheckConfig(val, expected_data): """Check the configuration nodes Args: - seq: Sequence number to check (0 or 1) + val: Sequence number to check (0 or 1) or fdt name expected_data: Expected contents of 'data' property """ cnode = dtb.GetNode('/configurations') self.assertIn('default', cnode.props) - self.assertEqual('config-2', cnode.props['default'].value) + default = ( + 'config-2' if len(val) == 1 else + 'config-test-fdt2' + ) + self.assertEqual(default, cnode.props['default'].value) - name = 'config-%d' % seq + name = 'config-%s' % val fnode = dtb.GetNode('/configurations/%s' % name) self.assertIsNotNone(fnode) self.assertEqual({'description','firmware', 'loadables', 'fdt'}, set(fnode.props.keys())) - self.assertEqual('conf-test-fdt%d.dtb' % seq, - fnode.props['description'].value) - self.assertEqual('fdt-%d' % seq, fnode.props['fdt'].value) + description = ( + 'conf-test-fdt%s.dtb' % val if len(val) == 1 else + 'conf-%s.dtb' % val + ) + self.assertEqual(description, fnode.props['description'].value) + self.assertEqual('fdt-%s' % val, fnode.props['fdt'].value) entry_args = { 'default-dt': 'test-fdt2', } + extra_indirs = None if use_fdt_list: entry_args['of-list'] = 'test-fdt1 test-fdt2' if default_dt: entry_args['default-dt'] = default_dt + if use_fdt_list: + extra_indirs = [os.path.join(self._indir, TEST_FDT_SUBDIR)] data = self._DoReadFileDtb( dts, entry_args=entry_args, - extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0] + extra_indirs=extra_indirs)[0] self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):]) fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)] @@ -4291,13 +4304,22 @@ class TestFunctional(unittest.TestCase): fnode = dtb.GetNode('/images/kernel') self.assertIn('data', fnode.props) - # Check all the properties in fdt-1 and fdt-2 - _CheckFdt(1, TEST_FDT1_DATA) - _CheckFdt(2, TEST_FDT2_DATA) + if use_seq_num == True: + # Check all the properties in fdt-1 and fdt-2 + _CheckFdt('1', TEST_FDT1_DATA) + _CheckFdt('2', TEST_FDT2_DATA) + + # Check configurations + _CheckConfig('1', TEST_FDT1_DATA) + _CheckConfig('2', TEST_FDT2_DATA) + else: + # Check all the properties in fdt-1 and fdt-2 + _CheckFdt('test-fdt1', TEST_FDT1_DATA) + _CheckFdt('test-fdt2', TEST_FDT2_DATA) - # Check configurations - _CheckConfig(1, TEST_FDT1_DATA) - _CheckConfig(2, TEST_FDT2_DATA) + # Check configurations + _CheckConfig('test-fdt1', TEST_FDT1_DATA) + _CheckConfig('test-fdt2', TEST_FDT2_DATA) def testFitFdt(self): """Test an image with an FIT with multiple FDT images""" @@ -7900,5 +7922,54 @@ fdt fdtmap Extract the devicetree blob from the fdtmap extra_indirs=[test_subdir])[0] + def testSimpleFitEncryptedData(self): + """Test an image with a FIT containing data to be encrypted""" + data = tools.read_file(self.TestFile("aes256.bin")) + self._MakeInputFile("keys/aes256.bin", data) + + keys_subdir = os.path.join(self._indir, "keys") + data = self._DoReadFileDtb( + '343_fit_encrypt_data.dts', + extra_indirs=[keys_subdir])[0] + + fit = fdt.Fdt.FromData(data) + fit.Scan() + + # Extract the encrypted data and the Initialization Vector from the FIT + node = fit.GetNode('/images/u-boot') + subnode = fit.GetNode('/images/u-boot/cipher') + data_size_unciphered = int.from_bytes(fit.GetProps(node)['data-size-unciphered'].bytes, + byteorder='big') + self.assertEqual(data_size_unciphered, len(U_BOOT_NODTB_DATA)) + + # Retrieve the key name from the FIT removing any null byte + key_name = fit.GetProps(subnode)['key-name-hint'].bytes.replace(b'\x00', b'') + with open(self.TestFile(key_name.decode('ascii') + '.bin'), 'rb') as file: + key = file.read() + iv = fit.GetProps(subnode)['iv'].bytes.hex() + enc_data = fit.GetProps(node)['data'].bytes + outdir = tools.get_output_dir() + enc_data_file = os.path.join(outdir, 'encrypted_data.bin') + tools.write_file(enc_data_file, enc_data) + data_file = os.path.join(outdir, 'data.bin') + + # Decrypt the encrypted data from the FIT and compare the data + tools.run('openssl', 'enc', '-aes-256-cbc', '-nosalt', '-d', '-in', + enc_data_file, '-out', data_file, '-K', key.hex(), '-iv', iv) + with open(data_file, 'r') as file: + dec_data = file.read() + self.assertEqual(U_BOOT_NODTB_DATA, dec_data.encode('ascii')) + + def testSimpleFitEncryptedDataMissingKey(self): + """Test an image with a FIT containing data to be encrypted but with a missing key""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('344_fit_encrypt_data_no_key.dts') + + self.assertIn("Filename 'aes256.bin' not found in input path", str(e.exception)) + + def testFitFdtName(self): + """Test an image with an FIT with multiple FDT images using NAME""" + self.CheckFitFdt('345_fit_fdt_name.dts', use_seq_num=False) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/343_fit_encrypt_data.dts b/tools/binman/test/343_fit_encrypt_data.dts new file mode 100644 index 00000000000..d70de3426cf --- /dev/null +++ b/tools/binman/test/343_fit_encrypt_data.dts @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + fit,encrypt; + description = "Test a FIT with encrypted data"; + #address-cells = <1>; + + images { + u-boot { + description = "U-Boot"; + type = "firmware"; + arch = "arm64"; + os = "U-Boot"; + compression = "none"; + load = <00000000>; + entry = <00000000>; + cipher { + algo = "aes256"; + key-name-hint = "aes256"; + }; + u-boot-nodtb { + }; + }; + fdt-1 { + description = "Flattened Device Tree blob"; + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + cipher { + algo = "aes256"; + key-name-hint = "aes256"; + }; + }; + }; + + configurations { + default = "conf-1"; + conf-1 { + description = "Boot U-Boot with FDT blob"; + firmware = "u-boot"; + fdt = "fdt-1"; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/344_fit_encrypt_data_no_key.dts b/tools/binman/test/344_fit_encrypt_data_no_key.dts new file mode 100644 index 00000000000..d70de3426cf --- /dev/null +++ b/tools/binman/test/344_fit_encrypt_data_no_key.dts @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + fit,encrypt; + description = "Test a FIT with encrypted data"; + #address-cells = <1>; + + images { + u-boot { + description = "U-Boot"; + type = "firmware"; + arch = "arm64"; + os = "U-Boot"; + compression = "none"; + load = <00000000>; + entry = <00000000>; + cipher { + algo = "aes256"; + key-name-hint = "aes256"; + }; + u-boot-nodtb { + }; + }; + fdt-1 { + description = "Flattened Device Tree blob"; + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + cipher { + algo = "aes256"; + key-name-hint = "aes256"; + }; + }; + }; + + configurations { + default = "conf-1"; + conf-1 { + description = "Boot U-Boot with FDT blob"; + firmware = "u-boot"; + fdt = "fdt-1"; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/345_fit_fdt_name.dts b/tools/binman/test/345_fit_fdt_name.dts new file mode 100644 index 00000000000..631a8e5f59b --- /dev/null +++ b/tools/binman/test/345_fit_fdt_name.dts @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + u-boot { + }; + fit { + description = "test-desc"; + #address-cells = <1>; + fit,fdt-list = "of-list"; + + images { + kernel { + description = "Vanilla Linux kernel"; + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "sha1"; + }; + u-boot { + }; + }; + @fdt-NAME { + description = "fdt-NAME.dtb"; + type = "flat_dt"; + compression = "none"; + hash { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "@config-DEFAULT-NAME"; + @config-NAME { + description = "conf-NAME.dtb"; + firmware = "uboot"; + loadables = "atf"; + fdt = "fdt-NAME"; + }; + }; + }; + u-boot-nodtb { + }; + }; +}; diff --git a/tools/binman/test/aes256.bin b/tools/binman/test/aes256.bin new file mode 100644 index 00000000000..09b8bf6254a --- /dev/null +++ b/tools/binman/test/aes256.bin @@ -0,0 +1 @@ +1234567890abcdefghijklmnopqrstuv
\ No newline at end of file diff --git a/tools/buildman/boards.py b/tools/buildman/boards.py index 3c2822715f3..9e7b486656b 100644 --- a/tools/buildman/boards.py +++ b/tools/buildman/boards.py @@ -19,7 +19,10 @@ import time from buildman import board from buildman import kconfiglib +from u_boot_pylib import command from u_boot_pylib.terminal import print_clear, tprint +from u_boot_pylib import tools +from u_boot_pylib import tout ### constant variables ### OUTPUT_FILE = 'boards.cfg' @@ -202,6 +205,7 @@ class KconfigScanner: os.environ['KCONFIG_OBJDIR'] = '' self._tmpfile = None self._conf = kconfiglib.Kconfig(warn=False) + self._srctree = srctree def __del__(self): """Delete a leftover temporary file before exit. @@ -239,7 +243,26 @@ class KconfigScanner: expect_target, match, rear = leaf.partition('_defconfig') assert match and not rear, f'{leaf} : invalid defconfig' - self._conf.load_config(defconfig) + temp = None + if b'#include' in tools.read_file(defconfig): + cmd = [ + os.getenv('CPP', 'cpp'), + '-nostdinc', '-P', + '-I', self._srctree, + '-undef', + '-x', 'assembler-with-cpp', + defconfig] + result = command.run_pipe([cmd], capture=True, capture_stderr=True) + temp = tempfile.NamedTemporaryFile(prefix='buildman-') + tools.write_file(temp.name, result.stdout, False) + fname = temp.name + tout.info(f'Processing #include to produce {defconfig}') + else: + fname = defconfig + + self._conf.load_config(fname) + if temp: + del temp self._tmpfile = None params = {} diff --git a/tools/buildman/buildman.rst b/tools/buildman/buildman.rst index e873611e596..924564b5700 100644 --- a/tools/buildman/buildman.rst +++ b/tools/buildman/buildman.rst @@ -186,23 +186,22 @@ Setting up #. Create ~/.buildman to tell buildman where to find tool chains (see buildman_settings_ for details). As an example:: - # Buildman settings file + # Buildman settings file - [toolchain] - root: / - rest: /toolchains/* - eldk: /opt/eldk-4.2 - arm: /opt/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2013.08_linux - aarch64: /opt/linaro/gcc-linaro-aarch64-none-elf-4.8-2013.10_linux + [toolchain] + root: / + rest: /toolchains/* + eldk: /opt/eldk-4.2 + arm: /opt/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2013.08_linux + aarch64: /opt/linaro/gcc-linaro-aarch64-none-elf-4.8-2013.10_linux - [toolchain-prefix] - arc = /opt/arc/arc_gnu_2021.03_prebuilt_elf32_le_linux_install/bin/arc-elf32- - - [toolchain-alias] - riscv = riscv32 - sh = sh4 - x86: i386 + [toolchain-prefix] + arc = /opt/arc/arc_gnu_2021.03_prebuilt_elf32_le_linux_install/bin/arc-elf32- + [toolchain-alias] + riscv = riscv32 + sh = sh4 + x86: i386 This selects the available toolchain paths. Add the base directory for each of your toolchains here. Buildman will search inside these directories @@ -934,6 +933,18 @@ a set of (tag, value) pairs. For example powerpc-linux-gcc will be noted as a toolchain for 'powerpc' and CROSS_COMPILE will be set to powerpc-linux- when using it. + The tilde character ``~`` is supported in paths, to represent the home + directory. + +'[toolchain-prefix]' section + This can be used to provide the full toolchain-prefix for one or more + architectures. The full CROSS_COMPILE prefix must be provided. These + typically have a higher priority than matches in the '[toolchain]', due to + this prefix. + + The tilde character ``~`` is supported in paths, to represent the home + directory. + '[toolchain-alias]' section This converts toolchain architecture names to U-Boot names. For example, if an x86 toolchains is called i386-linux-gcc it will not normally be @@ -1112,6 +1123,30 @@ The -U option uses the u-boot.env files which are produced by a build. Internally, buildman writes out an out-env file into the build directory for later comparison. +defconfig fragments +------------------- + +Buildman provides some initial support for configuration fragments. It can scan +these when present in defconfig files and handle the resuiting Kconfig +correctly. Thus it is possible to build a board which has a ``#include`` in the +defconfig file. + +For now, Buildman simply includes the files to produce a single output file, +using the C preprocessor. It does not call the ``merge_config.sh`` script. The +redefined/redundant logic in that script could fairly easily be repeated in +Buildman, to detect potential problems. For now it is not clear that this is +useful. + +To specify the C preprocessor to use, set the ``CPP`` environment variable. The +default is ``cpp``. + +Note that Buildman does not support adding fragments to existing boards, e.g. +like:: + + make qemu_riscv64_defconfig acpi.config + +This is partly because there is no way for Buildman to know which fragments are +valid on which boards. Building with clang ------------------- diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py index 0ac9fc7e44f..4e12c671a3d 100644 --- a/tools/buildman/func_test.py +++ b/tools/buildman/func_test.py @@ -2,8 +2,10 @@ # Copyright (c) 2014 Google, Inc # +import io import os from pathlib import Path +import re import shutil import sys import tempfile @@ -373,6 +375,22 @@ class TestFunctional(unittest.TestCase): def _HandleCommandSize(self, args): return command.CommandResult(return_code=0) + def _HandleCommandCpp(self, args): + # args ['-nostdinc', '-P', '-I', '/tmp/tmp7f17xk_o/src', '-undef', + # '-x', 'assembler-with-cpp', fname] + fname = args[7] + buf = io.StringIO() + for line in tools.read_file(fname, False).splitlines(): + if line.startswith('#include'): + # Example: #include <configs/renesas_rcar2.config> + m_incfname = re.match('#include <(.*)>', line) + data = tools.read_file(m_incfname.group(1), False) + for line in data.splitlines(): + print(line, file=buf) + else: + print(line, file=buf) + return command.CommandResult(stdout=buf.getvalue(), return_code=0) + def _HandleCommand(self, **kwargs): """Handle a command execution. @@ -406,6 +424,8 @@ class TestFunctional(unittest.TestCase): return self._HandleCommandObjcopy(args) elif cmd.endswith( 'size'): return self._HandleCommandSize(args) + elif cmd.endswith( 'cpp'): + return self._HandleCommandCpp(args) if not result: # Not handled, so abort @@ -1067,3 +1087,68 @@ endif result = self._RunControl('--print-arch', 'board0') self.assertEqual('arm\n', stdout.getvalue()) self.assertEqual('', stderr.getvalue()) + + def test_kconfig_scanner(self): + """Test using the kconfig scanner to determine important values + + Note that there is already a test_scan_defconfigs() which checks the + higher-level scan_defconfigs() function. This test checks just the + scanner itself + """ + src = self._git_dir + scanner = boards.KconfigScanner(src) + + # First do a simple sanity check + norm = os.path.join(src, 'board0_defconfig') + tools.write_file(norm, 'CONFIG_TARGET_BOARD0=y', False) + res = scanner.scan(norm, True) + self.assertEqual(({ + 'arch': 'arm', + 'cpu': 'armv7', + 'soc': '-', + 'vendor': 'Tester', + 'board': 'ARM Board 0', + 'config': 'config0', + 'target': 'board0'}, []), res) + + # Check that the SoC cannot be changed and the filename does not affect + # the resulting board + tools.write_file(norm, '''CONFIG_TARGET_BOARD2=y +CONFIG_SOC="fred" +''', False) + res = scanner.scan(norm, True) + self.assertEqual(({ + 'arch': 'powerpc', + 'cpu': 'ppc', + 'soc': 'mpc85xx', + 'vendor': 'Tester', + 'board': 'PowerPC board 1', + 'config': 'config2', + 'target': 'board0'}, []), res) + + # Check handling of missing information + tools.write_file(norm, '', False) + res = scanner.scan(norm, True) + self.assertEqual(({ + 'arch': '-', + 'cpu': '-', + 'soc': '-', + 'vendor': '-', + 'board': '-', + 'config': '-', + 'target': 'board0'}, + ['WARNING: board0_defconfig: No TARGET_BOARD0 enabled']), res) + + # check handling of #include files; see _HandleCommandCpp() + inc = os.path.join(src, 'common') + tools.write_file(inc, b'CONFIG_TARGET_BOARD0=y\n') + tools.write_file(norm, f'#include <{inc}>', False) + res = scanner.scan(norm, True) + self.assertEqual(({ + 'arch': 'arm', + 'cpu': 'armv7', + 'soc': '-', + 'vendor': 'Tester', + 'board': 'ARM Board 0', + 'config': 'config0', + 'target': 'board0'}, []), res) diff --git a/tools/buildman/main.py b/tools/buildman/main.py index 3cf877e5e68..a948f36d9c0 100755 --- a/tools/buildman/main.py +++ b/tools/buildman/main.py @@ -25,6 +25,7 @@ from buildman import cmdline from buildman import control from u_boot_pylib import test_util from u_boot_pylib import tools +from u_boot_pylib import tout def run_tests(skip_net_tests, debug, verbose, args): """Run the buildman tests @@ -93,8 +94,12 @@ def run_buildman(): # Build selected commits for selected boards else: - bsettings.setup(args.config_file) - ret_code = control.do_buildman(args) + try: + tout.init(tout.INFO if args.verbose else tout.WARNING) + bsettings.setup(args.config_file) + ret_code = control.do_buildman(args) + finally: + tout.uninit() return ret_code diff --git a/tools/buildman/test.py b/tools/buildman/test.py index 15801f6097f..385a34e5254 100644 --- a/tools/buildman/test.py +++ b/tools/buildman/test.py @@ -46,6 +46,16 @@ main: /usr/sbin wrapper = ccache ''' +settings_data_homedir = ''' +# Buildman settings file + +[toolchain] +main = ~/mypath + +[toolchain-prefix] +x86 = ~/mypath-x86- +''' + migration = '''===================== WARNING ====================== This board does not use CONFIG_DM. CONFIG_DM will be compulsory starting with the v2020.01 release. @@ -1030,6 +1040,46 @@ class TestBuild(unittest.TestCase): finally: os.environ['PATH'] = old_path + def testHomedir(self): + """Test using ~ in a toolchain or toolchain-prefix section""" + # Add some test settings + bsettings.setup(None) + bsettings.add_file(settings_data_homedir) + + # Set up the toolchains + home = os.path.expanduser('~') + toolchains = toolchain.Toolchains() + toolchains.GetSettings() + self.assertEqual([f'{home}/mypath'], toolchains.paths) + + # Check scanning + with test_util.capture_sys_output() as (stdout, _): + toolchains.Scan(verbose=True, raise_on_error=False) + lines = iter(stdout.getvalue().splitlines() + ['##done']) + self.assertEqual('Scanning for tool chains', next(lines)) + self.assertEqual(f" - scanning prefix '{home}/mypath-x86-'", + next(lines)) + self.assertEqual( + f"Error: No tool chain found for prefix '{home}/mypath-x86-gcc'", + next(lines)) + self.assertEqual(f" - scanning path '{home}/mypath'", next(lines)) + self.assertEqual(f" - looking in '{home}/mypath/.'", next(lines)) + self.assertEqual(f" - looking in '{home}/mypath/bin'", next(lines)) + self.assertEqual(f" - looking in '{home}/mypath/usr/bin'", + next(lines)) + self.assertEqual('##done', next(lines)) + + # Check adding a toolchain + with test_util.capture_sys_output() as (stdout, _): + toolchains.Add('~/aarch64-linux-gcc', test=True, verbose=True) + lines = iter(stdout.getvalue().splitlines() + ['##done']) + self.assertEqual('Tool chain test: BAD', next(lines)) + self.assertEqual(f'Command: {home}/aarch64-linux-gcc --version', + next(lines)) + self.assertEqual('', next(lines)) + self.assertEqual('', next(lines)) + self.assertEqual('##done', next(lines)) + if __name__ == "__main__": unittest.main() diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py index 0c8a4fa16eb..958f36f9f61 100644 --- a/tools/buildman/toolchain.py +++ b/tools/buildman/toolchain.py @@ -65,12 +65,13 @@ class Toolchain: """Create a new toolchain object. Args: - fname: Filename of the gcc component + fname: Filename of the gcc component, possibly with ~ or $HOME in it test: True to run the toolchain to test it verbose: True to print out the information priority: Priority to use for this toolchain, or PRIORITY_CALC to calculate it """ + fname = os.path.expanduser(fname) self.gcc = fname self.path = os.path.dirname(fname) self.override_toolchain = override_toolchain @@ -109,7 +110,7 @@ class Toolchain: self.priority)) else: print('BAD') - print('Command: ', cmd) + print(f"Command: {' '.join(cmd)}") print(result.stdout) print(result.stderr) else: @@ -296,10 +297,11 @@ class Toolchains: paths = [] for name, value in toolchains: + fname = os.path.expanduser(value) if '*' in value: - paths += glob.glob(value) + paths += glob.glob(fname) else: - paths.append(value) + paths.append(fname) return paths def GetSettings(self, show_warning=True): @@ -327,16 +329,17 @@ class Toolchains: toolchain = Toolchain(fname, test, verbose, priority, arch, self.override_toolchain) add_it = toolchain.ok - if toolchain.arch in self.toolchains: - add_it = (toolchain.priority < - self.toolchains[toolchain.arch].priority) if add_it: - self.toolchains[toolchain.arch] = toolchain - elif verbose: - print(("Toolchain '%s' at priority %d will be ignored because " - "another toolchain for arch '%s' has priority %d" % - (toolchain.gcc, toolchain.priority, toolchain.arch, - self.toolchains[toolchain.arch].priority))) + if toolchain.arch in self.toolchains: + add_it = (toolchain.priority < + self.toolchains[toolchain.arch].priority) + if add_it: + self.toolchains[toolchain.arch] = toolchain + elif verbose: + print(("Toolchain '%s' at priority %d will be ignored because " + "another toolchain for arch '%s' has priority %d" % + (toolchain.gcc, toolchain.priority, toolchain.arch, + self.toolchains[toolchain.arch].priority))) def ScanPath(self, path, verbose): """Scan a path for a valid toolchain @@ -372,7 +375,7 @@ class Toolchains: pathname_list.append(pathname) return pathname_list - def Scan(self, verbose): + def Scan(self, verbose, raise_on_error=True): """Scan for available toolchains and select the best for each arch. We look for all the toolchains we can file, figure out the @@ -384,11 +387,12 @@ class Toolchains: """ if verbose: print('Scanning for tool chains') for name, value in self.prefixes: - if verbose: print(" - scanning prefix '%s'" % value) - if os.path.exists(value): - self.Add(value, True, verbose, PRIORITY_FULL_PREFIX, name) + fname = os.path.expanduser(value) + if verbose: print(" - scanning prefix '%s'" % fname) + if os.path.exists(fname): + self.Add(fname, True, verbose, PRIORITY_FULL_PREFIX, name) continue - fname = value + 'gcc' + fname += 'gcc' if os.path.exists(fname): self.Add(fname, True, verbose, PRIORITY_PREFIX_GCC, name) continue @@ -396,8 +400,11 @@ class Toolchains: for f in fname_list: self.Add(f, True, verbose, PRIORITY_PREFIX_GCC_PATH, name) if not fname_list: - raise ValueError("No tool chain found for prefix '%s'" % - value) + msg = f"No tool chain found for prefix '{fname}'" + if raise_on_error: + raise ValueError(msg) + else: + print(f'Error: {msg}') for path in self.paths: if verbose: print(" - scanning path '%s'" % path) fnames = self.ScanPath(path, verbose) diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 967ac89fbde..d2848ab85f3 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -2,37 +2,62 @@ # This Dockerfile is used to build an image containing basic stuff to be used # to build U-Boot and run our test suites. -FROM ubuntu:jammy-20240808 +FROM ubuntu:jammy-20240911.1 LABEL org.opencontainers.image.authors="Tom Rini <trini@konsulko.com>" LABEL org.opencontainers.image.description=" This image is for building U-Boot inside a container" +# Used by docker to set the target platform: valid values are linux/arm64/v8 +# and linux/amd64 +ARG TARGETPLATFORM + +# Used by docker to set the build platform: the only valid value is linux/amd64 +ARG BUILDPLATFORM + # Make sure apt is happy ENV DEBIAN_FRONTEND=noninteractive +# Set architectures to build for (leaving out ARM which is an exception) +ENV ARCHS="aarch64 arc i386 m68k mips microblaze nios2 powerpc riscv64 riscv32 sh2 x86_64" + +# Mirror containing the toolchains +ENV MIRROR=https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin + +# Toolchain version +ENV TCVER=13.2.0 + +RUN echo "Building on $BUILDPLATFORM, for target $TARGETPLATFORM" + # Add LLVM repository -RUN apt-get update && apt-get install -y gnupg2 wget xz-utils && rm -rf /var/lib/apt/lists/* +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && apt-get install -y gnupg2 wget xz-utils RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - RUN echo deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main | tee /etc/apt/sources.list.d/llvm.list -# Manually install the kernel.org "Crosstool" based toolchains for gcc-13.2.0 -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-aarch64-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-arc-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-arm-linux-gnueabi.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-i386-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-m68k-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-mips-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-microblaze-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-nios2-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-powerpc-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-riscv64-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-riscv32-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-sh2-linux.tar.xz | tar -C /opt -xJ +# Create a list of URLs to process, then pass them into a 'while read' loop +RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then HOSTARCH=x86_64; else HOSTARCH=arm64; fi; ( \ + # Manually install the kernel.org "Crosstool"-based toolchains + for arch in $ARCHS; do \ + echo $MIRROR/$HOSTARCH/$TCVER/${HOSTARCH}-gcc-$TCVER-nolibc-${arch}-linux.tar.xz; \ + done; \ + \ + # Deal with ARM, which has a 'gnueabi' suffix + echo $MIRROR/${HOSTARCH}/$TCVER/${HOSTARCH}-gcc-$TCVER-nolibc-arm-linux-gnueabi.tar.xz; \ + \ + ) | while read url; do \ + # Read the URL and unpack it into /opt + wget -O - $url | tar -C /opt -xJ; \ + done # Manually install other toolchains -RUN wget -O - https://github.com/foss-xtensa/toolchain/releases/download/2020.07/x86_64-2020.07-xtensa-dc233c-elf.tar.gz | tar -C /opt -xz +RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \ + wget -O - https://github.com/foss-xtensa/toolchain/releases/download/2020.07/x86_64-2020.07-xtensa-dc233c-elf.tar.gz | tar -C /opt -xz; \ + fi # Update and install things from apt now -RUN apt-get update && apt-get install -y \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && apt-get install -y \ automake \ autopoint \ bc \ @@ -54,17 +79,15 @@ RUN apt-get update && apt-get install -y \ flex \ gawk \ gdisk \ + gettext \ git \ gnu-efi \ gnutls-dev \ graphviz \ - grub-efi-amd64-bin \ - grub-efi-ia32-bin \ help2man \ iasl \ imagemagick \ iputils-ping \ - libc6-i386 \ libconfuse-dev \ libgit2-dev \ libjson-glib-dev \ @@ -82,7 +105,7 @@ RUN apt-get update && apt-get install -y \ libtool \ libudev-dev \ libusb-1.0-0-dev \ - linux-image-kvm \ + linux-image-generic \ lzma-alone \ lzop \ mount \ @@ -118,8 +141,7 @@ RUN apt-get update && apt-get install -y \ vboot-utils \ xilinx-bootgen \ xxd \ - zip \ - && rm -rf /var/lib/apt/lists/* + zip # Make kernels readable for libguestfs tools to work correctly RUN chmod +r /boot/vmlinu* @@ -127,21 +149,19 @@ RUN chmod +r /boot/vmlinu* # Build GRUB UEFI targets for ARM & RISC-V, 32-bit and 64-bit RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \ cd /tmp/grub && \ - git checkout grub-2.06 && \ + git checkout grub-2.12 && \ git config --global user.name "GitLab CI Runner" && \ git config --global user.email trini@konsulko.com && \ - git cherry-pick 049efdd72eb7baa7b2bf8884391ee7fe650da5a0 && \ - git cherry-pick 403d6540cd608b2706cfa0cb4713f7e4b490ff45 && \ ./bootstrap && \ mkdir -p /opt/grub && \ ./configure --target=aarch64 --with-platform=efi \ CC=gcc \ - TARGET_CC=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-objcopy \ - TARGET_STRIP=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-strip \ - TARGET_NM=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-nm \ - TARGET_RANLIB=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-ranlib && \ - make && \ + TARGET_CC=/opt/gcc-${TCVER}-nolibc/aarch64-linux/bin/aarch64-linux-gcc \ + TARGET_OBJCOPY=/opt/gcc-${TCVER}-nolibc/aarch64-linux/bin/aarch64-linux-objcopy \ + TARGET_STRIP=/opt/gcc-${TCVER}-nolibc/aarch64-linux/bin/aarch64-linux-strip \ + TARGET_NM=/opt/gcc-${TCVER}-nolibc/aarch64-linux/bin/aarch64-linux-nm \ + TARGET_RANLIB=/opt/gcc-${TCVER}-nolibc/aarch64-linux/bin/aarch64-linux-ranlib && \ + make -j$(nproc) && \ ./grub-mkimage -O arm64-efi -o /opt/grub/grubaa64.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ lsefisystab loadenv lvm minicmd normal part_msdos part_gpt reboot \ @@ -150,12 +170,12 @@ RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \ make clean && \ ./configure --target=arm --with-platform=efi \ CC=gcc \ - TARGET_CC=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-objcopy \ - TARGET_STRIP=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-strip \ - TARGET_NM=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-nm \ - TARGET_RANLIB=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ranlib && \ - make && \ + TARGET_CC=/opt/gcc-${TCVER}-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc \ + TARGET_OBJCOPY=/opt/gcc-${TCVER}-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-objcopy \ + TARGET_STRIP=/opt/gcc-${TCVER}-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-strip \ + TARGET_NM=/opt/gcc-${TCVER}-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-nm \ + TARGET_RANLIB=/opt/gcc-${TCVER}-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ranlib && \ + make -j$(nproc) && \ ./grub-mkimage -O arm-efi -o /opt/grub/grubarm.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ lsefisystab loadenv lvm minicmd normal part_msdos part_gpt reboot \ @@ -164,17 +184,39 @@ RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \ make clean && \ ./configure --target=riscv64 --with-platform=efi \ CC=gcc \ - TARGET_CC=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-objcopy \ - TARGET_STRIP=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-strip \ - TARGET_NM=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-nm \ - TARGET_RANLIB=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-ranlib && \ - make && \ + TARGET_CC=/opt/gcc-${TCVER}-nolibc/riscv64-linux/bin/riscv64-linux-gcc \ + TARGET_OBJCOPY=/opt/gcc-${TCVER}-nolibc/riscv64-linux/bin/riscv64-linux-objcopy \ + TARGET_STRIP=/opt/gcc-${TCVER}-nolibc/riscv64-linux/bin/riscv64-linux-strip \ + TARGET_NM=/opt/gcc-${TCVER}-nolibc/riscv64-linux/bin/riscv64-linux-nm \ + TARGET_RANLIB=/opt/gcc-${TCVER}-nolibc/riscv64-linux/bin/riscv64-linux-ranlib && \ + make -j$(nproc) && \ ./grub-mkimage -O riscv64-efi -o /opt/grub/grubriscv64.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ lsefisystab loadenv lvm minicmd normal part_msdos part_gpt reboot \ search search_fs_file search_fs_uuid search_label serial sleep test \ true && \ + make clean && \ + ./configure --target=i386 --with-platform=efi \ + CC=gcc \ + TARGET_CC=/opt/gcc-${TCVER}-nolibc/i386-linux/bin/i386-linux-gcc \ + TARGET_OBJCOPY=/opt/gcc-${TCVER}-nolibc/i386-linux/bin/i386-linux-objcopy \ + TARGET_STRIP=/opt/gcc-${TCVER}-nolibc/i386-linux/bin/i386-linux-strip \ + TARGET_NM=/opt/gcc-${TCVER}-nolibc/i386-linux/bin/i386-linux-nm \ + TARGET_RANLIB=/opt/gcc-${TCVER}-nolibc/i386-linux/bin/i386-linux-ranlib && \ + make -j$(nproc) && \ + ./grub-mkimage -O i386-efi -o /opt/grub/grub_x86.efi --prefix= -d \ + grub-core normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd && \ + make clean && \ + ./configure --target=x86_64 --with-platform=efi \ + CC=gcc \ + TARGET_CC=/opt/gcc-${TCVER}-nolibc/x86_64-linux/bin/x86_64-linux-gcc \ + TARGET_OBJCOPY=/opt/gcc-${TCVER}-nolibc/x86_64-linux/bin/x86_64-linux-objcopy \ + TARGET_STRIP=/opt/gcc-${TCVER}-nolibc/x86_64-linux/bin/x86_64-linux-strip \ + TARGET_NM=/opt/gcc-${TCVER}-nolibc/x86_64-linux/bin/x86_64-linux-nm \ + TARGET_RANLIB=/opt/gcc-${TCVER}-nolibc/x86_64-linux/bin/x86_64-linux-ranlib && \ + make -j$(nproc) && \ + ./grub-mkimage -O x86_64-efi -o /opt/grub/grub_x64.efi --prefix= -d \ + grub-core normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd && \ rm -rf /tmp/grub RUN git clone https://gitlab.com/qemu-project/qemu.git /tmp/qemu && \ @@ -195,7 +237,7 @@ RUN git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git /tmp/t cd /tmp/tf-a/ && \ git checkout v2.10.0 && \ cd tools/fiptool && \ - make && \ + make -j$(nproc) && \ mkdir -p /usr/local/bin && \ cp fiptool /usr/local/bin && \ rm -rf /tmp/tf-a @@ -276,13 +318,17 @@ RUN virtualenv -p /usr/bin/python3 /tmp/venv && \ rm -rf /tmp/venv /tmp/*-requirements.txt # Create the buildman config file -RUN /bin/echo -e "[toolchain]\nroot = /usr" > ~/.buildman -RUN /bin/echo -e "kernelorg = /opt/gcc-13.2.0-nolibc/*" >> ~/.buildman -RUN /bin/echo -e "\n[toolchain-prefix]\nxtensa = /opt/2020.07/xtensa-dc233c-elf/bin/xtensa-dc233c-elf-" >> ~/.buildman; +RUN /bin/echo -e "[toolchain]\nkernelorg = /opt/gcc-${TCVER}-nolibc/*" > ~/.buildman +RUN /bin/echo -e "root = /usr" >> ~/.buildman +RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \ + /bin/echo -e "\n[toolchain-prefix]\nxtensa = /opt/2020.07/xtensa-dc233c-elf/bin/xtensa-dc233c-elf-" >> ~/.buildman; \ + fi +RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \ + /bin/echo -e "\n[toolchain-prefix]\naarch64 = /opt/gcc-${TCVER}-nolibc/aarch64-linux/bin/aarch64-linux-" >> ~/.buildman; \ + fi RUN /bin/echo -e "\n[toolchain-alias]\nsh = sh2" >> ~/.buildman -RUN /bin/echo -e "\nsandbox = x86_64" >> ~/.buildman RUN /bin/echo -e "\nx86 = i386" >> ~/.buildman; # Add mkbootimg tool RUN git clone https://android.googlesource.com/platform/system/tools/mkbootimg /home/uboot/mkbootimg -ENV PYTHONPATH "${PYTHONPATH}:/home/uboot/mkbootimg" +ENV PYTHONPATH="${PYTHONPATH}:/home/uboot/mkbootimg" diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py index f1f70568cfe..d5ecc4207d8 100644 --- a/tools/dtoc/fdt_util.py +++ b/tools/dtoc/fdt_util.py @@ -55,7 +55,7 @@ def fdt_cells_to_cpu(val, cells): out = out << 32 | fdt32_to_cpu(val[1]) return out -def EnsureCompiled(fname, tmpdir=None, capture_stderr=False): +def EnsureCompiled(fname, tmpdir=None, capture_stderr=False, indir=None): """Compile an fdt .dts source file into a .dtb binary blob if needed. Args: @@ -63,6 +63,7 @@ def EnsureCompiled(fname, tmpdir=None, capture_stderr=False): left alone tmpdir: Temporary directory for output files, or None to use the tools-module output directory + indir: List of directories where input files can be found Returns: Filename of resulting .dtb file @@ -79,6 +80,8 @@ def EnsureCompiled(fname, tmpdir=None, capture_stderr=False): dtb_output = tools.get_output_filename('source.dtb') search_paths = [os.path.join(os.getcwd(), 'include')] + if indir is not None: + search_paths += indir root, _ = os.path.splitext(fname) cc, args = tools.get_target_compile_tool('cc') args += ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__'] diff --git a/tools/image-host.c b/tools/image-host.c index 5e01b853c50..16389bd4880 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -535,7 +535,7 @@ fit_image_process_cipher(const char *keydir, void *keydest, void *fit, * size values * And, if needed, write the iv in the FIT file */ - if (keydest) { + if (keydest || (!keydest && !info.ivname)) { ret = info.cipher->add_cipher_data(&info, keydest, fit, node_noffset); if (ret) { fprintf(stderr, diff --git a/tools/imx8image.c b/tools/imx8image.c index 7a060811c7e..15510d3e712 100644 --- a/tools/imx8image.c +++ b/tools/imx8image.c @@ -734,7 +734,7 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align) fclose(fd); if (header.tag != IVT_HEADER_TAG_B0) { - fprintf(stderr, "header tag mismatched \n"); + fprintf(stderr, "header tag mismatched file %s\n", img_sp->filename); exit(EXIT_FAILURE); } else { file_off += diff --git a/tools/imx_cntr_image.sh b/tools/imx_cntr_image.sh index 972b95ccbee..07acd385631 100755 --- a/tools/imx_cntr_image.sh +++ b/tools/imx_cntr_image.sh @@ -14,6 +14,10 @@ for f in $blobs; do continue fi + if [ $f = "spl/u-boot-spl.bin" ]; then + continue + fi + if [ -f $f ]; then continue fi diff --git a/tools/u_boot_pylib/tools.py b/tools/u_boot_pylib/tools.py index 187725b5015..0499a75526f 100644 --- a/tools/u_boot_pylib/tools.py +++ b/tools/u_boot_pylib/tools.py @@ -123,6 +123,22 @@ def set_input_dirs(dirname): indir = dirname tout.debug("Using input directories %s" % indir) +def append_input_dirs(dirname): + """Append a list of input directories to the current list of input + directories + + Args: + dirname: a list of paths to input directories to use for obtaining + files needed by binman to place in the image. + """ + global indir + + for dir in dirname: + if dirname not in indir: + indir.append(dirname) + + tout.debug("Updated input directories %s" % indir) + def get_input_filename(fname, allow_missing=False): """Return a filename for use as input. |