From 21b3d7ceedd53f9b5eb00b777bdb1cf22183e289 Mon Sep 17 00:00:00 2001 From: Laurent Bonnans Date: Tue, 22 May 2018 10:19:33 +0200 Subject: Start moving everything for new directory structure --- meta-sota/classes/image_repo_manifest.bbclass | 23 + meta-sota/classes/image_types_ostree.bbclass | 259 ++++++++ meta-sota/classes/image_types_ota.bbclass | 142 +++++ meta-sota/classes/sota.bbclass | 49 ++ meta-sota/classes/sota_am335x-evm-wifi.bbclass | 16 + meta-sota/classes/sota_bleeding.inc | 1 + meta-sota/classes/sota_m3ulcb.bbclass | 8 + meta-sota/classes/sota_minnowboard.bbclass | 10 + meta-sota/classes/sota_none.bbclass | 4 + meta-sota/classes/sota_porter.bbclass | 9 + meta-sota/classes/sota_qemux86-64.bbclass | 11 + meta-sota/classes/sota_raspberrypi.bbclass | 20 + meta-sota/conf/distro/poky-sota-systemd.conf | 13 + meta-sota/conf/distro/poky-sota.conf | 9 + meta-sota/conf/distro/sota.conf.inc | 13 + meta-sota/conf/include/bblayers/sota.inc | 3 + .../conf/include/bblayers/sota_am335x-evm.inc | 2 + .../conf/include/bblayers/sota_intel-corei7-64.inc | 2 + meta-sota/conf/include/bblayers/sota_m3ulcb.inc | 2 + meta-sota/conf/include/bblayers/sota_porter.inc | 2 + .../conf/include/bblayers/sota_qemux86-64.inc | 1 + .../conf/include/bblayers/sota_raspberrypi2.inc | 3 + .../conf/include/bblayers/sota_raspberrypi3.inc | 3 + meta-sota/conf/layer.conf | 13 + meta-sota/lib/oeqa/selftest/cases/qemucommand.py | 1 + meta-sota/lib/oeqa/selftest/cases/updater.py | 692 +++++++++++++++++++++ .../recipes-core/images/initramfs-ostree-image.bb | 29 + .../recipes-sota/aktualizr/aktualizr-auto-prov.bb | 56 ++ .../aktualizr/aktualizr-ca-implicit-prov.bb | 72 +++ .../recipes-sota/aktualizr/aktualizr-hsm-prov.bb | 33 + .../aktualizr/aktualizr-implicit-prov.bb | 34 + meta-sota/recipes-sota/aktualizr/aktualizr_git.bb | 119 ++++ meta-sota/recipes-sota/aktualizr/credentials.inc | 1 + meta-sota/recipes-sota/aktualizr/environment.inc | 11 + meta-sota/recipes-sota/aktualizr/files/LICENSE | 373 +++++++++++ .../aktualizr/files/aktualizr-secondary.service | 9 + .../aktualizr/files/aktualizr-secondary.socket | 6 + .../aktualizr/files/aktualizr-serialcan.service | 15 + .../recipes-sota/aktualizr/files/aktualizr.service | 15 + meta-sota/recipes-sota/aktualizr/files/ca.cnf | 10 + .../recipes-sota/aktualizr/garage-sign-version.inc | 23 + meta-sota/recipes-sota/asn1c/asn1c.bb | 17 + .../asn1c/files/skeletons_dir_fix.patch | 44 ++ .../config/aktualizr-disable-send-ip.bb | 23 + .../config/aktualizr-example-interface.bb | 22 + .../recipes-sota/config/aktualizr-log-debug.bb | 23 + .../recipes-sota/config/files/05-log-debug.toml | 2 + .../config/files/30-disable-send-ip.toml | 2 + .../config/files/30-example-interface.toml | 2 + meta-sota/recipes-sota/config/files/LICENSE | 373 +++++++++++ meta-sota/recipes-sota/ostree-initrd/files/init.sh | 85 +++ .../recipes-sota/ostree-initrd/ostree-initrd.bb | 20 + meta-sota/recipes-sota/ostree/ostree_git.bb | 92 +++ .../ca-certificates/ca-certificates_%.bbappend | 1 + meta-sota/recipes-support/fuse/fuse_%.bbappend | 3 + meta-sota/recipes-support/gpgme/gpgme_%.bbappend | 1 + .../recipes-support/libgsystem/libgsystem_git.bb | 40 ++ ...und-for-a-buggy-version-of-openssl-1.0.2m.patch | 42 ++ meta-sota/recipes-support/libp11/libp11_0.4.7.bb | 39 ++ .../recipes-support/libssh2/libssh2_%.bbappend | 2 + .../recipes-support/lshw/files/cross-compile.patch | 39 ++ meta-sota/recipes-support/lshw/files/ldflags.patch | 42 ++ meta-sota/recipes-support/lshw/lshw_02.16.bb | 36 ++ .../python-canonicaljson/python-canonicaljson.bb | 18 + .../python-frozendict/python-frozendict.bb | 12 + .../python-petname/python-petname.bb | 16 + .../files/0001-Cross-compilation-tweaks.patch | 86 +++ .../sc-hsm-embedded/sc-hsm-embedded_git.bb | 22 + .../slcand-start/files/slcand@.service | 8 + .../recipes-support/slcand-start/slcand-start.bb | 21 + .../softhsm-testtoken/files/createtoken.service | 12 + .../softhsm-testtoken/files/createtoken.sh | 26 + .../softhsm-testtoken/softhsm-testtoken.bb | 27 + .../files/0001-Cross-compilation-tweaks.patch | 86 +++ meta-sota/recipes-support/softhsm/softhsm_git.bb | 27 + .../recipes-test/big-update/big-update_1.0.bb | 13 + .../recipes-test/big-update/big-update_2.0.bb | 13 + .../recipes-test/big-update/files/rand_file.py | 16 + .../files/25-dhcp-server.network | 12 + .../files/26-dhcp-client.network | 6 + .../files/27-dhcp-client-external.network | 6 + .../demo-network-config/primary-network-config.bb | 16 + .../secondary-network-config.bb | 20 + meta-sota/recipes-test/images/primary-image.bb | 14 + meta-sota/recipes-test/images/secondary-image.bb | 25 + 85 files changed, 3569 insertions(+) create mode 100644 meta-sota/classes/image_repo_manifest.bbclass create mode 100644 meta-sota/classes/image_types_ostree.bbclass create mode 100644 meta-sota/classes/image_types_ota.bbclass create mode 100644 meta-sota/classes/sota.bbclass create mode 100644 meta-sota/classes/sota_am335x-evm-wifi.bbclass create mode 100644 meta-sota/classes/sota_bleeding.inc create mode 100644 meta-sota/classes/sota_m3ulcb.bbclass create mode 100644 meta-sota/classes/sota_minnowboard.bbclass create mode 100644 meta-sota/classes/sota_none.bbclass create mode 100644 meta-sota/classes/sota_porter.bbclass create mode 100644 meta-sota/classes/sota_qemux86-64.bbclass create mode 100644 meta-sota/classes/sota_raspberrypi.bbclass create mode 100644 meta-sota/conf/distro/poky-sota-systemd.conf create mode 100644 meta-sota/conf/distro/poky-sota.conf create mode 100644 meta-sota/conf/distro/sota.conf.inc create mode 100644 meta-sota/conf/include/bblayers/sota.inc create mode 100644 meta-sota/conf/include/bblayers/sota_am335x-evm.inc create mode 100644 meta-sota/conf/include/bblayers/sota_intel-corei7-64.inc create mode 100644 meta-sota/conf/include/bblayers/sota_m3ulcb.inc create mode 100644 meta-sota/conf/include/bblayers/sota_porter.inc create mode 100644 meta-sota/conf/include/bblayers/sota_qemux86-64.inc create mode 100644 meta-sota/conf/include/bblayers/sota_raspberrypi2.inc create mode 100644 meta-sota/conf/include/bblayers/sota_raspberrypi3.inc create mode 100644 meta-sota/conf/layer.conf create mode 120000 meta-sota/lib/oeqa/selftest/cases/qemucommand.py create mode 100644 meta-sota/lib/oeqa/selftest/cases/updater.py create mode 100644 meta-sota/recipes-core/images/initramfs-ostree-image.bb create mode 100644 meta-sota/recipes-sota/aktualizr/aktualizr-auto-prov.bb create mode 100644 meta-sota/recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb create mode 100644 meta-sota/recipes-sota/aktualizr/aktualizr-hsm-prov.bb create mode 100644 meta-sota/recipes-sota/aktualizr/aktualizr-implicit-prov.bb create mode 100755 meta-sota/recipes-sota/aktualizr/aktualizr_git.bb create mode 100644 meta-sota/recipes-sota/aktualizr/credentials.inc create mode 100644 meta-sota/recipes-sota/aktualizr/environment.inc create mode 100644 meta-sota/recipes-sota/aktualizr/files/LICENSE create mode 100644 meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.service create mode 100644 meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.socket create mode 100644 meta-sota/recipes-sota/aktualizr/files/aktualizr-serialcan.service create mode 100644 meta-sota/recipes-sota/aktualizr/files/aktualizr.service create mode 100644 meta-sota/recipes-sota/aktualizr/files/ca.cnf create mode 100644 meta-sota/recipes-sota/aktualizr/garage-sign-version.inc create mode 100644 meta-sota/recipes-sota/asn1c/asn1c.bb create mode 100644 meta-sota/recipes-sota/asn1c/files/skeletons_dir_fix.patch create mode 100644 meta-sota/recipes-sota/config/aktualizr-disable-send-ip.bb create mode 100644 meta-sota/recipes-sota/config/aktualizr-example-interface.bb create mode 100644 meta-sota/recipes-sota/config/aktualizr-log-debug.bb create mode 100644 meta-sota/recipes-sota/config/files/05-log-debug.toml create mode 100644 meta-sota/recipes-sota/config/files/30-disable-send-ip.toml create mode 100644 meta-sota/recipes-sota/config/files/30-example-interface.toml create mode 100644 meta-sota/recipes-sota/config/files/LICENSE create mode 100644 meta-sota/recipes-sota/ostree-initrd/files/init.sh create mode 100644 meta-sota/recipes-sota/ostree-initrd/ostree-initrd.bb create mode 100644 meta-sota/recipes-sota/ostree/ostree_git.bb create mode 100644 meta-sota/recipes-support/ca-certificates/ca-certificates_%.bbappend create mode 100644 meta-sota/recipes-support/fuse/fuse_%.bbappend create mode 100644 meta-sota/recipes-support/gpgme/gpgme_%.bbappend create mode 100644 meta-sota/recipes-support/libgsystem/libgsystem_git.bb create mode 100644 meta-sota/recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch create mode 100644 meta-sota/recipes-support/libp11/libp11_0.4.7.bb create mode 100644 meta-sota/recipes-support/libssh2/libssh2_%.bbappend create mode 100644 meta-sota/recipes-support/lshw/files/cross-compile.patch create mode 100644 meta-sota/recipes-support/lshw/files/ldflags.patch create mode 100644 meta-sota/recipes-support/lshw/lshw_02.16.bb create mode 100644 meta-sota/recipes-support/python-canonicaljson/python-canonicaljson.bb create mode 100644 meta-sota/recipes-support/python-frozendict/python-frozendict.bb create mode 100644 meta-sota/recipes-support/python-petname/python-petname.bb create mode 100644 meta-sota/recipes-support/sc-hsm-embedded/files/0001-Cross-compilation-tweaks.patch create mode 100644 meta-sota/recipes-support/sc-hsm-embedded/sc-hsm-embedded_git.bb create mode 100644 meta-sota/recipes-support/slcand-start/files/slcand@.service create mode 100644 meta-sota/recipes-support/slcand-start/slcand-start.bb create mode 100644 meta-sota/recipes-support/softhsm-testtoken/files/createtoken.service create mode 100644 meta-sota/recipes-support/softhsm-testtoken/files/createtoken.sh create mode 100644 meta-sota/recipes-support/softhsm-testtoken/softhsm-testtoken.bb create mode 100644 meta-sota/recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch create mode 100644 meta-sota/recipes-support/softhsm/softhsm_git.bb create mode 100644 meta-sota/recipes-test/big-update/big-update_1.0.bb create mode 100644 meta-sota/recipes-test/big-update/big-update_2.0.bb create mode 100644 meta-sota/recipes-test/big-update/files/rand_file.py create mode 100644 meta-sota/recipes-test/demo-network-config/files/25-dhcp-server.network create mode 100644 meta-sota/recipes-test/demo-network-config/files/26-dhcp-client.network create mode 100644 meta-sota/recipes-test/demo-network-config/files/27-dhcp-client-external.network create mode 100644 meta-sota/recipes-test/demo-network-config/primary-network-config.bb create mode 100644 meta-sota/recipes-test/demo-network-config/secondary-network-config.bb create mode 100644 meta-sota/recipes-test/images/primary-image.bb create mode 100644 meta-sota/recipes-test/images/secondary-image.bb (limited to 'meta-sota') diff --git a/meta-sota/classes/image_repo_manifest.bbclass b/meta-sota/classes/image_repo_manifest.bbclass new file mode 100644 index 0000000..467fd9a --- /dev/null +++ b/meta-sota/classes/image_repo_manifest.bbclass @@ -0,0 +1,23 @@ +# Writes the repo manifest to the target filesystem in /etc/manifest.xml +# +# Author: Phil Wise +# Usage: add "inherit image_repo_manifest" to your image file +# To reproduce a build, copy the /etc/manifest.xml to .repo/manifests/yourname.xml +# then run: +# repo init -m yourname.xml +# repo sync +# For more information, see: +# https://web.archive.org/web/20161224194009/https://wiki.cyanogenmod.org/w/Doc:_Using_manifests + +HOSTTOOLS_NONFATAL += " repo " + +# Write build information to target filesystem +buildinfo () { + if [ $(which repo) ]; then + repo manifest --revision-as-HEAD -o ${IMAGE_ROOTFS}${sysconfdir}/manifest.xml || bbwarn "Android repo tool failed to run; manifest not copied" + else + bbwarn "Android repo tool not found; manifest not copied." + fi +} + +IMAGE_PREPROCESS_COMMAND += "buildinfo;" diff --git a/meta-sota/classes/image_types_ostree.bbclass b/meta-sota/classes/image_types_ostree.bbclass new file mode 100644 index 0000000..bc44e33 --- /dev/null +++ b/meta-sota/classes/image_types_ostree.bbclass @@ -0,0 +1,259 @@ +# OSTree deployment + +do_image_ostree[depends] += "ostree-native:do_populate_sysroot \ + openssl-native:do_populate_sysroot \ + coreutils-native:do_populate_sysroot \ + unzip-native:do_populate_sysroot \ + virtual/kernel:do_deploy \ + ${OSTREE_INITRAMFS_IMAGE}:do_image_complete" + +export OSTREE_REPO +export OSTREE_BRANCHNAME +export GARAGE_TARGET_NAME + +RAMDISK_EXT ?= ".${OSTREE_INITRAMFS_FSTYPES}" + +OSTREE_KERNEL ??= "${KERNEL_IMAGETYPE}" + +export SYSTEMD_USED = "${@oe.utils.ifelse(d.getVar('VIRTUAL-RUNTIME_init_manager', True) == 'systemd', 'true', '')}" + +IMAGE_CMD_ostree () { + if [ -z "$OSTREE_REPO" ]; then + bbfatal "OSTREE_REPO should be set in your local.conf" + fi + + if [ -z "$OSTREE_BRANCHNAME" ]; then + bbfatal "OSTREE_BRANCHNAME should be set in your local.conf" + fi + + OSTREE_ROOTFS=`mktemp -du ${WORKDIR}/ostree-root-XXXXX` + cp -a ${IMAGE_ROOTFS} ${OSTREE_ROOTFS} + chmod a+rx ${OSTREE_ROOTFS} + sync + + cd ${OSTREE_ROOTFS} + + # Create sysroot directory to which physical sysroot will be mounted + mkdir sysroot + ln -sf sysroot/ostree ostree + + rm -rf tmp/* + ln -sf sysroot/tmp tmp + + mkdir -p usr/rootdirs + + mv etc usr/ + # Implement UsrMove + dirs="bin sbin lib" + + for dir in ${dirs} ; do + if [ -d ${dir} ] && [ ! -L ${dir} ] ; then + mv ${dir} usr/rootdirs/ + rm -rf ${dir} + ln -sf usr/rootdirs/${dir} ${dir} + fi + done + + if [ -n "$SYSTEMD_USED" ]; then + mkdir -p usr/etc/tmpfiles.d + tmpfiles_conf=usr/etc/tmpfiles.d/00ostree-tmpfiles.conf + echo "d /var/rootdirs 0755 root root -" >>${tmpfiles_conf} + echo "L /var/rootdirs/home - - - - /sysroot/home" >>${tmpfiles_conf} + else + mkdir -p usr/etc/init.d + tmpfiles_conf=usr/etc/init.d/tmpfiles.sh + echo '#!/bin/sh' > ${tmpfiles_conf} + echo "mkdir -p /var/rootdirs; chmod 755 /var/rootdirs" >> ${tmpfiles_conf} + echo "ln -sf /sysroot/home /var/rootdirs/home" >> ${tmpfiles_conf} + + ln -s ../init.d/tmpfiles.sh usr/etc/rcS.d/S20tmpfiles.sh + fi + + # Preserve OSTREE_BRANCHNAME for future information + mkdir -p usr/share/sota/ + echo -n "${OSTREE_BRANCHNAME}" > usr/share/sota/branchname + + # Preserve data in /home to be later copied to /sysroot/home by sysroot + # generating procedure + mkdir -p usr/homedirs + if [ -d "home" ] && [ ! -L "home" ]; then + mv home usr/homedirs/home + ln -sf var/rootdirs/home home + fi + + # Move persistent directories to /var + dirs="opt mnt media srv" + + for dir in ${dirs}; do + if [ -d ${dir} ] && [ ! -L ${dir} ]; then + if [ "$(ls -A $dir)" ]; then + bbwarn "Data in /$dir directory is not preserved by OSTree. Consider moving it under /usr" + fi + + if [ -n "$SYSTEMD_USED" ]; then + echo "d /var/rootdirs/${dir} 0755 root root -" >>${tmpfiles_conf} + else + echo "mkdir -p /var/rootdirs/${dir}; chown 755 /var/rootdirs/${dir}" >>${tmpfiles_conf} + fi + rm -rf ${dir} + ln -sf var/rootdirs/${dir} ${dir} + fi + done + + if [ -d root ] && [ ! -L root ]; then + if [ "$(ls -A root)" ]; then + bberror "Data in /root directory is not preserved by OSTree." + exit 1 + fi + + if [ -n "$SYSTEMD_USED" ]; then + echo "d /var/roothome 0755 root root -" >>${tmpfiles_conf} + else + echo "mkdir -p /var/roothome; chown 755 /var/roothome" >>${tmpfiles_conf} + fi + + rm -rf root + ln -sf var/roothome root + fi + + if [ -n "${SOTA_SECONDARY_ECUS}" ]; then + mkdir -p var/sota/ecus + cp ${SOTA_SECONDARY_ECUS} var/sota/ecus + fi + + # Creating boot directories is required for "ostree admin deploy" + + mkdir -p boot/loader.0 + mkdir -p boot/loader.1 + ln -sf boot/loader.0 boot/loader + + checksum=`sha256sum ${DEPLOY_DIR_IMAGE}/${OSTREE_KERNEL} | cut -f 1 -d " "` + + cp ${DEPLOY_DIR_IMAGE}/${OSTREE_KERNEL} boot/vmlinuz-${checksum} + cp ${DEPLOY_DIR_IMAGE}/${OSTREE_INITRAMFS_IMAGE}-${MACHINE}${RAMDISK_EXT} boot/initramfs-${checksum} + + # Copy image manifest + cat ${IMAGE_MANIFEST} | cut -d " " -f1,3 > usr/package.manifest + + cd ${WORKDIR} + + # Create a tarball that can be then commited to OSTree repo + OSTREE_TAR=${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.ostree.tar.bz2 + tar -C ${OSTREE_ROOTFS} --xattrs --xattrs-include='*' -cjf ${OSTREE_TAR} . + sync + + rm -f ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2 + ln -s ${IMAGE_NAME}.rootfs.ostree.tar.bz2 ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2 + + if [ ! -d ${OSTREE_REPO} ]; then + ostree --repo=${OSTREE_REPO} init --mode=archive-z2 + fi + + # Commit the result + ostree --repo=${OSTREE_REPO} commit \ + --tree=dir=${OSTREE_ROOTFS} \ + --skip-if-unchanged \ + --branch=${OSTREE_BRANCHNAME} \ + --subject="Commit-id: ${IMAGE_NAME}" + + rm -rf ${OSTREE_ROOTFS} +} + +IMAGE_TYPEDEP_ostreepush = "ostree" +do_image_ostreepush[depends] += "aktualizr-native:do_populate_sysroot ca-certificates-native:do_populate_sysroot" +IMAGE_CMD_ostreepush () { + # Print warnings if credetials are not set or if the file has not been found. + if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then + if [ -e ${SOTA_PACKED_CREDENTIALS} ]; then + garage-push --repo=${OSTREE_REPO} \ + --ref=${OSTREE_BRANCHNAME} \ + --credentials=${SOTA_PACKED_CREDENTIALS} \ + --cacert=${STAGING_ETCDIR_NATIVE}/ssl/certs/ca-certificates.crt + else + bbwarn "SOTA_PACKED_CREDENTIALS file does not exist." + fi + else + bbwarn "SOTA_PACKED_CREDENTIALS not set. Please add SOTA_PACKED_CREDENTIALS." + fi +} + +IMAGE_TYPEDEP_garagesign = "ostreepush" +do_image_garage_sign[depends] += "aktualizr-native:do_populate_sysroot" +IMAGE_CMD_garagesign () { + if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then + # if credentials are issued by a server that doesn't support offline signing, exit silently + unzip -p ${SOTA_PACKED_CREDENTIALS} root.json targets.pub targets.sec tufrepo.url 2>&1 >/dev/null || exit 0 + + java_version=$( java -version 2>&1 | awk -F '"' '/version/ {print $2}' ) + if [ "${java_version}" = "" ]; then + bberror "Java is required for synchronization with update backend, but is not installed on the host machine" + exit 1 + elif [ "${java_version}" \< "1.8" ]; then + bberror "Java version >= 8 is required for synchronization with update backend" + exit 1 + fi + + rm -rf ${GARAGE_SIGN_REPO} + garage-sign init --repo tufrepo \ + --home-dir ${GARAGE_SIGN_REPO} \ + --credentials ${SOTA_PACKED_CREDENTIALS} + + ostree_target_hash=$(cat ${OSTREE_REPO}/refs/heads/${OSTREE_BRANCHNAME}) + + # Use OSTree target hash as version if none was provided by the user + target_version=${ostree_target_hash} + if [ -n "${GARAGE_TARGET_VERSION}" ]; then + target_version=${GARAGE_TARGET_VERSION} + fi + + # Push may fail due to race condition when multiple build machines try to push simultaneously + # in which case targets.json should be pulled again and the whole procedure repeated + push_success=0 + for push_retries in $( seq 3 ); do + garage-sign targets pull --repo tufrepo \ + --home-dir ${GARAGE_SIGN_REPO} + garage-sign targets add --repo tufrepo \ + --home-dir ${GARAGE_SIGN_REPO} \ + --name ${GARAGE_TARGET_NAME} \ + --format OSTREE \ + --version ${target_version} \ + --length 0 \ + --url "${GARAGE_TARGET_URL}" \ + --sha256 ${ostree_target_hash} \ + --hardwareids ${MACHINE} + garage-sign targets sign --repo tufrepo \ + --home-dir ${GARAGE_SIGN_REPO} \ + --key-name=targets + errcode=0 + garage-sign targets push --repo tufrepo \ + --home-dir ${GARAGE_SIGN_REPO} || errcode=$? + if [ "$errcode" -eq "0" ]; then + push_success=1 + break + else + bbwarn "Push to garage repository has failed, retrying" + fi + done + rm -rf ${GARAGE_SIGN_REPO} + + if [ "$push_success" -ne "1" ]; then + bberror "Couldn't push to garage repository" + exit 1 + fi + fi +} + +IMAGE_TYPEDEP_garagecheck = "ostreepush garagesign" +do_image_garagecheck[depends] += "aktualizr-native:do_populate_sysroot" +IMAGE_CMD_garagecheck () { + if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then + # if credentials are issued by a server that doesn't support offline signing, exit silently + unzip -p ${SOTA_PACKED_CREDENTIALS} root.json targets.pub targets.sec tufrepo.url 2>&1 >/dev/null || exit 0 + ostree_target_hash=$(cat ${OSTREE_REPO}/refs/heads/${OSTREE_BRANCHNAME}) + + garage-check --ref=${ostree_target_hash} \ + --credentials=${SOTA_PACKED_CREDENTIALS} \ + --cacert=${STAGING_ETCDIR_NATIVE}/ssl/certs/ca-certificates.crt + fi +} +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/classes/image_types_ota.bbclass b/meta-sota/classes/image_types_ota.bbclass new file mode 100644 index 0000000..9581971 --- /dev/null +++ b/meta-sota/classes/image_types_ota.bbclass @@ -0,0 +1,142 @@ +# Image to use with u-boot as BIOS and OSTree deployment system + +#inherit image_types + +# Boot filesystem size in MiB +# OSTree updates may require some space on boot file system for +# boot scripts, kernel and initramfs images +# + +do_image_otaimg[depends] += "e2fsprogs-native:do_populate_sysroot \ + ${@'grub:do_populate_sysroot' if d.getVar('OSTREE_BOOTLOADER', True) == 'grub' else ''} \ + ${@'virtual/bootloader:do_deploy' if d.getVar('OSTREE_BOOTLOADER', True) == 'u-boot' else ''}" + +calculate_size () { + BASE=$1 + SCALE=$2 + MIN=$3 + MAX=$4 + EXTRA=$5 + ALIGN=$6 + + SIZE=`echo "$BASE * $SCALE" | bc -l` + REM=`echo $SIZE | cut -d "." -f 2` + SIZE=`echo $SIZE | cut -d "." -f 1` + + if [ -n "$REM" -o ! "$REM" -eq 0 ]; then + SIZE=`expr $SIZE \+ 1` + fi + + if [ "$SIZE" -lt "$MIN" ]; then + SIZE=$MIN + fi + + SIZE=`expr $SIZE \+ $EXTRA` + SIZE=`expr $SIZE \+ $ALIGN \- 1` + SIZE=`expr $SIZE \- $SIZE \% $ALIGN` + + if [ -n "$MAX" ]; then + if [ "$SIZE" -gt "$MAX" ]; then + return -1 + fi + fi + + echo "${SIZE}" +} + +export OSTREE_OSNAME +export OSTREE_BRANCHNAME +export OSTREE_REPO +export OSTREE_BOOTLOADER + +export GARAGE_TARGET_NAME + +IMAGE_CMD_otaimg () { + if ${@bb.utils.contains('IMAGE_FSTYPES', 'otaimg', 'true', 'false', d)}; then + if [ -z "$OSTREE_REPO" ]; then + bbfatal "OSTREE_REPO should be set in your local.conf" + fi + + if [ -z "$OSTREE_OSNAME" ]; then + bbfatal "OSTREE_OSNAME should be set in your local.conf" + fi + + if [ -z "$OSTREE_BRANCHNAME" ]; then + bbfatal "OSTREE_BRANCHNAME should be set in your local.conf" + fi + + + PHYS_SYSROOT=`mktemp -d ${WORKDIR}/ota-sysroot-XXXXX` + + ostree admin --sysroot=${PHYS_SYSROOT} init-fs ${PHYS_SYSROOT} + ostree admin --sysroot=${PHYS_SYSROOT} os-init ${OSTREE_OSNAME} + + mkdir -p ${PHYS_SYSROOT}/boot/loader.0 + ln -s loader.0 ${PHYS_SYSROOT}/boot/loader + + if [ "${OSTREE_BOOTLOADER}" = "grub" ]; then + mkdir -p ${PHYS_SYSROOT}/boot/grub2 + ln -s ../loader/grub.cfg ${PHYS_SYSROOT}/boot/grub2/grub.cfg + elif [ "${OSTREE_BOOTLOADER}" = "u-boot" ]; then + touch ${PHYS_SYSROOT}/boot/loader/uEnv.txt + else + bberror "Invalid bootloader: ${OSTREE_BOOTLOADER}" + fi; + + ostree_target_hash=$(cat ${OSTREE_REPO}/refs/heads/${OSTREE_BRANCHNAME}) + + ostree --repo=${PHYS_SYSROOT}/ostree/repo pull-local --remote=${OSTREE_OSNAME} ${OSTREE_REPO} ${ostree_target_hash} + export OSTREE_BOOT_PARTITION="/boot" + kargs_list="" + for arg in ${OSTREE_KERNEL_ARGS}; do + kargs_list="${kargs_list} --karg-append=$arg" + done + + ostree admin --sysroot=${PHYS_SYSROOT} deploy ${kargs_list} --os=${OSTREE_OSNAME} ${ostree_target_hash} + + # Copy deployment /home and /var/sota to sysroot + HOME_TMP=`mktemp -d ${WORKDIR}/home-tmp-XXXXX` + tar --xattrs --xattrs-include='*' -C ${HOME_TMP} -xf ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2 ./usr/homedirs ./var/sota ./var/local || true + mv ${HOME_TMP}/var/sota ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/ || true + mv ${HOME_TMP}/var/local ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/ || true + # Create /var/sota if it doesn't exist yet + mkdir -p ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota || true + # Ensure the permissions are correctly set + chmod 700 ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota + mv ${HOME_TMP}/usr/homedirs/home ${PHYS_SYSROOT}/ || true + # Ensure that /var/local exists (AGL symlinks /usr/local to /var/local) + install -d ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/local + # Set package version for the first deployment + target_version=${ostree_target_hash} + if [ -n "${GARAGE_TARGET_VERSION}" ]; then + target_version=${GARAGE_TARGET_VERSION} + fi + echo "{\"${ostree_target_hash}\":\"${GARAGE_TARGET_NAME}-${target_version}\"}" > ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota/installed_versions + + rm -rf ${HOME_TMP} + + # Calculate image type + OTA_ROOTFS_SIZE=$(calculate_size `du -ks $PHYS_SYSROOT | cut -f 1` "${IMAGE_OVERHEAD_FACTOR}" "${IMAGE_ROOTFS_SIZE}" "${IMAGE_ROOTFS_MAXSIZE}" `expr ${IMAGE_ROOTFS_EXTRA_SPACE}` "${IMAGE_ROOTFS_ALIGNMENT}") + + if [ $OTA_ROOTFS_SIZE -lt 0 ]; then + exit -1 + fi + eval local COUNT=\"0\" + eval local MIN_COUNT=\"60\" + if [ $OTA_ROOTFS_SIZE -lt $MIN_COUNT ]; then + eval COUNT=\"$MIN_COUNT\" + fi + + # create image + rm -rf ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.otaimg + sync + dd if=/dev/zero of=${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.otaimg seek=$OTA_ROOTFS_SIZE count=$COUNT bs=1024 + mkfs.ext4 -O ^64bit ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.otaimg -L otaroot -d ${PHYS_SYSROOT} + rm -rf ${PHYS_SYSROOT} + + rm -f ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.otaimg + ln -s ${IMAGE_NAME}.otaimg ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.otaimg + fi +} + +IMAGE_TYPEDEP_otaimg = "ostree" diff --git a/meta-sota/classes/sota.bbclass b/meta-sota/classes/sota.bbclass new file mode 100644 index 0000000..38d4ce5 --- /dev/null +++ b/meta-sota/classes/sota.bbclass @@ -0,0 +1,49 @@ +python __anonymous() { + if bb.utils.contains('DISTRO_FEATURES', 'sota', True, False, d): + d.appendVarFlag("do_image_wic", "depends", " %s:do_image_otaimg" % d.getVar("IMAGE_BASENAME", True)) +} + +OVERRIDES .= "${@bb.utils.contains('DISTRO_FEATURES', 'sota', ':sota', '', d)}" + +HOSTTOOLS_NONFATAL += "java" + +SOTA_CLIENT ??= "aktualizr" +SOTA_CLIENT_PROV ??= "aktualizr-auto-prov" +IMAGE_INSTALL_append_sota = " ostree os-release ${SOTA_CLIENT} ${SOTA_CLIENT_PROV}" +IMAGE_CLASSES += " image_types_ostree image_types_ota" +IMAGE_FSTYPES += "${@bb.utils.contains('DISTRO_FEATURES', 'sota', 'ostreepush garagesign garagecheck otaimg wic', ' ', d)}" + +PACKAGECONFIG_append_pn-curl = " ssl" +PACKAGECONFIG_remove_pn-curl = "gnutls" + +WKS_FILE_sota ?= "sdimage-sota.wks" + +EXTRA_IMAGEDEPENDS_append_sota = " parted-native mtools-native dosfstools-native" + +OSTREE_INITRAMFS_FSTYPES ??= "${@oe.utils.ifelse(d.getVar('OSTREE_BOOTLOADER', True) == 'u-boot', 'ext4.gz.u-boot', 'ext4.gz')}" + +# Please redefine OSTREE_REPO in order to have a persistent OSTree repo +OSTREE_REPO ?= "${DEPLOY_DIR_IMAGE}/ostree_repo" +# For UPTANE operation, OSTREE_BRANCHNAME must start with "${MACHINE}-" +OSTREE_BRANCHNAME ?= "${MACHINE}" +OSTREE_OSNAME ?= "poky" +OSTREE_INITRAMFS_IMAGE ?= "initramfs-ostree-image" +OSTREE_BOOTLOADER ??= 'u-boot' + +GARAGE_SIGN_REPO ?= "${DEPLOY_DIR_IMAGE}/garage_sign_repo" +GARAGE_SIGN_KEYNAME ?= "garage-key" +GARAGE_TARGET_NAME ?= "${OSTREE_BRANCHNAME}" +GARAGE_TARGET_VERSION ?= "" +GARAGE_TARGET_URL ?= "https://example.com/" + +SOTA_MACHINE ??="none" +SOTA_MACHINE_rpi ?= "raspberrypi" +SOTA_MACHINE_porter ?= "porter" +SOTA_MACHINE_m3ulcb = "m3ulcb" +SOTA_MACHINE_intel-corei7-64 ?= "minnowboard" +SOTA_MACHINE_qemux86-64 ?= "qemux86-64" +SOTA_MACHINE_am335x-evm ?= "am335x-evm-wifi" + +inherit sota_${SOTA_MACHINE} + +inherit image_repo_manifest diff --git a/meta-sota/classes/sota_am335x-evm-wifi.bbclass b/meta-sota/classes/sota_am335x-evm-wifi.bbclass new file mode 100644 index 0000000..adefb47 --- /dev/null +++ b/meta-sota/classes/sota_am335x-evm-wifi.bbclass @@ -0,0 +1,16 @@ +KERNEL_IMAGETYPE_sota = "uImage" + +OSTREE_BOOTLOADER ?= "u-boot" + +EXTRA_IMAGEDEPENDS_append_sota = " acer-bootfiles" +IMAGE_BOOT_FILES_sota = "bootfiles/*" +OSTREE_KERNEL_ARGS ?= "ramdisk_size=16384 root=/dev/ram0 rw rootfstype=ext4 rootwait rootdelay=2 ostree_root=/dev/mmcblk0p2 console=ttyO0,115200n8l" + +IMAGE_INSTALL_append_sota = " uim iw wl18xx-calibrator wlconf wl18xx-fw hostapd wpa-supplicant" +IMAGE_INSTALL_remove_sota = " connman connman-client" + +PREFERRED_VERSION_linux-ti-staging_sota = "4.4.54+gitAUTOINC+ecd4eada6f" + +KERNEL_EXTRA_ARGS_append_sota = " LOADADDR=${UBOOT_ENTRYPOINT}" + +VIRTUAL-RUNTIME_net_manager_sota = "systemd" diff --git a/meta-sota/classes/sota_bleeding.inc b/meta-sota/classes/sota_bleeding.inc new file mode 100644 index 0000000..fc5947d --- /dev/null +++ b/meta-sota/classes/sota_bleeding.inc @@ -0,0 +1 @@ +SRCREV_pn-aktualizr ?= "${AUTOREV}" diff --git a/meta-sota/classes/sota_m3ulcb.bbclass b/meta-sota/classes/sota_m3ulcb.bbclass new file mode 100644 index 0000000..6b63af4 --- /dev/null +++ b/meta-sota/classes/sota_m3ulcb.bbclass @@ -0,0 +1,8 @@ +# Commit united image to OSTree, not just uImage +OSTREE_KERNEL = "Image" + +EXTRA_IMAGEDEPENDS_append_sota = " m3ulcb-ota-bootfiles" +IMAGE_BOOT_FILES_sota += "m3ulcb-ota-bootfiles/*" + +OSTREE_BOOTLOADER ?= "u-boot" +UBOOT_MACHINE_sota = "m3ulcb_defconfig" diff --git a/meta-sota/classes/sota_minnowboard.bbclass b/meta-sota/classes/sota_minnowboard.bbclass new file mode 100644 index 0000000..63510e3 --- /dev/null +++ b/meta-sota/classes/sota_minnowboard.bbclass @@ -0,0 +1,10 @@ +OSTREE_BOOTLOADER ?= "grub" +EFI_PROVIDER_sota = "grub-efi" + +WKS_FILE_sota = "efiimage-sota.wks" +IMAGE_BOOT_FILES_sota = "" + +IMAGE_FSTYPES_remove_sota = "live hddimg" +OSTREE_KERNEL_ARGS ?= "ramdisk_size=16384 rw rootfstype=ext4 rootwait rootdelay=2 console=ttyS0,115200 console=tty0" + +IMAGE_INSTALL_append = " minnowboard-efi-startup" diff --git a/meta-sota/classes/sota_none.bbclass b/meta-sota/classes/sota_none.bbclass new file mode 100644 index 0000000..c11b070 --- /dev/null +++ b/meta-sota/classes/sota_none.bbclass @@ -0,0 +1,4 @@ +# null machine it's here to make bitbake happy when SOTA_MACHINE is undefined +#python __anonymous() { +# bb.warn("SOTA functionality is not yet supported for your machine") +#} diff --git a/meta-sota/classes/sota_porter.bbclass b/meta-sota/classes/sota_porter.bbclass new file mode 100644 index 0000000..75ae579 --- /dev/null +++ b/meta-sota/classes/sota_porter.bbclass @@ -0,0 +1,9 @@ +# Commit united image to OSTree, not just uImage +OSTREE_KERNEL = "uImage+dtb" + +EXTRA_IMAGEDEPENDS_append_sota = " porter-bootfiles" +IMAGE_BOOT_FILES_sota += "porter-bootfiles/*" + +OSTREE_BOOTLOADER ?= "u-boot" +UBOOT_MACHINE_sota = "porter_config" + diff --git a/meta-sota/classes/sota_qemux86-64.bbclass b/meta-sota/classes/sota_qemux86-64.bbclass new file mode 100644 index 0000000..15b2043 --- /dev/null +++ b/meta-sota/classes/sota_qemux86-64.bbclass @@ -0,0 +1,11 @@ +IMAGE_FSTYPES_remove = "wic" + +# U-Boot support for SOTA +PREFERRED_PROVIDER_virtual/bootloader_sota = "u-boot" +UBOOT_MACHINE_sota = "qemu-x86_defconfig" +OSTREE_BOOTLOADER ?= "u-boot" +OSTREE_INITRAMFS_FSTYPES ?= "ext4.gz" + +OSTREE_KERNEL_ARGS ?= "ramdisk_size=16384 rw rootfstype=ext4 rootwait rootdelay=2 ostree_root=/dev/hda" + +IMAGE_ROOTFS_EXTRA_SPACE = "${@bb.utils.contains('DISTRO_FEATURES', 'sota', '65536', '', d)}" diff --git a/meta-sota/classes/sota_raspberrypi.bbclass b/meta-sota/classes/sota_raspberrypi.bbclass new file mode 100644 index 0000000..a5558b4 --- /dev/null +++ b/meta-sota/classes/sota_raspberrypi.bbclass @@ -0,0 +1,20 @@ +RPI_USE_U_BOOT_sota = "1" + +KERNEL_CLASSES_append_sota = " kernel-fitimage" +KERNEL_IMAGETYPE_sota = "fitImage" + +PREFERRED_PROVIDER_virtual/bootloader_sota ?= "u-boot" +UBOOT_ENTRYPOINT_sota ?= "0x00008000" + +IMAGE_FSTYPES_remove_sota = "rpi-sdimg" +OSTREE_BOOTLOADER ?= "u-boot" + +# OSTree puts its own boot.scr to bcm2835-bootfiles +IMAGE_BOOT_FILES_sota = "bcm2835-bootfiles/* u-boot.bin;${SDIMG_KERNELIMAGE}" + +# Just the overlays that will be used should be listed +KERNEL_DEVICETREE_raspberrypi2_sota ?= " bcm2709-rpi-2-b.dtb " +KERNEL_DEVICETREE_raspberrypi3_sota ?= " bcm2710-rpi-3-b.dtb overlays/vc4-kms-v3d.dtbo overlays/rpi-ft5406.dtbo" + +# Kernel args normally provided by RPi's internal bootloader. Non-updateable +OSTREE_KERNEL_ARGS_sota ?= " 8250.nr_uarts=1 bcm2708_fb.fbwidth=720 bcm2708_fb.fbheight=480 bcm2708_fb.fbswap=1 vc_mem.mem_base=0x3ec00000 vc_mem.mem_size=0x40000000 dwc_otg.lpm_enable=0 console=ttyS0,115200 usbhid.mousepoll=0 " diff --git a/meta-sota/conf/distro/poky-sota-systemd.conf b/meta-sota/conf/distro/poky-sota-systemd.conf new file mode 100644 index 0000000..7d008a9 --- /dev/null +++ b/meta-sota/conf/distro/poky-sota-systemd.conf @@ -0,0 +1,13 @@ +require conf/distro/poky.conf + +require conf/distro/sota.conf.inc + +DISTRO = "poky-sota" +DISTRO_NAME = "OTA-enabled Linux" +DISTRO_VERSION = "1.0" +DISTRO_CODENAME = "sota" + +DISTRO_FEATURES_append = " systemd" +VIRTUAL-RUNTIME_init_manager = "systemd" + +IMAGE_INSTALL_append = " connman connman-client" diff --git a/meta-sota/conf/distro/poky-sota.conf b/meta-sota/conf/distro/poky-sota.conf new file mode 100644 index 0000000..2bbc62b --- /dev/null +++ b/meta-sota/conf/distro/poky-sota.conf @@ -0,0 +1,9 @@ +require conf/distro/poky.conf +require conf/distro/sota.conf.inc + +DISTRO = "poky-sota" +DISTRO_NAME = "OTA-enabled Linux" +DISTRO_VERSION = "1.0" +DISTRO_CODENAME = "sota" + +IMAGE_INSTALL_append = " connman connman-client" diff --git a/meta-sota/conf/distro/sota.conf.inc b/meta-sota/conf/distro/sota.conf.inc new file mode 100644 index 0000000..ea1ca95 --- /dev/null +++ b/meta-sota/conf/distro/sota.conf.inc @@ -0,0 +1,13 @@ +# Common settings to enable SOTA +# This can be pulled into a custom distribution, or included in +# local.conf directly with: +# +# require conf/distro/sota.conf.inc + +DISTRO_FEATURES_append = " sota" +DISTRO_FEATURES_NATIVE_append = " sota" +INHERIT += " sota" +# Prelinking increases the size of downloads and causes build errors +USER_CLASSES_remove = "image-prelink" + +HOSTTOOLS_append = " sync sha256sum" diff --git a/meta-sota/conf/include/bblayers/sota.inc b/meta-sota/conf/include/bblayers/sota.inc new file mode 100644 index 0000000..0e5842a --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota.inc @@ -0,0 +1,3 @@ +BBLAYERS += "${METADIR}/meta-updater/meta-sota" +BBLAYERS += "${METADIR}/meta-openembedded/meta-filesystems" +BBLAYERS += "${METADIR}/meta-openembedded/meta-oe" diff --git a/meta-sota/conf/include/bblayers/sota_am335x-evm.inc b/meta-sota/conf/include/bblayers/sota_am335x-evm.inc new file mode 100644 index 0000000..f2d485d --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota_am335x-evm.inc @@ -0,0 +1,2 @@ + +BBLAYERS += " ${METADIR}/meta-ti " diff --git a/meta-sota/conf/include/bblayers/sota_intel-corei7-64.inc b/meta-sota/conf/include/bblayers/sota_intel-corei7-64.inc new file mode 100644 index 0000000..32bd644 --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota_intel-corei7-64.inc @@ -0,0 +1,2 @@ + +BBLAYERS += " ${METADIR}/meta-updater/meta-sota-minnowboard ${METADIR}/meta-intel " diff --git a/meta-sota/conf/include/bblayers/sota_m3ulcb.inc b/meta-sota/conf/include/bblayers/sota_m3ulcb.inc new file mode 100644 index 0000000..04f78e4 --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota_m3ulcb.inc @@ -0,0 +1,2 @@ + +BBLAYERS += " ${METADIR}/meta-renesas ${METADIR}/meta-renesas-rcar-gen3 ${METADIR}/meta-openembedded/meta-multimedia" diff --git a/meta-sota/conf/include/bblayers/sota_porter.inc b/meta-sota/conf/include/bblayers/sota_porter.inc new file mode 100644 index 0000000..8fcb12e --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota_porter.inc @@ -0,0 +1,2 @@ + +BBLAYERS += " ${METADIR}/meta-renesas ${METADIR}/meta-renesas/meta-rcar-gen2 ${METADIR}/meta-openembedded/meta-multimedia ${METADIR}/meta-sota-porter" diff --git a/meta-sota/conf/include/bblayers/sota_qemux86-64.inc b/meta-sota/conf/include/bblayers/sota_qemux86-64.inc new file mode 100644 index 0000000..2b79257 --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota_qemux86-64.inc @@ -0,0 +1 @@ +BBLAYERS += " ${METADIR}/meta-updater/meta-sota-qemux86-64 " diff --git a/meta-sota/conf/include/bblayers/sota_raspberrypi2.inc b/meta-sota/conf/include/bblayers/sota_raspberrypi2.inc new file mode 100644 index 0000000..726c862 --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota_raspberrypi2.inc @@ -0,0 +1,3 @@ +BBLAYERS += " ${METADIR}/meta-openembedded/meta-python " + +BBLAYERS += " ${METADIR}/meta-updater/meta-sota-raspberrypi ${METADIR}/meta-raspberrypi " diff --git a/meta-sota/conf/include/bblayers/sota_raspberrypi3.inc b/meta-sota/conf/include/bblayers/sota_raspberrypi3.inc new file mode 100644 index 0000000..726c862 --- /dev/null +++ b/meta-sota/conf/include/bblayers/sota_raspberrypi3.inc @@ -0,0 +1,3 @@ +BBLAYERS += " ${METADIR}/meta-openembedded/meta-python " + +BBLAYERS += " ${METADIR}/meta-updater/meta-sota-raspberrypi ${METADIR}/meta-raspberrypi " diff --git a/meta-sota/conf/layer.conf b/meta-sota/conf/layer.conf new file mode 100644 index 0000000..798ceba --- /dev/null +++ b/meta-sota/conf/layer.conf @@ -0,0 +1,13 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "sota" +BBFILE_PATTERN_sota = "^${LAYERDIR}/" +BBFILE_PRIORITY_sota = "7" + +LAYERDEPENDS_sota = "filesystems-layer" +LAYERSERIES_COMPAT_sota = "sumo" diff --git a/meta-sota/lib/oeqa/selftest/cases/qemucommand.py b/meta-sota/lib/oeqa/selftest/cases/qemucommand.py new file mode 120000 index 0000000..075cdb8 --- /dev/null +++ b/meta-sota/lib/oeqa/selftest/cases/qemucommand.py @@ -0,0 +1 @@ +../../../../scripts/qemucommand.py \ No newline at end of file diff --git a/meta-sota/lib/oeqa/selftest/cases/updater.py b/meta-sota/lib/oeqa/selftest/cases/updater.py new file mode 100644 index 0000000..2efef15 --- /dev/null +++ b/meta-sota/lib/oeqa/selftest/cases/updater.py @@ -0,0 +1,692 @@ +# pylint: disable=C0111,C0325 +import os +import logging +import re +import subprocess +import unittest +from time import sleep + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars +from qemucommand import QemuCommand + + +class SotaToolsTests(OESelftestTestCase): + + @classmethod + def setUpClass(cls): + super(SotaToolsTests, cls).setUpClass() + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build aktualizr-native tools') + bitbake('aktualizr-native') + + def test_push_help(self): + akt_native_run(self, 'garage-push --help') + + def test_deploy_help(self): + akt_native_run(self, 'garage-deploy --help') + + def test_garagesign_help(self): + akt_native_run(self, 'garage-sign --help') + + +class GeneralTests(OESelftestTestCase): + + def test_feature_sota(self): + result = get_bb_var('DISTRO_FEATURES').find('sota') + self.assertNotEqual(result, -1, 'Feature "sota" not set at DISTRO_FEATURES') + + def test_feature_systemd(self): + result = get_bb_var('DISTRO_FEATURES').find('systemd') + self.assertNotEqual(result, -1, 'Feature "systemd" not set at DISTRO_FEATURES') + + def test_credentials(self): + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build core-image-minimal') + self.append_config('SOTA_CLIENT_PROV = "aktualizr-auto-prov"') + bitbake('core-image-minimal') + credentials = get_bb_var('SOTA_PACKED_CREDENTIALS') + # skip the test if the variable SOTA_PACKED_CREDENTIALS is not set + if credentials is None: + raise unittest.SkipTest("Variable 'SOTA_PACKED_CREDENTIALS' not set.") + # Check if the file exists + self.assertTrue(os.path.isfile(credentials), "File %s does not exist" % credentials) + deploydir = get_bb_var('DEPLOY_DIR_IMAGE') + imagename = get_bb_var('IMAGE_LINK_NAME', 'core-image-minimal') + # Check if the credentials are included in the output image + result = runCmd('tar -jtvf %s/%s.tar.bz2 | grep sota_provisioning_credentials.zip' % + (deploydir, imagename), ignore_status=True) + self.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output) + + def test_java(self): + result = runCmd('which java', ignore_status=True) + self.assertEqual(result.status, 0, + "Java not found. Do you have a JDK installed on your host machine?") + + def test_add_package(self): + deploydir = get_bb_var('DEPLOY_DIR_IMAGE') + imagename = get_bb_var('IMAGE_LINK_NAME', 'core-image-minimal') + image_path = deploydir + '/' + imagename + '.otaimg' + logger = logging.getLogger("selftest") + + logger.info('Running bitbake with man in the image package list') + self.append_config('IMAGE_INSTALL_append = " man "') + bitbake('-c cleanall man') + bitbake('core-image-minimal') + result = runCmd('oe-pkgdata-util find-path /usr/bin/man') + self.assertEqual(result.output, 'man: /usr/bin/man') + path1 = os.path.realpath(image_path) + size1 = os.path.getsize(path1) + logger.info('First image %s has size %i' % (path1, size1)) + + logger.info('Running bitbake without man in the image package list') + self.append_config('IMAGE_INSTALL_remove = " man "') + bitbake('-c cleanall man') + bitbake('core-image-minimal') + result = runCmd('oe-pkgdata-util find-path /usr/bin/man', ignore_status=True) + self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output) + self.assertEqual(result.output, 'ERROR: Unable to find any package producing path /usr/bin/man') + path2 = os.path.realpath(image_path) + size2 = os.path.getsize(path2) + logger.info('Second image %s has size %i', path2, size2) + self.assertNotEqual(path1, path2, "Image paths are identical; image was not rebuilt.") + self.assertNotEqual(size1, size2, "Image sizes are identical; image was not rebuilt.") + + +class AktualizrToolsTests(OESelftestTestCase): + + @classmethod + def setUpClass(cls): + super(AktualizrToolsTests, cls).setUpClass() + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build aktualizr-native tools') + bitbake('aktualizr-native') + + def test_implicit_writer_help(self): + akt_native_run(self, 'aktualizr_implicit_writer --help') + + def test_cert_provider_help(self): + akt_native_run(self, 'aktualizr_cert_provider --help') + + def test_cert_provider_local_output(self): + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build aktualizr-implicit-prov') + bitbake('aktualizr-implicit-prov') + bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS', 'T'], 'aktualizr-native') + creds = bb_vars['SOTA_PACKED_CREDENTIALS'] + temp_dir = bb_vars['T'] + bb_vars_prov = get_bb_vars(['STAGING_DIR_NATIVE', 'libdir'], 'aktualizr-implicit-prov') + config = bb_vars_prov['STAGING_DIR_NATIVE'] + bb_vars_prov['libdir'] + '/sota/sota_implicit_prov.toml' + + akt_native_run(self, 'aktualizr_cert_provider -c {creds} -r -l {temp} -g {config}' + .format(creds=creds, temp=temp_dir, config=config)) + + # Might be nice if these names weren't hardcoded. + cert_path = temp_dir + '/client.pem' + self.assertTrue(os.path.isfile(cert_path), "Client certificate not found at %s." % cert_path) + self.assertTrue(os.path.getsize(cert_path) > 0, "Client certificate at %s is empty." % cert_path) + pkey_path = temp_dir + '/pkey.pem' + self.assertTrue(os.path.isfile(pkey_path), "Private key not found at %s." % pkey_path) + self.assertTrue(os.path.getsize(pkey_path) > 0, "Private key at %s is empty." % pkey_path) + ca_path = temp_dir + '/root.crt' + self.assertTrue(os.path.isfile(ca_path), "Client certificate not found at %s." % ca_path) + self.assertTrue(os.path.getsize(ca_path) > 0, "Client certificate at %s is empty." % ca_path) + + +class AutoProvTests(OESelftestTestCase): + + def setUpLocal(self): + layer = "meta-updater-qemux86-64" + result = runCmd('bitbake-layers show-layers') + if re.search(layer, result.output) is None: + # Assume the directory layout for finding other layers. We could also + # make assumptions by using 'show-layers', but either way, if the + # layers we need aren't where we expect them, we are out of like. + path = os.path.abspath(os.path.dirname(__file__)) + metadir = path + "/../../../../../" + self.meta_qemu = metadir + layer + runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu) + else: + self.meta_qemu = None + self.append_config('MACHINE = "qemux86-64"') + self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "') + # Test aktualizr-example-interface package. + self.append_config('IMAGE_INSTALL_append = " aktualizr-examples aktualizr-example-interface "') + self.qemu, self.s = qemu_launch(machine='qemux86-64') + + def tearDownLocal(self): + qemu_terminate(self.s) + if self.meta_qemu: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True) + + def qemu_command(self, command): + return qemu_send_command(self.qemu.ssh_port, command) + + def test_provisioning(self): + print('Checking machine name (hostname) of device:') + stdout, stderr, retcode = self.qemu_command('hostname') + self.assertEqual(retcode, 0, "Unable to check hostname. " + + "Is an ssh daemon (such as dropbear or openssh) installed on the device?") + machine = get_bb_var('MACHINE', 'core-image-minimal') + self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) + # Strip off line ending. + value = stdout.decode()[:-1] + self.assertEqual(value, machine, + 'MACHINE does not match hostname: ' + machine + ', ' + value) + print(value) + print('Checking output of aktualizr-info:') + ran_ok = False + for delay in [1, 2, 5, 10, 15]: + stdout, stderr, retcode = self.qemu_command('aktualizr-info') + if retcode == 0 and stderr == b'': + ran_ok = True + break + sleep(delay) + self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode()) + + verifyProvisioned(self, machine) + # Test aktualizr-example-interface package. + stdout, stderr, retcode = self.qemu_command('aktualizr-info') + self.assertIn(b'hardware ID: example1', stdout, + 'Legacy secondary initialization failed: ' + stderr.decode() + stdout.decode()) + self.assertIn(b'hardware ID: example2', stdout, + 'Legacy secondary initialization failed: ' + stderr.decode() + stdout.decode()) + + +class RpiTests(OESelftestTestCase): + + def setUpLocal(self): + # Add layers before changing the machine type, otherwise the sanity + # checker complains loudly. + layer_python = "meta-openembedded/meta-python" + layer_rpi = "meta-raspberrypi" + layer_upd_rpi = "meta-updater-raspberrypi" + result = runCmd('bitbake-layers show-layers') + # Assume the directory layout for finding other layers. We could also + # make assumptions by using 'show-layers', but either way, if the + # layers we need aren't where we expect them, we are out of like. + path = os.path.abspath(os.path.dirname(__file__)) + metadir = path + "/../../../../../" + if re.search(layer_python, result.output) is None: + self.meta_python = metadir + layer_python + runCmd('bitbake-layers add-layer "%s"' % self.meta_python) + else: + self.meta_python = None + if re.search(layer_rpi, result.output) is None: + self.meta_rpi = metadir + layer_rpi + runCmd('bitbake-layers add-layer "%s"' % self.meta_rpi) + else: + self.meta_rpi = None + if re.search(layer_upd_rpi, result.output) is None: + self.meta_upd_rpi = metadir + layer_upd_rpi + runCmd('bitbake-layers add-layer "%s"' % self.meta_upd_rpi) + else: + self.meta_upd_rpi = None + + # This is trickier that I would've thought. The fundamental problem is + # that the qemu layer changes the u-boot file extension to .rom, but + # raspberrypi still expects .bin. To prevent this, the qemu layer must + # be temporarily removed if it is present. It has to be removed by name + # without the complete path, but to add it back when we are done, we + # need the full path. + p = re.compile(r'meta-updater-qemux86-64\s*(\S*meta-updater-qemux86-64)\s') + m = p.search(result.output) + if m and m.lastindex > 0: + self.meta_qemu = m.group(1) + runCmd('bitbake-layers remove-layer meta-updater-qemux86-64') + else: + self.meta_qemu = None + + self.append_config('MACHINE = "raspberrypi3"') + self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "') + + def tearDownLocal(self): + if self.meta_qemu: + runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu, ignore_status=True) + if self.meta_upd_rpi: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_upd_rpi, ignore_status=True) + if self.meta_rpi: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_rpi, ignore_status=True) + if self.meta_python: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_python, ignore_status=True) + + def test_rpi(self): + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build rpi-basic-image') + self.append_config('SOTA_CLIENT_PROV = "aktualizr-auto-prov"') + bitbake('rpi-basic-image') + credentials = get_bb_var('SOTA_PACKED_CREDENTIALS') + # Skip the test if the variable SOTA_PACKED_CREDENTIALS is not set. + if credentials is None: + raise unittest.SkipTest("Variable 'SOTA_PACKED_CREDENTIALS' not set.") + # Check if the file exists. + self.assertTrue(os.path.isfile(credentials), "File %s does not exist" % credentials) + deploydir = get_bb_var('DEPLOY_DIR_IMAGE') + imagename = get_bb_var('IMAGE_LINK_NAME', 'rpi-basic-image') + # Check if the credentials are included in the output image. + result = runCmd('tar -jtvf %s/%s.tar.bz2 | grep sota_provisioning_credentials.zip' % + (deploydir, imagename), ignore_status=True) + self.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output) + + +class GrubTests(OESelftestTestCase): + + def setUpLocal(self): + layer_intel = "meta-intel" + layer_minnow = "meta-updater-minnowboard" + result = runCmd('bitbake-layers show-layers') + # Assume the directory layout for finding other layers. We could also + # make assumptions by using 'show-layers', but either way, if the + # layers we need aren't where we expect them, we are out of like. + path = os.path.abspath(os.path.dirname(__file__)) + metadir = path + "/../../../../../" + if re.search(layer_intel, result.output) is None: + self.meta_intel = metadir + layer_intel + runCmd('bitbake-layers add-layer "%s"' % self.meta_intel) + else: + self.meta_intel = None + if re.search(layer_minnow, result.output) is None: + self.meta_minnow = metadir + layer_minnow + runCmd('bitbake-layers add-layer "%s"' % self.meta_minnow) + else: + self.meta_minnow = None + self.append_config('MACHINE = "intel-corei7-64"') + self.append_config('OSTREE_BOOTLOADER = "grub"') + self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "') + self.qemu, self.s = qemu_launch(efi=True, machine='intel-corei7-64') + + def tearDownLocal(self): + qemu_terminate(self.s) + if self.meta_intel: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_intel, ignore_status=True) + if self.meta_minnow: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_minnow, ignore_status=True) + + def qemu_command(self, command): + return qemu_send_command(self.qemu.ssh_port, command) + + def test_grub(self): + print('Checking machine name (hostname) of device:') + stdout, stderr, retcode = self.qemu_command('hostname') + self.assertEqual(retcode, 0, "Unable to check hostname. " + + "Is an ssh daemon (such as dropbear or openssh) installed on the device?") + machine = get_bb_var('MACHINE', 'core-image-minimal') + self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) + # Strip off line ending. + value = stdout.decode()[:-1] + self.assertEqual(value, machine, + 'MACHINE does not match hostname: ' + machine + ', ' + value + + '\nIs TianoCore ovmf installed on your host machine?') + print(value) + print('Checking output of aktualizr-info:') + ran_ok = False + for delay in [1, 2, 5, 10, 15]: + stdout, stderr, retcode = self.qemu_command('aktualizr-info') + if retcode == 0 and stderr == b'': + ran_ok = True + break + sleep(delay) + self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode()) + + verifyProvisioned(self, machine) + + +class ImplProvTests(OESelftestTestCase): + + def setUpLocal(self): + layer = "meta-updater-qemux86-64" + result = runCmd('bitbake-layers show-layers') + if re.search(layer, result.output) is None: + # Assume the directory layout for finding other layers. We could also + # make assumptions by using 'show-layers', but either way, if the + # layers we need aren't where we expect them, we are out of like. + path = os.path.abspath(os.path.dirname(__file__)) + metadir = path + "/../../../../../" + self.meta_qemu = metadir + layer + runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu) + else: + self.meta_qemu = None + self.append_config('MACHINE = "qemux86-64"') + self.append_config('SOTA_CLIENT_PROV = " aktualizr-implicit-prov "') + self.qemu, self.s = qemu_launch(machine='qemux86-64') + + def tearDownLocal(self): + qemu_terminate(self.s) + if self.meta_qemu: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True) + + def qemu_command(self, command): + return qemu_send_command(self.qemu.ssh_port, command) + + def test_provisioning(self): + print('Checking machine name (hostname) of device:') + stdout, stderr, retcode = self.qemu_command('hostname') + self.assertEqual(retcode, 0, "Unable to check hostname. " + + "Is an ssh daemon (such as dropbear or openssh) installed on the device?") + machine = get_bb_var('MACHINE', 'core-image-minimal') + self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) + # Strip off line ending. + value = stdout.decode()[:-1] + self.assertEqual(value, machine, + 'MACHINE does not match hostname: ' + machine + ', ' + value) + print(value) + print('Checking output of aktualizr-info:') + ran_ok = False + for delay in [1, 2, 5, 10, 15]: + stdout, stderr, retcode = self.qemu_command('aktualizr-info') + if retcode == 0 and stderr == b'': + ran_ok = True + break + sleep(delay) + self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode()) + # Verify that device has NOT yet provisioned. + self.assertIn(b'Couldn\'t load device ID', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + self.assertIn(b'Couldn\'t load ECU serials', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + self.assertIn(b'Provisioned on server: no', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + self.assertIn(b'Fetched metadata: no', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + + # Run cert_provider. + bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native') + creds = bb_vars['SOTA_PACKED_CREDENTIALS'] + bb_vars_prov = get_bb_vars(['STAGING_DIR_NATIVE', 'libdir'], 'aktualizr-implicit-prov') + config = bb_vars_prov['STAGING_DIR_NATIVE'] + bb_vars_prov['libdir'] + '/sota/sota_implicit_prov.toml' + + akt_native_run(self, 'aktualizr_cert_provider -c {creds} -t root@localhost -p {port} -s -g {config}' + .format(creds=creds, port=self.qemu.ssh_port, config=config)) + + verifyProvisioned(self, machine) + + +class HsmTests(OESelftestTestCase): + + def setUpLocal(self): + layer = "meta-updater-qemux86-64" + result = runCmd('bitbake-layers show-layers') + if re.search(layer, result.output) is None: + # Assume the directory layout for finding other layers. We could also + # make assumptions by using 'show-layers', but either way, if the + # layers we need aren't where we expect them, we are out of like. + path = os.path.abspath(os.path.dirname(__file__)) + metadir = path + "/../../../../../" + self.meta_qemu = metadir + layer + runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu) + else: + self.meta_qemu = None + self.append_config('MACHINE = "qemux86-64"') + self.append_config('SOTA_CLIENT_PROV = "aktualizr-hsm-prov"') + self.append_config('SOTA_CLIENT_FEATURES = "hsm"') + self.qemu, self.s = qemu_launch(machine='qemux86-64') + + def tearDownLocal(self): + qemu_terminate(self.s) + if self.meta_qemu: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True) + + def qemu_command(self, command): + return qemu_send_command(self.qemu.ssh_port, command) + + def test_provisioning(self): + print('Checking machine name (hostname) of device:') + stdout, stderr, retcode = self.qemu_command('hostname') + self.assertEqual(retcode, 0, "Unable to check hostname. " + + "Is an ssh daemon (such as dropbear or openssh) installed on the device?") + machine = get_bb_var('MACHINE', 'core-image-minimal') + self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) + # Strip off line ending. + value = stdout.decode()[:-1] + self.assertEqual(value, machine, + 'MACHINE does not match hostname: ' + machine + ', ' + value + + '\nIs tianocore ovmf installed?') + print(value) + print('Checking output of aktualizr-info:') + ran_ok = False + for delay in [1, 2, 5, 10, 15]: + stdout, stderr, retcode = self.qemu_command('aktualizr-info') + if retcode == 0 and stderr == b'': + ran_ok = True + break + sleep(delay) + self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode()) + # Verify that device has NOT yet provisioned. + self.assertIn(b'Couldn\'t load device ID', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + self.assertIn(b'Couldn\'t load ECU serials', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + self.assertIn(b'Provisioned on server: no', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + self.assertIn(b'Fetched metadata: no', stdout, + 'Device already provisioned!? ' + stderr.decode() + stdout.decode()) + + # Verify that HSM is not yet initialized. + pkcs11_command = 'pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so -O' + stdout, stderr, retcode = self.qemu_command(pkcs11_command) + self.assertNotEqual(retcode, 0, 'pkcs11-tool succeeded before initialization: ' + + stdout.decode() + stderr.decode()) + softhsm2_command = 'softhsm2-util --show-slots' + stdout, stderr, retcode = self.qemu_command(softhsm2_command) + self.assertNotEqual(retcode, 0, 'softhsm2-tool succeeded before initialization: ' + + stdout.decode() + stderr.decode()) + + # Run cert_provider. + bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native') + creds = bb_vars['SOTA_PACKED_CREDENTIALS'] + bb_vars_prov = get_bb_vars(['STAGING_DIR_NATIVE', 'libdir'], 'aktualizr-hsm-prov') + config = bb_vars_prov['STAGING_DIR_NATIVE'] + bb_vars_prov['libdir'] + '/sota/sota_hsm_prov.toml' + + akt_native_run(self, 'aktualizr_cert_provider -c {creds} -t root@localhost -p {port} -r -s -g {config}' + .format(creds=creds, port=self.qemu.ssh_port, config=config)) + + # Verify that HSM is able to initialize. + ran_ok = False + for delay in [5, 5, 5, 5, 10]: + sleep(delay) + p11_out, p11_err, p11_ret = self.qemu_command(pkcs11_command) + hsm_out, hsm_err, hsm_ret = self.qemu_command(softhsm2_command) + if p11_ret == 0 and hsm_ret == 0 and hsm_err == b'': + ran_ok = True + break + self.assertTrue(ran_ok, 'pkcs11-tool or softhsm2-tool failed: ' + p11_err.decode() + + p11_out.decode() + hsm_err.decode() + hsm_out.decode()) + self.assertIn(b'present token', p11_err, 'pkcs11-tool failed: ' + p11_err.decode() + p11_out.decode()) + self.assertIn(b'X.509 cert', p11_out, 'pkcs11-tool failed: ' + p11_err.decode() + p11_out.decode()) + self.assertIn(b'Initialized: yes', hsm_out, 'softhsm2-tool failed: ' + + hsm_err.decode() + hsm_out.decode()) + self.assertIn(b'User PIN init.: yes', hsm_out, 'softhsm2-tool failed: ' + + hsm_err.decode() + hsm_out.decode()) + + # Check that pkcs11 output matches sofhsm output. + p11_p = re.compile(r'Using slot [0-9] with a present token \((0x[0-9a-f]*)\)\s') + p11_m = p11_p.search(p11_err.decode()) + self.assertTrue(p11_m, 'Slot number not found with pkcs11-tool: ' + p11_err.decode() + p11_out.decode()) + self.assertGreater(p11_m.lastindex, 0, 'Slot number not found with pkcs11-tool: ' + + p11_err.decode() + p11_out.decode()) + hsm_p = re.compile(r'Description:\s*SoftHSM slot ID (0x[0-9a-f]*)\s') + hsm_m = hsm_p.search(hsm_out.decode()) + self.assertTrue(hsm_m, 'Slot number not found with softhsm2-tool: ' + hsm_err.decode() + hsm_out.decode()) + self.assertGreater(hsm_m.lastindex, 0, 'Slot number not found with softhsm2-tool: ' + + hsm_err.decode() + hsm_out.decode()) + self.assertEqual(p11_m.group(1), hsm_m.group(1), 'Slot number does not match: ' + + p11_err.decode() + p11_out.decode() + hsm_err.decode() + hsm_out.decode()) + + verifyProvisioned(self, machine) + +class SecondaryTests(OESelftestTestCase): + @classmethod + def setUpClass(cls): + super(SecondaryTests, cls).setUpClass() + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build secondary-image') + bitbake('secondary-image') + + def setUpLocal(self): + layer = "meta-updater-qemux86-64" + result = runCmd('bitbake-layers show-layers') + if re.search(layer, result.output) is None: + # Assume the directory layout for finding other layers. We could also + # make assumptions by using 'show-layers', but either way, if the + # layers we need aren't where we expect them, we are out of like. + path = os.path.abspath(os.path.dirname(__file__)) + metadir = path + "/../../../../../" + self.meta_qemu = metadir + layer + runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu) + else: + self.meta_qemu = None + self.append_config('MACHINE = "qemux86-64"') + self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "') + self.qemu, self.s = qemu_launch(machine='qemux86-64', imagename='secondary-image') + + def tearDownLocal(self): + qemu_terminate(self.s) + if self.meta_qemu: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True) + + def qemu_command(self, command): + return qemu_send_command(self.qemu.ssh_port, command) + + def test_secondary_present(self): + print('Checking aktualizr-secondary is present') + stdout, stderr, retcode = self.qemu_command('aktualizr-secondary --help') + self.assertEqual(retcode, 0, "Unable to run aktualizr-secondary --help") + self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) + + def test_secondary_listening(self): + print('Checking aktualizr-secondary service is listening') + stdout, stderr, retcode = self.qemu_command('echo test | nc localhost 9030') + self.assertEqual(retcode, 0, "Unable to connect to secondary") + + +class PrimaryTests(OESelftestTestCase): + @classmethod + def setUpClass(cls): + super(PrimaryTests, cls).setUpClass() + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build primary-image') + bitbake('primary-image') + + def setUpLocal(self): + layer = "meta-updater-qemux86-64" + result = runCmd('bitbake-layers show-layers') + if re.search(layer, result.output) is None: + # Assume the directory layout for finding other layers. We could also + # make assumptions by using 'show-layers', but either way, if the + # layers we need aren't where we expect them, we are out of like. + path = os.path.abspath(os.path.dirname(__file__)) + metadir = path + "/../../../../../" + self.meta_qemu = metadir + layer + runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu) + else: + self.meta_qemu = None + self.append_config('MACHINE = "qemux86-64"') + self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "') + self.append_config('SOTA_CLIENT_FEATURES = "secondary-network"') + self.qemu, self.s = qemu_launch(machine='qemux86-64', imagename='primary-image') + + def tearDownLocal(self): + qemu_terminate(self.s) + if self.meta_qemu: + runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True) + + def qemu_command(self, command): + return qemu_send_command(self.qemu.ssh_port, command) + + def test_aktualizr_present(self): + print('Checking aktualizr is present') + stdout, stderr, retcode = self.qemu_command('aktualizr --help') + self.assertEqual(retcode, 0, "Unable to run aktualizr --help") + self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) + + +def qemu_launch(efi=False, machine=None, imagename=None): + logger = logging.getLogger("selftest") + logger.info('Running bitbake to build core-image-minimal') + bitbake('core-image-minimal') + # Create empty object. + args = type('', (), {})() + if imagename: + args.imagename = imagename + else: + args.imagename = 'core-image-minimal' + args.mac = None + # Could use DEPLOY_DIR_IMAGE here but it's already in the machine + # subdirectory. + args.dir = 'tmp/deploy/images' + args.efi = efi + args.machine = machine + args.kvm = None # Autodetect + args.no_gui = True + args.gdb = False + args.pcap = None + args.overlay = None + args.dry_run = False + args.secondary_network = False + + qemu = QemuCommand(args) + cmdline = qemu.command_line() + print('Booting image with run-qemu-ota...') + s = subprocess.Popen(cmdline) + sleep(10) + return qemu, s + + +def qemu_terminate(s): + try: + s.terminate() + except KeyboardInterrupt: + pass + + +def qemu_send_command(port, command): + command = ['ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@localhost -p ' + + str(port) + ' "' + command + '"'] + s2 = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = s2.communicate(timeout=60) + return stdout, stderr, s2.returncode + + +def akt_native_run(testInst, cmd, **kwargs): + # run a command supplied by aktualizr-native and checks that: + # - the executable exists + # - the command runs without error + # NOTE: the base test class must have built aktualizr-native (in + # setUpClass, for example) + bb_vars = get_bb_vars(['SYSROOT_DESTDIR', 'base_prefix', 'libdir', 'bindir'], + 'aktualizr-native') + sysroot = bb_vars['SYSROOT_DESTDIR'] + bb_vars['base_prefix'] + sysrootbin = bb_vars['SYSROOT_DESTDIR'] + bb_vars['bindir'] + libdir = bb_vars['libdir'] + + program, *_ = cmd.split(' ') + p = '{}/{}'.format(sysrootbin, program) + testInst.assertTrue(os.path.isfile(p), msg="No {} found ({})".format(program, p)) + env = dict(os.environ) + env['LD_LIBRARY_PATH'] = libdir + result = runCmd(cmd, env=env, native_sysroot=sysroot, ignore_status=True, **kwargs) + testInst.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output) + + +def verifyProvisioned(testInst, machine): + # Verify that device HAS provisioned. + ran_ok = False + for delay in [5, 5, 5, 5, 10, 10, 10, 10]: + stdout, stderr, retcode = testInst.qemu_command('aktualizr-info') + if retcode == 0 and stderr == b'' and stdout.decode().find('Fetched metadata: yes') >= 0: + ran_ok = True + break + sleep(delay) + testInst.assertIn(b'Device ID: ', stdout, 'Provisioning failed: ' + stderr.decode() + stdout.decode()) + testInst.assertIn(b'Primary ecu hardware ID: ' + machine.encode(), stdout, + 'Provisioning failed: ' + stderr.decode() + stdout.decode()) + testInst.assertIn(b'Fetched metadata: yes', stdout, 'Provisioning failed: ' + stderr.decode() + stdout.decode()) + p = re.compile(r'Device ID: ([a-z0-9-]*)\n') + m = p.search(stdout.decode()) + testInst.assertTrue(m, 'Device ID could not be read: ' + stderr.decode() + stdout.decode()) + testInst.assertGreater(m.lastindex, 0, 'Device ID could not be read: ' + stderr.decode() + stdout.decode()) + logger = logging.getLogger("selftest") + logger.info('Device successfully provisioned with ID: ' + m.group(1)) + + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-core/images/initramfs-ostree-image.bb b/meta-sota/recipes-core/images/initramfs-ostree-image.bb new file mode 100644 index 0000000..b2d9e27 --- /dev/null +++ b/meta-sota/recipes-core/images/initramfs-ostree-image.bb @@ -0,0 +1,29 @@ +# Netboot initramfs image. +DESCRIPTION = "OSTree initramfs image" + +PACKAGE_INSTALL = "ostree-switchroot ostree-initrd busybox base-passwd ${ROOTFS_BOOTSTRAP_INSTALL}" + +SYSTEMD_DEFAULT_TARGET = "initrd.target" + +# Do not pollute the initrd image with rootfs features +IMAGE_FEATURES = "" + +export IMAGE_BASENAME = "initramfs-ostree-image" +IMAGE_LINGUAS = "" + +LICENSE = "MIT" + +IMAGE_FSTYPES = "${OSTREE_INITRAMFS_FSTYPES}" + +inherit core-image + +IMAGE_ROOTFS_SIZE = "8192" + +# Users will often ask for extra space in their rootfs by setting this +# globally. Since this is a initramfs, we don't want to make it bigger +IMAGE_ROOTFS_EXTRA_SPACE = "0" +IMAGE_OVERHEAD_FACTOR = "1.0" + +BAD_RECOMMENDATIONS += "busybox-syslog" + + diff --git a/meta-sota/recipes-sota/aktualizr/aktualizr-auto-prov.bb b/meta-sota/recipes-sota/aktualizr/aktualizr-auto-prov.bb new file mode 100644 index 0000000..8deee7e --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/aktualizr-auto-prov.bb @@ -0,0 +1,56 @@ +SUMMARY = "Aktualizr configuration for autoprovisioning" +DESCRIPTION = "Systemd service and configurations for autoprovisioning Aktualizr, the SOTA Client application written in C++" +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" +DEPENDS = "aktualizr-native zip-native" +RDEPENDS_${PN} = "aktualizr" +PV = "1.0" +PR = "6" + +SRC_URI = " \ + file://LICENSE \ + " + +require environment.inc +require credentials.inc + +do_install() { + if [ -n "${SOTA_AUTOPROVISION_CREDENTIALS}" ]; then + bbwarn "SOTA_AUTOPROVISION_CREDENTIALS are ignored. Please use SOTA_PACKED_CREDENTIALS" + fi + if [ -n "${SOTA_AUTOPROVISION_URL}" ]; then + bbwarn "SOTA_AUTOPROVISION_URL is ignored. Please use SOTA_PACKED_CREDENTIALS" + fi + if [ -n "${SOTA_AUTOPROVISION_URL_FILE}" ]; then + bbwarn "SOTA_AUTOPROVISION_URL_FILE is ignored. Please use SOTA_PACKED_CREDENTIALS" + fi + if [ -n "${OSTREE_PUSH_CREDENTIALS}" ]; then + bbwarn "OSTREE_PUSH_CREDENTIALS is ignored. Please use SOTA_PACKED_CREDENTIALS" + fi + + install -m 0700 -d ${D}${libdir}/sota/conf.d + install -m 0700 -d ${D}${localstatedir}/sota + if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then + aktualizr_toml=${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'secondary-network', 'sota_autoprov_primary.toml', 'sota_autoprov.toml', d)} + + install -m 0644 ${STAGING_DIR_NATIVE}${libdir}/sota/${aktualizr_toml} ${D}${libdir}/sota/conf.d/20-sota.toml + + # deploy SOTA credentials + if [ -e ${SOTA_PACKED_CREDENTIALS} ]; then + cp ${SOTA_PACKED_CREDENTIALS} ${D}${localstatedir}/sota/sota_provisioning_credentials.zip + # Device should not be able to push data to treehub + zip -d ${D}${localstatedir}/sota/sota_provisioning_credentials.zip treehub.json + fi + fi +} + +FILES_${PN} = " \ + ${libdir}/sota/conf.d \ + ${libdir}/sota/conf.d/20-sota.toml \ + ${localstatedir}/sota \ + ${localstatedir}/sota/sota_provisioning_credentials.zip \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb b/meta-sota/recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb new file mode 100644 index 0000000..319074e --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb @@ -0,0 +1,72 @@ +SUMMARY = "Aktualizr configuration for implicit provisioning with CA" +DESCRIPTION = "Systemd service and configurations for implicitly provisioning Aktualizr using externally provided or generated CA" + +# WARNING: it is NOT a production solution. The secure way to provision devices is to create certificate request directly on the device +# (either with HSM/TPM or with software) and then sign it with a CA stored on a disconnected machine + +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" + +DEPENDS = "aktualizr-native openssl-native" +RDEPENDS_${PN} = "aktualizr" + +SRC_URI = " \ + file://LICENSE \ + file://ca.cnf \ + " +PV = "1.0" +PR = "1" + +require environment.inc +require credentials.inc + +export SOTA_CACERT_PATH +export SOTA_CAKEY_PATH + +do_install() { + install -m 0700 -d ${D}${libdir}/sota/conf.d + + if [ -z "${SOTA_PACKED_CREDENTIALS}" ]; then + bberror "SOTA_PACKED_CREDENTIALS are required for implicit provisioning" + fi + + if [ -z ${SOTA_CACERT_PATH} ]; then + SOTA_CACERT_PATH=${DEPLOY_DIR_IMAGE}/CA/cacert.pem + SOTA_CAKEY_PATH=${DEPLOY_DIR_IMAGE}/CA/ca.private.pem + mkdir -p ${DEPLOY_DIR_IMAGE}/CA + bbwarn "SOTA_CACERT_PATH is not specified, use default one at $SOTA_CACERT_PATH" + + if [ ! -f ${SOTA_CACERT_PATH} ]; then + bbwarn "${SOTA_CACERT_PATH} does not exist, generate a new CA" + SOTA_CACERT_DIR_PATH="$(dirname "$SOTA_CACERT_PATH")" + openssl genrsa -out ${SOTA_CACERT_DIR_PATH}/ca.private.pem 4096 + openssl req -key ${SOTA_CACERT_DIR_PATH}/ca.private.pem -new -x509 -days 7300 -out ${SOTA_CACERT_PATH} -subj "/C=DE/ST=Berlin/O=Reis und Kichererbsen e.V/commonName=meta-updater" -batch -config ${WORKDIR}/ca.cnf -extensions cacert + bbwarn "${SOTA_CACERT_PATH} has been created, you'll need to upload it to the server" + fi + fi + + if [ -z ${SOTA_CAKEY_PATH} ]; then + bberror "SOTA_CAKEY_PATH should be set when using implicit provisioning" + fi + + install -m 0700 -d ${D}${localstatedir}/sota + install -m 0644 ${STAGING_DIR_NATIVE}${libdir}/sota/sota_implicit_prov_ca.toml ${D}${libdir}/sota/conf.d/20-sota.toml + aktualizr_cert_provider --credentials ${SOTA_PACKED_CREDENTIALS} \ + --device-ca ${SOTA_CACERT_PATH} \ + --device-ca-key ${SOTA_CAKEY_PATH} \ + --root-ca \ + --server-url \ + --local ${D}${localstatedir}/sota \ + --config ${D}${libdir}/sota/conf.d/20-sota.toml +} + +FILES_${PN} = " \ + ${libdir}/sota/conf.d \ + ${libdir}/sota/conf.d/20-sota.toml \ + ${libdir}/sota/root.crt \ + ${localstatedir}/sota/* \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/aktualizr/aktualizr-hsm-prov.bb b/meta-sota/recipes-sota/aktualizr/aktualizr-hsm-prov.bb new file mode 100644 index 0000000..504f0d8 --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/aktualizr-hsm-prov.bb @@ -0,0 +1,33 @@ +SUMMARY = "Aktualizr configuration with HSM support" +DESCRIPTION = "Systemd service and configurations for HSM provisioning with Aktualizr, the SOTA Client application written in C++" +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" + +DEPENDS = "aktualizr-native" +RDEPENDS_${PN} = "aktualizr softhsm softhsm-testtoken" + +SRC_URI = " \ + file://LICENSE \ + " +PV = "1.0" +PR = "6" + +require environment.inc +require credentials.inc + +do_install() { + install -m 0700 -d ${D}${libdir}/sota/conf.d + if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then + aktualizr_implicit_writer -c ${SOTA_PACKED_CREDENTIALS} --no-root-ca \ + -i ${STAGING_DIR_NATIVE}${libdir}/sota/sota_hsm_prov.toml -o ${D}${libdir}/sota/conf.d/20-sota.toml -p ${D} + fi +} + +FILES_${PN} = " \ + ${libdir}/sota/conf.d \ + ${libdir}/sota/conf.d/20-sota.toml \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/aktualizr/aktualizr-implicit-prov.bb b/meta-sota/recipes-sota/aktualizr/aktualizr-implicit-prov.bb new file mode 100644 index 0000000..dcfaffb --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/aktualizr-implicit-prov.bb @@ -0,0 +1,34 @@ +SUMMARY = "Aktualizr configuration for implicit provisioning" +DESCRIPTION = "Systemd service and configurations for implicitly provisioning Aktualizr, the SOTA Client application written in C++" +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" + +DEPENDS = "aktualizr-native" +RDEPENDS_${PN} = "aktualizr" + +SRC_URI = " \ + file://LICENSE \ + " +PV = "1.0" +PR = "1" + +require environment.inc +require credentials.inc + +do_install() { + install -m 0700 -d ${D}${libdir}/sota/conf.d + if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then + aktualizr_implicit_writer -c ${SOTA_PACKED_CREDENTIALS} \ + -i ${STAGING_DIR_NATIVE}${libdir}/sota/sota_implicit_prov.toml -o ${D}${libdir}/sota/conf.d/20-sota.toml -p ${D} + fi +} + +FILES_${PN} = " \ + ${libdir}/sota/conf.d \ + ${libdir}/sota/conf.d/20-sota.toml \ + ${libdir}/sota/root.crt \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/aktualizr/aktualizr_git.bb b/meta-sota/recipes-sota/aktualizr/aktualizr_git.bb new file mode 100755 index 0000000..2c0d59f --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/aktualizr_git.bb @@ -0,0 +1,119 @@ +SUMMARY = "Aktualizr SOTA Client" +DESCRIPTION = "SOTA Client application written in C++" +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" + +DEPENDS = "boost curl openssl libarchive libsodium asn1c-native sqlite3 " +DEPENDS_append_class-target = "ostree ${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'hsm', ' libp11', '', d)} " +DEPENDS_append_class-native = "glib-2.0-native " + +RDEPENDS_${PN}_class-target = "lshw " +RDEPENDS_${PN}_append_class-target = " ${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'serialcan', ' slcand-start', '', d)} " + +PV = "1.0+git${SRCPV}" +PR = "7" + +SRC_URI = " \ + gitsm://github.com/advancedtelematic/aktualizr;branch=${BRANCH} \ + file://aktualizr.service \ + file://aktualizr-secondary.service \ + file://aktualizr-secondary.socket \ + file://aktualizr-serialcan.service \ + " +SRCREV = "3b89858cf8ce9a8331cc4e6a5d2b5783d2eb7ae9" +BRANCH ?= "master" + +S = "${WORKDIR}/git" + +inherit cmake + +inherit systemd + +SYSTEMD_PACKAGES = "${PN} ${PN}-secondary" +SYSTEMD_SERVICE_${PN} = "aktualizr.service" +SYSTEMD_SERVICE_${PN}-secondary = "aktualizr-secondary.socket" + +BBCLASSEXTEND =+ "native" + +require garage-sign-version.inc + +EXTRA_OECMAKE = "-DWARNING_AS_ERROR=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DAKTUALIZR_VERSION=${PV} \ + -DBUILD_LOAD_TESTS=OFF" +EXTRA_OECMAKE_append_class-target = " -DBUILD_OSTREE=ON \ + -DBUILD_ISOTP=ON \ + ${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'hsm', '-DBUILD_P11=ON', '', d)} " +EXTRA_OECMAKE_append_class-native = " -DBUILD_SOTA_TOOLS=ON \ + -DBUILD_OSTREE=OFF \ + -DBUILD_SYSTEMD=OFF \ + -DGARAGE_SIGN_VERSION=${GARAGE_SIGN_VERSION} \ + -DGARAGE_SIGN_SHA256=${GARAGE_SIGN_SHA256}" + +do_install_append () { + rm -fr ${D}${libdir}/systemd + rm -f ${D}${libdir}/sota/sota.toml # Only needed for the Debian package + install -d ${D}${libdir}/sota + install -m 0644 ${S}/config/sota_autoprov.toml ${D}/${libdir}/sota/sota_autoprov.toml + install -m 0644 ${S}/config/sota_autoprov_primary.toml ${D}/${libdir}/sota/sota_autoprov_primary.toml + install -m 0644 ${S}/config/sota_hsm_prov.toml ${D}/${libdir}/sota/sota_hsm_prov.toml + install -m 0644 ${S}/config/sota_implicit_prov.toml ${D}/${libdir}/sota/sota_implicit_prov.toml + install -m 0644 ${S}/config/sota_implicit_prov_ca.toml ${D}/${libdir}/sota/sota_implicit_prov_ca.toml + install -m 0644 ${S}/config/sota_secondary.toml ${D}/${libdir}/sota/sota_secondary.toml + install -d ${D}${systemd_unitdir}/system + install -m 0644 ${WORKDIR}/aktualizr-secondary.socket ${D}${systemd_unitdir}/system/aktualizr-secondary.socket + install -m 0644 ${WORKDIR}/aktualizr-secondary.service ${D}${systemd_unitdir}/system/aktualizr-secondary.service + install -m 0700 -d ${D}${libdir}/sota/conf.d + install -m 0700 -d ${D}${sysconfdir}/sota/conf.d +} + +do_install_append_class-target () { + install -m 0755 -d ${D}${systemd_unitdir}/system + aktualizr_service=${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'serialcan', '${WORKDIR}/aktualizr-serialcan.service', '${WORKDIR}/aktualizr.service', d)} + install -m 0644 ${aktualizr_service} ${D}${systemd_unitdir}/system/aktualizr.service +} + +do_install_append_class-native () { + install -m 0755 ${B}/src/sota_tools/garage-sign/bin/* ${D}${bindir} + install -m 0644 ${B}/src/sota_tools/garage-sign/lib/* ${D}${libdir} +} + +PACKAGES =+ " ${PN}-examples ${PN}-host-tools ${PN}-secondary " + +FILES_${PN} = " \ + ${bindir}/aktualizr \ + ${bindir}/aktualizr-info \ + ${bindir}/aktualizr-check-discovery \ + ${systemd_unitdir}/system/aktualizr.service \ + ${libdir}/sota/conf.d \ + ${sysconfdir}/sota/conf.d \ + " + +FILES_${PN}-examples = " \ + ${libdir}/sota/demo_secondary.json \ + ${bindir}/example-interface \ + ${bindir}/isotp-test-interface \ + " + +FILES_${PN}-host-tools = " \ + ${bindir}/aktualizr_cert_provider \ + ${bindir}/aktualizr_implicit_writer \ + ${bindir}/garage-deploy \ + ${bindir}/garage-push \ + ${libdir}/sota/sota_autoprov.toml \ + ${libdir}/sota/sota_autoprov_primary.toml \ + ${libdir}/sota/sota_hsm_prov.toml \ + ${libdir}/sota/sota_implicit_prov.toml \ + ${libdir}/sota/sota_implicit_prov_ca.toml \ + " + +FILES_${PN}-secondary = " \ + ${bindir}/aktualizr-secondary \ + ${libdir}/sota/sota_secondary.toml \ + ${systemd_unitdir}/system/aktualizr-secondary.socket \ + ${systemd_unitdir}/system/aktualizr-secondary.service \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/aktualizr/credentials.inc b/meta-sota/recipes-sota/aktualizr/credentials.inc new file mode 100644 index 0000000..256c8ff --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/credentials.inc @@ -0,0 +1 @@ +SRC_URI_append = "${@('file://' + d.getVar('SOTA_PACKED_CREDENTIALS', True)) if d.getVar('SOTA_PACKED_CREDENTIALS', True) else ''}" diff --git a/meta-sota/recipes-sota/aktualizr/environment.inc b/meta-sota/recipes-sota/aktualizr/environment.inc new file mode 100644 index 0000000..16e789e --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/environment.inc @@ -0,0 +1,11 @@ +export SOTA_VIRTUAL_SECONDARIES + +do_install_append() { + for sec in ${SOTA_VIRTUAL_SECONDARIES}; do + AKTUALIZR_PARAMETERS_VIRTUALSECS="${AKTUALIZR_PARAMETERS_VIRTUALSECS} --secondary-config $sec" + done + + echo "AKTUALIZR_CMDLINE_PARAMETERS=${AKTUALIZR_PARAMETERS_VIRTUALSECS}" > ${D}${libdir}/sota/sota.env +} + +FILES_${PN}_append = " ${libdir}/sota/sota.env" diff --git a/meta-sota/recipes-sota/aktualizr/files/LICENSE b/meta-sota/recipes-sota/aktualizr/files/LICENSE new file mode 100644 index 0000000..a612ad9 --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/files/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.service b/meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.service new file mode 100644 index 0000000..a1e0e1b --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.service @@ -0,0 +1,9 @@ +[Unit] +Description=Aktualizr SOTA Client (UPTANE Secondary) + +[Service] +RestartSec=10 +Restart=always +EnvironmentFile=-/etc/sota/sota.env +ExecStart=/usr/bin/aktualizr-secondary --config /usr/lib/sota/sota_secondary.toml + diff --git a/meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.socket b/meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.socket new file mode 100644 index 0000000..da0ee44 --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/files/aktualizr-secondary.socket @@ -0,0 +1,6 @@ +[Socket] +ListenStream=9030 +ListenDatagram=9031 + +[Install] +WantedBy=sockets.target \ No newline at end of file diff --git a/meta-sota/recipes-sota/aktualizr/files/aktualizr-serialcan.service b/meta-sota/recipes-sota/aktualizr/files/aktualizr-serialcan.service new file mode 100644 index 0000000..b42f348 --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/files/aktualizr-serialcan.service @@ -0,0 +1,15 @@ +[Unit] +Description=Aktualizr SOTA Client +Wants=network-online.target slcand@ttyACM0.service +After=network.target network-online.target slcand@ttyACM0.service + +Requires=network-online.target + +[Service] +RestartSec=10 +Restart=always +EnvironmentFile=/usr/lib/sota/sota.env +ExecStart=/bin/sh -c "(ip addr | grep can0) && /usr/bin/aktualizr $AKTUALIZR_CMDLINE_PARAMETERS" + +[Install] +WantedBy=multi-user.target diff --git a/meta-sota/recipes-sota/aktualizr/files/aktualizr.service b/meta-sota/recipes-sota/aktualizr/files/aktualizr.service new file mode 100644 index 0000000..1c2e1df --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/files/aktualizr.service @@ -0,0 +1,15 @@ +[Unit] +Description=Aktualizr SOTA Client +Wants=network-online.target +After=network.target network-online.target +Requires=network-online.target + +[Service] +RestartSec=10 +Restart=always +EnvironmentFile=/usr/lib/sota/sota.env +EnvironmentFile=-/etc/sota/sota.env +ExecStart=/usr/bin/aktualizr $AKTUALIZR_CMDLINE_PARAMETERS + +[Install] +WantedBy=multi-user.target diff --git a/meta-sota/recipes-sota/aktualizr/files/ca.cnf b/meta-sota/recipes-sota/aktualizr/files/ca.cnf new file mode 100644 index 0000000..352ec38 --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/files/ca.cnf @@ -0,0 +1,10 @@ +[req] +req_extensions = cacert +distinguished_name = req_distinguished_name + +[req_distinguished_name] + +[cacert] +basicConstraints = critical,CA:true +keyUsage = keyCertSign + diff --git a/meta-sota/recipes-sota/aktualizr/garage-sign-version.inc b/meta-sota/recipes-sota/aktualizr/garage-sign-version.inc new file mode 100644 index 0000000..66e3ffd --- /dev/null +++ b/meta-sota/recipes-sota/aktualizr/garage-sign-version.inc @@ -0,0 +1,23 @@ + +python () { + if d.getVar("GARAGE_SIGN_VERSION", True) or not d.getVar("SOTA_PACKED_CREDENTIALS", True): + return + import json + import urllib.request + import zipfile + with zipfile.ZipFile(d.getVar("SOTA_PACKED_CREDENTIALS", True), 'r') as zip_ref: + try: + with zip_ref.open('tufrepo.url', mode='r') as url_file: + url = url_file.read().decode() + '/health/version' + except (KeyError, ValueError, RuntimeError): + return + r = urllib.request.urlopen(url) + if r.code != 200: + return + resp = r.read().decode('utf-8') + j = json.loads(resp) + version = 'cli-' + j['version'] + '.tgz' + d.setVar("GARAGE_SIGN_VERSION", version) +} + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/asn1c/asn1c.bb b/meta-sota/recipes-sota/asn1c/asn1c.bb new file mode 100644 index 0000000..9d1517d --- /dev/null +++ b/meta-sota/recipes-sota/asn1c/asn1c.bb @@ -0,0 +1,17 @@ +SUMMARY = "ASN.1 to C compiler" +DESCRIPTION = "Generates serialization routines from ASN.1 schemas" +HOMEPAGE = "http://lionet.info/asn1c" +SECTION = "base" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://LICENSE;md5=ee8bfaaa7d71cf3edb079475e6716d4b" + +inherit autotools native + +PV = "0.9.28" +SRC_URI = "https://github.com/vlm/asn1c/releases/download/v${PV}/asn1c-${PV}.tar.gz \ + file://skeletons_dir_fix.patch" +SRC_URI[sha256sum] = "8007440b647ef2dd9fb73d931c33ac11764e6afb2437dbe638bb4e5fc82386b9" + +BBCLASSEXTEND = "native nativesdk" + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/asn1c/files/skeletons_dir_fix.patch b/meta-sota/recipes-sota/asn1c/files/skeletons_dir_fix.patch new file mode 100644 index 0000000..f1caa2f --- /dev/null +++ b/meta-sota/recipes-sota/asn1c/files/skeletons_dir_fix.patch @@ -0,0 +1,44 @@ +From 1a1c2c94f700cf0f4dc5dba863950b16477fdc6d Mon Sep 17 00:00:00 2001 +From: Laurent Bonnans +Date: Thu, 25 Jan 2018 09:49:41 +0100 +Subject: [PATCH] Patch the skeletons directory detection + +Detect `share/asn1c` from `bin/` if it exists +--- + asn1c/asn1c.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/asn1c/asn1c.c b/asn1c/asn1c.c +index eb1eff7c..dd9fc832 100644 +--- a/asn1c/asn1c.c ++++ b/asn1c/asn1c.c +@@ -226,22 +226,21 @@ main(int ac, char **av) { + if(skeletons_dir == NULL) { + struct stat sb; + skeletons_dir = DATADIR; +- if((av[-optind][0] == '.' || av[-optind][1] == '/') +- && stat(skeletons_dir, &sb)) { ++ if(stat(skeletons_dir, &sb)) { + /* + * The default skeletons directory does not exist, + * compute it from my file name: +- * ./asn1c/asn1c -> ./skeletons ++ * ./asn1c/asn1c -> ./share/asn1c + */ + char *p; + size_t len; + + p = a1c_dirname(av[-optind]); + +- len = strlen(p) + sizeof("/../skeletons"); ++ len = strlen(p) + sizeof("/../share/asn1c"); + skeletons_dir = malloc(len); + assert(skeletons_dir); +- snprintf(skeletons_dir, len, "%s/../skeletons", p); ++ snprintf(skeletons_dir, len, "%s/../share/asn1c", p); + if(stat(skeletons_dir, &sb)) { + fprintf(stderr, + "WARNING: skeletons are neither in " +-- +2.15.1 + diff --git a/meta-sota/recipes-sota/config/aktualizr-disable-send-ip.bb b/meta-sota/recipes-sota/config/aktualizr-disable-send-ip.bb new file mode 100644 index 0000000..cab7696 --- /dev/null +++ b/meta-sota/recipes-sota/config/aktualizr-disable-send-ip.bb @@ -0,0 +1,23 @@ +SUMMARY = "Disable IP reporting in Aktualizr" +DESCRIPTION = "Configures aktualizr to disable IP reporting to the server" +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" + +SRC_URI = " \ + file://LICENSE \ + file://30-disable-send-ip.toml \ + " + +do_install_append () { + install -m 0700 -d ${D}${libdir}/sota/conf.d + install -m 0644 ${WORKDIR}/30-disable-send-ip.toml ${D}${libdir}/sota/conf.d/30-disable-send-ip.toml +} + +FILES_${PN} = " \ + ${libdir}/sota/conf.d/30-disable-send-ip.toml \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: + diff --git a/meta-sota/recipes-sota/config/aktualizr-example-interface.bb b/meta-sota/recipes-sota/config/aktualizr-example-interface.bb new file mode 100644 index 0000000..37a9184 --- /dev/null +++ b/meta-sota/recipes-sota/config/aktualizr-example-interface.bb @@ -0,0 +1,22 @@ +SUMMARY = "Aktualizr example interface" +DESCRIPTION = "Aktualizr example interface for legacy secondaries" +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" + +SRC_URI = " \ + file://LICENSE \ + file://30-example-interface.toml \ + " + +do_install_append () { + install -m 0700 -d ${D}${libdir}/sota/conf.d + install -m 0644 ${WORKDIR}/30-example-interface.toml ${D}${libdir}/sota/conf.d/30-example-interface.toml +} + +FILES_${PN} = " \ + ${libdir}/sota/conf.d/30-example-interface.toml \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-sota/config/aktualizr-log-debug.bb b/meta-sota/recipes-sota/config/aktualizr-log-debug.bb new file mode 100644 index 0000000..e628616 --- /dev/null +++ b/meta-sota/recipes-sota/config/aktualizr-log-debug.bb @@ -0,0 +1,23 @@ +SUMMARY = "Set debug logging in Aktualizr" +DESCRIPTION = "Configures aktualizr to log at a debugging level" +HOMEPAGE = "https://github.com/advancedtelematic/aktualizr" +SECTION = "base" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" + +SRC_URI = " \ + file://LICENSE \ + file://05-log-debug.toml \ + " + +do_install_append () { + install -m 0700 -d ${D}${libdir}/sota/conf.d + install -m 0644 ${WORKDIR}/05-log-debug.toml ${D}${libdir}/sota/conf.d/05-log-debug.toml +} + +FILES_${PN} = " \ + ${libdir}/sota/conf.d/05-log-debug.toml \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: + diff --git a/meta-sota/recipes-sota/config/files/05-log-debug.toml b/meta-sota/recipes-sota/config/files/05-log-debug.toml new file mode 100644 index 0000000..100a146 --- /dev/null +++ b/meta-sota/recipes-sota/config/files/05-log-debug.toml @@ -0,0 +1,2 @@ +[logger] +loglevel = 0 diff --git a/meta-sota/recipes-sota/config/files/30-disable-send-ip.toml b/meta-sota/recipes-sota/config/files/30-disable-send-ip.toml new file mode 100644 index 0000000..5cd5108 --- /dev/null +++ b/meta-sota/recipes-sota/config/files/30-disable-send-ip.toml @@ -0,0 +1,2 @@ +[telemetry] +report_network = false diff --git a/meta-sota/recipes-sota/config/files/30-example-interface.toml b/meta-sota/recipes-sota/config/files/30-example-interface.toml new file mode 100644 index 0000000..fc4e9ec --- /dev/null +++ b/meta-sota/recipes-sota/config/files/30-example-interface.toml @@ -0,0 +1,2 @@ +[uptane] +legacy_interface = "/usr/bin/example-interface" diff --git a/meta-sota/recipes-sota/config/files/LICENSE b/meta-sota/recipes-sota/config/files/LICENSE new file mode 100644 index 0000000..a612ad9 --- /dev/null +++ b/meta-sota/recipes-sota/config/files/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/meta-sota/recipes-sota/ostree-initrd/files/init.sh b/meta-sota/recipes-sota/ostree-initrd/files/init.sh new file mode 100644 index 0000000..d7e0429 --- /dev/null +++ b/meta-sota/recipes-sota/ostree-initrd/files/init.sh @@ -0,0 +1,85 @@ +#!/bin/sh +set -eu + +# ------------------------------------------- + +log_info() { echo "$0[$$]: $*" >&2; } +log_error() { echo "$0[$$]: ERROR $*" >&2; } + +do_mount_fs() { + log_info "mounting FS: $*" + [[ -e /proc/filesystems ]] && { grep -q "$1" /proc/filesystems || { log_error "Unknown filesystem"; return 1; } } + [[ -d "$2" ]] || mkdir -p "$2" + [[ -e /proc/mounts ]] && { grep -q -e "^$1 $2 $1" /proc/mounts && { log_info "$2 ($1) already mounted"; return 0; } } + mount -t "$1" "$1" "$2" +} + +bail_out() { + log_error "$@" + log_info "Rebooting..." + #exec reboot -f + exec sh +} + +get_ostree_sysroot() { + for opt in $(cat /proc/cmdline); do + arg=$(echo "$opt" | cut -d'=' -f1) + if [ "$arg" == "ostree_root" ]; then + echo "$opt" | cut -d'=' -f2- + return + fi + done + echo "LABEL=otaroot" +} + +export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/lib/ostree + +log_info "Starting OSTree initrd script" + +do_mount_fs proc /proc +do_mount_fs sysfs /sys +do_mount_fs devtmpfs /dev +do_mount_fs devpts /dev/pts +do_mount_fs tmpfs /dev/shm +do_mount_fs tmpfs /tmp +do_mount_fs tmpfs /run + +# check if smack is active (and if so, mount smackfs) +grep -q smackfs /proc/filesystems && { + do_mount_fs smackfs /sys/fs/smackfs + + # adjust current label and network label + echo System >/proc/self/attr/current + echo System >/sys/fs/smackfs/ambient +} + +mkdir -p /sysroot +ostree_sysroot=$(get_ostree_sysroot) + +mount "$ostree_sysroot" /sysroot || { + # The SD card in the R-Car M3 takes a bit of time to come up + # Retry the mount if it fails the first time + log_info "Mounting $ostree_sysroot failed, waiting 5s for the device to be available..." + sleep 5 + mount "$ostree_sysroot" /sysroot || bail_out "Unable to mount $ostree_sysroot as physical sysroot" +} +ostree-prepare-root /sysroot + +# move mounted devices to new root +cd /sysroot +for x in dev proc run; do + log_info "Moving /$x to new rootfs" + mount -o move "/$x" "$x" +done + +# switch to new rootfs +log_info "Switching to new rootfs" +mkdir -p run/initramfs + +pivot_root . run/initramfs || bail_out "pivot_root failed." + +log_info "Launching target init" + +exec chroot . sh -c 'umount /run/initramfs; exec /sbin/init' \ + dev/console 2>&1 + diff --git a/meta-sota/recipes-sota/ostree-initrd/ostree-initrd.bb b/meta-sota/recipes-sota/ostree-initrd/ostree-initrd.bb new file mode 100644 index 0000000..6046c81 --- /dev/null +++ b/meta-sota/recipes-sota/ostree-initrd/ostree-initrd.bb @@ -0,0 +1,20 @@ +SUMMARY = "Extremely basic live image init script" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" +SRC_URI = "file://init.sh" + +S = "${WORKDIR}" + +PV = "3" + +do_install() { + install -dm 0755 ${D}/etc + touch ${D}/etc/initrd-release + install -dm 0755 ${D}/dev + install -dm 0755 ${D}/sbin + install -m 0755 ${WORKDIR}/init.sh ${D}/sbin/init +} + +inherit allarch + +FILES_${PN} += " /dev /etc/initrd-release /sbin/init " diff --git a/meta-sota/recipes-sota/ostree/ostree_git.bb b/meta-sota/recipes-sota/ostree/ostree_git.bb new file mode 100644 index 0000000..cdcb485 --- /dev/null +++ b/meta-sota/recipes-sota/ostree/ostree_git.bb @@ -0,0 +1,92 @@ +SUMMARY = "Tool for managing bootable, immutable, versioned filesystem trees" +LICENSE = "GPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=5f30f0716dfdd0d91eb439ebec522ec2" + +inherit autotools-brokensep pkgconfig systemd gobject-introspection + +INHERIT_remove_class-native = "systemd" + +SRC_URI = "gitsm://github.com/ostreedev/ostree.git;branch=master" + +SRCREV="854a823e05d6fe8b610c02c2a71eaeb2bf1e98a6" + +PV = "v2017.13" +PR = "1" + +S = "${WORKDIR}/git" + +BBCLASSEXTEND = "native" + +DEPENDS += "attr libarchive glib-2.0 pkgconfig gpgme libgsystem fuse e2fsprogs gtk-doc-native curl xz" +DEPENDS_append = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', ' systemd', '', d)}" +DEPENDS_remove_class-native = "systemd-native" + +RDEPENDS_${PN} = "util-linux-libuuid util-linux-libblkid util-linux-libmount libcap bash" + +EXTRA_OECONF = "CFLAGS='-Wno-error=missing-prototypes' --with-libarchive --disable-gtk-doc --disable-gtk-doc-html --disable-gtk-doc-pdf --disable-man --with-smack --with-builtin-grub2-mkconfig --with-curl --without-soup" +EXTRA_OECONF_append_class-native = " --enable-wrpseudo-compat" + +# Path to ${prefix}/lib/ostree/ostree-grub-generator is hardcoded on the +# do_configure stage so we do depend on it +SYSROOT_DIR = "${STAGING_DIR_TARGET}" +SYSROOT_DIR_class-native = "${STAGING_DIR_NATIVE}" +do_configure[vardeps] += "SYSROOT_DIR" + +SYSTEMD_REQUIRED = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}" +SYSTEMD_REQUIRED_class-native = "" + +SYSTEMD_SERVICE_${PN} = "ostree-prepare-root.service ostree-remount.service" +SYSTEMD_SERVICE_${PN}_class-native = "" + +PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}" +PACKAGECONFIG_class-native = "" +PACKAGECONFIG[systemd] = "--with-systemdsystemunitdir=${systemd_unitdir}/system/ --with-dracut" + +FILES_${PN} += "${libdir}/ostree/ ${libdir}/ostbuild" + +export STAGING_INCDIR +export STAGING_LIBDIR + +do_configure() { + unset docdir + NOCONFIGURE=1 ./autogen.sh + oe_runconf +} + +do_compile_prepend() { + export BUILD_SYS="${BUILD_SYS}" + export HOST_SYS="${HOST_SYS}" +} + +export SYSTEMD_REQUIRED + +do_install_append() { + if [ -n ${SYSTEMD_REQUIRED} ]; then + install -m 0644 -D ${S}/src/boot/ostree-prepare-root.service ${D}${systemd_unitdir}/system/ostree-prepare-root.service + install -m 0644 -D ${S}/src/boot/ostree-remount.service ${D}${systemd_unitdir}/system/ostree-remount.service + fi +} + +do_install_append_class-native() { + create_wrapper ${D}${bindir}/ostree OSTREE_GRUB2_EXEC="${STAGING_LIBDIR_NATIVE}/ostree/ostree-grub-generator" +} + + +FILES_${PN} += " \ + ${@'${systemd_unitdir}/system/' if d.getVar('SYSTEMD_REQUIRED', True) else ''} \ + ${@'${libdir}/dracut/modules.d/98ostree/module-setup.sh' if d.getVar('SYSTEMD_REQUIRED', True) else ''} \ + ${datadir}/gir-1.0 \ + ${datadir}/gir-1.0/OSTree-1.0.gir \ + ${libdir}/girepository-1.0 \ + ${libdir}/girepository-1.0/OSTree-1.0.typelib \ + ${libdir}/tmpfiles.d/ostree-tmpfiles.conf \ + ${datadir}/bash-completion/completions/ostree \ + ${systemd_unitdir}/system-generators/ostree-system-generator \ +" + +PACKAGES =+ "${PN}-switchroot" + +FILES_${PN}-switchroot = "${libdir}/ostree/ostree-prepare-root" +RDEPENDS_${PN}-switchroot = "" +DEPENDS_remove_class-native = "systemd-native" + diff --git a/meta-sota/recipes-support/ca-certificates/ca-certificates_%.bbappend b/meta-sota/recipes-support/ca-certificates/ca-certificates_%.bbappend new file mode 100644 index 0000000..cc95a68 --- /dev/null +++ b/meta-sota/recipes-support/ca-certificates/ca-certificates_%.bbappend @@ -0,0 +1 @@ +SYSROOT_DIRS += "${sysconfdir}" diff --git a/meta-sota/recipes-support/fuse/fuse_%.bbappend b/meta-sota/recipes-support/fuse/fuse_%.bbappend new file mode 100644 index 0000000..85bdf50 --- /dev/null +++ b/meta-sota/recipes-support/fuse/fuse_%.bbappend @@ -0,0 +1,3 @@ +BBCLASSEXTEND_append_sota = " native" + +PACKAGES_append_class-native_sota = "${@bb.utils.contains('DISTRO_FEATURES', 'sota', ' fuse-utils-dbg-native fuse-utils-native libulockmgr-native libulockmgr-dev-native libulockmgr-dbg-native', ' ', d)}" diff --git a/meta-sota/recipes-support/gpgme/gpgme_%.bbappend b/meta-sota/recipes-support/gpgme/gpgme_%.bbappend new file mode 100644 index 0000000..fccb949 --- /dev/null +++ b/meta-sota/recipes-support/gpgme/gpgme_%.bbappend @@ -0,0 +1 @@ +BBCLASSEXTEND_append_sota = " native" diff --git a/meta-sota/recipes-support/libgsystem/libgsystem_git.bb b/meta-sota/recipes-support/libgsystem/libgsystem_git.bb new file mode 100644 index 0000000..e2b362f --- /dev/null +++ b/meta-sota/recipes-support/libgsystem/libgsystem_git.bb @@ -0,0 +1,40 @@ +SUMMARY = "GIO-based library, targeted primarily for use by operating system components" +LICENSE = "GPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=5f30f0716dfdd0d91eb439ebec522ec2" + +SRC_URI = "gitsm://github.com/GNOME/libgsystem.git" +SRCREV="d606bec68ddfea78de4b03c3f3568afb71bdc1ce" + +S = "${WORKDIR}/git" + +inherit autotools-brokensep gobject-introspection + +DEPENDS += "attr glib-2.0 pkgconfig libcap gtk-doc-native gpgme" +RDEPENDS_${PN} = "xz " +RDEPENDS_${PN}_append = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', ' systemd', '', d)}" + +RDEPENDS_${PN}_remove_class-native = "systemd-native" + +BBCLASSEXTEND = "native" + +export STAGING_INCDIR +export STAGING_LIBDIR + +do_configure() { + #NOCONFIGURE=true ./autogen.sh + autoreconf -vfi + oe_runconf +} + +do_compile_prepend() { + export BUILD_SYS="${BUILD_SYS}" + export HOST_SYS="${HOST_SYS}" +} + +FILES_${PN} += " \ + ${datadir} \ + ${datadir}/gir-1.0 \ + ${datadir}/gir-1.0/GSystem-1.0.gir \ + ${libdir}/girepository-1.0/ \ + ${libdir}/girepository-1.0/GSystem-1.0.typelib \ +" diff --git a/meta-sota/recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch b/meta-sota/recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch new file mode 100644 index 0000000..902352c --- /dev/null +++ b/meta-sota/recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch @@ -0,0 +1,42 @@ +From ccab5ce63dd5d3dbb4bd02998d21d34407e550f2 Mon Sep 17 00:00:00 2001 +From: Anton Gerasimov +Date: Fri, 19 Jan 2018 12:44:27 +0100 +Subject: [PATCH] Workaround for a buggy version of openssl (1.0.2m) + +--- + src/p11_pkey.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/p11_pkey.c b/src/p11_pkey.c +index 45d5ad3..75625e6 100644 +--- a/src/p11_pkey.c ++++ b/src/p11_pkey.c +@@ -139,8 +139,14 @@ static void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src) + + #endif + +-#if OPENSSL_VERSION_NUMBER < 0x100020d0L || defined(LIBRESSL_VERSION_NUMBER) +-static void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, ++#if OPENSSL_VERSION_NUMBER < 0x10002100L || defined(LIBRESSL_VERSION_NUMBER) ++ ++# if (OPENSSL_VERSION_NUMBER & 0xFFFFFFF0) == 0x100020d0L ++# undef EVP_PKEY_meth_get_sign ++# undef EVP_PKEY_meth_get_decrypt ++# endif ++ ++void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, + int (**psign_init) (EVP_PKEY_CTX *ctx), + int (**psign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, +@@ -152,7 +158,7 @@ static void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, + *psign = pmeth->sign; + } + +-static void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth, ++void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth, + int (**pdecrypt_init) (EVP_PKEY_CTX *ctx), + int (**pdecrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, +-- +2.15.1 + diff --git a/meta-sota/recipes-support/libp11/libp11_0.4.7.bb b/meta-sota/recipes-support/libp11/libp11_0.4.7.bb new file mode 100644 index 0000000..02d9e50 --- /dev/null +++ b/meta-sota/recipes-support/libp11/libp11_0.4.7.bb @@ -0,0 +1,39 @@ +SUMMARY = "Library for using PKCS" +DESCRIPTION = "\ +Libp11 is a library implementing a small layer on top of PKCS \ +make using PKCS" +HOMEPAGE = "http://www.opensc-project.org/libp11" +SECTION = "Development/Libraries" +LICENSE = "LGPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=fad9b3332be894bab9bc501572864b29" +DEPENDS = "libtool openssl" +RDEPENDS_${PN} += " opensc" + +SRC_URI = "git://github.com/OpenSC/libp11.git \ + file://0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch" +SRCREV = "da725ab727342083478150a203a3c80c4551feb4" + +S = "${WORKDIR}/git" + +inherit autotools pkgconfig + +# Currently, Makefile dependencies are incorrectly defined which causes build errors +# The number of jobs is high +# See https://github.com/OpenSC/libp11/issues/94 +PARALLEL_MAKE = "" +EXTRA_OECONF = "--disable-static" + +do_install_append () { + rm -rf ${D}${libdir}/*.la + rm -rf ${D}${docdir}/${BPN} +} + +FILES_${PN} = "${libdir}/engines/pkcs11.so \ + ${libdir}/engines/libpkcs11${SOLIBS} \ + ${libdir}/libp11${SOLIBS}" + +FILES_${PN}-dev = " \ + ${libdir}/engines/libpkcs11${SOLIBSDEV} \ + ${libdir}/libp11${SOLIBSDEV} \ + ${libdir}/pkgconfig/libp11.pc \ + /usr/include" diff --git a/meta-sota/recipes-support/libssh2/libssh2_%.bbappend b/meta-sota/recipes-support/libssh2/libssh2_%.bbappend new file mode 100644 index 0000000..bebaf84 --- /dev/null +++ b/meta-sota/recipes-support/libssh2/libssh2_%.bbappend @@ -0,0 +1,2 @@ +# meta-oe/recipes-support/libssh2 +BBCLASSEXTEND_append_sota = " native" diff --git a/meta-sota/recipes-support/lshw/files/cross-compile.patch b/meta-sota/recipes-support/lshw/files/cross-compile.patch new file mode 100644 index 0000000..221b7e5 --- /dev/null +++ b/meta-sota/recipes-support/lshw/files/cross-compile.patch @@ -0,0 +1,39 @@ +--- + src/Makefile | 2 +- + src/core/Makefile | 2 +- + src/gui/Makefile | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/src/Makefile ++++ b/src/Makefile +@@ -18,7 +18,7 @@ export MANDIR + export DATADIR + export SQLITE + +-CXX?=c++ ++CXX?=$(CROSS_COMPILE)c++ + INCLUDES=-I./core/ + DEFINES=-DPREFIX=\"$(PREFIX)\" -DSBINDIR=\"$(SBINDIR)\" -DMANDIR=\"$(MANDIR)\" -DDATADIR=\"$(DATADIR)\" + CXXFLAGS=-g -Wall -g $(INCLUDES) $(DEFINES) $(RPM_OPT_FLAGS) +--- a/src/core/Makefile ++++ b/src/core/Makefile +@@ -1,6 +1,6 @@ + PACKAGENAME?=lshw + +-CXX=c++ ++CXX?=$(CROSS_COMPILE)c++ + INCLUDES= + DEFINES=-DPREFIX=\"$(PREFIX)\" -DSBINDIR=\"$(SBINDIR)\" -DMANDIR=\"$(MANDIR)\" -DDATADIR=\"$(DATADIR)\" + CXXFLAGS?=-g -Wall $(INCLUDES) $(DEFINES) $(RPM_OPT_FLAGS) +--- a/src/gui/Makefile ++++ b/src/gui/Makefile +@@ -1,7 +1,7 @@ + PACKAGENAME?=lshw + +-CXX?=c++ +-CC?=cc ++CXX?=$(CROSS_COMPILE)c++ ++CC?=$(CROSS_COMPILE)cc + STRIP?=strip + OBJCOPY?=objcopy + diff --git a/meta-sota/recipes-support/lshw/files/ldflags.patch b/meta-sota/recipes-support/lshw/files/ldflags.patch new file mode 100644 index 0000000..83e0410 --- /dev/null +++ b/meta-sota/recipes-support/lshw/files/ldflags.patch @@ -0,0 +1,42 @@ +diff -Naur /home/anton/lshw-old/src/Makefile lshw-B.02.16/src/Makefile +--- /home/anton/lshw-old/src/Makefile 2017-02-07 16:21:52.554738182 +0100 ++++ lshw-B.02.16/src/Makefile 2017-02-07 16:22:45.578588072 +0100 +@@ -25,9 +25,9 @@ + ifeq ($(SQLITE), 1) + CXXFLAGS+= -DSQLITE $(shell pkg-config --cflags sqlite3) + endif +-LDFLAGS=-L./core/ -g ++LDEXTRAS=-L./core/ -g + ifneq ($(shell $(LD) --help 2| grep -- --as-needed), ) +- LDFLAGS+= -Wl,--as-needed ++ LDEXTRAS+= -Wl,--as-needed + endif + LDSTATIC=-static + LIBS=-llshw -lresolv +@@ -37,7 +37,7 @@ + + export CXXFLAGS + export LIBS +-export LDFLAGS ++export LDEXTRAS + + DATAFILES = pci.ids usb.ids oui.txt manuf.txt + +@@ -51,7 +51,7 @@ + +make -C core all + + $(PACKAGENAME): core $(PACKAGENAME).o +- $(CXX) $(LDFLAGS) -o $@ $(PACKAGENAME).o $(LIBS) ++ $(CXX) $(LDFLAGS) ${LDEXTRAS} -o $@ $(PACKAGENAME).o $(LIBS) + + .PHONY: po + po: +@@ -69,7 +69,7 @@ + static: $(PACKAGENAME)-static + + $(PACKAGENAME)-static: core core/lib$(PACKAGENAME).a $(PACKAGENAME).o +- $(CXX) $(LDSTATIC) $(LDFLAGS) -o $@ $(PACKAGENAME).o $(LIBS) ++ $(CXX) $(LDSTATIC) $(LDFLAGS) ${LDEXTRAS} -o $@ $(PACKAGENAME).o $(LIBS) + $(STRIP) $@ + + .PHONY: compressed diff --git a/meta-sota/recipes-support/lshw/lshw_02.16.bb b/meta-sota/recipes-support/lshw/lshw_02.16.bb new file mode 100644 index 0000000..99901ff --- /dev/null +++ b/meta-sota/recipes-support/lshw/lshw_02.16.bb @@ -0,0 +1,36 @@ +# From meta-linaro +# http://git.linaro.org/openembedded/meta-linaro.git + +DESCRIPTION = "A small tool to provide detailed information on the hardware \ +configuration of the machine. It can report exact memory configuration, \ +firmware version, mainboard configuration, CPU version and speed, cache \ +configuration, bus speed, etc. on DMI-capable or EFI systems." +SUMMARY = "Hardware lister" +HOMEPAGE = "http://ezix.org/project/wiki/HardwareLiSter" +SECTION = "console/tools" +LICENSE = "GPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f" +DEPENDS = "pciutils \ + usbutils" +COMPATIBLE_HOST = "(i.86|x86_64|arm|aarch64).*-linux" + +SRC_URI="http://ezix.org/software/files/lshw-B.${PV}.tar.gz \ + file://cross-compile.patch \ + file://ldflags.patch \ + " + +SRC_URI[md5sum] = "67479167add605e8f001097c30e96d0d" +SRC_URI[sha256sum] = "809882429555b93259785cc261dbff04c16c93d064db5f445a51945bc47157cb" + +S="${WORKDIR}/lshw-B.${PV}" + +do_compile() { + # build core only - don't ship gui + oe_runmake -C src core +} + +do_install() { + oe_runmake install DESTDIR=${D} + # data files provided by dependencies + rm -rf ${D}/usr/share/lshw +} diff --git a/meta-sota/recipes-support/python-canonicaljson/python-canonicaljson.bb b/meta-sota/recipes-support/python-canonicaljson/python-canonicaljson.bb new file mode 100644 index 0000000..d8a0728 --- /dev/null +++ b/meta-sota/recipes-support/python-canonicaljson/python-canonicaljson.bb @@ -0,0 +1,18 @@ +DESCRIPTION = "python-canonicaljson recipe" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=2ee41112a44fe7014dce33e26468ba93" + +SRCREV = "92e2c06871cc275c2a8b8e3e899141a212aae0e8" +SRC_URI = "git://github.com/matrix-org/python-canonicaljson.git" +S = "${WORKDIR}/git" + +# Generate with: +# git describe --tags | cut -b2- +PV = "1.0.0" +inherit setuptools + +RDEPENDS_${PN} = "\ + python-simplejson \ + python-frozendict \ + " diff --git a/meta-sota/recipes-support/python-frozendict/python-frozendict.bb b/meta-sota/recipes-support/python-frozendict/python-frozendict.bb new file mode 100644 index 0000000..79fe5c8 --- /dev/null +++ b/meta-sota/recipes-support/python-frozendict/python-frozendict.bb @@ -0,0 +1,12 @@ +DESCRIPTION = "python-frozendict recipe" + +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://${S}/LICENSE.txt;md5=f4da037a49c09b456fdbbc7a5bd36132" + +SRCREV = "c5d16bafcca7b72ff3e8f40d3a9081e4c9233f1b" +SRC_URI = "git://github.com/slezica/python-frozendict.git" +S = "${WORKDIR}/git" + +PV = "1.2" +inherit setuptools + diff --git a/meta-sota/recipes-support/python-petname/python-petname.bb b/meta-sota/recipes-support/python-petname/python-petname.bb new file mode 100644 index 0000000..9abd5d9 --- /dev/null +++ b/meta-sota/recipes-support/python-petname/python-petname.bb @@ -0,0 +1,16 @@ +DESCRIPTION = "python-petname recipe" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" + +SRCREV = "d0b767cdb1567defb104f29c3fd022239a7f231e" +SRC_URI = "git://github.com/dustinkirkland/python-petname.git" +S = "${WORKDIR}/git" + +PV = "2.2" +inherit setuptools +RDEPENDS_${PN} = " python-setuptools \ + python-argparse \ + " + +FILES_${PN} = "${libdir} ${bindir}/petname" diff --git a/meta-sota/recipes-support/sc-hsm-embedded/files/0001-Cross-compilation-tweaks.patch b/meta-sota/recipes-support/sc-hsm-embedded/files/0001-Cross-compilation-tweaks.patch new file mode 100644 index 0000000..b3a7622 --- /dev/null +++ b/meta-sota/recipes-support/sc-hsm-embedded/files/0001-Cross-compilation-tweaks.patch @@ -0,0 +1,86 @@ +From b6add28acb884b6006216e8422cc18504483c72e Mon Sep 17 00:00:00 2001 +From: Anton Gerasimov +Date: Fri, 8 Sep 2017 15:08:40 +0200 +Subject: [PATCH] Cross-compilation tweaks + +--- + m4/acx_openssl.m4 | 2 ++ + m4/acx_openssl_ecc.m4 | 3 +++ + m4/acx_openssl_fips.m4 | 2 ++ + m4/acx_openssl_gost.m4 | 2 ++ + 4 files changed, 9 insertions(+) + +diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 +index e90c78f..9de6055 100644 +--- a/m4/acx_openssl.m4 ++++ b/m4/acx_openssl.m4 +@@ -25,6 +25,7 @@ AC_DEFUN([ACX_OPENSSL],[ + AC_CHECK_HEADERS([openssl/ssl.h],,[AC_MSG_ERROR([Can't find OpenSSL headers])]) + AC_CHECK_LIB(crypto, BN_new,,[AC_MSG_ERROR([Can't find OpenSSL library])]) + ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING([for OpenSSL version]) + CHECK_OPENSSL_VERSION=m4_format(0x%02x%02x%02x000L, $1, $2, $3) + AC_LANG_PUSH([C]) +@@ -51,6 +52,7 @@ AC_DEFUN([ACX_OPENSSL],[ + AC_MSG_ERROR([OpenSSL library too old ($1.$2.$3 or later required)]) + ],[]) + AC_LANG_POP([C]) ++ fi + + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS +diff --git a/m4/acx_openssl_ecc.m4 b/m4/acx_openssl_ecc.m4 +index 612c505..ba2389d 100644 +--- a/m4/acx_openssl_ecc.m4 ++++ b/m4/acx_openssl_ecc.m4 +@@ -1,4 +1,5 @@ + AC_DEFUN([ACX_OPENSSL_ECC],[ ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING(for OpenSSL ECC support) + + tmp_CPPFLAGS=$CPPFLAGS +@@ -32,6 +33,8 @@ AC_DEFUN([ACX_OPENSSL_ECC],[ + ],[]) + AC_LANG_POP([C]) + ++ fi ++ + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS + ]) +diff --git a/m4/acx_openssl_fips.m4 b/m4/acx_openssl_fips.m4 +index 0491397..896cdbf 100644 +--- a/m4/acx_openssl_fips.m4 ++++ b/m4/acx_openssl_fips.m4 +@@ -1,4 +1,5 @@ + AC_DEFUN([ACX_OPENSSL_FIPS],[ ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING(for OpenSSL FIPS capable library) + + tmp_CPPFLAGS=$CPPFLAGS +@@ -47,4 +48,5 @@ AC_DEFUN([ACX_OPENSSL_FIPS],[ + + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS ++ fi + ]) +diff --git a/m4/acx_openssl_gost.m4 b/m4/acx_openssl_gost.m4 +index dca489b..34c39d8 100644 +--- a/m4/acx_openssl_gost.m4 ++++ b/m4/acx_openssl_gost.m4 +@@ -1,4 +1,5 @@ + AC_DEFUN([ACX_OPENSSL_GOST],[ ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING(for OpenSSL GOST support) + + tmp_CPPFLAGS=$CPPFLAGS +@@ -62,4 +63,5 @@ AC_DEFUN([ACX_OPENSSL_GOST],[ + + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS ++ fi + ]) +-- +2.7.4 + diff --git a/meta-sota/recipes-support/sc-hsm-embedded/sc-hsm-embedded_git.bb b/meta-sota/recipes-support/sc-hsm-embedded/sc-hsm-embedded_git.bb new file mode 100644 index 0000000..062d514 --- /dev/null +++ b/meta-sota/recipes-support/sc-hsm-embedded/sc-hsm-embedded_git.bb @@ -0,0 +1,22 @@ +SUMMARY = "Smartcard HSM driver" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://COPYING;md5=55b854a477953696452f698a3af5de1c" + +inherit autotools-brokensep + + +SRC_URI = "git://github.com/CardContact/sc-hsm-embedded.git;branch=master" +SRCREV="a45155d4249575ebdfb16ff26fdedbc4c4813002" + +S = "${WORKDIR}/git" + +DEPENDS += " openssl pcsc-lite" + +do_configure() { + autoreconf -fi + oe_runconf +} + +FILES_${PN} += "${libdir}" +FILES_SOLIBSDEV = "" + diff --git a/meta-sota/recipes-support/slcand-start/files/slcand@.service b/meta-sota/recipes-support/slcand-start/files/slcand@.service new file mode 100644 index 0000000..c539568 --- /dev/null +++ b/meta-sota/recipes-support/slcand-start/files/slcand@.service @@ -0,0 +1,8 @@ +[Unit] +Description=Serial CAN daemon (can-utils) + +[Service] +Type=forking +ExecStart=/usr/bin/slcand -o -c -s4 %I can0 +ExecStartPost=/bin/sh -c '/bin/sleep 3; /sbin/ip link set can0 up' + diff --git a/meta-sota/recipes-support/slcand-start/slcand-start.bb b/meta-sota/recipes-support/slcand-start/slcand-start.bb new file mode 100644 index 0000000..dfefaea --- /dev/null +++ b/meta-sota/recipes-support/slcand-start/slcand-start.bb @@ -0,0 +1,21 @@ +SUMMARY = "Mock smartcard for aktualizr" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \ + file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" + + +inherit systemd + +RDEPENDS_${PN} = "can-utils" + +SRC_URI = "file://slcand@.service" + +SYSTEMD_SERVICE_${PN} = "slcand@.service" + +do_install() { + install -d ${D}${systemd_unitdir}/system + install -m 0644 ${WORKDIR}/slcand@.service ${D}${systemd_unitdir}/system/slcand@.service +} + +FILES_${PN} = "${systemd_unitdir}/system/createtoken.service" + diff --git a/meta-sota/recipes-support/softhsm-testtoken/files/createtoken.service b/meta-sota/recipes-support/softhsm-testtoken/files/createtoken.service new file mode 100644 index 0000000..23317b9 --- /dev/null +++ b/meta-sota/recipes-support/softhsm-testtoken/files/createtoken.service @@ -0,0 +1,12 @@ +[Unit] +Description=Create a mock smartcard for testing +Before=aktualizr.service +RequiredBy=aktualizr.service + +[Service] +RestartSec=10 +Restart=on-failure +ExecStart=/usr/bin/createtoken.sh + +[Install] +WantedBy=aktualizr.service diff --git a/meta-sota/recipes-support/softhsm-testtoken/files/createtoken.sh b/meta-sota/recipes-support/softhsm-testtoken/files/createtoken.sh new file mode 100644 index 0000000..b01db47 --- /dev/null +++ b/meta-sota/recipes-support/softhsm-testtoken/files/createtoken.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +if pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so -O; then + # The token has already been initialized, exit + exit 0 +fi + +if ! ls /var/sota/token/pkey.pem /var/sota/token/client.pem /var/sota/token/pkey.pem; then + # Key/certificate pair is not present, repeat + exit 1 +fi + +mkdir -p /var/lib/softhsm/tokens +softhsm2-util --init-token --slot 0 --label "Virtual token" --pin 1234 --so-pin 1234 + +softhsm2-util --import /var/sota/token/pkey.pem --label "pkey" --id 02 --token 'Virtual token' --pin 1234 +openssl x509 -outform der -in /var/sota/token/client.pem -out /var/sota/token/client.der +pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so --id 1 --write-object /var/sota/token/client.der --type cert --login --pin 1234 + +# Import UPTANE keypair if it exists +if [ -f /var/sota/token/ecukey.pem ]; then + openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in /var/sota/token/ecukey.pem -out /var/sota/token/ecukey.p8 + softhsm2-util --import /var/sota/token/ecukey.p8 --label "uptanekey" --id 03 --token 'Virtual token' --pin 1234 +fi + +exit 0 diff --git a/meta-sota/recipes-support/softhsm-testtoken/softhsm-testtoken.bb b/meta-sota/recipes-support/softhsm-testtoken/softhsm-testtoken.bb new file mode 100644 index 0000000..c5691db --- /dev/null +++ b/meta-sota/recipes-support/softhsm-testtoken/softhsm-testtoken.bb @@ -0,0 +1,27 @@ +SUMMARY = "Mock smartcard for aktualizr" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \ + file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" + + +inherit systemd + +RDEPENDS_${PN} = "softhsm libp11" +DEPENDS_append = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', ' systemd', '', d)}" + + +SRC_URI = "file://createtoken.service \ + file://createtoken.sh" + +SYSTEMD_SERVICE_${PN} = "createtoken.service" + +do_install() { + install -d ${D}${systemd_unitdir}/system + install -m 0644 ${WORKDIR}/createtoken.service ${D}${systemd_unitdir}/system/createtoken.service + install -d ${D}${bindir} + install -m 0744 ${WORKDIR}/createtoken.sh ${D}${bindir}/createtoken.sh +} + +FILES_${PN} = "${bindir}/createtoken.sh \ + ${systemd_unitdir}/system/createtoken.service" + diff --git a/meta-sota/recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch b/meta-sota/recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch new file mode 100644 index 0000000..b3a7622 --- /dev/null +++ b/meta-sota/recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch @@ -0,0 +1,86 @@ +From b6add28acb884b6006216e8422cc18504483c72e Mon Sep 17 00:00:00 2001 +From: Anton Gerasimov +Date: Fri, 8 Sep 2017 15:08:40 +0200 +Subject: [PATCH] Cross-compilation tweaks + +--- + m4/acx_openssl.m4 | 2 ++ + m4/acx_openssl_ecc.m4 | 3 +++ + m4/acx_openssl_fips.m4 | 2 ++ + m4/acx_openssl_gost.m4 | 2 ++ + 4 files changed, 9 insertions(+) + +diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 +index e90c78f..9de6055 100644 +--- a/m4/acx_openssl.m4 ++++ b/m4/acx_openssl.m4 +@@ -25,6 +25,7 @@ AC_DEFUN([ACX_OPENSSL],[ + AC_CHECK_HEADERS([openssl/ssl.h],,[AC_MSG_ERROR([Can't find OpenSSL headers])]) + AC_CHECK_LIB(crypto, BN_new,,[AC_MSG_ERROR([Can't find OpenSSL library])]) + ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING([for OpenSSL version]) + CHECK_OPENSSL_VERSION=m4_format(0x%02x%02x%02x000L, $1, $2, $3) + AC_LANG_PUSH([C]) +@@ -51,6 +52,7 @@ AC_DEFUN([ACX_OPENSSL],[ + AC_MSG_ERROR([OpenSSL library too old ($1.$2.$3 or later required)]) + ],[]) + AC_LANG_POP([C]) ++ fi + + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS +diff --git a/m4/acx_openssl_ecc.m4 b/m4/acx_openssl_ecc.m4 +index 612c505..ba2389d 100644 +--- a/m4/acx_openssl_ecc.m4 ++++ b/m4/acx_openssl_ecc.m4 +@@ -1,4 +1,5 @@ + AC_DEFUN([ACX_OPENSSL_ECC],[ ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING(for OpenSSL ECC support) + + tmp_CPPFLAGS=$CPPFLAGS +@@ -32,6 +33,8 @@ AC_DEFUN([ACX_OPENSSL_ECC],[ + ],[]) + AC_LANG_POP([C]) + ++ fi ++ + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS + ]) +diff --git a/m4/acx_openssl_fips.m4 b/m4/acx_openssl_fips.m4 +index 0491397..896cdbf 100644 +--- a/m4/acx_openssl_fips.m4 ++++ b/m4/acx_openssl_fips.m4 +@@ -1,4 +1,5 @@ + AC_DEFUN([ACX_OPENSSL_FIPS],[ ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING(for OpenSSL FIPS capable library) + + tmp_CPPFLAGS=$CPPFLAGS +@@ -47,4 +48,5 @@ AC_DEFUN([ACX_OPENSSL_FIPS],[ + + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS ++ fi + ]) +diff --git a/m4/acx_openssl_gost.m4 b/m4/acx_openssl_gost.m4 +index dca489b..34c39d8 100644 +--- a/m4/acx_openssl_gost.m4 ++++ b/m4/acx_openssl_gost.m4 +@@ -1,4 +1,5 @@ + AC_DEFUN([ACX_OPENSSL_GOST],[ ++ if test "$cross_compiling" != yes; then + AC_MSG_CHECKING(for OpenSSL GOST support) + + tmp_CPPFLAGS=$CPPFLAGS +@@ -62,4 +63,5 @@ AC_DEFUN([ACX_OPENSSL_GOST],[ + + CPPFLAGS=$tmp_CPPFLAGS + LIBS=$tmp_LIBS ++ fi + ]) +-- +2.7.4 + diff --git a/meta-sota/recipes-support/softhsm/softhsm_git.bb b/meta-sota/recipes-support/softhsm/softhsm_git.bb new file mode 100644 index 0000000..c26903d --- /dev/null +++ b/meta-sota/recipes-support/softhsm/softhsm_git.bb @@ -0,0 +1,27 @@ +SUMMARY = "HSM emulator" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://LICENSE;md5=ef3f77a3507c3d91e75b9f2bdaee4210" + +inherit autotools-brokensep + + +SRC_URI = "git://github.com/opendnssec/SoftHSMv2.git;branch=master \ + file://0001-Cross-compilation-tweaks.patch" +SRCREV="1f7498c0c65b1b1ad5e1bdbd87e9d4b100705745" + +S = "${WORKDIR}/git" + +DEPENDS += " openssl" + +EXTRA_OECONF = "--disable-gost --with-openssl=${STAGING_LIBDIR}/.." + +do_configure() { + unset docdir + sh ./autogen.sh + oe_runconf +} + +FILES_${PN} = "${bindir} \ + ${libdir}/softhsm \ + ${sysconfdir} \ + ${localstatedir}/lib/softhsm " diff --git a/meta-sota/recipes-test/big-update/big-update_1.0.bb b/meta-sota/recipes-test/big-update/big-update_1.0.bb new file mode 100644 index 0000000..68b9746 --- /dev/null +++ b/meta-sota/recipes-test/big-update/big-update_1.0.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "Example Package with 10MB of random, seeded content" +LICENSE = "CLOSED" + +SRC_URI = "file://rand_file.py" + +FILES_${PN} = "/usr/lib/big-update" + +DEPENDS = "coreutils-native" + +do_install() { + install -d ${D}/usr/lib/big-update + python ${S}/../rand_file.py ${D}/usr/lib/big-update/a-big-file $(numfmt --from=iec 10M) +} diff --git a/meta-sota/recipes-test/big-update/big-update_2.0.bb b/meta-sota/recipes-test/big-update/big-update_2.0.bb new file mode 100644 index 0000000..20c8138 --- /dev/null +++ b/meta-sota/recipes-test/big-update/big-update_2.0.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "Example Package with 12MB of random, seeded content" +LICENSE = "CLOSED" + +SRC_URI = "file://rand_file.py" + +FILES_${PN} = "/usr/lib/big-update" + +DEPENDS = "coreutils-native" + +do_install() { + install -d ${D}/usr/lib/big-update + python ${S}/../rand_file.py ${D}/usr/lib/big-update/a-big-file $(numfmt --from=iec 12M) +} diff --git a/meta-sota/recipes-test/big-update/files/rand_file.py b/meta-sota/recipes-test/big-update/files/rand_file.py new file mode 100644 index 0000000..0f4f16e --- /dev/null +++ b/meta-sota/recipes-test/big-update/files/rand_file.py @@ -0,0 +1,16 @@ +import sys +from random import seed, randint + +def main(): + n = int(sys.argv[2]) + ba = bytearray(n) + + seed(42) + for i in range(0, n): + ba[i] = randint(0, 255) + + with open(sys.argv[1], 'wb') as f: + f.write(bytes(ba)) + +if __name__ == "__main__": + main() diff --git a/meta-sota/recipes-test/demo-network-config/files/25-dhcp-server.network b/meta-sota/recipes-test/demo-network-config/files/25-dhcp-server.network new file mode 100644 index 0000000..4766f9a --- /dev/null +++ b/meta-sota/recipes-test/demo-network-config/files/25-dhcp-server.network @@ -0,0 +1,12 @@ +[Match] +Name=enp0s4 + +[Network] +Description=Private internal network between aktualizr Primary and Secondary nodes +DHCPServer=yes +Address=10.0.3.1/24 +IPForward=yes +IPMasquerade=yes + +[DHCPServer] +PoolOffset=10 \ No newline at end of file diff --git a/meta-sota/recipes-test/demo-network-config/files/26-dhcp-client.network b/meta-sota/recipes-test/demo-network-config/files/26-dhcp-client.network new file mode 100644 index 0000000..319664f --- /dev/null +++ b/meta-sota/recipes-test/demo-network-config/files/26-dhcp-client.network @@ -0,0 +1,6 @@ +[Match] +Name=enp0s4 + +[Network] +Description=Private internal network between aktualizr Primary and Secondary nodes +DHCP=yes diff --git a/meta-sota/recipes-test/demo-network-config/files/27-dhcp-client-external.network b/meta-sota/recipes-test/demo-network-config/files/27-dhcp-client-external.network new file mode 100644 index 0000000..ba49593 --- /dev/null +++ b/meta-sota/recipes-test/demo-network-config/files/27-dhcp-client-external.network @@ -0,0 +1,6 @@ +[Match] +Name=enp0s3 + +[Network] +Description=External network for secondary +DHCP=yes diff --git a/meta-sota/recipes-test/demo-network-config/primary-network-config.bb b/meta-sota/recipes-test/demo-network-config/primary-network-config.bb new file mode 100644 index 0000000..78678a2 --- /dev/null +++ b/meta-sota/recipes-test/demo-network-config/primary-network-config.bb @@ -0,0 +1,16 @@ +DESCRIPTION = "Sample network configuration for an Uptane Primary" +LICENSE = "CLOSED" + +inherit allarch + +SRC_URI = "file://25-dhcp-server.network" + + +FILES_${PN} = "/usr/lib/systemd/network" + +PR = "1" + +do_install() { + install -d ${D}/usr/lib/systemd/network + install -m 0644 ${WORKDIR}/25-dhcp-server.network ${D}/usr/lib/systemd/network/ +} diff --git a/meta-sota/recipes-test/demo-network-config/secondary-network-config.bb b/meta-sota/recipes-test/demo-network-config/secondary-network-config.bb new file mode 100644 index 0000000..9091c65 --- /dev/null +++ b/meta-sota/recipes-test/demo-network-config/secondary-network-config.bb @@ -0,0 +1,20 @@ +DESCRIPTION = "Sample network configuration for an Uptane Secondary" +LICENSE = "CLOSED" + +inherit allarch + +SRC_URI = "\ + file://26-dhcp-client.network \ + file://27-dhcp-client-external.network \ + " + + +FILES_${PN} = "/usr/lib/systemd/network" + +PR = "1" + +do_install() { + install -d ${D}/usr/lib/systemd/network + install -m 0644 ${WORKDIR}/26-dhcp-client.network ${D}/usr/lib/systemd/network/ + install -m 0644 ${WORKDIR}/27-dhcp-client-external.network ${D}/usr/lib/systemd/network/ +} diff --git a/meta-sota/recipes-test/images/primary-image.bb b/meta-sota/recipes-test/images/primary-image.bb new file mode 100644 index 0000000..6d2df94 --- /dev/null +++ b/meta-sota/recipes-test/images/primary-image.bb @@ -0,0 +1,14 @@ +include recipes-core/images/core-image-minimal.bb + +SUMMARY = "A minimal Uptane Primary image running aktualizr, for testing with a Linux secondary" + +LICENSE = "MIT" + +IMAGE_INSTALL_remove = " \ + " + +IMAGE_INSTALL_append = " \ + primary-network-config \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/meta-sota/recipes-test/images/secondary-image.bb b/meta-sota/recipes-test/images/secondary-image.bb new file mode 100644 index 0000000..9adbdc5 --- /dev/null +++ b/meta-sota/recipes-test/images/secondary-image.bb @@ -0,0 +1,25 @@ +include recipes-core/images/core-image-minimal.bb + +SUMMARY = "A minimal Uptane Secondary image running aktualizr-secondary" + +LICENSE = "MIT" + + +# Remove default aktualizr primary, and the provisioning configuration (which +# RDEPENDS on aktualizr) +IMAGE_INSTALL_remove = " \ + aktualizr \ + aktualizr-auto-prov \ + aktualizr-ca-implicit-prov \ + aktualizr-hsm-prov \ + aktualizr-implicit-prov \ + connman \ + connman-client \ + " + +IMAGE_INSTALL_append = " \ + aktualizr-secondary \ + secondary-network-config \ + " + +# vim:set ts=4 sw=4 sts=4 expandtab: -- cgit v1.2.3-54-g00ecf