From 1a549c8961a6db72db374a4db2be598b30c9c46d Mon Sep 17 00:00:00 2001 From: Ilya Lukin <4.shket@gmail.com> Date: Fri, 14 Jul 2023 17:39:32 +0300 Subject: crc32: Drop duplicates crc header includes Fixes: 3db711085752 ("crc32: Use the crc.h header for crc functions") Signed-off-by: Ilya Lukin <4.shket@gmail.com> --- tools/default_image.c | 1 - 1 file changed, 1 deletion(-) (limited to 'tools') diff --git a/tools/default_image.c b/tools/default_image.c index 0e49ab33015..04bc85bf932 100644 --- a/tools/default_image.c +++ b/tools/default_image.c @@ -15,7 +15,6 @@ #include "imagetool.h" #include "mkimage.h" -#include #include #include -- cgit v1.2.3 From d5737b3f6a0239caf2dd5578a4bc8ebfccfdee3b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Aug 2023 16:40:28 -0600 Subject: expo: Tidy up the expo.py tool and usage Tidy up this tool a little: - define which arguments are needed - split the enum values out into a header file - warn if no enum values are found - display the dtc error if something goes wrong - avoid a Python traceback on error Signed-off-by: Simon Glass --- tools/expo.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/expo.py b/tools/expo.py index c6eb87aec73..ea80c70f04e 100755 --- a/tools/expo.py +++ b/tools/expo.py @@ -69,7 +69,10 @@ def calc_ids(fname): def run_expo(args): """Run the expo program""" - ids = calc_ids(args.enum_fname) + fname = args.enum_fname or args.layout + ids = calc_ids(fname) + if not ids: + print(f"Warning: No enum ID values found in file '{fname}'") indata = tools.read_file(args.layout) @@ -88,10 +91,10 @@ def run_expo(args): with open('/tmp/asc', 'wb') as outf: outf.write(data) - proc = subprocess.run('dtc', input=data, capture_output=True, check=True) + proc = subprocess.run('dtc', input=data, capture_output=True) edtb = proc.stdout if proc.stderr: - print(proc.stderr) + print(f"Devicetree compiler error:\n{proc.stderr.decode('utf-8')}") return 1 tools.write_file(args.outfile, edtb) return 0 @@ -109,11 +112,13 @@ def parse_args(argv): args is a list of string arguments """ parser = argparse.ArgumentParser() + parser.add_argument('-D', '--debug', action='store_true', + help='Enable full debug traceback') parser.add_argument('-e', '--enum-fname', type=str, - help='C file containing enum declaration for expo items') - parser.add_argument('-l', '--layout', type=str, - help='Devicetree file source .dts for expo layout') - parser.add_argument('-o', '--outfile', type=str, + help='.dts or C file containing enum declaration for expo items') + parser.add_argument('-l', '--layout', type=str, required=True, + help='Devicetree file source .dts for expo layout (and perhaps enums)') + parser.add_argument('-o', '--outfile', type=str, required=True, help='Filename to write expo layout dtb') return parser.parse_args(argv) @@ -122,6 +127,9 @@ def start_expo(): """Start the expo program""" args = parse_args(sys.argv[1:]) + if not args.debug: + sys.tracebacklimit = 0 + ret_code = run_expo(args) sys.exit(ret_code) -- cgit v1.2.3 From f25820b1aef76c2059db69ac2f2e076f0764f4c3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 24 Aug 2023 13:55:46 -0600 Subject: CI: Add ChromiumOS utilities We need cgpt and futility for building test images. Add them. Signed-off-by: Simon Glass --- tools/docker/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools') diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 3d2b64a355f..6e6ae9ebed4 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -39,6 +39,7 @@ RUN apt-get update && apt-get install -y \ binutils-dev \ bison \ build-essential \ + cgpt \ clang-16 \ coreutils \ cpio \ @@ -115,6 +116,8 @@ RUN apt-get update && apt-get install -y \ util-linux \ uuid-dev \ virtualenv \ + vboot-kernel-utils \ + vboot-utils \ xxd \ zip \ && rm -rf /var/lib/apt/lists/* -- cgit v1.2.3 From 11934281526bda3be51783380b55c332804d043d Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 25 Aug 2023 13:21:26 -0400 Subject: CI: Update to gcc-13.2.0 The latest kernel.org toolchains for gcc are now 13.2.0, so upgrade to that. Reviewed-by: Simon Glass Signed-off-by: Tom Rini --- tools/buildman/toolchain.py | 2 +- tools/docker/Dockerfile | 58 ++++++++++++++++++++++----------------------- 2 files changed, 30 insertions(+), 30 deletions(-) (limited to 'tools') diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py index b05001194e4..79c7c11a110 100644 --- a/tools/buildman/toolchain.py +++ b/tools/buildman/toolchain.py @@ -499,7 +499,7 @@ class Toolchains: if arch == 'aarch64': arch = 'arm64' base = 'https://www.kernel.org/pub/tools/crosstool/files/bin' - versions = ['13.1.0', '12.2.0'] + versions = ['13.2.0', '12.2.0'] links = [] for version in versions: url = '%s/%s/%s/' % (base, arch, version) diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 6e6ae9ebed4..27821ae43a0 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -14,19 +14,19 @@ RUN apt-get update && apt-get install -y gnupg2 wget xz-utils && rm -rf /var/lib 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-16 main | tee /etc/apt/sources.list.d/llvm.list -# Manually install the kernel.org "Crosstool" based toolchains for gcc-13.1.0 -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.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.1.0/x86_64-gcc-13.1.0-nolibc-sh2-linux.tar.xz | tar -C /opt -xJ +# 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 # 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 @@ -137,11 +137,11 @@ RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \ mkdir -p /opt/grub && \ ./configure --target=aarch64 --with-platform=efi \ CC=gcc \ - TARGET_CC=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-objcopy \ - TARGET_STRIP=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-strip \ - TARGET_NM=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-nm \ - TARGET_RANLIB=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-ranlib && \ + 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 && \ ./grub-mkimage -O arm64-efi -o /opt/grub/grubaa64.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ @@ -151,11 +151,11 @@ 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.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-objcopy \ - TARGET_STRIP=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-strip \ - TARGET_NM=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-nm \ - TARGET_RANLIB=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ranlib && \ + 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 && \ ./grub-mkimage -O arm-efi -o /opt/grub/grubarm.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ @@ -165,11 +165,11 @@ 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.1.0-nolibc/riscv64-linux/bin/riscv64-linux-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-objcopy \ - TARGET_STRIP=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-strip \ - TARGET_NM=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-nm \ - TARGET_RANLIB=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-ranlib && \ + 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 && \ ./grub-mkimage -O riscv64-efi -o /opt/grub/grubriscv64.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ @@ -280,7 +280,7 @@ RUN virtualenv -p /usr/bin/python3 /tmp/venv && \ # Create the buildman config file RUN /bin/echo -e "[toolchain]\nroot = /usr" > ~/.buildman -RUN /bin/echo -e "kernelorg = /opt/gcc-13.1.0-nolibc/*" >> ~/.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 "\n[toolchain-alias]\nsh = sh2" >> ~/.buildman RUN /bin/echo -e "\nsandbox = x86_64" >> ~/.buildman -- cgit v1.2.3 From 453c3fb48141f60eb9b7ab5545d94c88dc5af40c Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 25 Aug 2023 13:21:27 -0400 Subject: CI: Move to latest Ubuntu "Jammy" tag Move to the latest "Jammy" tag from Ubuntu. Reviewed-by: Simon Glass Signed-off-by: Tom Rini --- tools/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 27821ae43a0..279b3a3504c 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -2,7 +2,7 @@ # 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-20230624 +FROM ubuntu:jammy-20230804 MAINTAINER Tom Rini LABEL Description=" This image is for building U-Boot inside a container" -- cgit v1.2.3 From d71e7116997f14097735f04cc7847f0a68dbc485 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Tue, 22 Aug 2023 23:09:54 +0530 Subject: binman: bintool: Build a tool from a list of commands Add support to build a tool from source with a list of commands. This is useful when a tool can be built with multiple commands instead of a single command. Signed-off-by: Sughosh Ganu Reviewed-by: Simon Glass --- tools/binman/bintool.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/binman/bintool.py b/tools/binman/bintool.py index 0b0f56dbbba..3c4ad1adbb9 100644 --- a/tools/binman/bintool.py +++ b/tools/binman/bintool.py @@ -328,7 +328,7 @@ class Bintool: return result.stdout @classmethod - def build_from_git(cls, git_repo, make_target, bintool_path, flags=None): + def build_from_git(cls, git_repo, make_targets, bintool_path, flags=None): """Build a bintool from a git repo This clones the repo in a temporary directory, builds it with 'make', @@ -336,7 +336,8 @@ class Bintool: Args: git_repo (str): URL of git repo - make_target (str): Target to pass to 'make' to build the tool + make_targets (list of str): List of targets to pass to 'make' to build + the tool bintool_path (str): Relative path of the tool in the repo, after build is complete flags (list of str): Flags or variables to pass to make, or None @@ -350,12 +351,14 @@ class Bintool: tmpdir = tempfile.mkdtemp(prefix='binmanf.') print(f"- clone git repo '{git_repo}' to '{tmpdir}'") tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir) - print(f"- build target '{make_target}'") - cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}', - make_target] - if flags: - cmd += flags - tools.run(*cmd) + for target in make_targets: + print(f"- build target '{target}'") + cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}', + target] + if flags: + cmd += flags + tools.run(*cmd) + fname = os.path.join(tmpdir, bintool_path) if not os.path.exists(fname): print(f"- File '{fname}' was not produced") -- cgit v1.2.3 From 3bd6fb980bd900301e8387bd6f93a53ae5f16bc7 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Tue, 22 Aug 2023 23:09:58 +0530 Subject: btool: mkeficapsule: Add a bintool for EFI capsule generation Add a bintool for generating EFI capsules. This calls the mkeficapsule tool which generates the capsules. Signed-off-by: Sughosh Ganu Reviewed-by: Simon Glass --- tools/binman/btool/mkeficapsule.py | 101 +++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 tools/binman/btool/mkeficapsule.py (limited to 'tools') diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py new file mode 100644 index 00000000000..61179747ffa --- /dev/null +++ b/tools/binman/btool/mkeficapsule.py @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2023 Linaro Limited +# +"""Bintool implementation for mkeficapsule tool + +mkeficapsule is a tool used for generating EFI capsules. + +The following are the commandline options to be provided +to the tool +Usage: mkeficapsule [options] +Options: + -g, --guid guid for image blob type + -i, --index update image index + -I, --instance update hardware instance + -v, --fw-version firmware version + -p, --private-key private key file + -c, --certificate signer's certificate file + -m, --monotonic-count monotonic count + -d, --dump_sig dump signature (*.p7) + -A, --fw-accept firmware accept capsule, requires GUID, no image blob + -R, --fw-revert firmware revert capsule, takes no GUID, no image blob + -o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff + -h, --help print a help message +""" + +from binman import bintool + +class Bintoolmkeficapsule(bintool.Bintool): + """Handles the 'mkeficapsule' tool + + This bintool is used for generating the EFI capsules. The + capsule generation parameters can either be specified through + commandline, or through a config file. + """ + def __init__(self, name): + super().__init__(name, 'mkeficapsule tool for generating capsules') + + def generate_capsule(self, image_index, image_guid, hardware_instance, + payload, output_fname, priv_key, pub_key, + monotonic_count=0, version=0, oemflags=0): + """Generate a capsule through commandline-provided parameters + + Args: + image_index (int): Unique number for identifying payload image + image_guid (str): GUID used for identifying the image + hardware_instance (int): Optional unique hardware instance of + a device in the system. 0 if not being used + payload (str): Path to the input payload image + output_fname (str): Path to the output capsule file + priv_key (str): Path to the private key + pub_key(str): Path to the public key + monotonic_count (int): Count used when signing an image + version (int): Image version (Optional) + oemflags (int): Optional 16 bit OEM flags + + Returns: + str: Tool output + """ + args = [ + f'--index={image_index}', + f'--guid={image_guid}', + f'--instance={hardware_instance}' + ] + + if version: + args += [f'--fw-version={version}'] + if oemflags: + args += [f'--capoemflag={oemflags}'] + if priv_key and pub_key: + args += [ + f'--monotonic-count={monotonic_count}', + f'--private-key={priv_key}', + f'--certificate={pub_key}' + ] + + args += [ + payload, + output_fname + ] + + return self.run_cmd(*args) + + def fetch(self, method): + """Fetch handler for mkeficapsule + + This builds the tool from source + + Returns: + tuple: + str: Filename of fetched file to copy to a suitable directory + str: Name of temp directory to remove, or None + """ + if method != bintool.FETCH_BUILD: + return None + + cmd = ['tools-only_defconfig', 'tools'] + result = self.build_from_git( + 'https://source.denx.de/u-boot/u-boot.git', + cmd, + 'tools/mkeficapsule') + return result -- cgit v1.2.3 From b617611b27a0c91df6fbb44d84edaa160079bc9c Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Tue, 22 Aug 2023 23:09:59 +0530 Subject: binman: capsule: Add support for generating EFI capsules Add support in binman for generating EFI capsules. The capsule parameters can be specified through the capsule binman entry. Also add test cases in binman for testing capsule generation. Signed-off-by: Sughosh Ganu Reviewed-by: Simon Glass --- tools/binman/entries.rst | 64 +++++++++++ tools/binman/etype/efi_capsule.py | 143 ++++++++++++++++++++++++ tools/binman/ftest.py | 118 +++++++++++++++++++ tools/binman/test/311_capsule.dts | 21 ++++ tools/binman/test/312_capsule_signed.dts | 23 ++++ tools/binman/test/313_capsule_version.dts | 22 ++++ tools/binman/test/314_capsule_signed_ver.dts | 24 ++++ tools/binman/test/315_capsule_oemflags.dts | 22 ++++ tools/binman/test/316_capsule_missing_key.dts | 22 ++++ tools/binman/test/317_capsule_missing_index.dts | 20 ++++ tools/binman/test/318_capsule_missing_guid.dts | 19 ++++ 11 files changed, 498 insertions(+) create mode 100644 tools/binman/etype/efi_capsule.py create mode 100644 tools/binman/test/311_capsule.dts create mode 100644 tools/binman/test/312_capsule_signed.dts create mode 100644 tools/binman/test/313_capsule_version.dts create mode 100644 tools/binman/test/314_capsule_signed_ver.dts create mode 100644 tools/binman/test/315_capsule_oemflags.dts create mode 100644 tools/binman/test/316_capsule_missing_key.dts create mode 100644 tools/binman/test/317_capsule_missing_index.dts create mode 100644 tools/binman/test/318_capsule_missing_guid.dts (limited to 'tools') diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index e7dfe6b2a36..801bd946742 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -468,6 +468,70 @@ updating the EC on startup via software sync. +.. _etype_efi_capsule: + +Entry: capsule: Entry for generating EFI Capsule files +------------------------------------------------------ + +The parameters needed for generation of the capsules can be provided +as properties in the entry. + +Properties / Entry arguments: + - image-index: Unique number for identifying corresponding + payload image. Number between 1 and descriptor count, i.e. + the total number of firmware images that can be updated. Mandatory + property. + - image-guid: Image GUID which will be used for identifying the + updatable image on the board. Mandatory property. + - hardware-instance: Optional number for identifying unique + hardware instance of a device in the system. Default value of 0 + for images where value is not to be used. + - fw-version: Value of image version that can be put on the capsule + through the Firmware Management Protocol(FMP) header. + - monotonic-count: Count used when signing an image. + - private-key: Path to PEM formatted .key private key file. Mandatory + property for generating signed capsules. + - public-key-cert: Path to PEM formatted .crt public key certificate + file. Mandatory property for generating signed capsules. + - oem-flags - OEM flags to be passed through capsule header. + + Since this is a subclass of Entry_section, all properties of the parent + class also apply here. Except for the properties stated as mandatory, the + rest of the properties are optional. + +For more details on the description of the capsule format, and the capsule +update functionality, refer Section 8.5 and Chapter 23 in the `UEFI +specification`_. + +The capsule parameters like image index and image GUID are passed as +properties in the entry. The payload to be used in the capsule is to be +provided as a subnode of the capsule entry. + +A typical capsule entry node would then look something like this:: + + capsule { + type = "efi-capsule"; + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + hardware-instance = <0x0>; + private-key = "path/to/the/private/key"; + public-key-cert = "path/to/the/public-key-cert"; + oem-flags = <0x8000>; + + u-boot { + }; + }; + +In the above example, the capsule payload is the U-Boot image. The +capsule entry would read the contents of the payload and put them +into the capsule. Any external file can also be specified as the +payload using the blob-ext subnode. + +.. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf + + + .. _etype_encrypted: Entry: encrypted: Externally built encrypted binary blob diff --git a/tools/binman/etype/efi_capsule.py b/tools/binman/etype/efi_capsule.py new file mode 100644 index 00000000000..006eb630adb --- /dev/null +++ b/tools/binman/etype/efi_capsule.py @@ -0,0 +1,143 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2023 Linaro Limited +# +# Entry-type module for producing a EFI capsule +# + +import os + +from binman.entry import Entry +from binman.etype.section import Entry_section +from dtoc import fdt_util +from u_boot_pylib import tools + +class Entry_efi_capsule(Entry_section): + """Generate EFI capsules + + The parameters needed for generation of the capsules can + be provided as properties in the entry. + + Properties / Entry arguments: + - image-index: Unique number for identifying corresponding + payload image. Number between 1 and descriptor count, i.e. + the total number of firmware images that can be updated. Mandatory + property. + - image-guid: Image GUID which will be used for identifying the + updatable image on the board. Mandatory property. + - hardware-instance: Optional number for identifying unique + hardware instance of a device in the system. Default value of 0 + for images where value is not to be used. + - fw-version: Value of image version that can be put on the capsule + through the Firmware Management Protocol(FMP) header. + - monotonic-count: Count used when signing an image. + - private-key: Path to PEM formatted .key private key file. Mandatory + property for generating signed capsules. + - public-key-cert: Path to PEM formatted .crt public key certificate + file. Mandatory property for generating signed capsules. + - oem-flags - OEM flags to be passed through capsule header. + + Since this is a subclass of Entry_section, all properties of the parent + class also apply here. Except for the properties stated as mandatory, the + rest of the properties are optional. + + For more details on the description of the capsule format, and the capsule + update functionality, refer Section 8.5 and Chapter 23 in the `UEFI + specification`_. + + The capsule parameters like image index and image GUID are passed as + properties in the entry. The payload to be used in the capsule is to be + provided as a subnode of the capsule entry. + + A typical capsule entry node would then look something like this + + capsule { + type = "efi-capsule"; + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + hardware-instance = <0x0>; + private-key = "path/to/the/private/key"; + public-key-cert = "path/to/the/public-key-cert"; + oem-flags = <0x8000>; + + u-boot { + }; + }; + + In the above example, the capsule payload is the U-Boot image. The + capsule entry would read the contents of the payload and put them + into the capsule. Any external file can also be specified as the + payload using the blob-ext subnode. + + .. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf + """ + def __init__(self, section, etype, node): + super().__init__(section, etype, node) + self.required_props = ['image-index', 'image-guid'] + self.image_index = 0 + self.image_guid = '' + self.hardware_instance = 0 + self.monotonic_count = 0 + self.fw_version = 0 + self.oem_flags = 0 + self.private_key = '' + self.public_key_cert = '' + self.auth = 0 + + def ReadNode(self): + super().ReadNode() + + self.image_index = fdt_util.GetInt(self._node, 'image-index') + self.image_guid = fdt_util.GetString(self._node, 'image-guid') + self.fw_version = fdt_util.GetInt(self._node, 'fw-version') + self.hardware_instance = fdt_util.GetInt(self._node, 'hardware-instance') + self.monotonic_count = fdt_util.GetInt(self._node, 'monotonic-count') + self.oem_flags = fdt_util.GetInt(self._node, 'oem-flags') + + self.private_key = fdt_util.GetString(self._node, 'private-key') + self.public_key_cert = fdt_util.GetString(self._node, 'public-key-cert') + if ((self.private_key and not self.public_key_cert) or (self.public_key_cert and not self.private_key)): + self.Raise('Both private key and public key certificate need to be provided') + elif not (self.private_key and self.public_key_cert): + self.auth = 0 + else: + self.auth = 1 + + def BuildSectionData(self, required): + def get_binman_test_guid(type_str): + TYPE_TO_GUID = { + 'binman-test' : '09d7cf52-0720-4710-91d1-08469b7fe9c8' + } + return TYPE_TO_GUID[type_str] + + private_key = '' + public_key_cert = '' + if self.auth: + if not os.path.isabs(self.private_key): + private_key = tools.get_input_filename(self.private_key) + if not os.path.isabs(self.public_key_cert): + public_key_cert = tools.get_input_filename(self.public_key_cert) + data, payload, uniq = self.collect_contents_to_file( + self._entries.values(), 'capsule_in') + outfile = self._filename if self._filename else 'capsule.%s' % uniq + capsule_fname = tools.get_output_filename(outfile) + guid = self.image_guid + if self.image_guid == "binman-test": + guid = get_binman_test_guid('binman-test') + + ret = self.mkeficapsule.generate_capsule(self.image_index, + guid, + self.hardware_instance, + payload, + capsule_fname, + private_key, + public_key_cert, + self.monotonic_count, + self.fw_version, + self.oem_flags) + if ret is not None: + os.remove(payload) + return tools.read_file(capsule_fname) + + def AddBintools(self, btools): + self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 1293e9dbf42..8e419645a6d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -48,6 +48,7 @@ U_BOOT_VPL_DATA = b'vpl76543210fedcbazywxyz_' BLOB_DATA = b'89' ME_DATA = b'0abcd' VGA_DATA = b'vga' +EFI_CAPSULE_DATA = b'efi' U_BOOT_DTB_DATA = b'udtb' U_BOOT_SPL_DTB_DATA = b'spldtb' U_BOOT_TPL_DTB_DATA = b'tpldtb' @@ -119,6 +120,11 @@ COMP_BINTOOLS = ['bzip2', 'gzip', 'lz4', 'lzma_alone', 'lzop', 'xz', 'zstd'] TEE_ADDR = 0x5678 +# Firmware Management Protocol(FMP) GUID +FW_MGMT_GUID = 'edd5cb6d2de8444cbda17194199ad92a' +# Image GUID specified in the DTS +CAPSULE_IMAGE_GUID = '52cfd7092007104791d108469b7fe9c8' + class TestFunctional(unittest.TestCase): """Functional tests for binman @@ -215,6 +221,7 @@ class TestFunctional(unittest.TestCase): TestFunctional._MakeInputFile('scp.bin', SCP_DATA) TestFunctional._MakeInputFile('rockchip-tpl.bin', ROCKCHIP_TPL_DATA) TestFunctional._MakeInputFile('ti_unsecure.bin', TI_UNSECURE_DATA) + TestFunctional._MakeInputFile('capsule_input.bin', EFI_CAPSULE_DATA) # Add a few .dtb files for testing TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR, @@ -7216,5 +7223,116 @@ fdt fdtmap Extract the devicetree blob from the fdtmap self.assertRegex(err, "Image 'image'.*missing bintools.*: bootgen") + def _CheckCapsule(self, data, signed_capsule=False, version_check=False, + capoemflags=False): + fmp_signature = "4d535331" # 'M', 'S', 'S', '1' + fmp_size = "10" + fmp_fw_version = "02" + oemflag = "0080" + + payload_data = EFI_CAPSULE_DATA + + # TODO - Currently, these offsets for capsule fields are hardcoded. + # There are plans to add support to the mkeficapsule tool to dump + # the capsule contents which can then be used for capsule + # verification. + + # Firmware Management Protocol(FMP) GUID - offset(0 - 32) + self.assertEqual(FW_MGMT_GUID, data.hex()[:32]) + # Image GUID - offset(96 - 128) + self.assertEqual(CAPSULE_IMAGE_GUID, data.hex()[96:128]) + + if capoemflags: + # OEM Flags - offset(40 - 44) + self.assertEqual(oemflag, data.hex()[40:44]) + if signed_capsule and version_check: + # FMP header signature - offset(4770 - 4778) + self.assertEqual(fmp_signature, data.hex()[4770:4778]) + # FMP header size - offset(4778 - 4780) + self.assertEqual(fmp_size, data.hex()[4778:4780]) + # firmware version - offset(4786 - 4788) + self.assertEqual(fmp_fw_version, data.hex()[4786:4788]) + # payload offset signed capsule(4802 - 4808) + self.assertEqual(payload_data.hex(), data.hex()[4802:4808]) + elif signed_capsule: + # payload offset signed capsule(4770 - 4776) + self.assertEqual(payload_data.hex(), data.hex()[4770:4776]) + elif version_check: + # FMP header signature - offset(184 - 192) + self.assertEqual(fmp_signature, data.hex()[184:192]) + # FMP header size - offset(192 - 194) + self.assertEqual(fmp_size, data.hex()[192:194]) + # firmware version - offset(200 - 202) + self.assertEqual(fmp_fw_version, data.hex()[200:202]) + # payload offset for non-signed capsule with version header(216 - 222) + self.assertEqual(payload_data.hex(), data.hex()[216:222]) + else: + # payload offset for non-signed capsule with no version header(184 - 190) + self.assertEqual(payload_data.hex(), data.hex()[184:190]) + + def testCapsuleGen(self): + """Test generation of EFI capsule""" + data = self._DoReadFile('311_capsule.dts') + + self._CheckCapsule(data) + + def testSignedCapsuleGen(self): + """Test generation of EFI capsule""" + data = tools.read_file(self.TestFile("key.key")) + self._MakeInputFile("key.key", data) + data = tools.read_file(self.TestFile("key.pem")) + self._MakeInputFile("key.crt", data) + + data = self._DoReadFile('312_capsule_signed.dts') + + self._CheckCapsule(data, signed_capsule=True) + + def testCapsuleGenVersionSupport(self): + """Test generation of EFI capsule with version support""" + data = self._DoReadFile('313_capsule_version.dts') + + self._CheckCapsule(data, version_check=True) + + def testCapsuleGenSignedVer(self): + """Test generation of signed EFI capsule with version information""" + data = tools.read_file(self.TestFile("key.key")) + self._MakeInputFile("key.key", data) + data = tools.read_file(self.TestFile("key.pem")) + self._MakeInputFile("key.crt", data) + + data = self._DoReadFile('314_capsule_signed_ver.dts') + + self._CheckCapsule(data, signed_capsule=True, version_check=True) + + def testCapsuleGenCapOemFlags(self): + """Test generation of EFI capsule with OEM Flags set""" + data = self._DoReadFile('315_capsule_oemflags.dts') + + self._CheckCapsule(data, capoemflags=True) + + def testCapsuleGenKeyMissing(self): + """Test that binman errors out on missing key""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('316_capsule_missing_key.dts') + + self.assertIn("Both private key and public key certificate need to be provided", + str(e.exception)) + + def testCapsuleGenIndexMissing(self): + """Test that binman errors out on missing image index""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('317_capsule_missing_index.dts') + + self.assertIn("entry is missing properties: image-index", + str(e.exception)) + + def testCapsuleGenGuidMissing(self): + """Test that binman errors out on missing image GUID""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('318_capsule_missing_guid.dts') + + self.assertIn("entry is missing properties: image-guid", + str(e.exception)) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/311_capsule.dts b/tools/binman/test/311_capsule.dts new file mode 100644 index 00000000000..8eb4250b14b --- /dev/null +++ b/tools/binman/test/311_capsule.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/312_capsule_signed.dts b/tools/binman/test/312_capsule_signed.dts new file mode 100644 index 00000000000..d1c76e269c7 --- /dev/null +++ b/tools/binman/test/312_capsule_signed.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + private-key = "key.key"; + public-key-cert = "key.crt"; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/313_capsule_version.dts b/tools/binman/test/313_capsule_version.dts new file mode 100644 index 00000000000..bafef3609e0 --- /dev/null +++ b/tools/binman/test/313_capsule_version.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/314_capsule_signed_ver.dts b/tools/binman/test/314_capsule_signed_ver.dts new file mode 100644 index 00000000000..85c784bba43 --- /dev/null +++ b/tools/binman/test/314_capsule_signed_ver.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + private-key = "key.key"; + public-key-cert = "key.crt"; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/315_capsule_oemflags.dts b/tools/binman/test/315_capsule_oemflags.dts new file mode 100644 index 00000000000..f736e8758fd --- /dev/null +++ b/tools/binman/test/315_capsule_oemflags.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + oem-flags = <0x8000>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/316_capsule_missing_key.dts b/tools/binman/test/316_capsule_missing_key.dts new file mode 100644 index 00000000000..2080b50e3dd --- /dev/null +++ b/tools/binman/test/316_capsule_missing_key.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + private-key = "tools/binman/test/key.key"; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/317_capsule_missing_index.dts b/tools/binman/test/317_capsule_missing_index.dts new file mode 100644 index 00000000000..aadb61f6477 --- /dev/null +++ b/tools/binman/test/317_capsule_missing_index.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/318_capsule_missing_guid.dts b/tools/binman/test/318_capsule_missing_guid.dts new file mode 100644 index 00000000000..d76afba853e --- /dev/null +++ b/tools/binman/test/318_capsule_missing_guid.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; -- cgit v1.2.3 From 8d8851e8fd52fdfbafd1dcb5faa66f20f9588d97 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Thu, 17 Aug 2023 18:36:10 +0300 Subject: tools: image-host: print error messages to stderr The make by default cuts off the stdout output from external tools, so all error messages from the image-host are not shown in a make output. Besides that, it is a common approach to use stderr stream for error messages. Use stderr for all error messages in image-host. Signed-off-by: Oleksandr Suvorov Reviewed-by: Simon Glass --- tools/image-host.c | 202 ++++++++++++++++++++++++++++------------------------- 1 file changed, 107 insertions(+), 95 deletions(-) (limited to 'tools') diff --git a/tools/image-host.c b/tools/image-host.c index 4a24dee8153..ca4950312f9 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -38,9 +38,9 @@ static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); if (ret) { - printf("Can't set hash '%s' property for '%s' node(%s)\n", - FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), - fdt_strerror(ret)); + fprintf(stderr, "Can't set hash '%s' property for '%s' node(%s)\n", + FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), + fdt_strerror(ret)); return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; } @@ -72,21 +72,23 @@ static int fit_image_process_hash(void *fit, const char *image_name, node_name = fit_get_name(fit, noffset, NULL); if (fit_image_hash_get_algo(fit, noffset, &algo)) { - printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, + "Can't get hash algo property for '%s' hash node in '%s' image node\n", + node_name, image_name); return -ENOENT; } if (calculate_hash(data, size, algo, value, &value_len)) { - printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", - algo, node_name, image_name); + fprintf(stderr, + "Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", + algo, node_name, image_name); return -EPROTONOSUPPORT; } ret = fit_set_hash_value(fit, noffset, value, value_len); if (ret) { - printf("Can't set hash value for '%s' hash node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, "Can't set hash value for '%s' hash node in '%s' image node\n", + node_name, image_name); return ret; } @@ -170,8 +172,9 @@ static int fit_image_setup_sig(struct image_sign_info *info, node_name = fit_get_name(fit, noffset, NULL); if (!algo_name) { if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { - printf("Can't get algo property for '%s' signature node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, + "Can't get algo property for '%s' signature node in '%s' image node\n", + node_name, image_name); return -1; } } @@ -191,8 +194,9 @@ static int fit_image_setup_sig(struct image_sign_info *info, info->require_keys = require_keys; info->engine_id = engine_id; if (!info->checksum || !info->crypto) { - printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n", - algo_name, node_name, image_name); + fprintf(stderr, + "Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n", + algo_name, node_name, image_name); return -1; } @@ -241,8 +245,8 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile, region.size = size; ret = info.crypto->sign(&info, ®ion, 1, &value, &value_len); if (ret) { - printf("Failed to sign '%s' signature node in '%s' image node: %d\n", - node_name, image_name, ret); + fprintf(stderr, "Failed to sign '%s' signature node in '%s' image node: %d\n", + node_name, image_name, ret); /* We allow keys to be missing */ if (ret == -ENOENT) @@ -255,8 +259,9 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile, if (ret) { if (ret == -FDT_ERR_NOSPACE) return -ENOSPC; - printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n", - node_name, image_name, fdt_strerror(ret)); + fprintf(stderr, + "Can't write signature for '%s' signature node in '%s' conf node: %s\n", + node_name, image_name, fdt_strerror(ret)); return -1; } free(value); @@ -272,8 +277,9 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile, if (keydest) { ret = info.crypto->add_verify_data(&info, keydest); if (ret < 0) { - printf("Failed to add verification data for '%s' signature node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, + "Failed to add verification data for '%s' signature node in '%s' image node\n", + node_name, image_name); return ret; } /* Return the node that was written to */ @@ -293,37 +299,37 @@ static int fit_image_read_data(char *filename, unsigned char *data, /* Open file */ fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) { - printf("Can't open file %s (err=%d => %s)\n", - filename, errno, strerror(errno)); + fprintf(stderr, "Can't open file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); return -1; } /* Compute file size */ if (fstat(fd, &sbuf) < 0) { - printf("Can't fstat file %s (err=%d => %s)\n", - filename, errno, strerror(errno)); + fprintf(stderr, "Can't fstat file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); goto err; } /* Check file size */ if (sbuf.st_size != expected_size) { - printf("File %s don't have the expected size (size=%lld, expected=%d)\n", - filename, (long long)sbuf.st_size, expected_size); + fprintf(stderr, "File %s don't have the expected size (size=%lld, expected=%d)\n", + filename, (long long)sbuf.st_size, expected_size); goto err; } /* Read data */ n = read(fd, data, sbuf.st_size); if (n < 0) { - printf("Can't read file %s (err=%d => %s)\n", - filename, errno, strerror(errno)); + fprintf(stderr, "Can't read file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); goto err; } /* Check that we have read all the file */ if (n != sbuf.st_size) { - printf("Can't read all file %s (read %zd bytes, expected %lld)\n", - filename, n, (long long)sbuf.st_size); + fprintf(stderr, "Can't read all file %s (read %zd bytes, expected %lld)\n", + filename, n, (long long)sbuf.st_size); goto err; } @@ -341,15 +347,15 @@ static int get_random_data(void *data, int size) int i, ret; if (!tmp) { - printf("%s: pointer data is NULL\n", __func__); + fprintf(stderr, "%s: pointer data is NULL\n", __func__); ret = -1; goto out; } ret = clock_gettime(CLOCK_MONOTONIC, &date); if (ret) { - printf("%s: clock_gettime has failed (%s)\n", __func__, - strerror(errno)); + fprintf(stderr, "%s: clock_gettime has failed (%s)\n", __func__, + strerror(errno)); goto out; } @@ -374,8 +380,8 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, int ret = -1; if (fit_image_cipher_get_algo(fit, noffset, &algo_name)) { - printf("Can't get algo name for cipher in image '%s'\n", - image_name); + fprintf(stderr, "Can't get algo name for cipher in image '%s'\n", + image_name); goto out; } @@ -384,8 +390,8 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, /* Read the key name */ info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); if (!info->keyname) { - printf("Can't get key name for cipher in image '%s'\n", - image_name); + fprintf(stderr, "Can't get key name for cipher in image '%s'\n", + image_name); goto out; } @@ -403,7 +409,7 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, info->cipher = image_get_cipher_algo(algo_name); if (!info->cipher) { - printf("Can't get algo for cipher '%s'\n", image_name); + fprintf(stderr, "Can't get algo for cipher '%s'\n", image_name); goto out; } @@ -412,7 +418,7 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, info->keydir, info->keyname, ".bin"); info->key = malloc(info->cipher->key_len); if (!info->key) { - printf("Can't allocate memory for key\n"); + fprintf(stderr, "Can't allocate memory for key\n"); ret = -1; goto out; } @@ -423,7 +429,7 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, info->iv = malloc(info->cipher->iv_len); if (!info->iv) { - printf("Can't allocate memory for iv\n"); + fprintf(stderr, "Can't allocate memory for iv\n"); ret = -1; goto out; } @@ -457,7 +463,7 @@ int fit_image_write_cipher(void *fit, int image_noffset, int noffset, goto out; } if (ret) { - printf("Can't replace data with ciphered data (err = %d)\n", ret); + fprintf(stderr, "Can't replace data with ciphered data (err = %d)\n", ret); goto out; } @@ -468,7 +474,7 @@ int fit_image_write_cipher(void *fit, int image_noffset, int noffset, goto out; } if (ret) { - printf("Can't add unciphered data size (err = %d)\n", ret); + fprintf(stderr, "Can't add unciphered data size (err = %d)\n", ret); goto out; } @@ -508,8 +514,9 @@ fit_image_process_cipher(const char *keydir, void *keydest, void *fit, if (keydest) { ret = info.cipher->add_cipher_data(&info, keydest, fit, node_noffset); if (ret) { - printf("Failed to add verification data for cipher '%s' in image '%s'\n", - info.keyname, image_name); + fprintf(stderr, + "Failed to add verification data for cipher '%s' in image '%s'\n", + info.keyname, image_name); goto out; } } @@ -538,13 +545,13 @@ int fit_image_cipher_data(const char *keydir, void *keydest, /* Get image name */ image_name = fit_get_name(fit, image_noffset, NULL); if (!image_name) { - printf("Can't get image name\n"); + fprintf(stderr, "Can't get image name\n"); return -1; } /* Get image data and data length */ if (fit_image_get_data(fit, image_noffset, &data, &size)) { - printf("Can't get image data/size\n"); + fprintf(stderr, "Can't get image data/size\n"); return -1; } @@ -558,7 +565,7 @@ int fit_image_cipher_data(const char *keydir, void *keydest, if (fdt_getprop(fit, image_noffset, "data-size-unciphered", &len)) return 0; if (len != -FDT_ERR_NOTFOUND) { - printf("Failure testing for data-size-unciphered\n"); + fprintf(stderr, "Failure testing for data-size-unciphered\n"); return -1; } @@ -568,7 +575,7 @@ int fit_image_cipher_data(const char *keydir, void *keydest, if (cipher_node_offset == -FDT_ERR_NOTFOUND) return 0; if (cipher_node_offset < 0) { - printf("Failure getting cipher node\n"); + fprintf(stderr, "Failure getting cipher node\n"); return -1; } if (!IMAGE_ENABLE_ENCRYPT || !keydir) @@ -624,7 +631,7 @@ int fit_image_add_verification_data(const char *keydir, const char *keyfile, /* Get image data and data length */ if (fit_image_get_data(fit, image_noffset, &data, &size)) { - printf("Can't get image data/size\n"); + fprintf(stderr, "Can't get image data/size\n"); return -1; } @@ -765,8 +772,9 @@ static int fit_config_add_hash(const void *fit, int image_noffset, } if (!hash_count) { - printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", - conf_name, sig_name, iname); + fprintf(stderr, + "Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", + conf_name, sig_name, iname); return -ENOMSG; } @@ -775,9 +783,10 @@ static int fit_config_add_hash(const void *fit, int image_noffset, FIT_CIPHER_NODENAME); if (noffset != -FDT_ERR_NOTFOUND) { if (noffset < 0) { - printf("Failed to get cipher node in configuration '%s/%s' image '%s': %s\n", - conf_name, sig_name, iname, - fdt_strerror(noffset)); + fprintf(stderr, + "Failed to get cipher node in configuration '%s/%s' image '%s': %s\n", + conf_name, sig_name, iname, + fdt_strerror(noffset)); return -EIO; } ret = fdt_get_path(fit, noffset, path, sizeof(path)); @@ -790,13 +799,13 @@ static int fit_config_add_hash(const void *fit, int image_noffset, return 0; err_mem: - printf("Out of memory processing configuration '%s/%s'\n", conf_name, - sig_name); + fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name, + sig_name); return -ENOMEM; err_path: - printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n", - iname, conf_name, sig_name, fdt_strerror(ret)); + fprintf(stderr, "Failed to get path for image '%s' in configuration '%s/%s': %s\n", + iname, conf_name, sig_name, fdt_strerror(ret)); return -ENOENT; } @@ -857,8 +866,9 @@ static int fit_config_get_hash_list(const void *fit, int conf_noffset, iname, index); if (image_noffset < 0) { - printf("Failed to find image '%s' in configuration '%s/%s'\n", - iname, conf_name, sig_name); + fprintf(stderr, + "Failed to find image '%s' in configuration '%s/%s'\n", + iname, conf_name, sig_name); if (allow_missing) continue; @@ -875,16 +885,16 @@ static int fit_config_get_hash_list(const void *fit, int conf_noffset, } if (!image_count) { - printf("Failed to find any images for configuration '%s/%s'\n", - conf_name, sig_name); + fprintf(stderr, "Failed to find any images for configuration '%s/%s'\n", + conf_name, sig_name); return -ENOMSG; } return 0; err_mem: - printf("Out of memory processing configuration '%s/%s'\n", conf_name, - sig_name); + fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name, + sig_name); return -ENOMEM; } @@ -946,21 +956,21 @@ static int fit_config_get_regions(const void *fit, int conf_noffset, fdt_regions, ARRAY_SIZE(fdt_regions), path, sizeof(path), 1); if (count < 0) { - printf("Failed to hash configuration '%s/%s': %s\n", conf_name, - sig_name, fdt_strerror(ret)); + fprintf(stderr, "Failed to hash configuration '%s/%s': %s\n", conf_name, + sig_name, fdt_strerror(ret)); return -EIO; } if (count == 0) { - printf("No data to hash for configuration '%s/%s': %s\n", - conf_name, sig_name, fdt_strerror(ret)); + fprintf(stderr, "No data to hash for configuration '%s/%s': %s\n", + conf_name, sig_name, fdt_strerror(ret)); return -EINVAL; } /* Build our list of data blocks */ region = fit_region_make_list(fit, fdt_regions, count, NULL); if (!region) { - printf("Out of memory hashing configuration '%s/%s'\n", - conf_name, sig_name); + fprintf(stderr, "Out of memory hashing configuration '%s/%s'\n", + conf_name, sig_name); return -ENOMEM; } @@ -972,8 +982,8 @@ static int fit_config_get_regions(const void *fit, int conf_noffset, } region_prop = malloc(len); if (!region_prop) { - printf("Out of memory setting up regions for configuration '%s/%s'\n", - conf_name, sig_name); + fprintf(stderr, "Out of memory setting up regions for configuration '%s/%s'\n", + conf_name, sig_name); return -ENOMEM; } for (i = len = 0; i < node_inc.count; @@ -1038,8 +1048,8 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, &value_len); free(region); if (ret) { - printf("Failed to sign '%s' signature node in '%s' conf node\n", - node_name, conf_name); + fprintf(stderr, "Failed to sign '%s' signature node in '%s' conf node\n", + node_name, conf_name); /* We allow keys to be missing */ if (ret == -ENOENT) @@ -1053,8 +1063,9 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, if (ret) { if (ret == -FDT_ERR_NOSPACE) return -ENOSPC; - printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n", - node_name, conf_name, fdt_strerror(ret)); + fprintf(stderr, + "Can't write signature for '%s' signature node in '%s' conf node: %s\n", + node_name, conf_name, fdt_strerror(ret)); return -1; } free(value); @@ -1067,8 +1078,9 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, if (keydest) { ret = info.crypto->add_verify_data(&info, keydest); if (ret < 0) { - printf("Failed to add verification data for '%s' signature node in '%s' configuration node\n", - node_name, conf_name); + fprintf(stderr, + "Failed to add verification data for '%s' signature node in '%s' configuration node\n", + node_name, conf_name); } return ret; } @@ -1148,7 +1160,7 @@ static int read_pub_key(const char *keydir, const void *name, /* Read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { - printf("Couldn't read certificate"); + fprintf(stderr, "Couldn't read certificate"); ret = -EINVAL; goto err_cert; } @@ -1156,7 +1168,7 @@ static int read_pub_key(const char *keydir, const void *name, /* Get the public key from the certificate. */ key = X509_get_pubkey(cert); if (!key) { - printf("Couldn't read public key\n"); + fprintf(stderr, "Couldn't read public key\n"); ret = -EINVAL; goto err_pubkey; } @@ -1164,7 +1176,7 @@ static int read_pub_key(const char *keydir, const void *name, /* Get DER form */ ret = i2d_PublicKey(key, pubkey); if (ret < 0) { - printf("Couldn't get DER form\n"); + fprintf(stderr, "Couldn't get DER form\n"); ret = -EINVAL; goto err_pubkey; } @@ -1203,11 +1215,11 @@ int fit_pre_load_data(const char *keydir, void *keydest, void *fit) /* Check that all mandatory properties are present */ if (!algo_name || !key_name) { if (!algo_name) - printf("The property algo-name is missing in the node %s\n", - IMAGE_PRE_LOAD_PATH); + fprintf(stderr, "The property algo-name is missing in the node %s\n", + IMAGE_PRE_LOAD_PATH); if (!key_name) - printf("The property key-name is missing in the node %s\n", - IMAGE_PRE_LOAD_PATH); + fprintf(stderr, "The property key-name is missing in the node %s\n", + IMAGE_PRE_LOAD_PATH); ret = -EINVAL; goto out; } @@ -1221,8 +1233,8 @@ int fit_pre_load_data(const char *keydir, void *keydest, void *fit) ret = fdt_setprop(keydest, pre_load_noffset, "public-key", pubkey, pubkey_len); if (ret) - printf("Can't set public-key in node %s (ret = %d)\n", - IMAGE_PRE_LOAD_PATH, ret); + fprintf(stderr, "Can't set public-key in node %s (ret = %d)\n", + IMAGE_PRE_LOAD_PATH, ret); out: return ret; @@ -1239,8 +1251,8 @@ int fit_cipher_data(const char *keydir, void *keydest, void *fit, /* Find images parent node offset */ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); + fprintf(stderr, "Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return images_noffset; } @@ -1276,8 +1288,8 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, /* Find images parent node offset */ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); + fprintf(stderr, "Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return images_noffset; } @@ -1293,9 +1305,9 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, fit, noffset, comment, require_keys, engine_id, cmdname, algo_name); if (ret) { - printf("Can't add verification data for node '%s' (%s)\n", - fdt_get_name(fit, noffset, NULL), - fdt_strerror(ret)); + fprintf(stderr, "Can't add verification data for node '%s' (%s)\n", + fdt_get_name(fit, noffset, NULL), + fdt_strerror(ret)); return ret; } } @@ -1307,8 +1319,8 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, /* Find configurations parent node offset */ confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); if (confs_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_CONFS_PATH, fdt_strerror(confs_noffset)); + fprintf(stderr, "Can't find images parent node '%s' (%s)\n", + FIT_CONFS_PATH, fdt_strerror(confs_noffset)); return -ENOENT; } -- cgit v1.2.3 From 0ad3eef38121b378cac1383b13b7365b1b9b1922 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 31 Jul 2023 00:16:52 +0200 Subject: tools: relocate-rela: Fix BE symtab handling The symtab contains data in target endianness, convert the data to native endianness before doing any operations and on them, and back to target endianness before updating the bin file. Signed-off-by: Marek Vasut Tested-by: Michal Simek # microblaze, arm64 Reviewed-by: Angelo Dureghello --- tools/relocate-rela.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c index f230ec5676c..e28e7fcc6f5 100644 --- a/tools/relocate-rela.c +++ b/tools/relocate-rela.c @@ -78,6 +78,14 @@ static uint32_t elf32_to_cpu(uint32_t data) return be32_to_cpu(data); } +static uint32_t cpu_to_elf32(uint32_t data) +{ + if (ei_data == ELFDATA2LSB) + return cpu_to_le32(data); + + return cpu_to_be32(data); +} + static bool supported_rela(Elf64_Rela *rela) { uint64_t mask = 0xffffffffULL; /* would be different on 32-bit */ @@ -602,14 +610,16 @@ static int rela_elf32(char **argv, FILE *f) } debug("Symbol description:\n"); - debug(" st_name:\t0x%x\n", symbols.st_name); - debug(" st_value:\t0x%x\n", symbols.st_value); - debug(" st_size:\t0x%x\n", symbols.st_size); + debug(" st_name:\t0x%x\n", elf32_to_cpu(symbols.st_name)); + debug(" st_value:\t0x%x\n", elf32_to_cpu(symbols.st_value)); + debug(" st_size:\t0x%x\n", elf32_to_cpu(symbols.st_size)); - value = swrela.r_addend + symbols.st_value; + value = swrela.r_addend + elf32_to_cpu(symbols.st_value); debug("Value:\t0x%x\n", value); + value = cpu_to_elf32(value); + if (fseek(f, addr, SEEK_SET) < 0) { fprintf(stderr, "%s: %s: seek to %" PRIx32 " failed: %s\n", -- cgit v1.2.3 From bf10b9201c1ed198f76bc0a35fc64951de7583bc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 27 Aug 2023 00:25:35 +0200 Subject: tools: relocate-rela: Add M68K support Add M68K ELF32 support into this tool, so it can patch static rela into M68K u-boot-nodtb.bin . This is the first step toward M68K relocation support, and in turn, removal of NEEDS_MANUAL_RELOC from the codebase altogether. Tested-by: Michal Simek # microblaze, arm64 Signed-off-by: Marek Vasut --- tools/relocate-rela.c | 116 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 31 deletions(-) (limited to 'tools') diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c index e28e7fcc6f5..613abd25ef4 100644 --- a/tools/relocate-rela.c +++ b/tools/relocate-rela.c @@ -24,6 +24,30 @@ #define R_AARCH64_RELATIVE 1027 #endif +#ifndef EM_M68K +#define EM_M68K 4 +#endif + +#ifndef R_68K_NONE +#define R_68K_NONE 0 +#endif + +#ifndef R_68K_32 +#define R_68K_32 1 +#endif + +#ifndef R_68K_GLOB_DAT +#define R_68K_GLOB_DAT 20 +#endif + +#ifndef R_68K_JMP_SLOT +#define R_68K_JMP_SLOT 21 +#endif + +#ifndef R_68K_RELATIVE +#define R_68K_RELATIVE 22 +#endif + #ifndef EM_MICROBLAZE #define EM_MICROBLAZE 189 #endif @@ -46,6 +70,7 @@ static int ei_class; static int ei_data; +static int machine; static uint64_t rela_start, rela_end, text_base, dyn_start; @@ -111,7 +136,7 @@ static int decode_elf64(FILE *felf, char **argv) uint64_t sh_addr, sh_offset, sh_size; Elf64_Half sh_index, sh_num; Elf64_Shdr *sh_table; /* Elf symbol table */ - int ret, i, machine; + int ret, i; char *sh_str; debug("64bit version\n"); @@ -245,7 +270,7 @@ static int decode_elf32(FILE *felf, char **argv) uint32_t sh_addr, sh_offset, sh_size; Elf32_Half sh_index, sh_num; Elf32_Shdr *sh_table; /* Elf symbol table */ - int ret, i, machine; + int ret, i; char *sh_str; debug("32bit version\n"); @@ -262,12 +287,20 @@ static int decode_elf32(FILE *felf, char **argv) machine = elf16_to_cpu(header.e_machine); debug("Machine %d\n", machine); - if (machine != EM_MICROBLAZE) { + if (machine != EM_MICROBLAZE && machine != EM_M68K) { fprintf(stderr, "%s: Not supported machine type\n", argv[0]); return 30; } text_base = elf32_to_cpu(header.e_entry); + /* + * M68K ELF entry point is MONITOR_BASE, not TEXT_BASE. + * TEXT_BASE is always MONITOR_BASE &~ 0x7ff, so clear + * those bits here. + */ + if (machine == EM_M68K) + text_base &= ~0x7ff; + section_header_base = elf32_to_cpu(header.e_shoff); section_header_size = elf16_to_cpu(header.e_shentsize) * elf16_to_cpu(header.e_shnum); @@ -488,25 +521,44 @@ static bool supported_rela32(Elf32_Rela *rela, uint32_t *type) debug("Type:\t"); - switch (*type) { - case R_MICROBLAZE_32: - debug("R_MICROBLAZE_32\n"); - return true; - case R_MICROBLAZE_GLOB_DAT: - debug("R_MICROBLAZE_GLOB_DAT\n"); - return true; - case R_MICROBLAZE_NONE: - debug("R_MICROBLAZE_NONE - ignoring - do nothing\n"); - return false; - case R_MICROBLAZE_REL: - debug("R_MICROBLAZE_REL\n"); - return true; - default: - fprintf(stderr, "warning: unsupported relocation type %" - PRIu32 " at %" PRIx32 "\n", *type, rela->r_offset); - - return false; + if (machine == EM_M68K) { + switch (*type) { + case R_68K_32: + debug("R_68K_32\n"); + return true; + case R_68K_GLOB_DAT: + debug("R_68K_GLOB_DAT\n"); + return true; + case R_68K_JMP_SLOT: + debug("R_68K_JMP_SLOT\n"); + return true; + case R_68K_NONE: + debug("R_68K_NONE - ignoring - do nothing\n"); + return false; + case R_68K_RELATIVE: + debug("R_68K_RELATIVE\n"); + return true; + } + } else { + switch (*type) { + case R_MICROBLAZE_32: + debug("R_MICROBLAZE_32\n"); + return true; + case R_MICROBLAZE_GLOB_DAT: + debug("R_MICROBLAZE_GLOB_DAT\n"); + return true; + case R_MICROBLAZE_NONE: + debug("R_MICROBLAZE_NONE - ignoring - do nothing\n"); + return false; + case R_MICROBLAZE_REL: + debug("R_MICROBLAZE_REL\n"); + return true; + } } + fprintf(stderr, "warning: unsupported relocation type %" + PRIu32 " at %" PRIx32 "\n", *type, rela->r_offset); + + return false; } static int rela_elf32(char **argv, FILE *f) @@ -569,8 +621,8 @@ static int rela_elf32(char **argv, FILE *f) debug("Addr:\t0x%" PRIx32 "\n", addr); - switch (type) { - case R_MICROBLAZE_REL: + if ((machine == EM_M68K && type == R_68K_RELATIVE) || + (machine == EM_MICROBLAZE && type == R_MICROBLAZE_REL)) { if (fseek(f, addr, SEEK_SET) < 0) { fprintf(stderr, "%s: %s: seek to %" PRIx32 " failed: %s\n", @@ -585,9 +637,12 @@ static int rela_elf32(char **argv, FILE *f) argv[0], argv[1], addr); return 4; } - break; - case R_MICROBLAZE_32: - case R_MICROBLAZE_GLOB_DAT: + } else if ((machine == EM_M68K && + (type == R_68K_32 || type == R_68K_GLOB_DAT || + type == R_68K_JMP_SLOT)) || + (machine == EM_MICROBLAZE && + (type == R_MICROBLAZE_32 || + type == R_MICROBLAZE_GLOB_DAT))) { /* global symbols read it and add reloc offset */ index = swrela.r_info >> 8; pos_dyn = dyn_start + sizeof(Elf32_Sym) * index; @@ -632,12 +687,11 @@ static int rela_elf32(char **argv, FILE *f) argv[0], argv[1], addr); return 4; } - - break; - case R_MICROBLAZE_NONE: + } else if (machine == EM_M68K && type == R_68K_NONE) { + debug("R_68K_NONE - skip\n"); + } else if (machine == EM_MICROBLAZE && type == R_MICROBLAZE_NONE) { debug("R_MICROBLAZE_NONE - skip\n"); - break; - default: + } else { fprintf(stderr, "warning: unsupported relocation type %" PRIu32 " at %" PRIx32 "\n", type, rela.r_offset); -- cgit v1.2.3 From b87f904709fa86e485c6f424ea2a380999910db0 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Sun, 20 Aug 2023 13:31:29 -0400 Subject: CI: Drop some jobs we didn't really utilize - We have added more TODO/etc comments since this task was created and never focused on removing them. - The output of sloccount isn't preserved or looked at, and if desired should be in the release stats pages instead somehow. - The results of cppcheck aren't investigated and require modeling work to be useful to start with. Signed-off-by: Tom Rini Reviewed-by: Simon Glass --- tools/docker/Dockerfile | 2 -- 1 file changed, 2 deletions(-) (limited to 'tools') diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 279b3a3504c..1acb5413c7e 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -43,7 +43,6 @@ RUN apt-get update && apt-get install -y \ clang-16 \ coreutils \ cpio \ - cppcheck \ curl \ device-tree-compiler \ dosfstools \ @@ -105,7 +104,6 @@ RUN apt-get update && apt-get install -y \ python3-virtualenv \ rpm2cpio \ sbsigntool \ - sloccount \ socat \ softhsm2 \ sparse \ -- cgit v1.2.3 From a467fb58b1b0534f1a212ce12a50aa21c02a6b97 Mon Sep 17 00:00:00 2001 From: Nikhil M Jain Date: Fri, 1 Sep 2023 16:09:13 +0530 Subject: tools: logos: Rename TI logo files Change the file name from ti.gz and ti.bmp to ti_logos_414x97_32bpp to help user understand the resolution and identify the logo files when placed in the boot partition and update the splashfile name with the same in .env file. Signed-off-by: Nikhil M Jain Reviewed-by: Devarsh Thakkar --- tools/logos/ti.bmp | Bin 160770 -> 0 bytes tools/logos/ti.gz | Bin 12285 -> 0 bytes tools/logos/ti_logo_414x97_32bpp.bmp | Bin 0 -> 160770 bytes tools/logos/ti_logo_414x97_32bpp.bmp.gz | Bin 0 -> 12285 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tools/logos/ti.bmp delete mode 100644 tools/logos/ti.gz create mode 100644 tools/logos/ti_logo_414x97_32bpp.bmp create mode 100644 tools/logos/ti_logo_414x97_32bpp.bmp.gz (limited to 'tools') diff --git a/tools/logos/ti.bmp b/tools/logos/ti.bmp deleted file mode 100644 index 7fee6e81e07..00000000000 Binary files a/tools/logos/ti.bmp and /dev/null differ diff --git a/tools/logos/ti.gz b/tools/logos/ti.gz deleted file mode 100644 index 3a5b45e0358..00000000000 Binary files a/tools/logos/ti.gz and /dev/null differ diff --git a/tools/logos/ti_logo_414x97_32bpp.bmp b/tools/logos/ti_logo_414x97_32bpp.bmp new file mode 100644 index 00000000000..7fee6e81e07 Binary files /dev/null and b/tools/logos/ti_logo_414x97_32bpp.bmp differ diff --git a/tools/logos/ti_logo_414x97_32bpp.bmp.gz b/tools/logos/ti_logo_414x97_32bpp.bmp.gz new file mode 100644 index 00000000000..3a5b45e0358 Binary files /dev/null and b/tools/logos/ti_logo_414x97_32bpp.bmp.gz differ -- cgit v1.2.3 From 64fd30d367a1d5e33dbcbc2d017ca0431242155c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 17 Sep 2023 13:47:30 +0200 Subject: tools: mkimage: Add StarFive SPL image support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The StarFive JH7110 base boards require a header to be prefixed to the SPL binary image. This has previously done with a vendor tool 'spl_tool' published under a GPL-2-or-later license. Integrate this capability into mkimage. Signed-off-by: Heinrich Schuchardt Tested-by: Chanho Park Tested-by: Milan P. Stanić --- tools/Makefile | 1 + tools/sfspl.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 tools/sfspl.c (limited to 'tools') diff --git a/tools/Makefile b/tools/Makefile index 3d0c4b0dd6a..1aa1e36137b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -123,6 +123,7 @@ dumpimage-mkimage-objs := aisimage.o \ pblimage.o \ pbl_crc32.o \ renesas_spkgimage.o \ + sfspl.o \ vybridimage.o \ stm32image.o \ $(ROCKCHIP_OBS) \ diff --git a/tools/sfspl.c b/tools/sfspl.c new file mode 100644 index 00000000000..ec18a0a77e7 --- /dev/null +++ b/tools/sfspl.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright Heinrich Schuchardt + * + * The StarFive JH7110 requires to prepend a header to u-boot-spl.bin describing + * the payload length and CRC32. + * + * This module implements support in mkimage and dumpimage for this file format. + * + * StarFive's spl_tool available under GPL-2.0-and-later at + * https://github.com/starfive-tech/Tools implements writing the same file + * format and served as a reference. + */ + +#include +#include +#include +#include +#include "imagetool.h" + +#define DEFAULT_VERSION 0x01010101 +#define DEFAULT_BACKUP 0x200000U +#define DEFAULT_OFFSET 0x240 + +/** + * struct spl_hdr - header for SPL on JH7110 + * + * All fields are low-endian. + */ +struct spl_hdr { + /** @offset: offset to SPL header (0x240) */ + unsigned int offset; + /** @bkp_offs: address of backup SPL, defaults to DEFAULT_BACKUP */ + unsigned int bkp_offs; + /** @zero1: set to zero */ + unsigned int zero1[159]; + /** @version: header version, defaults to DEFAULT_VERSION */ + unsigned int version; + /** @file_size: file size */ + unsigned int file_size; + /** @hdr_size: size of the file header (0x400) */ + unsigned int hdr_size; + /** @crc32: CRC32 */ + unsigned int crc32; + /** @zero2: set to zero */ + unsigned int zero2[91]; +}; + +static int sfspl_check_params(struct image_tool_params *params) +{ + /* Only the RISC-V architecture is supported */ + if (params->Aflag && params->arch != IH_ARCH_RISCV) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int sfspl_verify_header(unsigned char *buf, int size, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = (void *)buf; + unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); + unsigned int file_size = le32_to_cpu(hdr->file_size); + unsigned int crc = le32_to_cpu(hdr->crc32); + unsigned int crc_check; + + if (size < 0 || + (size_t)size < sizeof(struct spl_hdr) || + (size_t)size < hdr_size + file_size) { + printf("Truncated file\n"); + return EXIT_FAILURE; + } + if (hdr->version != DEFAULT_VERSION) { + printf("Unknown file format version\n"); + return EXIT_FAILURE; + } + crc_check = crc32(0, &buf[hdr_size], size - hdr_size); + if (crc_check != crc) { + printf("Incorrect CRC32\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static void sfspl_print_header(const void *buf, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = (void *)buf; + unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); + unsigned int file_size = le32_to_cpu(hdr->file_size); + + printf("Header size: %u\n", hdr_size); + printf("Payload size: %u\n", file_size); +} + +static int sfspl_image_extract_subimage(void *ptr, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = (void *)ptr; + unsigned char *buf = ptr; + int fd; + unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); + unsigned int file_size = le32_to_cpu(hdr->file_size); + + if (params->pflag) { + printf("Invalid image index %d\n", params->pflag); + return EXIT_FAILURE; + } + + fd = open(params->outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + perror("Can write file"); + return EXIT_FAILURE; + } + if (write(fd, &buf[hdr_size], file_size) != file_size) { + perror("Cannot write file"); + return EXIT_FAILURE; + } + close(fd); + + return EXIT_SUCCESS; +} + +static int sfspl_check_image_type(uint8_t type) +{ + if (type == IH_TYPE_STARFIVE_SPL) + return EXIT_SUCCESS; + + return EXIT_FAILURE; +} + +static void sfspl_set_header(void *buf, struct stat *sbuf, int infd, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = buf; + unsigned int file_size; + unsigned int crc; + + file_size = params->file_size - sizeof(struct spl_hdr); + crc = crc32(0, &((unsigned char *)buf)[sizeof(struct spl_hdr)], + file_size); + + hdr->offset = cpu_to_le32(DEFAULT_OFFSET); + hdr->bkp_offs = cpu_to_le32(DEFAULT_BACKUP); + hdr->version = cpu_to_le32(DEFAULT_VERSION); + hdr->file_size = cpu_to_le32(file_size); + hdr->hdr_size = cpu_to_le32(sizeof(struct spl_hdr)); + hdr->crc32 = cpu_to_le32(crc); +} + +static int sfspl_vrec_header(struct image_tool_params *params, + struct image_type_params *tparams) +{ + tparams->hdr = calloc(sizeof(struct spl_hdr), 1); + + /* No padding */ + return 0; +} + +U_BOOT_IMAGE_TYPE( + sfspl, /* id */ + "StarFive SPL Image", /* name */ + sizeof(struct spl_hdr), /* header_size */ + NULL, /* header */ + sfspl_check_params, /* check_params */ + sfspl_verify_header, /* verify header */ + sfspl_print_header, /* print header */ + sfspl_set_header, /* set header */ + sfspl_image_extract_subimage, /* extract_subimage */ + sfspl_check_image_type, /* check_image_type */ + NULL, /* fflag_handle */ + sfspl_vrec_header /* vrec_header */ +); -- cgit v1.2.3 From dee8739a1ba5fe8cdf1c51b168dbc56f7bd921c4 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 15 Sep 2023 14:12:03 +0200 Subject: trace: Use 64bit variable for start and len tputq() requires variables to have 64bit width that's why make them 64bit to clean alignment requirement. Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/6edb34ef1f10010d2380f964fb6b4fb3dc257799.1694779918.git.michal.simek@amd.com --- tools/proftool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/proftool.c b/tools/proftool.c index 101bcb63334..869a2a32c51 100644 --- a/tools/proftool.c +++ b/tools/proftool.c @@ -1493,7 +1493,8 @@ static int write_pages(struct twriter *tw, enum out_format_t out_format, static int write_flyrecord(struct twriter *tw, enum out_format_t out_format, int *missing_countp, int *skip_countp) { - int start, ret, len; + unsigned long long start, len; + int ret; FILE *fout = tw->fout; char str[200]; -- cgit v1.2.3 From ad0f3cdc219c9482c728cdbcf43cfcc2dfba04e2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 15 Sep 2023 14:12:04 +0200 Subject: trace: Move trace_clocks description above record offset calculation Flyrecord tracing data are page aligned that's why it is necessary to calculate alignment properly. Because trace_clocks description is the part of record length it is necessary to have information about length earlier. Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/d3853d91b6fa7e3a1e5c24dd3c17335cf0041b5b.1694779918.git.michal.simek@amd.com --- tools/proftool.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/proftool.c b/tools/proftool.c index 869a2a32c51..7c95a94482f 100644 --- a/tools/proftool.c +++ b/tools/proftool.c @@ -1500,6 +1500,10 @@ static int write_flyrecord(struct twriter *tw, enum out_format_t out_format, tw->ptr += fprintf(fout, "flyrecord%c", 0); + snprintf(str, sizeof(str), + "[local] global counter uptime perf mono mono_raw boot x86-tsc\n"); + len = strlen(str); + /* trace data */ start = ALIGN(tw->ptr + 16, TRACE_PAGE_SIZE); tw->ptr += tputq(fout, start); @@ -1510,9 +1514,6 @@ static int write_flyrecord(struct twriter *tw, enum out_format_t out_format, return -1; tw->ptr += ret; - snprintf(str, sizeof(str), - "[local] global counter uptime perf mono mono_raw boot x86-tsc\n"); - len = strlen(str); tw->ptr += tputq(fout, len); tw->ptr += tputs(fout, str); -- cgit v1.2.3 From 8750d35ee295b0713d621a7d667515ef63fca246 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 15 Sep 2023 14:12:05 +0200 Subject: trace: Fix alignment logic in flyrecord header Current alignment which is using 16 bytes is not correct in connection to trace_clocks description and it's length. That's why use start_addr variable and record proper size based on used entries. Fixes: be16fc81b2ed ("trace: Update proftool to use new binary format"). Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/691dad64df80993ca4cfb6d0e33964ed26f50bee.1694779918.git.michal.simek@amd.com --- tools/proftool.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/proftool.c b/tools/proftool.c index 7c95a94482f..fca45e4a5af 100644 --- a/tools/proftool.c +++ b/tools/proftool.c @@ -1493,19 +1493,43 @@ static int write_pages(struct twriter *tw, enum out_format_t out_format, static int write_flyrecord(struct twriter *tw, enum out_format_t out_format, int *missing_countp, int *skip_countp) { - unsigned long long start, len; + unsigned long long start, start_ofs, len; int ret; FILE *fout = tw->fout; char str[200]; + /* Record start pointer */ + start_ofs = tw->ptr; + debug("Start of flyrecord header at: 0x%llx\n", start_ofs); + tw->ptr += fprintf(fout, "flyrecord%c", 0); + /* flyrecord\0 - allocated 10 bytes */ + start_ofs += 10; + + /* + * 8 bytes that are a 64-bit word containing the offset into the file + * that holds the data for the CPU. + * + * 8 bytes that are a 64-bit word containing the size of the CPU + * data at that offset. + */ + start_ofs += 16; + snprintf(str, sizeof(str), "[local] global counter uptime perf mono mono_raw boot x86-tsc\n"); len = strlen(str); + /* trace clock length - 8 bytes */ + start_ofs += 8; + /* trace clock data */ + start_ofs += len; + + debug("Calculated flyrecord header end at: 0x%llx, trace clock len: 0x%llx\n", + start_ofs, len); + /* trace data */ - start = ALIGN(tw->ptr + 16, TRACE_PAGE_SIZE); + start = ALIGN(start_ofs, TRACE_PAGE_SIZE); tw->ptr += tputq(fout, start); /* use a placeholder for the size */ @@ -1517,6 +1541,9 @@ static int write_flyrecord(struct twriter *tw, enum out_format_t out_format, tw->ptr += tputq(fout, len); tw->ptr += tputs(fout, str); + debug("End of flyrecord header at: 0x%x, offset: 0x%llx\n", + tw->ptr, start); + debug("trace text base %lx, map file %lx\n", text_base, text_offset); ret = write_pages(tw, out_format, missing_countp, skip_countp); -- cgit v1.2.3 From 124a0da55429c75b04f791227ed5ab716ce37612 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 7 Sep 2023 10:00:17 -0600 Subject: buildman: Keep all common output files Make a list of common output extensions and use it to ensure that the -k option preserves all of these. Signed-off-by: Simon Glass Suggested-by: Tom Rini Reviewed-by: Tom Rini --- tools/buildman/builderthread.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py index 25f460c207d..6a61f64da1d 100644 --- a/tools/buildman/builderthread.py +++ b/tools/buildman/builderthread.py @@ -23,6 +23,9 @@ from u_boot_pylib import command RETURN_CODE_RETRY = -1 BASE_ELF_FILENAMES = ['u-boot', 'spl/u-boot-spl', 'tpl/u-boot-tpl'] +# Common extensions for images +COMMON_EXTS = ['.bin', '.rom', '.itb', '.img'] + def mkdir(dirname, parents=False): """Make a directory if it doesn't already exist. @@ -636,10 +639,11 @@ class BuilderThread(threading.Thread): # Now write the actual build output if keep_outputs: - copy_files( - result.out_dir, build_dir, '', - ['u-boot*', '*.bin', '*.map', '*.img', 'MLO', 'SPL', - 'include/autoconf.mk', 'spl/u-boot-spl*']) + to_copy = ['u-boot*', '*.map', 'MLO', 'SPL', + 'include/autoconf.mk', 'spl/u-boot-spl*', + 'tpl/u-boot-tpl*', 'vpl/u-boot-vpl*'] + to_copy += [f'*{ext}' for ext in COMMON_EXTS] + copy_files(result.out_dir, build_dir, '', to_copy) def _send_result(self, result): """Send a result to the builder for processing -- cgit v1.2.3 From 283dcb63cb7d124fa427938f39aa9362872e02fc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 7 Sep 2023 10:00:18 -0600 Subject: buildman: Show progress when regenerating the board.cfg file This can take a while, so show a message when starting. Signed-off-by: Simon Glass Reported-by Tom Rini --- tools/buildman/boards.py | 15 ++++++++++++--- tools/buildman/control.py | 3 ++- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/buildman/boards.py b/tools/buildman/boards.py index eef3f19f7ad..341a5056dfd 100644 --- a/tools/buildman/boards.py +++ b/tools/buildman/boards.py @@ -19,6 +19,7 @@ import time from buildman import board from buildman import kconfiglib +from u_boot_pylib.terminal import print_clear, tprint ### constant variables ### OUTPUT_FILE = 'boards.cfg' @@ -863,11 +864,19 @@ class Boards: Returns: bool: True if all is well, False if there were warnings """ - if not force and output_is_new(output, CONFIG_DIR, '.'): + if not force: if not quiet: - print(f'{output} is up to date. Nothing to do.') - return True + tprint('\rChecking for Kconfig changes...', newline=False) + is_new = output_is_new(output, CONFIG_DIR, '.') + print_clear() + if is_new: + if not quiet: + print(f'{output} is up to date. Nothing to do.') + return True + if not quiet: + tprint('\rGenerating board list...', newline=False) params_list, warnings = self.build_board_list(CONFIG_DIR, '.', jobs) + print_clear() for warn in warnings: print(warn, file=sys.stderr) self.format_and_output(params_list, output) diff --git a/tools/buildman/control.py b/tools/buildman/control.py index f2ffb7f5b4a..8f6850c5211 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -621,7 +621,8 @@ def do_buildman(args, toolchains=None, make_func=None, brds=None, if not brds: brds = get_boards_obj(output_dir, args.regen_board_list, args.maintainer_check, args.full_check, - args.threads, args.verbose) + args.threads, args.verbose and + not args.print_arch and not args.print_prefix) if isinstance(brds, int): return brds -- cgit v1.2.3 From 2ce06f56cbbebd785b5e4c4a83ccec0d0a78e76d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 7 Sep 2023 10:00:19 -0600 Subject: buildman: Start the clock when the build starts The Kconfig and maintainer processing can take a while, sometimes 5 seconds or more. This skews the timing printed by buildmand when the build completes. Start the clock when the threads start to avoid this problem. Signed-off-by: Simon Glass Suggested-by: Tom Rini --- tools/buildman/builder.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index ecbd368c47a..5305477c5be 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -328,7 +328,7 @@ class Builder: self._build_period_us = None self._complete_delay = None self._next_delay_update = datetime.now() - self._start_time = datetime.now() + self._start_time = None self._step = step self._error_lines = 0 self.no_subdirs = no_subdirs @@ -1778,6 +1778,7 @@ class Builder: self._prepare_output_space() if not self._ide: tprint('\rStarting build...', newline=False) + self._start_time = datetime.now() self.setup_build(board_selected, commits) self.process_result(None) self.thread_exceptions = [] -- cgit v1.2.3