Import 80d60e7 from yoctoproject.org meta-arm
To support ARMv8 SoCs.
meta-arm has several patch files. Since they are maintained by the
upstream meta-arm community, add meta-arm to the ignore list in
run-repotest.
Change-Id: Ia87a2e947bbabd347d256eccc47a343e1c885479
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/meta-arm/ci/armgcc.yml b/meta-arm/ci/armgcc.yml
new file mode 100644
index 0000000..d46f0b3
--- /dev/null
+++ b/meta-arm/ci/armgcc.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+
+local_conf_header:
+ cc: |
+ GCCVERSION = "arm-11.2"
diff --git a/meta-arm/ci/base.yml b/meta-arm/ci/base.yml
new file mode 100644
index 0000000..eff466e
--- /dev/null
+++ b/meta-arm/ci/base.yml
@@ -0,0 +1,53 @@
+header:
+ version: 11
+
+distro: poky
+
+defaults:
+ repos:
+ refspec: master
+
+repos:
+ meta-arm:
+ layers:
+ meta-arm:
+ meta-arm-bsp:
+ meta-arm-toolchain:
+
+ poky:
+ url: https://git.yoctoproject.org/git/poky
+ layers:
+ meta:
+ meta-poky:
+
+env:
+ BB_LOGCONFIG: ""
+ TOOLCHAIN_DIR: ""
+
+local_conf_header:
+ base: |
+ BB_SERVER_TIMEOUT = "60"
+ CONF_VERSION = "2"
+ BB_NUMBER_THREADS = "16"
+ PARALLEL_MAKE = "-j16"
+ LICENSE_FLAGS_ACCEPTED += "Arm-FVP-EULA"
+ setup: |
+ PACKAGE_CLASSES = "package_ipk"
+ PACKAGECONFIG:remove:pn-qemu-system-native = "gtk+ sdl"
+ EXTRA_IMAGE_FEATURES:append = " debug-tweaks"
+ PACKAGECONFIG:append:pn-perf = " coresight"
+ INHERIT += "rm_work"
+ DISTRO_FEATURES:remove = "ptest"
+ kvm: |
+ QEMU_USE_KVM = ""
+ perf: |
+ CORE_IMAGE_EXTRA_INSTALL += "perf"
+ sshkeys: |
+ CORE_IMAGE_EXTRA_INSTALL += "ssh-pregen-hostkeys"
+ universally_failing_tests: |
+ TEST_SUITES:remove = "opkg"
+
+machine: unset
+
+target:
+ - core-image-sato
diff --git a/meta-arm/ci/check-machine-coverage b/meta-arm/ci/check-machine-coverage
new file mode 100755
index 0000000..f329fce
--- /dev/null
+++ b/meta-arm/ci/check-machine-coverage
@@ -0,0 +1,28 @@
+#! /usr/bin/env python3
+
+from pathlib import Path
+import sys
+from listmachines import list_machines
+
+metaarm = Path.cwd()
+
+if metaarm.name != "meta-arm":
+ print("Not running inside meta-arm")
+ sys.exit(1)
+
+# Find all layers
+layers = (p.name for p in metaarm.glob("meta-*") if p.is_dir())
+# All machine configurations
+machines = list_machines(layers)
+
+# All kas files
+kas = metaarm.glob("ci/*.yml")
+kas = set(p.stem for p in kas)
+
+missing = machines - kas
+print(f"The following machines are missing: {', '.join(sorted(missing))}.")
+
+covered = len(machines) - len(missing)
+total = len(machines)
+percent = int(covered / total * 100)
+print(f"Coverage: {percent}%")
diff --git a/meta-arm/ci/check-warnings b/meta-arm/ci/check-warnings
new file mode 100755
index 0000000..89ae955
--- /dev/null
+++ b/meta-arm/ci/check-warnings
@@ -0,0 +1,19 @@
+#! /bin/bash
+
+# Expects the path to a log file as $1, and if this file has any content
+# then display the contents and exit with an error code.
+
+set -e -u
+
+LOGFILE=$1
+
+LINES=$(grep --invert-match "attempting MIRRORS if available" $LOGFILE | wc -l)
+if test "$LINES" -ne 0; then
+ echo ==============================
+ echo The build had warnings/errors:
+ echo ==============================
+ cat $LOGFILE
+ exit 1
+fi
+
+exit 0
diff --git a/meta-arm/ci/clang.yml b/meta-arm/ci/clang.yml
new file mode 100644
index 0000000..80b9a4e
--- /dev/null
+++ b/meta-arm/ci/clang.yml
@@ -0,0 +1,16 @@
+header:
+ version: 11
+
+repos:
+ meta-clang:
+ url: https://github.com/kraj/meta-clang
+
+local_conf_header:
+ clang: |
+ TOOLCHAIN = "clang"
+ # Clang causes more binaries to have buildpaths in the debug symbols
+ # https://github.com/llvm/llvm-project/issues/56609
+ WARN_QA:remove = "buildpaths"
+
+target:
+ - core-image-base
diff --git a/meta-arm/ci/corstone1000-common.yml b/meta-arm/ci/corstone1000-common.yml
new file mode 100644
index 0000000..6599d97
--- /dev/null
+++ b/meta-arm/ci/corstone1000-common.yml
@@ -0,0 +1,13 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-openembedded.yml
+local_conf_header:
+ perf: |
+
+distro: poky-tiny
+
+target:
+ - perf
+ - corstone1000-image
diff --git a/meta-arm/ci/corstone1000-fvp.yml b/meta-arm/ci/corstone1000-fvp.yml
new file mode 100644
index 0000000..1586504
--- /dev/null
+++ b/meta-arm/ci/corstone1000-fvp.yml
@@ -0,0 +1,12 @@
+header:
+ version: 11
+ includes:
+ - ci/corstone1000-common.yml
+
+local_conf_header:
+ fvp-config: |
+ # Remove Dropbear SSH as it will not fit into the corstone1000 image.
+ IMAGE_FEATURES:remove = " ssh-server-dropbear"
+ INHERIT += "fvpboot"
+
+machine: corstone1000-fvp
diff --git a/meta-arm/ci/corstone1000-mps3.yml b/meta-arm/ci/corstone1000-mps3.yml
new file mode 100644
index 0000000..2df7d97
--- /dev/null
+++ b/meta-arm/ci/corstone1000-mps3.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/corstone1000-common.yml
+
+machine: corstone1000-mps3
diff --git a/meta-arm/ci/corstone500.yml b/meta-arm/ci/corstone500.yml
new file mode 100644
index 0000000..ef78cac
--- /dev/null
+++ b/meta-arm/ci/corstone500.yml
@@ -0,0 +1,18 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+local_conf_header:
+ testimagefvp: |
+ INHERIT += "fvpboot"
+ IMAGE_FEATURES:remove = " ssh-server-dropbear"
+ perf: |
+
+machine: corstone500
+
+distro: poky-tiny
+
+target:
+ - core-image-minimal
+ - perf
diff --git a/meta-arm/ci/edk2.yml b/meta-arm/ci/edk2.yml
new file mode 100644
index 0000000..1261bf1
--- /dev/null
+++ b/meta-arm/ci/edk2.yml
@@ -0,0 +1,17 @@
+header:
+ version: 11
+
+local_conf_header:
+ bootfirmware: |
+ PREFERRED_PROVIDER_virtual/bootloader = "edk2-firmware"
+ MACHINE_FEATURES += "efi"
+ TFA_UBOOT = "0"
+ TFA_UEFI = "1"
+
+ EXTRA_IMAGEDEPENDS += "edk2-firmware"
+ EFI_PROVIDER ?= "grub-efi"
+
+ QB_DEFAULT_BIOS = "QEMU_EFI.fd"
+ WKS_FILE ?= "efi-disk.wks.in"
+ failing_tests: |
+ TEST_SUITES:remove = "xorg"
diff --git a/meta-arm/ci/external-gccarm.yml b/meta-arm/ci/external-gccarm.yml
new file mode 100644
index 0000000..2af8b5e
--- /dev/null
+++ b/meta-arm/ci/external-gccarm.yml
@@ -0,0 +1,8 @@
+header:
+ version: 11
+
+local_conf_header:
+ cc: |
+ SKIP_RECIPE[gcc-cross-arm] = "Using external toolchain"
+ TCMODE = "external-arm"
+ EXTERNAL_TOOLCHAIN = "${TOPDIR}/toolchains/${TARGET_ARCH}"
diff --git a/meta-arm/ci/fvp-base-arm32.yml b/meta-arm/ci/fvp-base-arm32.yml
new file mode 100644
index 0000000..be4b008
--- /dev/null
+++ b/meta-arm/ci/fvp-base-arm32.yml
@@ -0,0 +1,18 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: fvp-base-arm32
+
+local_conf_header:
+ testimagefvp: |
+ INHERIT = "fvpboot"
+ # This fails but we can't add to the ignorelist from meta-arm yet
+ # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14604
+ TEST_SUITES:remove = "parselogs"
+ # Tell testimage to connect to localhost:8122, and forward that to SSH in the FVP.
+ TEST_TARGET_IP = "127.0.0.1:8122"
+ FVP_CONFIG[bp.virtio_net.hostbridge.userNetPorts] = "8122=22"
+ failing_tests: |
+ TEST_SUITES:remove = "xorg"
diff --git a/meta-arm/ci/fvp-base.yml b/meta-arm/ci/fvp-base.yml
new file mode 100644
index 0000000..fa2ddb3
--- /dev/null
+++ b/meta-arm/ci/fvp-base.yml
@@ -0,0 +1,18 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: fvp-base
+
+local_conf_header:
+ testimagefvp: |
+ INHERIT += "fvpboot"
+ # This fails but we can't add to the ignorelist from meta-arm yet
+ # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14604
+ TEST_SUITES:remove = "parselogs"
+ # Tell testimage to connect to localhost:8022, and forward that to SSH in the FVP.
+ TEST_TARGET_IP = "localhost:8022"
+ FVP_CONFIG[bp.virtio_net.hostbridge.userNetPorts] ?= "8022=22"
+ failing_tests: |
+ TEST_SUITES:remove = "xorg"
diff --git a/meta-arm/ci/fvp-baser-aemv8r64.yml b/meta-arm/ci/fvp-baser-aemv8r64.yml
new file mode 100644
index 0000000..40818bc
--- /dev/null
+++ b/meta-arm/ci/fvp-baser-aemv8r64.yml
@@ -0,0 +1,7 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: fvp-baser-aemv8r64
+
diff --git a/meta-arm/ci/fvps.yml b/meta-arm/ci/fvps.yml
new file mode 100644
index 0000000..576faa3
--- /dev/null
+++ b/meta-arm/ci/fvps.yml
@@ -0,0 +1,20 @@
+# Simple target to build the FVPs that are publically available
+
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: qemuarm64
+
+local_conf_header:
+ sdk: |
+ SDKMACHINE = "x86_64"
+
+target:
+ - nativesdk-fvp-base-a-aem
+ - nativesdk-fvp-n1-edge
+ - nativesdk-fvp-sgi575
+ - nativesdk-fvp-corstone500
+ - nativesdk-fvp-corstone1000
+ - nativesdk-fvp-tc0
diff --git a/meta-arm/ci/gem5-arm64.yml b/meta-arm/ci/gem5-arm64.yml
new file mode 100644
index 0000000..90913f3
--- /dev/null
+++ b/meta-arm/ci/gem5-arm64.yml
@@ -0,0 +1,16 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-openembedded.yml
+
+repos:
+ meta-arm:
+ layers:
+ meta-gem5:
+
+machine: gem5-arm64
+
+target:
+ - core-image-minimal
+ - gem5-aarch64-native
diff --git a/meta-arm/ci/gem5-atp-arm64.yml b/meta-arm/ci/gem5-atp-arm64.yml
new file mode 100644
index 0000000..626947b
--- /dev/null
+++ b/meta-arm/ci/gem5-atp-arm64.yml
@@ -0,0 +1,15 @@
+header:
+ version: 11
+ includes:
+ - ci/gem5-arm64.yml
+
+repos:
+ meta-arm:
+ layers:
+ meta-atp:
+
+machine: gem5-atp-arm64
+
+target:
+ - atp-native
+ - core-image-minimal
diff --git a/meta-arm/ci/generic-arm64.yml b/meta-arm/ci/generic-arm64.yml
new file mode 100644
index 0000000..873c9fd
--- /dev/null
+++ b/meta-arm/ci/generic-arm64.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: generic-arm64
diff --git a/meta-arm/ci/get-binary-toolchains b/meta-arm/ci/get-binary-toolchains
new file mode 100755
index 0000000..bfdd8c5
--- /dev/null
+++ b/meta-arm/ci/get-binary-toolchains
@@ -0,0 +1,46 @@
+#!/bin/bash
+set -u
+
+HOST_ARCH=$(uname -m)
+VER="11.2-2022.02"
+
+DOWNLOAD_DIR=$1
+TOOLCHAIN_DIR=$2
+TOOLCHAIN_LINK_DIR=$3
+
+# These should be already created by .gitlab-ci.yml, but do here if run outside of that env
+mkdir -p $DOWNLOAD_DIR $TOOLCHAIN_DIR $TOOLCHAIN_LINK_DIR
+
+if [ $HOST_ARCH = "aarch64" ]; then
+ #AArch64 Linux hosted cross compilers
+
+ #AArch32 target with hard float (arm-none-linux-gnueabihf)
+ wget -P $DOWNLOAD_DIR -nc https://developer.arm.com/-/media/Files/downloads/gnu/$VER/binrel/gcc-arm-$VER-$HOST_ARCH-arm-none-linux-gnueabihf.tar.xz
+elif [ $HOST_ARCH = "x86_64" ]; then
+ #x86_64 Linux hosted cross compilers
+
+ #AArch32 target with hard float (arm-linux-none-gnueabihf)
+ wget -P $DOWNLOAD_DIR -nc https://developer.arm.com/-/media/Files/downloads/gnu/$VER/binrel/gcc-arm-$VER-$HOST_ARCH-arm-none-linux-gnueabihf.tar.xz
+
+ #AArch64 GNU/Linux target (aarch64-none-linux-gnu)
+ wget -P $DOWNLOAD_DIR -nc https://developer.arm.com/-/media/Files/downloads/gnu/$VER/binrel/gcc-arm-$VER-$HOST_ARCH-aarch64-none-linux-gnu.tar.xz
+
+ #AArch64 GNU/Linux target (aarch64_be-none-linux-gnu)
+ wget -P $DOWNLOAD_DIR -nc https://developer.arm.com/-/media/Files/downloads/gnu/$VER/binrel/gcc-arm-$VER-$HOST_ARCH-aarch64_be-none-linux-gnu.tar.xz
+else
+ echo "ERROR - Unknown build arch of $HOST_ARCH"
+ exit 1
+fi
+
+for i in arm aarch64 aarch64_be; do
+ if [ ! -d $TOOLCHAIN_DIR/gcc-arm-$VER-$HOST_ARCH-$i-none-linux-gnu*/ ]; then
+ if [ ! -f $DOWNLOAD_DIR/gcc-arm-$VER-$HOST_ARCH-$i-none-linux-gnu*.tar.xz ]; then
+ continue
+ fi
+
+ tar -C $TOOLCHAIN_DIR -axvf $DOWNLOAD_DIR/gcc-arm-$VER-$HOST_ARCH-$i-none-linux-gnu*.tar.xz
+ fi
+
+ # Setup a link for the toolchain to use local to the building machine (e.g., not in a shared location)
+ ln -s $TOOLCHAIN_DIR/gcc-arm-$VER-$HOST_ARCH-$i-none-linux-gnu* $TOOLCHAIN_LINK_DIR/$i
+done
diff --git a/meta-arm/ci/jobs-to-kas b/meta-arm/ci/jobs-to-kas
new file mode 100755
index 0000000..d6896b7
--- /dev/null
+++ b/meta-arm/ci/jobs-to-kas
@@ -0,0 +1,27 @@
+#! /bin/bash
+
+# This script is expecting an input of machine name, optionally followed by a
+# colon and a list of one or more parameters separated by commas between
+# brackets. For example, the following are acceptable:
+# corstone500
+# fvp-base: [testimage]
+# qemuarm64-secureboot: [clang, glibc, testimage]
+#
+# Turn this list into a series of yml files separated by colons to pass to kas
+
+set -e -u
+
+FILES="ci/$(echo $1 | cut -d ':' -f 1).yml"
+
+for i in $(echo $1 | cut -s -d ':' -f 2 | sed 's/[][,]//g'); do
+ # Given that there are no yml files for gcc or glibc, as those are the
+ # defaults, we can simply ignore those parameters. They are necessary
+ # to pass in so that matrix can correctly setup all of the permutations
+ # of each individual run.
+ if [[ $i == 'none' || $i == 'gcc' || $i == 'glibc' || $i == 'uboot' ]]; then
+ continue
+ fi
+ FILES+=":ci/$i.yml"
+done
+
+echo $FILES
diff --git a/meta-arm/ci/juno.yml b/meta-arm/ci/juno.yml
new file mode 100644
index 0000000..b2ee60a
--- /dev/null
+++ b/meta-arm/ci/juno.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: juno
diff --git a/meta-arm/ci/listmachines.py b/meta-arm/ci/listmachines.py
new file mode 100755
index 0000000..04d207e
--- /dev/null
+++ b/meta-arm/ci/listmachines.py
@@ -0,0 +1,29 @@
+#! /usr/bin/env python3
+
+import pathlib
+import typing
+import sys
+
+"""
+List all of the machines available under the listed sub-layers of meta-arm.
+"""
+def list_machines(layers: typing.Sequence[str]) -> typing.Set[str]:
+ machines = set()
+
+ # We know we're in meta-arm/scripts, so find the top-level directory
+ metaarm = pathlib.Path(__file__).resolve().parent.parent
+ if metaarm.name != "meta-arm":
+ raise Exception("Not running inside meta-arm")
+
+ for layer in layers:
+ machines |= set(p.stem for p in (metaarm / layer / "conf" / "machine").glob("*.conf"))
+ return machines
+
+if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ machines = list_machines(sys.argv[1:])
+ print(" ".join(sorted(machines)))
+ sys.exit(0)
+ else:
+ print("Usage:\n$ %s [layer name ...] " % sys.argv[0])
+ sys.exit(1)
diff --git a/meta-arm/ci/logging.yml b/meta-arm/ci/logging.yml
new file mode 100644
index 0000000..3af1029
--- /dev/null
+++ b/meta-arm/ci/logging.yml
@@ -0,0 +1,13 @@
+# Python logging configuration to write all warnings to a separate file
+version: 1
+
+handlers:
+ warnings:
+ class: logging.FileHandler
+ level: WARNING
+ filename: warnings.log
+ formatter: BitBake.logfileFormatter
+
+loggers:
+ BitBake:
+ handlers: [warnings]
diff --git a/meta-arm/ci/meta-openembedded.yml b/meta-arm/ci/meta-openembedded.yml
new file mode 100644
index 0000000..bed338d
--- /dev/null
+++ b/meta-arm/ci/meta-openembedded.yml
@@ -0,0 +1,11 @@
+header:
+ version: 11
+
+repos:
+ meta-openembedded:
+ url: https://git.openembedded.org/meta-openembedded
+ layers:
+ meta-filesystems:
+ meta-networking:
+ meta-oe:
+ meta-python:
diff --git a/meta-arm/ci/meta-virtualization.yml b/meta-arm/ci/meta-virtualization.yml
new file mode 100644
index 0000000..1cd0e21
--- /dev/null
+++ b/meta-arm/ci/meta-virtualization.yml
@@ -0,0 +1,8 @@
+header:
+ version: 11
+ includes:
+ - ci/meta-openembedded.yml
+
+repos:
+ meta-virtualization:
+ url: git://git.yoctoproject.org/meta-virtualization
diff --git a/meta-arm/ci/meta-zephyr.yml b/meta-arm/ci/meta-zephyr.yml
new file mode 100644
index 0000000..bdd0e2b
--- /dev/null
+++ b/meta-arm/ci/meta-zephyr.yml
@@ -0,0 +1,13 @@
+header:
+ version: 11
+ includes:
+ - ci/meta-openembedded.yml
+
+repos:
+ meta-zephyr:
+ url: https://git.yoctoproject.org/git/meta-zephyr
+ layers:
+ meta-zephyr-core:
+
+target:
+ - zephyr-kernel-test-all
diff --git a/meta-arm/ci/microbit-v1.yml b/meta-arm/ci/microbit-v1.yml
new file mode 100644
index 0000000..b850148
--- /dev/null
+++ b/meta-arm/ci/microbit-v1.yml
@@ -0,0 +1,7 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-zephyr.yml
+
+machine: microbit-v1
diff --git a/meta-arm/ci/musca-b1.yml b/meta-arm/ci/musca-b1.yml
new file mode 100644
index 0000000..dc9814d
--- /dev/null
+++ b/meta-arm/ci/musca-b1.yml
@@ -0,0 +1,15 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-zephyr.yml
+
+local_conf_header:
+ nonbuilding_tests: |
+ ZEPHYRTESTS:remove = "common sleep poll device queue"
+
+machine: musca-b1
+
+target:
+ - trusted-firmware-m
+ - zephyr-kernel-test-all
diff --git a/meta-arm/ci/musca-s1.yml b/meta-arm/ci/musca-s1.yml
new file mode 100644
index 0000000..80a59c4
--- /dev/null
+++ b/meta-arm/ci/musca-s1.yml
@@ -0,0 +1,15 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-zephyr.yml
+
+local_conf_header:
+ nonbuilding_tests: |
+ ZEPHYRTESTS:remove = "common sleep poll device queue"
+
+machine: musca-s1
+
+target:
+ - trusted-firmware-m
+ - zephyr-kernel-test-all
diff --git a/meta-arm/ci/musl.yml b/meta-arm/ci/musl.yml
new file mode 100644
index 0000000..ee7905e
--- /dev/null
+++ b/meta-arm/ci/musl.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+
+local_conf_header:
+ libc: |
+ TCLIBC = "musl"
diff --git a/meta-arm/ci/n1sdp.yml b/meta-arm/ci/n1sdp.yml
new file mode 100644
index 0000000..797a522
--- /dev/null
+++ b/meta-arm/ci/n1sdp.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: n1sdp
diff --git a/meta-arm/ci/patchreview b/meta-arm/ci/patchreview
new file mode 100755
index 0000000..b23eda1
--- /dev/null
+++ b/meta-arm/ci/patchreview
@@ -0,0 +1,286 @@
+#! /usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+# TODO
+# - option to just list all broken files
+# - test suite
+# - validate signed-off-by
+
+import argparse
+import collections
+import json
+import os
+import re
+import subprocess
+
+status_values = (
+ "accepted",
+ "pending",
+ "inappropriate",
+ "backport",
+ "submitted",
+ "denied",
+)
+
+
+class PatchResult:
+ # Whether the patch has an Upstream-Status or not
+ missing_upstream_status = False
+ # If the Upstream-Status tag is malformed in some way (string for bad bit)
+ malformed_upstream_status = None
+ # If the Upstream-Status value is unknown (boolean)
+ unknown_upstream_status = False
+ # The upstream status value (Pending, etc)
+ upstream_status = None
+ # Whether the patch has a Signed-off-by or not
+ missing_sob = False
+ # Whether the Signed-off-by tag is malformed in some way
+ malformed_sob = False
+ # The Signed-off-by tag value
+ sob = None
+ # Whether a patch looks like a CVE but doesn't have a CVE tag
+ missing_cve = False
+
+
+class Summary:
+ total = 0
+ cve_missing = 0
+ sob_missing = 0
+ sob_malformed = 0
+ status_missing = 0
+ status_malformed = 0
+ status_pending = 0
+
+def blame_patch(patch):
+ """
+ From a patch filename, return a list of "commit summary (author name <author
+ email>)" strings representing the history.
+ """
+ return subprocess.check_output(("git", "log",
+ "--follow", "--find-renames", "--diff-filter=A",
+ "--format=%s (%aN <%aE>)",
+ "--", patch)).decode("utf-8").splitlines()
+
+def patchreview(patches):
+ # General pattern: start of line, optional whitespace, tag with optional
+ # hyphen or spaces, maybe a colon, some whitespace, then the value, all case
+ # insensitive.
+ sob_re = re.compile(r"^[\t ]*(Signed[-_ ]off[-_ ]by:?)[\t ]*(.+)", re.IGNORECASE | re.MULTILINE)
+ status_re = re.compile(r"^[\t ]*(Upstream[-_ ]Status:?)[\t ]*(\w*)", re.IGNORECASE | re.MULTILINE)
+ cve_tag_re = re.compile(r"^[\t ]*(CVE:)[\t ]*(.*)", re.IGNORECASE | re.MULTILINE)
+ cve_re = re.compile(r"cve-[0-9]{4}-[0-9]{4,6}", re.IGNORECASE)
+
+ results = {}
+
+ for patch in patches:
+
+ result = PatchResult()
+ results[patch] = result
+
+ content = open(patch, encoding="ascii", errors="ignore").read()
+
+ # Find the Signed-off-by tag
+ match = sob_re.search(content)
+ if match:
+ value = match.group(1)
+ if value != "Signed-off-by:":
+ result.malformed_sob = value
+ result.sob = match.group(2)
+ else:
+ result.missing_sob = True
+
+ # Find the Upstream-Status tag
+ match = status_re.search(content)
+ if match:
+ value = match.group(1)
+ if value != "Upstream-Status:":
+ result.malformed_upstream_status = value
+
+ value = match.group(2).lower()
+ # TODO: check case
+ if value not in status_values:
+ result.unknown_upstream_status = True
+ result.upstream_status = value
+ else:
+ result.missing_upstream_status = True
+
+ # Check that patches which looks like CVEs have CVE tags
+ if cve_re.search(patch) or cve_re.search(content):
+ if not cve_tag_re.search(content):
+ result.missing_cve = True
+ # TODO: extract CVE list
+
+ return results
+
+
+def analyse(results, want_blame=False, verbose=True):
+ """
+ want_blame: display blame data for each malformed patch
+ verbose: display per-file results instead of just summary
+ """
+
+ # want_blame requires verbose, so disable blame if we're not verbose
+ if want_blame and not verbose:
+ want_blame = False
+
+ summary = Summary()
+
+ for patch in sorted(results):
+ r = results[patch]
+ summary.total += 1
+ need_blame = False
+
+ # Build statistics
+ if r.missing_sob:
+ summary.sob_missing += 1
+ if r.malformed_sob:
+ summary.sob_malformed += 1
+ if r.missing_upstream_status:
+ summary.status_missing += 1
+ if r.malformed_upstream_status or r.unknown_upstream_status:
+ summary.status_malformed += 1
+ # Count patches with no status as pending
+ summary.status_pending += 1
+ if r.missing_cve:
+ summary.cve_missing += 1
+ if r.upstream_status == "pending":
+ summary.status_pending += 1
+
+ # Output warnings
+ if r.missing_sob:
+ need_blame = True
+ if verbose:
+ print("Missing Signed-off-by tag (%s)" % patch)
+ if r.malformed_sob:
+ need_blame = True
+ if verbose:
+ print("Malformed Signed-off-by '%s' (%s)" % (r.malformed_sob, patch))
+ if r.missing_cve:
+ need_blame = True
+ if verbose:
+ print("Missing CVE tag (%s)" % patch)
+ if r.missing_upstream_status:
+ need_blame = True
+ if verbose:
+ print("Missing Upstream-Status tag (%s)" % patch)
+ if r.malformed_upstream_status:
+ need_blame = True
+ if verbose:
+ print("Malformed Upstream-Status '%s' (%s)" % (r.malformed_upstream_status, patch))
+ if r.unknown_upstream_status:
+ need_blame = True
+ if verbose:
+ print("Unknown Upstream-Status value '%s' (%s)" % (r.upstream_status, patch))
+
+ if want_blame and need_blame:
+ print("\n".join(blame_patch(patch)) + "\n")
+
+ return summary
+
+
+def display_summary(summary, verbose):
+ def percent(num):
+ try:
+ return "%d (%d%%)" % (num, round(num * 100.0 / summary.total))
+ except ZeroDivisionError:
+ return "N/A"
+
+ if verbose:
+ print()
+
+ print("""Total patches found: %d
+Patches missing Signed-off-by: %s
+Patches with malformed Signed-off-by: %s
+Patches missing CVE: %s
+Patches missing Upstream-Status: %s
+Patches with malformed Upstream-Status: %s
+Patches in Pending state: %s""" % (summary.total,
+ percent(summary.sob_missing),
+ percent(summary.sob_malformed),
+ percent(summary.cve_missing),
+ percent(summary.status_missing),
+ percent(summary.status_malformed),
+ percent(summary.status_pending)))
+
+
+def generate_metrics(summary, output):
+ # https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md
+ # Summary attribute name, MetricPoint help
+ mapping = (
+ ("total", "Total patches"),
+ ("cve_missing", "Patches missing CVE tag"),
+ ("sob_malformed", "Patches with malformed Signed-off-by"),
+ ("sob_missing", "Patches with missing Signed-off-by"),
+ ("status_malformed", "Patches with malformed Upstream-Status"),
+ ("status_missing", "Patches with missing Upstream-Status"),
+ ("status_pending", "Patches with Pending Upstream-Status")
+ )
+ for attr, help in mapping:
+ metric = f"patch_check_{attr}"
+ value = getattr(summary, attr)
+ output.write(f"""
+# TYPE {metric} gauge
+# HELP {help}
+{metric} {value}
+""")
+ output.write("\n# EOF\n")
+
+def histogram(results):
+ import math
+
+ from toolz import dicttoolz, recipes
+ counts = recipes.countby(lambda r: r.upstream_status, results.values())
+ bars = dicttoolz.valmap(lambda v: "#" * int(math.ceil(float(v) / len(results) * 100)), counts)
+ for k in bars:
+ print("%-20s %s (%d)" % (k.capitalize() if k else "No status", bars[k], counts[k]))
+
+def gather_patches(directories):
+ patches = []
+ for directory in directories:
+ filenames = subprocess.check_output(("git", "-C", directory, "ls-files", "recipes-*/**/*.patch", "recipes-*/**/*.diff")).decode("utf-8").split()
+ patches += [os.path.join(directory, f) for f in filenames]
+ return patches
+
+if __name__ == "__main__":
+ args = argparse.ArgumentParser(description="Patch Review Tool")
+ args.add_argument("-b", "--blame", action="store_true", help="show blame for malformed patches")
+ args.add_argument("-v", "--verbose", action="store_true", help="show per-patch results")
+ args.add_argument("-g", "--histogram", action="store_true", help="show patch histogram")
+ args.add_argument("-j", "--json", help="update JSON")
+ args.add_argument("-m", "--metrics", type=argparse.FileType('w'), help="write OpenMetrics")
+ args.add_argument("dirs", metavar="DIRECTORY", nargs="+", help="directory to scan")
+ args = args.parse_args()
+
+ patches = gather_patches(args.dirs)
+ results = patchreview(patches)
+ summary = analyse(results, want_blame=args.blame, verbose=args.verbose)
+ display_summary(summary, verbose=args.verbose)
+
+ if args.json:
+ if os.path.isfile(args.json):
+ data = json.load(open(args.json))
+ else:
+ data = []
+
+ row = collections.Counter()
+ row["total"] = len(results)
+ row["date"] = subprocess.check_output(["git", "-C", args.dirs[0], "show", "-s", "--pretty=format:%cd", "--date=format:%s"]).decode("utf-8").strip()
+ for r in results.values():
+ if r.upstream_status in status_values:
+ row[r.upstream_status] += 1
+ if r.malformed_upstream_status or r.missing_upstream_status:
+ row["malformed-upstream-status"] += 1
+ if r.malformed_sob or r.missing_sob:
+ row["malformed-sob"] += 1
+
+ data.append(row)
+ json.dump(data, open(args.json, "w"))
+
+ if args.metrics:
+ generate_metrics(summary, args.metrics)
+
+ if args.histogram:
+ print()
+ histogram(results)
diff --git a/meta-arm/ci/qemu-cortex-a53.yml b/meta-arm/ci/qemu-cortex-a53.yml
new file mode 100644
index 0000000..3eec580
--- /dev/null
+++ b/meta-arm/ci/qemu-cortex-a53.yml
@@ -0,0 +1,9 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-zephyr.yml
+
+# FIXME - testimage fails all tests currently, but all the tests build
+
+machine: qemu-cortex-a53
diff --git a/meta-arm/ci/qemu-cortex-m3.yml b/meta-arm/ci/qemu-cortex-m3.yml
new file mode 100644
index 0000000..f45cb9e
--- /dev/null
+++ b/meta-arm/ci/qemu-cortex-m3.yml
@@ -0,0 +1,20 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-zephyr.yml
+
+repos:
+ meta-zephyr:
+ layers:
+ meta-zephyr-bsp:
+
+local_conf_header:
+ tclibc: |
+ TCLIBC = "newlib"
+ nonbuilding_tests: |
+ ZEPHYRTESTS:remove = "common context pending poll sleep"
+ qemu_opts: |
+ QB_OPT_APPEND = "-icount shift=3,align=off,sleep=on -rtc clock=vm"
+
+machine: qemu-cortex-m3
diff --git a/meta-arm/ci/qemu-cortex-r5.yml b/meta-arm/ci/qemu-cortex-r5.yml
new file mode 100644
index 0000000..cfcb7b9
--- /dev/null
+++ b/meta-arm/ci/qemu-cortex-r5.yml
@@ -0,0 +1,11 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+ - ci/meta-zephyr.yml
+
+local_conf_header:
+ nonbuilding_tests: |
+ ZEPHYRTESTS:remove = "common poll sleep queue device"
+
+machine: qemu-cortex-r5
diff --git a/meta-arm/ci/qemu-generic-arm64.yml b/meta-arm/ci/qemu-generic-arm64.yml
new file mode 100644
index 0000000..87cbd2f
--- /dev/null
+++ b/meta-arm/ci/qemu-generic-arm64.yml
@@ -0,0 +1,14 @@
+header:
+ version: 11
+ includes:
+ - ci/generic-arm64.yml
+
+local_conf_header:
+ failing_tests: |
+ DEFAULT_TEST_SUITES:remove = "parselogs"
+
+machine: qemu-generic-arm64
+
+target:
+ - core-image-base
+ - sbsa-acs
diff --git a/meta-arm/ci/qemuarm-secureboot.yml b/meta-arm/ci/qemuarm-secureboot.yml
new file mode 100644
index 0000000..044661c
--- /dev/null
+++ b/meta-arm/ci/qemuarm-secureboot.yml
@@ -0,0 +1,12 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: qemuarm-secureboot
+
+target:
+ - core-image-base
+ - optee-examples
+ - optee-test
+ - optee-os-tadevkit
diff --git a/meta-arm/ci/qemuarm.yml b/meta-arm/ci/qemuarm.yml
new file mode 100644
index 0000000..4155847
--- /dev/null
+++ b/meta-arm/ci/qemuarm.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: qemuarm
diff --git a/meta-arm/ci/qemuarm64-secureboot.yml b/meta-arm/ci/qemuarm64-secureboot.yml
new file mode 100644
index 0000000..7e15a76
--- /dev/null
+++ b/meta-arm/ci/qemuarm64-secureboot.yml
@@ -0,0 +1,18 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: qemuarm64-secureboot
+
+local_conf_header:
+ failing_tests: |
+ # software IO TLB: Cannot allocate buffer
+ DEFAULT_TEST_SUITES:remove = "parselogs"
+
+target:
+ - core-image-base
+ - optee-examples
+ - optee-test
+ - optee-spdevkit
+ - optee-os-tadevkit
diff --git a/meta-arm/ci/qemuarm64.yml b/meta-arm/ci/qemuarm64.yml
new file mode 100644
index 0000000..6639034
--- /dev/null
+++ b/meta-arm/ci/qemuarm64.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: qemuarm64
diff --git a/meta-arm/ci/qemuarmv5.yml b/meta-arm/ci/qemuarmv5.yml
new file mode 100644
index 0000000..18c7a15
--- /dev/null
+++ b/meta-arm/ci/qemuarmv5.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: qemuarmv5
diff --git a/meta-arm/ci/selftest.yml b/meta-arm/ci/selftest.yml
new file mode 100644
index 0000000..9a58735
--- /dev/null
+++ b/meta-arm/ci/selftest.yml
@@ -0,0 +1,7 @@
+header:
+ version: 11
+
+local_conf_header:
+ setup: |
+ BB_LOGCONFIG = ""
+ SANITY_TESTED_DISTROS = ""
diff --git a/meta-arm/ci/sgi575.yml b/meta-arm/ci/sgi575.yml
new file mode 100644
index 0000000..1895fc5
--- /dev/null
+++ b/meta-arm/ci/sgi575.yml
@@ -0,0 +1,6 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: sgi575
diff --git a/meta-arm/ci/tc0.yml b/meta-arm/ci/tc0.yml
new file mode 100644
index 0000000..b2f75d5
--- /dev/null
+++ b/meta-arm/ci/tc0.yml
@@ -0,0 +1,9 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: tc0
+
+target:
+ - tc-artifacts-image
diff --git a/meta-arm/ci/tc1.yml b/meta-arm/ci/tc1.yml
new file mode 100644
index 0000000..fd9acbd
--- /dev/null
+++ b/meta-arm/ci/tc1.yml
@@ -0,0 +1,9 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+machine: tc1
+
+target:
+ - tc-artifacts-image
diff --git a/meta-arm/ci/testimage-zephyr.yml b/meta-arm/ci/testimage-zephyr.yml
new file mode 100644
index 0000000..83e17a7
--- /dev/null
+++ b/meta-arm/ci/testimage-zephyr.yml
@@ -0,0 +1,9 @@
+header:
+ version: 11
+
+local_conf_header:
+ testimage: |
+ IMAGE_CLASSES += "testimage"
+ TEST_TARGET = "QemuTargetZephyr"
+ TEST_SUITES = "zephyr"
+ TESTIMAGE_AUTO = "1"
diff --git a/meta-arm/ci/testimage.yml b/meta-arm/ci/testimage.yml
new file mode 100644
index 0000000..a26dcaf
--- /dev/null
+++ b/meta-arm/ci/testimage.yml
@@ -0,0 +1,13 @@
+header:
+ version: 11
+
+local_conf_header:
+ testimage: |
+ IMAGE_CLASSES += "testimage"
+ TESTIMAGE_AUTO = "1"
+ slirp: |
+ TEST_RUNQEMUPARAMS = "slirp"
+ TEST_SERVER_IP = "127.0.0.1"
+ QEMU_USE_SLIRP = "1"
+ sshd: |
+ IMAGE_FEATURES:append = " ssh-server-dropbear"
diff --git a/meta-arm/ci/tftf.yml b/meta-arm/ci/tftf.yml
new file mode 100644
index 0000000..6e42d9c
--- /dev/null
+++ b/meta-arm/ci/tftf.yml
@@ -0,0 +1,7 @@
+header:
+ version: 9
+
+local_conf_header:
+ tftf: |
+ TFA_UBOOT = "0"
+ TFTF_TESTS = "1"
diff --git a/meta-arm/ci/toolchains.yml b/meta-arm/ci/toolchains.yml
new file mode 100644
index 0000000..080d8d9
--- /dev/null
+++ b/meta-arm/ci/toolchains.yml
@@ -0,0 +1,19 @@
+header:
+ version: 11
+ includes:
+ - ci/base.yml
+
+# Target is arm64 and SDK is x86-64 to ensure that we exercise both
+# architectures
+
+machine: qemuarm64
+local_conf_header:
+ toolchains: |
+ SDKMACHINE = "x86_64"
+
+target:
+ - gcc-aarch64-none-elf
+ - nativesdk-gcc-aarch64-none-elf
+ - gcc-arm-none-eabi
+ - nativesdk-gcc-arm-none-eabi
+ - nativesdk-androidclang
diff --git a/meta-arm/ci/update-repos b/meta-arm/ci/update-repos
new file mode 100755
index 0000000..a68257b
--- /dev/null
+++ b/meta-arm/ci/update-repos
@@ -0,0 +1,43 @@
+#! /usr/bin/env python3
+
+# Update clones of the repositories we need in KAS_REPO_REF_DIR to speed up fetches
+
+import sys
+import os
+import subprocess
+import pathlib
+
+def repo_shortname(url):
+ # Taken from Kas (Repo.__getattr__) to ensure the logic is right
+ from urllib.parse import urlparse
+ url = urlparse(url)
+ return ('{url.netloc}{url.path}'
+ .format(url=url)
+ .replace('@', '.')
+ .replace(':', '.')
+ .replace('/', '.')
+ .replace('*', '.'))
+
+repositories = (
+ "https://git.yoctoproject.org/git/poky",
+ "https://git.openembedded.org/meta-openembedded",
+ "https://git.yoctoproject.org/git/meta-virtualization",
+ "https://git.yoctoproject.org/git/meta-zephyr",
+ "https://github.com/kraj/meta-clang",
+)
+
+if __name__ == "__main__":
+ if "KAS_REPO_REF_DIR" not in os.environ:
+ print("KAS_REPO_REF_DIR needs to be set")
+ sys.exit(1)
+
+ base_repodir = pathlib.Path(os.environ["KAS_REPO_REF_DIR"])
+
+ for repo in repositories:
+ repodir = base_repodir / repo_shortname(repo)
+ if repodir.exists():
+ print("Updating %s..." % repo)
+ subprocess.run(["git", "-C", repodir, "fetch"], check=True)
+ else:
+ print("Cloning %s..." % repo)
+ subprocess.run(["git", "clone", "--bare", repo, repodir], check=True)
diff --git a/meta-arm/ci/xen.yml b/meta-arm/ci/xen.yml
new file mode 100644
index 0000000..d8b75d4
--- /dev/null
+++ b/meta-arm/ci/xen.yml
@@ -0,0 +1,11 @@
+header:
+ version: 11
+ includes:
+ - ci/meta-virtualization.yml
+
+local_conf_header:
+ meta-virt: |
+ DISTRO_FEATURES:append = " virtualization xen"
+
+target:
+ - xen-image-minimal