All of lore.kernel.org
 help / color / mirror / Atom feed
* [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update
@ 2020-06-25 13:21 Quirin Gylstorff
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard Quirin Gylstorff
                   ` (5 more replies)
  0 siblings, 6 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-25 13:21 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 5496 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

This patchset adds efibootguard, swupdate to allow A/B updates in
cip-core. The update mechanism is currently only implemented for x86_64.


Quirin Gylstorff (4):
  recipes-bsp: Add efibootguard
  patches: add libubootenv
  recipes-core: add swupdate
  wic: Add wks files for A/B Partition update

 classes/kconfig-snippets.bbclass              |  90 ++++
 classes/swupdate-config.bbclass               |  76 +++
 classes/swupdate-img.bbclass                  |  75 +++
 .../0001-u-boot-add-libubootenv.patch         | 169 +++++++
 kas/cip.yml                                   |   4 +
 kas/opt/ebg-swu.yml                           |  26 +
 .../efibootguard/efibootguard_0.6-git+isar.bb |  46 ++
 recipes-bsp/efibootguard/files/debian/compat  |   1 +
 .../efibootguard/files/debian/control.tmpl    |  20 +
 .../files/debian/efibootguard-dev.install     |   3 +
 .../files/debian/efibootguard.install         |   2 +
 recipes-bsp/efibootguard/files/debian/rules   |  21 +
 .../swupdate/files/debian/changelog.tmpl      |   6 +
 recipes-core/swupdate/files/debian/compat     |   1 +
 .../swupdate/files/debian/control.tmpl        |  15 +
 recipes-core/swupdate/files/debian/copyright  |  36 ++
 recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
 .../swupdate/files/debian/swupdate.examples   |   2 +
 .../swupdate/files/debian/swupdate.install    |   2 +
 .../swupdate/files/debian/swupdate.manpages   |   5 +
 .../swupdate/files/debian/swupdate.tmpfile    |   2 +
 recipes-core/swupdate/files/debian/watch      |  12 +
 recipes-core/swupdate/files/postinst          |   2 +
 recipes-core/swupdate/files/swupdate.cfg      |   6 +
 .../swupdate/files/swupdate.service.example   |  11 +
 .../swupdate/files/swupdate.socket.example    |  11 +
 .../swupdate/files/swupdate.socket.tmpl       |  13 +
 .../swupdate/files/swupdate_defconfig         |  83 ++++
 .../swupdate_defconfig_efibootguard.snippet   |   3 +
 .../files/swupdate_defconfig_lua.snippet      |   2 +
 .../swupdate_defconfig_luahandler.snippet     |   4 +
 .../files/swupdate_defconfig_mtd.snippet      |   1 +
 .../files/swupdate_defconfig_u-boot.snippet   |   3 +
 .../files/swupdate_defconfig_ubi.snippet      |   6 +
 .../swupdate/files/swupdate_handlers.lua      | 449 ++++++++++++++++++
 recipes-core/swupdate/swupdate.bb             |  54 +++
 .../wic/plugins/source/efibootguard-boot.py   | 162 +++++++
 .../wic/plugins/source/efibootguard-efi.py    | 102 ++++
 wic/ebg-sysparts.inc                          |   8 +
 wic/qemu-amd64-efibootguard.wks               |   5 +
 wic/simatic-ipc227e-efibootguard.wks          |   5 +
 wic/swupdate-partition.inc                    |   4 +
 42 files changed, 1578 insertions(+)
 create mode 100644 classes/kconfig-snippets.bbclass
 create mode 100644 classes/swupdate-config.bbclass
 create mode 100644 classes/swupdate-img.bbclass
 create mode 100644 isar-patches/0001-u-boot-add-libubootenv.patch
 create mode 100644 kas/opt/ebg-swu.yml
 create mode 100644 recipes-bsp/efibootguard/efibootguard_0.6-git+isar.bb
 create mode 100644 recipes-bsp/efibootguard/files/debian/compat
 create mode 100644 recipes-bsp/efibootguard/files/debian/control.tmpl
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard.install
 create mode 100755 recipes-bsp/efibootguard/files/debian/rules
 create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/compat
 create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/copyright
 create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
 create mode 100644 recipes-core/swupdate/files/debian/watch
 create mode 100644 recipes-core/swupdate/files/postinst
 create mode 100644 recipes-core/swupdate/files/swupdate.cfg
 create mode 100644 recipes-core/swupdate/files/swupdate.service.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
 create mode 100644 recipes-core/swupdate/swupdate.bb
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-boot.py
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-efi.py
 create mode 100644 wic/ebg-sysparts.inc
 create mode 100644 wic/qemu-amd64-efibootguard.wks
 create mode 100644 wic/simatic-ipc227e-efibootguard.wks
 create mode 100644 wic/swupdate-partition.inc

-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4816): https://lists.cip-project.org/g/cip-dev/message/4816
Mute This Topic: https://lists.cip-project.org/mt/75102472/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard
  2020-06-25 13:21 [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update Quirin Gylstorff
@ 2020-06-25 13:21 ` Quirin Gylstorff
  2020-06-26 13:37   ` Jan Kiszka
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 2/4] patches: add libubootenv Quirin Gylstorff
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-25 13:21 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 15742 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add the bootloader efibootguard for A/B partition update
on x86 with EFI.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 .../efibootguard/efibootguard_0.6-git+isar.bb |  46 +++++
 recipes-bsp/efibootguard/files/debian/compat  |   1 +
 .../efibootguard/files/debian/control.tmpl    |  20 +++
 .../files/debian/efibootguard-dev.install     |   3 +
 .../files/debian/efibootguard.install         |   2 +
 recipes-bsp/efibootguard/files/debian/rules   |  21 +++
 .../wic/plugins/source/efibootguard-boot.py   | 162 ++++++++++++++++++
 .../wic/plugins/source/efibootguard-efi.py    | 102 +++++++++++
 8 files changed, 357 insertions(+)
 create mode 100644 recipes-bsp/efibootguard/efibootguard_0.6-git+isar.bb
 create mode 100644 recipes-bsp/efibootguard/files/debian/compat
 create mode 100644 recipes-bsp/efibootguard/files/debian/control.tmpl
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard.install
 create mode 100755 recipes-bsp/efibootguard/files/debian/rules
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-boot.py
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-efi.py

diff --git a/recipes-bsp/efibootguard/efibootguard_0.6-git+isar.bb b/recipes-bsp/efibootguard/efibootguard_0.6-git+isar.bb
new file mode 100644
index 0000000..bf8b50d
--- /dev/null
+++ b/recipes-bsp/efibootguard/efibootguard_0.6-git+isar.bb
@@ -0,0 +1,46 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+DESCRIPTION = "efibootguard boot loader"
+DESCRIPTION_DEV = "efibootguard development library"
+HOMEPAGE = "https://github.com/siemens/efibootguard"
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
+MAINTAINER = "Jan Kiszka <jan.kiszka@siemens.com>"
+
+SRC_URI = "git://github.com/siemens/efibootguard.git;branch=master;protocol=https \
+           file://debian \
+          "
+
+S = "${WORKDIR}/git"
+
+SRCREV = "85cae10c9411c52208947d63a2287cfd6e81068a"
+
+PROVIDES = "${PN}"
+PROVIDES += "${PN}-dev"
+
+BUILD_DEB_DEPENDS = "gnu-efi,libpci-dev,check,pkg-config,libc6-dev-i386"
+
+inherit dpkg
+
+TEMPLATE_FILES = "debian/control.tmpl"
+TEMPLATE_VARS += "DESCRIPTION_DEV BUILD_DEB_DEPENDS"
+
+do_prepare_build() {
+    cp -R ${WORKDIR}/debian ${S}
+    deb_add_changelog
+}
+
+dpkg_runbuild_append() {
+    install -m 0755 -d ${DEPLOY_DIR_IMAGE}
+    install -m 0755 ${S}/efibootguardx64.efi ${DEPLOY_DIR_IMAGE}/bootx64.efi
+    install -m 0755 ${S}/bg_setenv ${DEPLOY_DIR_IMAGE}/bg_setenv
+}
diff --git a/recipes-bsp/efibootguard/files/debian/compat b/recipes-bsp/efibootguard/files/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/recipes-bsp/efibootguard/files/debian/control.tmpl b/recipes-bsp/efibootguard/files/debian/control.tmpl
new file mode 100644
index 0000000..54b1994
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/control.tmpl
@@ -0,0 +1,20 @@
+Source: ${PN}
+Section: base
+Priority: optional
+Standards-Version: 3.9.6
+Build-Depends: ${BUILD_DEB_DEPENDS}
+Homepage: ${HOMEPAGE}
+Maintainer: ${MAINTAINER}
+
+Package: ${PN}
+Depends: ${shlibs:Depends}
+Section: base
+Architecture: ${DISTRO_ARCH}
+Priority: required
+Description: ${DESCRIPTION}
+
+Package: ${PN}-dev
+Section: base
+Architecture: ${DISTRO_ARCH}
+Priority: optional
+Description: ${DESCRIPTION_DEV}
diff --git a/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install b/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
new file mode 100644
index 0000000..7b45bd8
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
@@ -0,0 +1,3 @@
+include/ebgenv.h usr/include/efibootguard
+libebgenv.a usr/lib/x86_64-linux-gnu
+
diff --git a/recipes-bsp/efibootguard/files/debian/efibootguard.install b/recipes-bsp/efibootguard/files/debian/efibootguard.install
new file mode 100644
index 0000000..8a8d9d3
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/efibootguard.install
@@ -0,0 +1,2 @@
+bg_setenv usr/bin
+bg_printenv usr/bin
diff --git a/recipes-bsp/efibootguard/files/debian/rules b/recipes-bsp/efibootguard/files/debian/rules
new file mode 100755
index 0000000..82e9e0e
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/rules
@@ -0,0 +1,21 @@
+#!/usr/bin/make -f
+export DH_VERBOSE=1
+export DEB_BUILD_OPTIONS=hardening=-stackprotector
+export DPKG_EXPORT_BUILDFLAGS=1
+include /usr/share/dpkg/default.mk
+
+override_dh_auto_test:
+	# we do not run the tests; that avoids having to pull the fff submodule
+
+override_dh_auto_install:
+	# install using Debian's .install files rather than
+	# make install in order to have a proper package split.
+
+override_dh_installchangelogs:
+	# we're not interested in changelogs
+
+override_dh_installdocs:
+	# we're not interested in docs
+
+%:
+	dh $@ --with autoreconf
diff --git a/scripts/lib/wic/plugins/source/efibootguard-boot.py b/scripts/lib/wic/plugins/source/efibootguard-boot.py
new file mode 100644
index 0000000..38d2b2e
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/efibootguard-boot.py
@@ -0,0 +1,162 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Copyright (c) 2014, Intel Corporation.
+# Copyright (c) 2018, Siemens AG.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# DESCRIPTION
+# This implements the 'efibootguard-boot' source plugin class for 'wic'
+#
+# AUTHORS
+# Tom Zanussi <tom.zanussi (at] linux.intel.com>
+# Claudius Heine <ch (at] denx.de>
+# Andreas Reichel <andreas.reichel.ext (at] siemens.com>
+# Christian Storm <christian.storm (at] siemens.com>
+
+import os
+import fnmatch
+import sys
+import logging
+
+msger = logging.getLogger('wic')
+
+from wic.pluginbase import SourcePlugin
+from wic.utils.misc import exec_cmd, get_bitbake_var, BOOTDD_EXTRA_SPACE
+
+class EfibootguardBootPlugin(SourcePlugin):
+    """
+    Create EFI Boot Guard partition hosting the
+    environment file plus Kernel files.
+    """
+
+    name = 'efibootguard-boot'
+
+    @classmethod
+    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
+                             oe_builddir, deploy_dir, kernel_dir,
+                             rootfs_dir, native_sysroot):
+        """
+        Called to do the actual content population for a partition, i.e.,
+        populate an EFI Boot Guard environment partition plus Kernel files.
+        """
+
+        kernel_image = get_bitbake_var("KERNEL_IMAGE")
+        if not kernel_image:
+            msger.warning("KERNEL_IMAGE not set. Use default:")
+            kernel_image = "vmlinuz"
+        boot_image = kernel_image
+
+        initrd_image = get_bitbake_var("INITRD_IMAGE")
+        if not initrd_image:
+            msger.warning("INITRD_IMAGE not set\n")
+            initrd_image = "initrd.img"
+        bootloader = creator.ks.bootloader
+
+        deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
+        if not deploy_dir:
+            msger.error("DEPLOY_DIR_IMAGE not set, exiting\n")
+            sys.exit(1)
+        creator.deploy_dir = deploy_dir
+
+        wdog_timeout = get_bitbake_var("WDOG_TIMEOUT")
+        if not wdog_timeout:
+            msger.error("Specify watchdog timeout for \
+            efibootguard in local.conf with WDOG_TIMEOUT=")
+            exit(1)
+
+
+        boot_files = source_params.get("files", "").split(' ')
+        cmdline = bootloader.append
+        root_dev = source_params.get("root", None)
+        if not root_dev:
+            msger.error("Specify root in source params")
+            exit(1)
+            root_dev = root_dev.replace(":", "=")
+
+        cmdline += " root=%s rw" % root_dev
+        boot_files.append(kernel_image)
+        boot_files.append(initrd_image)
+        cmdline += "initrd=%s" % initrd_image if initrd_image else ""
+
+        part_rootfs_dir = "%s/disk/%s.%s" % (cr_workdir,
+                                             part.label, part.lineno)
+        create_dir_cmd = "install -d %s" % part_rootfs_dir
+        exec_cmd(create_dir_cmd)
+
+        cwd = os.getcwd()
+        os.chdir(part_rootfs_dir)
+        config_cmd = '%s/bg_setenv -f . -k "C:%s:%s" %s -r %s -w %s' \
+            % (
+                deploy_dir,
+                part.label.upper(),
+                boot_image,
+                '-a "%s"' % cmdline if cmdline else "",
+                source_params.get("revision", 1),
+                wdog_timeout
+            )
+        exec_cmd(config_cmd, True)
+        os.chdir(cwd)
+
+        boot_files = list(filter(None, boot_files))
+        for boot_file in boot_files:
+            if os.path.isfile("%s/%s" % (kernel_dir, kernel_image)):
+                install_cmd = "install -m 0644 %s/%s %s/%s" % \
+                    (kernel_dir, boot_file, part_rootfs_dir, boot_file)
+                exec_cmd(install_cmd)
+            else:
+                msger.error("file %s not found in directory %s",
+                            boot_file, kernel_dir)
+                exit(1)
+        cls._create_img(part_rootfs_dir, part, cr_workdir)
+
+    @classmethod
+    def _create_img(cls, part_rootfs_dir, part, cr_workdir):
+            # Write label as utf-16le to EFILABEL file
+        with open("%s/EFILABEL" % part_rootfs_dir, 'wb') as filedescriptor:
+            filedescriptor.write(part.label.upper().encode("utf-16le"))
+
+        du_cmd = "du --apparent-size -ks %s" % part_rootfs_dir
+        blocks = int(exec_cmd(du_cmd).split()[0])
+
+        extra_blocks = part.get_extra_block_count(blocks)
+        if extra_blocks < BOOTDD_EXTRA_SPACE:
+            extra_blocks = BOOTDD_EXTRA_SPACE
+
+        blocks += extra_blocks
+        blocks = blocks + (16 - (blocks % 16))
+
+        msger.debug("Added %d extra blocks to %s to get to %d total blocks",
+                    extra_blocks, part.mountpoint, blocks)
+
+        # dosfs image, created by mkdosfs
+        bootimg = "%s/%s.%s.img" % (cr_workdir, part.label, part.lineno)
+
+        dosfs_cmd = "mkdosfs -F 16 -S 512 -n %s -C %s %d" % \
+            (part.label.upper(), bootimg, blocks)
+        exec_cmd(dosfs_cmd)
+
+        mcopy_cmd = "mcopy -v -i %s -s %s/* ::/" % (bootimg, part_rootfs_dir)
+        exec_cmd(mcopy_cmd, True)
+
+        chmod_cmd = "chmod 644 %s" % bootimg
+        exec_cmd(chmod_cmd)
+
+        du_cmd = "du -Lbks %s" % bootimg
+        bootimg_size = int(exec_cmd(du_cmd).split()[0])
+
+        part.size = bootimg_size
+        part.source_file = bootimg
diff --git a/scripts/lib/wic/plugins/source/efibootguard-efi.py b/scripts/lib/wic/plugins/source/efibootguard-efi.py
new file mode 100644
index 0000000..5ee451f
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/efibootguard-efi.py
@@ -0,0 +1,102 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Copyright (c) 2014, Intel Corporation.
+# Copyright (c) 2018, Siemens AG.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# DESCRIPTION
+# This implements the 'efibootguard-efi' source plugin class for 'wic'
+#
+# AUTHORS
+# Tom Zanussi <tom.zanussi (at] linux.intel.com>
+# Claudius Heine <ch (at] denx.de>
+# Andreas Reichel <andreas.reichel.ext (at] siemens.com>
+# Christian Storm <christian.storm (at] siemens.com>
+
+import logging
+import os
+
+msger = logging.getLogger('wic')
+
+from wic.pluginbase import SourcePlugin
+from wic.utils.misc import exec_cmd, get_bitbake_var, BOOTDD_EXTRA_SPACE
+
+class EfibootguardEFIPlugin(SourcePlugin):
+    """
+    Create EFI bootloader partition containing the EFI Boot Guard Bootloader.
+    """
+
+    name = 'efibootguard-efi'
+
+    @classmethod
+    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
+                             oe_builddir, deploy_dir, kernel_dir,
+                             rootfs_dir, native_sysroot):
+        """
+        Called to do the actual content population for a partition, i.e.,
+        populate an EFI boot partition containing the EFI Boot Guard
+        bootloader binary.
+        """
+        deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
+        creator.deploy_dir = deploy_dir
+        bootloader_files = source_params.get("bootloader")
+        if not bootloader_files:
+            bootloader_files = "bootx64.efi"
+        bootloader_files = bootloader_files.split(' ')
+        part_rootfs_dir = "%s/disk/%s.%s" % (cr_workdir,
+                                             part.label,
+                                             part.lineno)
+        create_dir_cmd = "install -d %s/EFI/BOOT" % part_rootfs_dir
+        exec_cmd(create_dir_cmd)
+
+        for bootloader in bootloader_files:
+            cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (deploy_dir,
+                                                  bootloader,
+                                                  part_rootfs_dir,
+                                                  bootloader)
+            exec_cmd(cp_cmd, True)
+        du_cmd = "du --apparent-size -ks %s" % part_rootfs_dir
+        blocks = int(exec_cmd(du_cmd).split()[0])
+
+        extra_blocks = part.get_extra_block_count(blocks)
+        if extra_blocks < BOOTDD_EXTRA_SPACE:
+            extra_blocks = BOOTDD_EXTRA_SPACE
+        blocks += extra_blocks
+        blocks = blocks + (16 - (blocks % 16))
+
+        msger.debug("Added %d extra blocks to %s to get to %d total blocks",
+                    extra_blocks, part.mountpoint, blocks)
+
+        # dosfs image, created by mkdosfs
+        efi_part_image = "%s/%s.%s.img" % (cr_workdir, part.label, part.lineno)
+
+        dosfs_cmd = "mkdosfs -S 512 -n %s -C %s %d" % \
+            (part.label.upper(), efi_part_image, blocks)
+        exec_cmd(dosfs_cmd)
+
+        mcopy_cmd = "mcopy -v -i %s -s %s/* ::/" % \
+            (efi_part_image, part_rootfs_dir)
+        exec_cmd(mcopy_cmd, True)
+
+        chmod_cmd = "chmod 644 %s" % efi_part_image
+        exec_cmd(chmod_cmd)
+
+        du_cmd = "du -Lbks %s" % efi_part_image
+        efi_part_image_size = int(exec_cmd(du_cmd).split()[0])
+
+        part.size = efi_part_image_size
+        part.source_file = efi_part_image
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4817): https://lists.cip-project.org/g/cip-dev/message/4817
Mute This Topic: https://lists.cip-project.org/mt/75102473/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core RFC 2/4] patches: add libubootenv
  2020-06-25 13:21 [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update Quirin Gylstorff
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard Quirin Gylstorff
@ 2020-06-25 13:21 ` Quirin Gylstorff
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 3/4] recipes-core: add swupdate Quirin Gylstorff
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-25 13:21 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 7686 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

swupdate 2020.04 requires libubootenv as build dependency.

libubootenv is a library that provides a hardware independent
way to access to U-Boot environment. U-Boot has its default environment
compiled board-dependently and this means that tools to access the environment
are also board specific, too.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 .../0001-u-boot-add-libubootenv.patch         | 169 ++++++++++++++++++
 kas/cip.yml                                   |   4 +
 2 files changed, 173 insertions(+)
 create mode 100644 isar-patches/0001-u-boot-add-libubootenv.patch

diff --git a/isar-patches/0001-u-boot-add-libubootenv.patch b/isar-patches/0001-u-boot-add-libubootenv.patch
new file mode 100644
index 0000000..10a5b4a
--- /dev/null
+++ b/isar-patches/0001-u-boot-add-libubootenv.patch
@@ -0,0 +1,169 @@
+From 76897e89977f895495e21e37cb76f90392d55ef9 Mon Sep 17 00:00:00 2001
+From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
+Date: Fri, 19 Jun 2020 17:00:36 +0200
+Subject: [PATCH v2] u-boot: add libubootenv
+
+Add the new library libubootenv and remove fw_printenv and fw_setenv
+form u-boot-tools as the are now part of the new library.
+
+libubootenv is a library that provides a hardware independent
+way to access to U-Boot environment. U-Boot has its default environment
+compiled board-dependently and this means that tools to access the environment
+are also board specific, too.
+
+libubootenv conflicts with u-boot-tools from Debian 10
+as both try to install fw_printenv and fw_sentenv. This conflict is not
+part of the control file as it breaks the installation of custom u-boot-tools
+from the u-boot-sources.
+
+Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
+---
+ meta-isar/conf/machine/de0-nano-soc.conf      |  2 +-
+ .../libubootenv/files/debian/compat           |  1 +
+ .../libubootenv/files/debian/control.tmpl     | 15 +++++++++
+ .../libubootenv/files/debian/rules.tmpl       | 24 ++++++++++++++
+ .../libubootenv/libubootenv_0.2.bb            | 32 +++++++++++++++++++
+ .../files/debian/u-boot-tools.conffiles       |  1 -
+ .../u-boot/files/debian/u-boot-tools.install  |  2 --
+ .../u-boot/files/debian/u-boot-tools.links    |  1 -
+ 8 files changed, 73 insertions(+), 5 deletions(-)
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/compat
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+ create mode 100644 meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+ delete mode 100644 meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
+ delete mode 100644 meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
+
+diff --git a/meta-isar/conf/machine/de0-nano-soc.conf b/meta-isar/conf/machine/de0-nano-soc.conf
+index 3a2c009..6558d90 100644
+--- a/meta-isar/conf/machine/de0-nano-soc.conf
++++ b/meta-isar/conf/machine/de0-nano-soc.conf
+@@ -15,4 +15,4 @@ WKS_FILE ?= "de0-nano-soc.wks.in"
+ IMAGER_INSTALL += "u-boot-de0-nano-soc"
+ IMAGER_BUILD_DEPS += "u-boot-de0-nano-soc"
+ 
+-IMAGE_INSTALL += "u-boot-tools u-boot-script"
++IMAGE_INSTALL += "u-boot-tools libubootenv u-boot-script"
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/compat b/meta/recipes-bsp/libubootenv/files/debian/compat
+new file mode 100644
+index 0000000..b4de394
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/compat
+@@ -0,0 +1 @@
++11
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/control.tmpl b/meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+new file mode 100644
+index 0000000..fade69a
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+@@ -0,0 +1,15 @@
++Source: libubootenv
++Section: embedded
++Priority: optional
++Maintainer: Stefano Babic <sbabic@denx.de>
++Build-Depends: ${BUILD_DEB_DEPENDS}
++Standards-Version: 4.2.1
++Homepage: https://sbabic.github.io/libubootenv
++
++Package: libubootenv
++Architecture: any
++Depends: ${DEBIAN_DEPENDS}
++Description: libubootenv is a library that provides a hardware independent
++ way to access to U-Boot environment. U-Boot has its default environment
++ compiled board-dependently and this means that tools to access the environment
++ are also board specific, too.
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl b/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+new file mode 100644
+index 0000000..56ccd19
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+@@ -0,0 +1,24 @@
++#!/usr/bin/make -f
++
++ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
++export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
++export CC=$(DEB_HOST_GNU_TYPE)-gcc
++export LD=$(DEB_HOST_GNU_TYPE)-gcc
++endif
++
++export DH_VERBOSE = 1
++
++export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
++
++override_dh_auto_configure:
++	dh_auto_configure --
++
++%:
++	echo $@
++	dh $@
++
++override_dh_installchangelogs:
++	true
++
++override_dh_installdocs:
++	true
+diff --git a/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb b/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+new file mode 100644
+index 0000000..1be058c
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+@@ -0,0 +1,32 @@
++# libubootenv
++#
++# This software is a part of ISAR.
++# Copyright (c) Siemens AG, 2020
++#
++# SPDX-License-Identifier: MIT
++
++DESCRIPTION = "swupdate utility for software updates"
++HOMEPAGE= "https://github.com/sbabic/swupdate"
++LICENSE = "GPL-2.0"
++LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
++SRC_URI = "gitsm://github.com/sbabic/libubootenv.git;branch=master;protocol=https"
++
++SRCREV = "bf6ff631c0e38cede67268ceb8bf1383b5f8848e"
++
++BUILD_DEB_DEPENDS = "cmake, zlib1g-dev"
++
++SRC_URI += "file://debian"
++TEMPLATE_FILES = "debian/control.tmpl debian/rules.tmpl"
++TEMPLATE_VARS += "BUILD_DEB_DEPENDS DEFCONFIG DEBIAN_DEPENDS"
++
++
++inherit dpkg
++
++S = "${WORKDIR}/git"
++
++do_prepare_build() {
++        DEBDIR=${S}/debian
++        install -d ${DEBDIR}
++        cp -R ${WORKDIR}/debian ${S}
++        deb_add_changelog
++}
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
+deleted file mode 100644
+index d49a8fb..0000000
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
++++ /dev/null
+@@ -1 +0,0 @@
+-/etc/fw_env.config
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
+index d1ae3e0..2893b9a 100644
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
++++ b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
+@@ -1,5 +1,3 @@
+ tools/dumpimage		/usr/bin/
+-tools/env/fw_printenv	/usr/bin/
+ tools/mkenvimage	/usr/bin/
+ tools/mkimage		/usr/bin/
+-tools/env/fw_env.config	/etc
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
+deleted file mode 100644
+index 92f5a6c..0000000
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
++++ /dev/null
+@@ -1 +0,0 @@
+-/usr/bin/fw_printenv /usr/bin/fw_setenv
+-- 
+2.20.1
+
diff --git a/kas/cip.yml b/kas/cip.yml
index 019b31e..0da07db 100644
--- a/kas/cip.yml
+++ b/kas/cip.yml
@@ -22,6 +22,10 @@ repos:
     refspec: 351af175bc54a201c6f44307d4e998bd6c0afdb8
     layers:
       meta:
+    patches:
+      01-libubootenv:
+        path: isar-patches/0001-u-boot-add-libubootenv.patch
+        repo: cip-core
 
 bblayers_conf_header:
   standard: |
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4818): https://lists.cip-project.org/g/cip-dev/message/4818
Mute This Topic: https://lists.cip-project.org/mt/75102474/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core RFC 3/4] recipes-core: add swupdate
  2020-06-25 13:21 [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update Quirin Gylstorff
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard Quirin Gylstorff
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 2/4] patches: add libubootenv Quirin Gylstorff
@ 2020-06-25 13:21 ` Quirin Gylstorff
  2020-06-26 13:05   ` Jan Kiszka
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 4/4] wic: Add wks files for A/B Partition update Quirin Gylstorff
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-25 13:21 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 45099 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add swupdate for A/B software updates. Currently the Round Robin
handler in lua supports efibootguard as bootloader. The u-boot
implementation is outstanding.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 classes/kconfig-snippets.bbclass              |  90 ++++
 classes/swupdate-config.bbclass               |  76 +++
 classes/swupdate-img.bbclass                  |  75 +++
 .../swupdate/files/debian/changelog.tmpl      |   6 +
 recipes-core/swupdate/files/debian/compat     |   1 +
 .../swupdate/files/debian/control.tmpl        |  15 +
 recipes-core/swupdate/files/debian/copyright  |  36 ++
 recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
 .../swupdate/files/debian/swupdate.examples   |   2 +
 .../swupdate/files/debian/swupdate.install    |   2 +
 .../swupdate/files/debian/swupdate.manpages   |   5 +
 .../swupdate/files/debian/swupdate.tmpfile    |   2 +
 recipes-core/swupdate/files/debian/watch      |  12 +
 recipes-core/swupdate/files/postinst          |   2 +
 recipes-core/swupdate/files/swupdate.cfg      |   6 +
 .../swupdate/files/swupdate.service.example   |  11 +
 .../swupdate/files/swupdate.socket.example    |  11 +
 .../swupdate/files/swupdate.socket.tmpl       |  13 +
 .../swupdate/files/swupdate_defconfig         |  83 ++++
 .../swupdate_defconfig_efibootguard.snippet   |   3 +
 .../files/swupdate_defconfig_lua.snippet      |   2 +
 .../swupdate_defconfig_luahandler.snippet     |   4 +
 .../files/swupdate_defconfig_mtd.snippet      |   1 +
 .../files/swupdate_defconfig_u-boot.snippet   |   3 +
 .../files/swupdate_defconfig_ubi.snippet      |   6 +
 .../swupdate/files/swupdate_handlers.lua      | 449 ++++++++++++++++++
 recipes-core/swupdate/swupdate.bb             |  54 +++
 27 files changed, 1000 insertions(+)
 create mode 100644 classes/kconfig-snippets.bbclass
 create mode 100644 classes/swupdate-config.bbclass
 create mode 100644 classes/swupdate-img.bbclass
 create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/compat
 create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/copyright
 create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
 create mode 100644 recipes-core/swupdate/files/debian/watch
 create mode 100644 recipes-core/swupdate/files/postinst
 create mode 100644 recipes-core/swupdate/files/swupdate.cfg
 create mode 100644 recipes-core/swupdate/files/swupdate.service.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
 create mode 100644 recipes-core/swupdate/swupdate.bb

diff --git a/classes/kconfig-snippets.bbclass b/classes/kconfig-snippets.bbclass
new file mode 100644
index 0000000..d754654
--- /dev/null
+++ b/classes/kconfig-snippets.bbclass
@@ -0,0 +1,90 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+KCONFIG_SNIPPETS = ""
+
+# The following function defines the kconfig snippet system
+# with automatich debian dependency injection
+#
+# To define a feature set, the user has to define the following
+# variable to an empty string:
+#
+# KFEATURE_featurename = ""
+#
+# Then, required additions to the variables can be defined:
+#
+# KFEATURE_featurename[KCONFIG_SNIPPETS] = "file://snippet-file-name.snippet"
+# KFEATURE_featurename[SRC_URI] = "file://required-file.txt"
+# KFEATURE_featurename[DEPENDS] = "deb-pkg1 deb-pkg2 deb-pkg3"
+# KFEATURE_featurename[DEBIAN_DEPENDS] = "deb-pkg1"
+# KFEATURE_featurename[BUILD_DEB_DEPENDS] = "deb-pkg1,deb-pkg2,deb-pkg3"
+
+# The 'KCONFIG_SNIPPETS' flag gives a list of URI entries, where only
+# file:// is supported. These snippets are appended to the DEFCONFIG file.
+#
+# Features can depend on other features via the following mechanism:
+#
+# KFEATURE_DEPS[feature1] = "feature2"
+
+python () {
+    requested_features = d.getVar("KFEATURES", True) or ""
+
+    features = set(requested_features.split())
+    old_features = set()
+    feature_deps = d.getVarFlags("KFEATURE_DEPS") or {}
+    while old_features != features:
+        diff_features = old_features.symmetric_difference(features)
+        old_features = features.copy()
+        for i in diff_features:
+            features.update(feature_deps.get(i, "").split())
+
+    for f in sorted(features):
+        bb.debug(2, "Feature: " + f)
+        varname = "KFEATURE_" + f
+        dummyvar = d.getVar(varname, False)
+        if dummyvar == None:
+            bb.error("Feature var " + f + " must be defined with needed flags.")
+        else:
+            feature_flags = d.getVarFlags(varname)
+            for feature_varname in sorted(feature_flags):
+                if feature_flags.get(feature_varname, "") != "":
+                    sep = " "
+
+                    # Required to add KCONFIG_SNIPPETS to SRC_URI here,
+                    # because 'SRC_URI += "${KCONFIG_SNIPPETS}"' would
+                    # conflict with SRC_APT feature.
+                    if feature_varname == "KCONFIG_SNIPPETS":
+                        d.appendVar('SRC_URI',
+                            " " + feature_flags[feature_varname].strip())
+
+                    # BUILD_DEP_DEPENDS and DEBIAN_DEPENDS is ',' separated
+                    # Only add ',' if there is already something there
+                    if feature_varname in ["BUILD_DEB_DEPENDS",
+                                           "DEBIAN_DEPENDS"]:
+                        sep = "," if d.getVar(feature_varname) else ""
+
+                    d.appendVar(feature_varname,
+                        sep + feature_flags[feature_varname].strip())
+}
+
+# DEFCONFIG must be a predefined bitbake variable and the corresponding file
+# must exist in the WORKDIR.
+# The resulting generated config is the same file suffixed with ".gen"
+
+do_prepare_build_prepend() {
+        sh -x
+        GENCONFIG="${WORKDIR}/${DEFCONFIG}".gen
+        rm -f "$GENCONFIG"
+        cp "${WORKDIR}/${DEFCONFIG}" "$GENCONFIG"
+        for CONFIG_SNIPPET in $(echo "${KCONFIG_SNIPPETS}" | sed 's#file://##g')
+        do
+                cat ${WORKDIR}/$CONFIG_SNIPPET >> "$GENCONFIG"
+        done
+}
diff --git a/classes/swupdate-config.bbclass b/classes/swupdate-config.bbclass
new file mode 100644
index 0000000..7ce51c5
--- /dev/null
+++ b/classes/swupdate-config.bbclass
@@ -0,0 +1,76 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+# This class manages the config snippets together with their dependencies
+# to build SWUpdate
+
+inherit kconfig-snippets
+
+BUILD_DEB_DEPENDS = " \
+    zlib1g-dev, debhelper, libconfig-dev, libarchive-dev, \
+    python-sphinx:native, dh-systemd, libsystemd-dev"
+
+KFEATURE_lua = ""
+KFEATURE_lua[BUILD_DEB_DEPENDS] = "liblua5.3-dev"
+KFEATURE_lua[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_lua.snippet"
+
+KFEATURE_luahandler = ""
+KFEATURE_luahandler[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_luahandler.snippet"
+KFEATURE_luahandler[SRC_URI] = "file://${SWUPDATE_LUASCRIPT}"
+
+KFEATURE_DEPS = ""
+KFEATURE_DEPS[luahandler] = "lua"
+
+KFEATURE_efibootguard = ""
+KFEATURE_efibootguard[BUILD_DEB_DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[DEBIAN_DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_efibootguard.snippet"
+
+KFEATURE_mtd = ""
+KFEATURE_mtd[BUILD_DEB_DEPENDS] = "libmtd-dev"
+KFEATURE_mtd[DEPENDS] = "mtd-utils"
+KFEATURE_mtd[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_mtd.snippet"
+
+KFEATURE_ubi = ""
+KFEATURE_ubi[BUILD_DEB_DEPENDS] = "libubi-dev"
+KFEATURE_ubi[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_ubi.snippet"
+
+KFEATURE_DEPS[ubi] = "mtd"
+
+KFEATURE_u-boot = ""
+KFEATURE_u-boot[BUILD_DEB_DEPENDS] = "u-boot-${MACHINE}-dev"
+KFEATURE_u-boot[DEBIAN_DEPENDS] = "u-boot-tools"
+KFEATURE_u-boot[DEPENDS] = "${U_BOOT}"
+KFEATURE_u-boot[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_u-boot.snippet"
+
+SWUPDATE_LUASCRIPT ?= "swupdate_handlers.lua"
+
+def get_bootloader_featureset(d):
+    bootloader = d.getVar("BOOTLOADER", True) or ""
+    if bootloader == "efibootguard":
+        return "efibootguard"
+    if bootloader == "u-boot":
+        return "u-boot"
+    return ""
+
+SWUPDATE_KFEATURES ??= ""
+KFEATURES = "${SWUPDATE_KFEATURES}"
+KFEATURES += "${@get_bootloader_featureset(d)}"
+
+# Astonishingly, as an anonymous python function, BOOTLOADER is always None
+# one time before it gets set. So the following must be a task.
+python do_check_bootloader () {
+    bootloader = d.getVar("BOOTLOADER", True) or "None"
+    if not bootloader in ["efibootguard", "u-boot"]:
+        bb.warn("swupdate: BOOTLOADER set to incompatible value: " + bootloader)
+}
+addtask check_bootloader before do_fetch
+
diff --git a/classes/swupdate-img.bbclass b/classes/swupdate-img.bbclass
new file mode 100644
index 0000000..a21d6ec
--- /dev/null
+++ b/classes/swupdate-img.bbclass
@@ -0,0 +1,75 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+SWU_IMAGE_FILE ?= "${PN}-${DISTRO}-${MACHINE}.swu"
+SWU_DESCRIPTION_FILE ?= "sw-description"
+SWU_ADDITIONAL_FILES ?= ""
+SWU_SIGNED ?= ""
+SWU_SIGNATURE_EXT ?= "sig"
+SWU_SIGNATURE_TYPE ?= "rsa"
+
+IMAGER_INSTALL += "${@'openssl' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}"
+
+do_swupdate_image[stamp-extra-info] = "${DISTRO}-${MACHINE}"
+do_swupdate_image[cleandirs] += "${WORKDIR}/swu"
+do_swupdate_image() {
+    rm -f '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
+    cp '${WORKDIR}/${SWU_DESCRIPTION_FILE}' '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
+
+    # Create symlinks for files used in the update image
+    for file in ${SWU_ADDITIONAL_FILES}; do
+        if [ -e "${WORKDIR}/$file" ]; then
+            ln -s "${WORKDIR}/$file" "${WORKDIR}/swu/$file"
+        else
+            ln -s "${DEPLOY_DIR_IMAGE}/$file" "${WORKDIR}/swu/$file"
+        fi
+    done
+
+    # Prepare for signing
+    sign='${@'x' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}'
+    if [ -n "$sign" ]; then
+        image_do_mounts
+        cp -f '${SIGN_KEY}' '${WORKDIR}/dev.key'
+        test -e '${SIGN_CRT}' && cp -f '${SIGN_CRT}' '${WORKDIR}/dev.crt'
+
+        # Fill in file check sums
+        for file in ${SWU_ADDITIONAL_FILES}; do
+            sed -i "s:$file-sha256:$(sha256sum '${WORKDIR}/swu/'$file | cut -f 1 -d ' '):g" \
+                '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
+        done
+    fi
+
+    cd "${WORKDIR}/swu"
+    for file in '${SWU_DESCRIPTION_FILE}' ${SWU_ADDITIONAL_FILES}; do
+        echo "$file"
+        if [ -n "$sign" -a \
+             '${SWU_DESCRIPTION_FILE}' = "$file" ]; then
+            if [ "${SWU_SIGNATURE_TYPE}" = "rsa" ]; then
+                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl dgst \
+                    -sha256 -sign '${PP_WORK}/dev.key' \
+                    '${PP_WORK}/swu/'"$file" \
+                        > '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}'
+            elif [ "${SWU_SIGNATURE_TYPE}" = "cms" ]; then
+                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl cms \
+                    -sign -in '${PP_WORK}/swu/'"$file" \
+                    -out '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}' \
+                    -signer '${PP_WORK}/dev.crt' \
+                    -inkey '${PP_WORK}/dev.key' \
+                    -outform DER -nosmimecap -binary
+            fi
+            echo "$file".'${SWU_SIGNATURE_EXT}'
+        fi
+    done | cpio -ovL -H crc \
+        > '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
+    cd -
+}
+
+addtask swupdate_image before do_build after do_copy_boot_files do_install_imager_deps do_transform_template
diff --git a/recipes-core/swupdate/files/debian/changelog.tmpl b/recipes-core/swupdate/files/debian/changelog.tmpl
new file mode 100644
index 0000000..81087d3
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/changelog.tmpl
@@ -0,0 +1,6 @@
+swupdate (${PV}) unstable; urgency=medium
+
+  * SWUpdate
+
+ --  Christian Storm <christian.storm@siemens.com>  Thu, 31 Jan 2019 15:23:56 +0100
+
diff --git a/recipes-core/swupdate/files/debian/compat b/recipes-core/swupdate/files/debian/compat
new file mode 100644
index 0000000..b4de394
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/compat
@@ -0,0 +1 @@
+11
diff --git a/recipes-core/swupdate/files/debian/control.tmpl b/recipes-core/swupdate/files/debian/control.tmpl
new file mode 100644
index 0000000..2b92850
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/control.tmpl
@@ -0,0 +1,15 @@
+Source: swupdate
+Section: embedded
+Priority: optional
+Maintainer: Stefano Babic <sbabic@denx.de>
+Build-Depends: ${BUILD_DEB_DEPENDS}
+Standards-Version: 4.2.1
+Homepage: http://sbabic.github.io/swupdate
+
+Package: swupdate
+Architecture: any
+Depends: ${DEBIAN_DEPENDS}
+Description: reliable way to update an embedded system
+ This project is thought to help to update an embedded system from a storage media or from network.
+ However, it should be mainly considered as a framework, where further protocols or installers
+ (in SWUpdate they are called handlers) can be easily added to the application.
diff --git a/recipes-core/swupdate/files/debian/copyright b/recipes-core/swupdate/files/debian/copyright
new file mode 100644
index 0000000..f920942
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/copyright
@@ -0,0 +1,36 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: swupdate
+Maintainer: Stefano Babic <sbabic@denx.de>
+Source: http://github.com/sbabic/swupdate
+
+Files: *
+Copyright: 2014-2017 Stefano Babic <sbabic@denx.de>
+
+License: GPL-2 with OpenSSL exception
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ In addition, as a special exception, the author of this
+ program gives permission to link the code of its
+ release with the OpenSSL project's "OpenSSL" library (or
+ with modified versions of it that use the same license as
+ the "OpenSSL" library), and distribute the linked
+ executables. You must obey the GNU General Public
+ License in all respects for all of the code used other
+ than "OpenSSL".  If you modify this file, you may extend
+ this exception to your version of the file, but you are
+ not obligated to do so.  If you do not wish to do so,
+ delete this exception statement from your version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
diff --git a/recipes-core/swupdate/files/debian/rules.tmpl b/recipes-core/swupdate/files/debian/rules.tmpl
new file mode 100755
index 0000000..54cca57
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/rules.tmpl
@@ -0,0 +1,30 @@
+#!/usr/bin/make -f
+
+ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
+export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
+export CC=$(DEB_HOST_GNU_TYPE)-gcc
+export LD=$(DEB_HOST_GNU_TYPE)-gcc
+endif
+
+export DH_VERBOSE = 1
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
+
+documentation: configure
+	make man
+
+configure:
+	make ${DEFCONFIG}
+
+build: documentation configure
+	dh $@
+
+%:
+	echo $@
+	dh $@
+
+override_dh_installchangelogs:
+	true
+
+override_dh_installdocs:
+	true
diff --git a/recipes-core/swupdate/files/debian/swupdate.examples b/recipes-core/swupdate/files/debian/swupdate.examples
new file mode 100644
index 0000000..c257b75
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.examples
@@ -0,0 +1,2 @@
+examples/configuration
+examples/description
diff --git a/recipes-core/swupdate/files/debian/swupdate.install b/recipes-core/swupdate/files/debian/swupdate.install
new file mode 100644
index 0000000..8957cc6
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.install
@@ -0,0 +1,2 @@
+swupdate usr/bin
+swupdate.cfg /etc
diff --git a/recipes-core/swupdate/files/debian/swupdate.manpages b/recipes-core/swupdate/files/debian/swupdate.manpages
new file mode 100644
index 0000000..c3438e0
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.manpages
@@ -0,0 +1,5 @@
+doc/build/man/swupdate.1
+doc/build/man/client.1
+doc/build/man/sendtohawkbit.1
+doc/build/man/hawkbitcfg.1
+doc/build/man/progress.1
diff --git a/recipes-core/swupdate/files/debian/swupdate.tmpfile b/recipes-core/swupdate/files/debian/swupdate.tmpfile
new file mode 100644
index 0000000..4743672
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.tmpfile
@@ -0,0 +1,2 @@
+X /tmp/datadst
+X /tmp/scripts
diff --git a/recipes-core/swupdate/files/debian/watch b/recipes-core/swupdate/files/debian/watch
new file mode 100644
index 0000000..bc4c53e
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/watch
@@ -0,0 +1,12 @@
+# Example watch control file for uscan
+# Rename this file to "watch" and then you can run the "uscan" command
+# to check for upstream updates and more.
+# See uscan(1) for format
+
+# Compulsory line, this is a version 4 file
+version=4
+
+# GitHub hosted projects
+opts="filenamemangle="s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
+   https://github.com/<user>/swupdate/tags \
+   (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
diff --git a/recipes-core/swupdate/files/postinst b/recipes-core/swupdate/files/postinst
new file mode 100644
index 0000000..f15ac10
--- /dev/null
+++ b/recipes-core/swupdate/files/postinst
@@ -0,0 +1,2 @@
+#!/bin/sh
+deb-systemd-helper enable swupdate.socket || true
diff --git a/recipes-core/swupdate/files/swupdate.cfg b/recipes-core/swupdate/files/swupdate.cfg
new file mode 100644
index 0000000..e0222f1
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.cfg
@@ -0,0 +1,6 @@
+globals :
+{
+    verbose = true;
+    loglevel = 10;
+    syslog = false;
+};
diff --git a/recipes-core/swupdate/files/swupdate.service.example b/recipes-core/swupdate/files/swupdate.service.example
new file mode 100644
index 0000000..d0b821e
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.service.example
@@ -0,0 +1,11 @@
+[Unit]
+Description=SWUpdate daemon
+Documentation=https://github.com/sbabic/swupdate
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/swupdate -f /etc/swupdate.cfg
+KillMode=mixed
+
+[Install]
+WantedBy=multi-user.target
diff --git a/recipes-core/swupdate/files/swupdate.socket.example b/recipes-core/swupdate/files/swupdate.socket.example
new file mode 100644
index 0000000..2b75671
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.socket.example
@@ -0,0 +1,11 @@
+[Unit]
+Description=SWUpdate socket listener
+Documentation=https://github.com/sbabic/swupdate
+Documentation=https://sbabic.github.io/swupdate
+
+[Socket]
+ListenStream=/tmp/sockinstctrl
+ListenStream=/tmp/swupdateprog
+
+[Install]
+WantedBy=sockets.target
diff --git a/recipes-core/swupdate/files/swupdate.socket.tmpl b/recipes-core/swupdate/files/swupdate.socket.tmpl
new file mode 100644
index 0000000..8e7fc1d
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.socket.tmpl
@@ -0,0 +1,13 @@
+[Unit]
+Description=SWUpdate socket listener
+Documentation=https://github.com/sbabic/swupdate
+Documentation=https://sbabic.github.io/swupdate
+
+[Socket]
+SocketUser=${SWUPDATE_SOCKET_OWNER}
+SocketGroup=root
+ListenStream=/tmp/sockinstctrl
+ListenStream=/tmp/swupdateprog
+
+[Install]
+WantedBy=sockets.target
diff --git a/recipes-core/swupdate/files/swupdate_defconfig b/recipes-core/swupdate/files/swupdate_defconfig
new file mode 100644
index 0000000..9ae7cb5
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig
@@ -0,0 +1,83 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Swupdate Configuration
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Swupdate Settings
+#
+
+#
+# General Configuration
+#
+# CONFIG_CURL is not set
+# CONFIG_CURL_SSL is not set
+CONFIG_SYSTEMD=y
+CONFIG_SCRIPTS=y
+# CONFIG_HW_COMPATIBILITY is not set
+CONFIG_SW_VERSIONS_FILE="/etc/sw-versions"
+
+#
+# Socket Paths
+#
+CONFIG_SOCKET_CTRL_PATH="/tmp/sockinstctrl"
+CONFIG_SOCKET_PROGRESS_PATH="/tmp/swupdateprog"
+CONFIG_SOCKET_REMOTE_HANDLER_DIRECTORY="/tmp/"
+# CONFIG_MTD is not set
+# CONFIG_LUA is not set
+# CONFIG_LUAPKG is not set
+# CONFIG_FEATURE_SYSLOG is not set
+
+#
+# Build Options
+#
+CONFIG_CROSS_COMPILE=""
+CONFIG_SYSROOT=""
+CONFIG_EXTRA_CFLAGS=""
+CONFIG_EXTRA_LDFLAGS=""
+CONFIG_EXTRA_LDLIBS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_WERROR is not set
+# CONFIG_NOCLEANUP is not set
+# CONFIG_BOOTLOADER_EBG is not set
+# CONFIG_UBOOT is not set
+# CONFIG_BOOTLOADER_NONE is not set
+# CONFIG_BOOTLOADER_GRUB is not set
+# CONFIG_DOWNLOAD is not set
+# CONFIG_DOWNLOAD_SSL is not set
+# CONFIG_CHANNEL_CURL is not set
+# CONFIG_HASH_VERIFY=y
+# CONFIG_SIGNED_IMAGES is not set
+# CONFIG_ENCRYPTED_IMAGES is not set
+# CONFIG_SURICATTA is not set
+# CONFIG_WEBSERVER is not set
+CONFIG_GUNZIP=y
+
+#
+# Parser Features
+#
+CONFIG_LIBCONFIG=y
+CONFIG_PARSERROOT=""
+# CONFIG_JSON is not set
+# CONFIG_LUAEXTERNAL is not set
+# CONFIG_SETEXTPARSERNAME is not set
+# CONFIG_SETSWDESCRIPTION is not set
+
+#
+# Image Handlers
+#
+CONFIG_RAW=y
+# CONFIG_LUASCRIPTHANDLER is not set
+# CONFIG_SHELLSCRIPTHANDLER is not set
+# CONFIG_HANDLER_IN_LUA is not set
+# CONFIG_EMBEDDED_LUA_HANDLER is not set
+# CONFIG_EMBEDDED_LUA_HANDLER_SOURCE is not set
+CONFIG_ARCHIVE=y
+# CONFIG_REMOTE_HANDLER is not set
+# CONFIG_SWUFORWARDER_HANDLER is not set
+# CONFIG_BOOTLOADERHANDLER is not set
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
new file mode 100644
index 0000000..8e3688c
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
@@ -0,0 +1,3 @@
+CONFIG_BOOTLOADER_NONE=n
+CONFIG_BOOTLOADER_EBG=y
+CONFIG_BOOTLOADERHANDLER=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
new file mode 100644
index 0000000..b39f9df
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
@@ -0,0 +1,2 @@
+CONFIG_LUA=y
+CONFIG_LUAPKG="lua53"
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
new file mode 100644
index 0000000..b4a2de8
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
@@ -0,0 +1,4 @@
+CONFIG_LUASCRIPTHANDLER=y
+CONFIG_HANDLER_IN_LUA=y
+CONFIG_EMBEDDED_LUA_HANDLER=y
+CONFIG_EMBEDDED_LUA_HANDLER_SOURCE="swupdate_handlers.lua"
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
new file mode 100644
index 0000000..eab98dd
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
@@ -0,0 +1 @@
+CONFIG_MTD=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
new file mode 100644
index 0000000..6b5832a
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
@@ -0,0 +1,3 @@
+CONFIG_UBOOT=y
+CONFIG_UBOOT_FWENV="/etc/fw_env.config"
+CONFIG_BOOTLOADERHANDLER=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
new file mode 100644
index 0000000..d1c7732
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
@@ -0,0 +1,6 @@
+CONFIG_UBIVOL=y
+CONFIG_UBIATTACH=y
+CONFIG_UBIBLACKLIST=""
+CONFIG_UBIWHITELIST=""
+CONFIG_UBIVIDOFFSET=0
+CONFIG_CFI=y
diff --git a/recipes-core/swupdate/files/swupdate_handlers.lua b/recipes-core/swupdate/files/swupdate_handlers.lua
new file mode 100644
index 0000000..c9b9962
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_handlers.lua
@@ -0,0 +1,449 @@
+--[[
+
+    Round-robin Image and File Handler.
+
+    Copyright (C) 2019, Siemens AG
+
+    Author: Christian Storm <christian.storm@siemens.com>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+
+    An `sw-description` file using these handlers may look like:
+        software =
+        {
+            version = "0.1.0";
+            images: ({
+                filename = "rootfs.ext4";
+                device = "sda4,sda5";
+                type = "roundrobin";
+                compressed = false;
+            });
+            files: ({
+                filename = "vmlinuz";
+                path = "vmlinuz";
+                type = "kernelfile";
+                device = "sda2,sda3";
+                filesystem = "vfat";
+            },
+            {
+                filename = "initrd.img";
+                path = "initrd.img";
+                type = "kernelfile";
+                device = "sda2,sda3";
+                filesystem = "vfat";
+            });
+        }
+
+    The semantics is as follows: Instead of having a fixed target device,
+    the 'roundrobin' image handler calculates the target device by parsing
+    /proc/cmdline, matching the root=<device> kernel parameter against its
+    'device' attribute's list of devices, and sets the actual target
+    device to the next 'device' attribute list entry in a round-robin
+    manner. The actual flashing is done via chain-calling another handler,
+    defaulting to the "raw" handler.
+
+    The 'kernelfile' file handler reuses the 'roundrobin' handler's target
+    device calculation by reading the actual target device from the same
+    index into its 'device' attribute's list of devices. The actual placing
+    of files into this partition is done via chain-calling another handler,
+    defaulting to the "rawfile" handler.
+
+    In the above example, if /dev/sda4 is currently booted according to
+    /proc/cmdline, /dev/sda5 will be flashed and the vmlinuz and initrd.img
+    files will be placed on /dev/sda3. If /dev/sda5 is booted, /dev/sda4
+    will be flashed and the vmlinuz and initrd.img files are placed on
+    /dev/sda2.
+    In addition to "classical" device nodes as in this example, partition
+    UUIDs as reported, e.g., by `blkid -s PARTUUID` are also supported.
+    UBI volumes are supported as well by specifying a CSV list of
+    ubi<number>:<label> items.
+
+    Configuration is done via an INI-style configuration file located at
+    /etc/swupdate.handler.ini or via compiled-in configuration (by
+    embedding the Lua handler script into the SWUpdate binary via using
+    CONFIG_EMBEDDED_LUA_HANDLER), the latter having precedence over the
+    former. See the example configuration below.
+    If uncommenting this example block, it will take precedence over any
+    /etc/swupdate.handler.ini configuration file.
+
+    The chain-called handlers can either be specified in the configuration,
+    i.e., a static run-time setting, or via the 'chainhandler' property of
+    an 'image' or 'file' section in the sw-description, with the latter
+    taking precedence over the former, e.g.,
+        ...
+        images: ({
+                filename = "rootfs.ext4";
+                device = "sda4,sda5";
+                type = "roundrobin";
+                properties: {
+                    chainhandler = "myraw";
+                };
+            });
+        ...
+    Such a sw-description fragment will chain-call the imaginary "myraw"
+    handler regardless of what's been configured in the compiled-in or the
+    configuration file.
+    When chain-calling the "rdiff_image" handler, its 'rdiffbase' property
+    is subject to round-robin as well, i.e., the 'rdiffbase' property is
+    expected to be a CSV list as for the 'device' property, and the actual
+    'rdiffbase' property value is calculated following the same round-robin
+    calculation mechanism stated above prior to chain-calling the actual
+    "rdiff_image" handler, e.g.,
+        images: ({
+                filename = "rootfs.ext4";
+                type = "roundrobin";
+                device = "sda4,sda5";
+                properties: {
+                    chainhandler = "rdiff_image";
+                    rdiffbase="sda1,sda2";
+                };
+            });
+    will set the 'rdiffbase' property to /dev/sda2 (/dev/sda1) if /dev/sda4
+    (/dev/sda5) is the currently booted root file system according to
+    /proc/cmdline parsing.
+
+]]
+
+
+local configuration = [[
+[bootloader]
+# Required: bootloader name, uboot and ebg currently supported.
+name=ebg
+# Required: bootloader-specific key-value pairs, e.g., for ebg:
+kernelname=linux.signed.efi
+# For relying on FAT labels, prefix bootlabels with 'L:', e.g., L:BOOT0.
+# For using custom labels, i.e., relying on the contents of an EFILABEL
+# file within the partition, prefix it with 'C:', e.g., C:BOOT0.
+bootlabel={ "C:BOOT0:", "C:BOOT1:" }
+
+# Optional: handler to chain-call for the 'roundrobin' handler,
+# defaulting to 'raw'
+[roundrobin]
+chainhandler=raw
+
+# Optional: handler to chain-call for the 'kernelfile' handler,
+# defaulting to 'rawfile'
+[kernelfile]
+chainhandler=rawfile
+]]
+
+-- Default configuration file, tried if no compiled-in config is available.
+local cfgfile = "/etc/swupdate.handler.ini"
+
+-- Table holding the configuration.
+local config = {}
+
+-- Mandatory configuration [section] and keys
+local BOOTLOADERCFG = {
+    ebg   = {
+        bootloader = {"name", "bootlabel", "kernelname"}
+    },
+    -- TODO fill with mandatory U-Boot configuration
+    uboot = {
+        bootloader = {"name"}
+    }
+}
+
+-- enum-alikes to make code more readable
+local BOOTLOADER = { EBG = "ebg", UBOOT = "uboot" }
+local PARTTYPE   = { UUID = 1, PLAIN = 2, UBI = 3 }
+
+-- Target table describing the target device the image is to be/has been flashed to.
+local rrtarget = {
+    size = function(self)
+        local _size = 0
+        for index in pairs(self) do _size = _size + 1 end
+        return _size - 1
+    end
+}
+
+-- Helper function parsing CSV fields of a struct img_type such as
+-- the "device" fields or the "rdiffbase" property.
+local get_device_list = function(device_node_csv_list)
+    local device_list = {}
+    for item in device_node_csv_list:gmatch("([^,]+)") do
+        local device_node = item:gsub("/dev/", "")
+        device_list[#device_list+1] = device_node
+        device_list[device_node] = #device_list
+    end
+    return device_list
+end
+
+-- Helper function to determine device node location.
+local get_device_path = function(device_node)
+    if device_node:match("ubi%d+:%S+") then
+        return 0, device_node, PARTTYPE.UBI
+    end
+    local device_path = string.format("/dev/disk/by-partuuid/%s", device_node)
+    local file = io.open(device_path, "rb" )
+    if file then
+        file:close()
+        return 0, device_path, PARTTYPE.UUID
+    end
+    device_path = string.format("/dev/%s", device_node)
+    file = io.open(device_path, "rb" )
+    if file then
+        file:close()
+        return 0, device_path, PARTTYPE.PLAIN
+    end
+    swupdate.error(string.format("Cannot access target device node /dev/{,disk/by-partuuid}/%s", device_node))
+    return 1, nil, nil
+end
+
+-- Helper function parsing the INI-style configuration.
+local get_config = function()
+    -- Return configuration right away if it's already parsed.
+    if config ~= nil and #config > 0 then
+        return config
+    end
+
+    -- Get configuration INI-style string.
+    if not configuration then
+        swupdate.trace(string.format("No compiled-in config found, trying %s", cfgfile))
+        local file = io.open(cfgfile, "r" )
+        if not file then
+            swupdate.error(string.format("Cannot open config file %s", cfgfile))
+            return nil
+        end
+        configuration = file:read("*a")
+        file:close()
+    end
+    if configuration:sub(-1) ~= "\n" then
+        configuration=configuration.."\n"
+    end
+
+    -- Parse INI-style contents into config table.
+    local sec, key, value
+    for line in configuration:gmatch("(.-)\n") do
+        if line:match("^%[([%w%p]+)%][%s]*") then
+            sec = line:match("^%[([%w%p]+)%][%s]*")
+            config[sec] = {}
+        elseif sec then
+            key, value = line:match("^([%w%p]-)=(.*)$")
+            if key and value then
+                if tonumber(value)  then value = tonumber(value) end
+                if value == "true"  then value = true            end
+                if value == "false" then value = false           end
+                if value:sub(1,1) == "{" then
+                    local _value = {}
+                    for _key, _ in value:gmatch("\"(%S+)\"") do
+                        table.insert(_value, _key)
+                    end
+                    value = _value
+                end
+                config[sec][key] = value
+            else
+                if not line:match("^$") and not line:match("^#") then
+                    swupdate.warn(string.format("Syntax error, skipping '%s'", line))
+                end
+            end
+        else
+            swupdate.error(string.format("Syntax error. no [section] encountered."))
+            return nil
+        end
+    end
+
+    -- Check config table for mandatory key existence.
+    if config["bootloader"] == nil or config["bootloader"]["name"] == nil then
+        swupdate.error(string.format("Syntax error. no [bootloader] encountered or name= missing therein."))
+        return nil
+    end
+    local bcfg = BOOTLOADERCFG[config.bootloader.name]
+    if not bcfg then
+        swupdate.error(string.format("Bootloader unsupported, name=uboot|ebg missing in [bootloader]?."))
+        return nil
+    end
+    for sec, _ in pairs(bcfg) do
+        for _, key in pairs(bcfg[sec]) do
+            if config[sec] == nil or config[sec][key] == nil then
+                swupdate.error(string.format("Mandatory config key %s= in [%s] not found.", key, sec))
+            end
+        end
+    end
+
+    return config
+end
+
+-- Round-robin image handler for updating the root partition.
+function handler_roundrobin(image)
+    -- Read configuration.
+    if not get_config() then
+        swupdate.error("Cannot read configuration.")
+        return 1
+    end
+
+    -- Check if we can chain-call the handler.
+    local chained_handler = "raw"
+    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
+        chained_handler = image.properties["chainhandler"]
+    elseif config["roundrobin"] ~= nil and config["roundrobin"]["chainhandler"] ~= nil then
+        chained_handler = config["roundrobin"]["chainhandler"]
+    end
+    if not swupdate.handler[chained_handler] then
+        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution.", chained_handler))
+        return 1
+    end
+
+    -- Get device list for round-robin.
+    local devices = get_device_list(image.device)
+    if #devices < 2 then
+        swupdate.error("Specify at least 2 devices in the device= property for 'roundrobin'.")
+        return 1
+    end
+
+    -- Check that rrtarget is unset, else a reboot may be pending.
+    if rrtarget:size() > 0 then
+        swupdate.warn("The 'roundrobin' handler has been run. Is a reboot pending?")
+    end
+
+    -- Determine current root device.
+    local file = io.open("/proc/cmdline", "r")
+    if not file then
+        swupdate.error("Cannot open /proc/cmdline.")
+        return 1
+    end
+    local cmdline = file:read("*l")
+    file:close()
+
+    local rootparam, rootdevice
+    for item in cmdline:gmatch("%S+") do
+        rootparam, rootdevice = item:match("(root=[%u=]*[/dev/]*(%S+))")
+        if rootparam and rootdevice then break end
+    end
+    if not rootdevice then
+      swupdate.error("Cannot determine current root device.")
+      return 1
+    end
+    swupdate.info(string.format("Current root device is: %s", rootdevice))
+
+    if not devices[rootdevice] then
+        swupdate.error(string.format("Current root device '%s' is not in round-robin root devices list: %s", rootdevice, image.device:gsub("/dev/", "")))
+        return 1
+    end
+
+    -- Perform round-robin calculation for target.
+    local err
+    rrtarget.index = devices[rootdevice] % #devices + 1
+    rrtarget.device_node = devices[rrtarget.index]
+    err, rrtarget.device_path, rrtarget.parttype = get_device_path(devices[rrtarget.index])
+    if err ~= 0 then
+        return 1
+    end
+    swupdate.info(string.format("Using '%s' as 'roundrobin' target via '%s' handler.", rrtarget.device_path, chained_handler))
+
+    -- If the chain-called handler is rdiff_image, adapt the rdiffbase property
+    if chained_handler == "rdiff_image" then
+        if image.properties ~= nil and image.properties["rdiffbase"] ~= nil then
+            local rdiffbase_devices = get_device_list(image.properties["rdiffbase"])
+            if #rdiffbase_devices < 2 then
+                swupdate.error("Specify at least 2 devices in the rdiffbase= property for 'roundrobin'.")
+                return 1
+            end
+            err, image.propierties["rdiffbase"], _ = get_device_path(rdiffbase_devices[rrtarget.index])
+            if err ~= 0 then
+                return 1
+            end
+            swupdate.info(string.format("Using device %s as rdiffbase.", image.properties["rdiffbase"]))
+        else
+            swupdate.error("Property 'rdiffbase' is missing in sw-description.")
+            return 1
+        end
+    end
+
+    -- Actually flash the partition.
+    local msg
+    image.type = chained_handler
+    image.device = rrtarget.device_path
+    err, msg = swupdate.call_handler(chained_handler, image)
+    if err ~= 0 then
+        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
+        return 1
+    end
+
+    if config.bootloader.name == BOOTLOADER.EBG then
+      if rootparam then
+        local value = cmdline:gsub(
+            rootparam:gsub("%-", "%%-"),
+            string.format("root=%s%s",
+                (rrtarget.parttype == PARTTYPE.PLAIN and "") or (rrtarget.parttype == PARTTYPE.UBI and "") or "PARTUUID=",
+                 rrtarget.parttype == PARTTYPE.PLAIN and rrtarget.device_path or devices[rrtarget.index]
+            )
+        )
+        swupdate.info(string.format("Setting EFI Bootguard environment: kernelparams=%s", value))
+        swupdate.set_bootenv("kernelparams", value)
+      end
+    elseif config.bootloader.name == BOOTLOADER.UBOOT then
+        -- Update U-Boot environment.
+        swupdate.info(string.format("Setting U-Boot environment"))
+        local value = rrtarget.index
+        swupdate.set_bootenv("swupdpart", value);
+    end
+
+    return 0
+end
+
+-- File handler for updating kernel files.
+function handler_kernelfile(image)
+    -- Check if we can chain-call the handler.
+    local chained_handler = "rawfile"
+    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
+        chained_handler = image.properties["chainhandler"]
+    elseif config["kernelfile"] ~= nil and config["kernelfile"]["chainhandler"] ~= nil then
+        chained_handler = config["kernelfile"]["chainhandler"]
+    end
+    if not swupdate.handler[chained_handler] then
+        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution."), chained_handler)
+        return 1
+    end
+
+    -- Check that rrtarget is set, else the 'roundrobin' handler hasn't been run.
+    if rrtarget:size() == 0 then
+        swupdate.error("The 'roundrobin' handler hasn't been run.")
+        swupdate.info("Place 'roundrobin' above 'kernelfile' in sw-description.")
+        return 1
+    end
+
+    -- Get device list for round-robin.
+    local devices = get_device_list(image.device)
+    if #devices < 2 then
+        swupdate.error("Specify at least 2 devices in the device= property for 'kernelfile'.")
+        return 1
+    end
+    if rrtarget.index > #devices then
+        swupdate.error("Cannot map kernel partition to root partition.")
+        return 1
+    end
+
+    -- Perform round-robin indexing for target.
+    local err
+    err, image.device, _ = get_device_path(devices[rrtarget.index])
+    if err ~= 0 then
+        return 1
+    end
+    swupdate.info(string.format("Using '%s' as 'kernelfile' target via '%s' handler.", image.device, chained_handler))
+
+    -- Actually copy the 'kernelfile' files.
+    local msg
+    image.type = chained_handler
+    err, msg = swupdate.call_handler(chained_handler, image)
+    if err ~= 0 then
+        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
+        return 1
+    end
+
+    if config.bootloader.name == BOOTLOADER.EBG then
+        -- Update EFI Boot Guard environment: kernelfile
+        local value = string.format("%s%s", config.bootloader.bootlabel[rrtarget.index], config.bootloader.kernelname)
+        swupdate.info(string.format("Setting EFI Bootguard environment: kernelfile=%s", value))
+        swupdate.set_bootenv("kernelfile", value)
+    elseif config.bootloader.name == BOOTLOADER.UBOOT then
+        -- Update U-Boot environment.
+        swupdate.info(string.format("Setting U-Boot environment"))
+        -- TODO
+    end
+
+    return 0
+end
+
+swupdate.register_handler("roundrobin", handler_roundrobin, swupdate.HANDLER_MASK.IMAGE_HANDLER)
+swupdate.register_handler("kernelfile", handler_kernelfile, swupdate.HANDLER_MASK.FILE_HANDLER)
diff --git a/recipes-core/swupdate/swupdate.bb b/recipes-core/swupdate/swupdate.bb
new file mode 100644
index 0000000..9c58f7d
--- /dev/null
+++ b/recipes-core/swupdate/swupdate.bb
@@ -0,0 +1,54 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+hDESCRIPTION = "swupdate utility for software updates"
+HOMEPAGE= "https://github.com/sbabic/swupdate"
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
+
+SRC_URI = "gitsm://code.siemens.com/mirror/swupdate.git;branch=master;protocol=https"
+
+SRCREV = "1a6dfbb5a0be978ac1a159758e278ab4d44167e2"
+PV = "2020.4-git+isar"
+
+DEFCONFIG := "swupdate_defconfig"
+
+SRC_URI += "file://debian \
+            file://${DEFCONFIG} \
+            file://${PN}.cfg"
+
+DEPENDS += "libubootenv"
+
+DEBIAN_DEPENDS = "${shlibs:Depends}, ${misc:Depends}"
+
+inherit dpkg
+inherit swupdate-config
+
+KFEATURES += "luahandler"
+
+S = "${WORKDIR}/git"
+
+TEMPLATE_FILES = "debian/changelog.tmpl debian/control.tmpl debian/rules.tmpl"
+TEMPLATE_VARS += "BUILD_DEB_DEPENDS DEFCONFIG DEBIAN_DEPENDS"
+
+do_prepare_build() {
+        DEBDIR=${S}/debian
+        cp -R ${WORKDIR}/debian ${S}
+
+        install -m 0644 ${WORKDIR}/${PN}.cfg ${S}/swupdate.cfg
+        install -m 0644 ${WORKDIR}/${DEFCONFIG}.gen ${S}/configs/${DEFCONFIG}
+
+        if ! grep -q "configs/${DEFCONFIG}" ${S}/.gitignore
+        then
+                echo "configs/${DEFCONFIG}" >> ${S}/.gitignore
+        fi
+        # luahandler
+        install -m 0644 ${WORKDIR}/${SWUPDATE_LUASCRIPT} ${S}
+}
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4819): https://lists.cip-project.org/g/cip-dev/message/4819
Mute This Topic: https://lists.cip-project.org/mt/75102475/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core RFC 4/4] wic: Add wks files for A/B Partition update
  2020-06-25 13:21 [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update Quirin Gylstorff
                   ` (2 preceding siblings ...)
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 3/4] recipes-core: add swupdate Quirin Gylstorff
@ 2020-06-25 13:21 ` Quirin Gylstorff
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
  2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
  5 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-25 13:21 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 3704 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add wks for:
- simatic-ipc227e
- qemu-amd64

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 kas/opt/ebg-swu.yml                  | 26 ++++++++++++++++++++++++++
 wic/ebg-sysparts.inc                 |  8 ++++++++
 wic/qemu-amd64-efibootguard.wks      |  5 +++++
 wic/simatic-ipc227e-efibootguard.wks |  5 +++++
 wic/swupdate-partition.inc           |  4 ++++
 5 files changed, 48 insertions(+)
 create mode 100644 kas/opt/ebg-swu.yml
 create mode 100644 wic/ebg-sysparts.inc
 create mode 100644 wic/qemu-amd64-efibootguard.wks
 create mode 100644 wic/simatic-ipc227e-efibootguard.wks
 create mode 100644 wic/swupdate-partition.inc

diff --git a/kas/opt/ebg-swu.yml b/kas/opt/ebg-swu.yml
new file mode 100644
index 0000000..5b39730
--- /dev/null
+++ b/kas/opt/ebg-swu.yml
@@ -0,0 +1,26 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+header:
+  version: 8
+
+local_conf_header:
+  swupdate: |
+    IMAGE_INSTALL_append = " swupdate efibootguard"
+    BOOTLOADER = "efibootguard"
+
+  efibootguard: |
+    WDOG_TIMEOUT = "0"
+    WICVARS += "WDOG_TIMEOUT"
+
+  wic: |
+    IMAGE_TYPE = "wic-img"
+    WKS_FILE = "${MACHINE}-${BOOTLOADER}.wks"
diff --git a/wic/ebg-sysparts.inc b/wic/ebg-sysparts.inc
new file mode 100644
index 0000000..dea99e8
--- /dev/null
+++ b/wic/ebg-sysparts.inc
@@ -0,0 +1,8 @@
+# default partition layout EFI Boot Guard usage
+
+# EFI partition containing efibootguard bootloader binary
+part --source efibootguard-efi  --ondisk sda --size 16M --extra-space 0 --overhead-factor 1 --label efi   --align 1024 --part-type=EF00 --active
+
+# EFI Boot Guard environment/config partitions plus Kernel files
+part --source efibootguard-boot --ondisk sda --size 32M --extra-space 0 --overhead-factor 1 --label BOOT0 --align 1024 --part-type=0700 --sourceparams "revision=2,root=PARTUUID:fedcba98-7654-3210-cafe-5e0710000001"
+part --source efibootguard-boot --ondisk sda --size 32M --extra-space 0 --overhead-factor 1 --label BOOT1 --align 1024 --part-type=0700 --sourceparams "revision=1,root=PARTUUID:fedcba98-7654-3210-cafe-5e0710000002"
diff --git a/wic/qemu-amd64-efibootguard.wks b/wic/qemu-amd64-efibootguard.wks
new file mode 100644
index 0000000..74446d3
--- /dev/null
+++ b/wic/qemu-amd64-efibootguard.wks
@@ -0,0 +1,5 @@
+# short-description: Simatic-ipc227e with EFI Boot Guard and SWUpdate
+# long-description: Disk image for Simatic-ipc227e with EFI Boot Guard and SWUpdate
+
+include ebg-sysparts.inc
+include swupdate-partition.inc
diff --git a/wic/simatic-ipc227e-efibootguard.wks b/wic/simatic-ipc227e-efibootguard.wks
new file mode 100644
index 0000000..74446d3
--- /dev/null
+++ b/wic/simatic-ipc227e-efibootguard.wks
@@ -0,0 +1,5 @@
+# short-description: Simatic-ipc227e with EFI Boot Guard and SWUpdate
+# long-description: Disk image for Simatic-ipc227e with EFI Boot Guard and SWUpdate
+
+include ebg-sysparts.inc
+include swupdate-partition.inc
diff --git a/wic/swupdate-partition.inc b/wic/swupdate-partition.inc
new file mode 100644
index 0000000..15fbe80
--- /dev/null
+++ b/wic/swupdate-partition.inc
@@ -0,0 +1,4 @@
+part --source rootfs --uuid "fedcba98-7654-3210-cafe-5e0710000001" --size 1000M   --extra-space 128M --overhead-factor 1 --label systema --align 1024 --fstype=ext4
+part  --source rootfs --uuid "fedcba98-7654-3210-cafe-5e0710000002" --size 1000M   --extra-space 128M --overhead-factor 1 --label systemb --align 1024 --fstype=ext4
+
+bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 rootwait earlyprintk"
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4820): https://lists.cip-project.org/g/cip-dev/message/4820
Mute This Topic: https://lists.cip-project.org/mt/75102476/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [cip-dev] [isar-cip-core RFC 3/4] recipes-core: add swupdate
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 3/4] recipes-core: add swupdate Quirin Gylstorff
@ 2020-06-26 13:05   ` Jan Kiszka
  2020-06-29  9:03     ` Quirin Gylstorff
  0 siblings, 1 reply; 22+ messages in thread
From: Jan Kiszka @ 2020-06-26 13:05 UTC (permalink / raw)
  To: Q. Gylstorff, cip-dev

[-- Attachment #1: Type: text/plain, Size: 46800 bytes --]

On 25.06.20 15:21, Q. Gylstorff wrote:
> From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
> 
> Add swupdate for A/B software updates. Currently the Round Robin
> handler in lua supports efibootguard as bootloader. The u-boot
> implementation is outstanding.
> 
> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
> ---
>   classes/kconfig-snippets.bbclass              |  90 ++++
>   classes/swupdate-config.bbclass               |  76 +++
>   classes/swupdate-img.bbclass                  |  75 +++
>   .../swupdate/files/debian/changelog.tmpl      |   6 +
>   recipes-core/swupdate/files/debian/compat     |   1 +
>   .../swupdate/files/debian/control.tmpl        |  15 +
>   recipes-core/swupdate/files/debian/copyright  |  36 ++
>   recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
>   .../swupdate/files/debian/swupdate.examples   |   2 +
>   .../swupdate/files/debian/swupdate.install    |   2 +
>   .../swupdate/files/debian/swupdate.manpages   |   5 +
>   .../swupdate/files/debian/swupdate.tmpfile    |   2 +
>   recipes-core/swupdate/files/debian/watch      |  12 +
>   recipes-core/swupdate/files/postinst          |   2 +
>   recipes-core/swupdate/files/swupdate.cfg      |   6 +
>   .../swupdate/files/swupdate.service.example   |  11 +
>   .../swupdate/files/swupdate.socket.example    |  11 +
>   .../swupdate/files/swupdate.socket.tmpl       |  13 +
>   .../swupdate/files/swupdate_defconfig         |  83 ++++
>   .../swupdate_defconfig_efibootguard.snippet   |   3 +
>   .../files/swupdate_defconfig_lua.snippet      |   2 +
>   .../swupdate_defconfig_luahandler.snippet     |   4 +
>   .../files/swupdate_defconfig_mtd.snippet      |   1 +
>   .../files/swupdate_defconfig_u-boot.snippet   |   3 +
>   .../files/swupdate_defconfig_ubi.snippet      |   6 +
>   .../swupdate/files/swupdate_handlers.lua      | 449 ++++++++++++++++++
>   recipes-core/swupdate/swupdate.bb             |  54 +++
>   27 files changed, 1000 insertions(+)
>   create mode 100644 classes/kconfig-snippets.bbclass
>   create mode 100644 classes/swupdate-config.bbclass
>   create mode 100644 classes/swupdate-img.bbclass
>   create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
>   create mode 100644 recipes-core/swupdate/files/debian/compat
>   create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
>   create mode 100644 recipes-core/swupdate/files/debian/copyright
>   create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
>   create mode 100644 recipes-core/swupdate/files/debian/watch
>   create mode 100644 recipes-core/swupdate/files/postinst
>   create mode 100644 recipes-core/swupdate/files/swupdate.cfg
>   create mode 100644 recipes-core/swupdate/files/swupdate.service.example
>   create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
>   create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
>   create mode 100644 recipes-core/swupdate/swupdate.bb
> 
> diff --git a/classes/kconfig-snippets.bbclass b/classes/kconfig-snippets.bbclass
> new file mode 100644
> index 0000000..d754654
> --- /dev/null
> +++ b/classes/kconfig-snippets.bbclass
> @@ -0,0 +1,90 @@
> +#
> +# CIP Core, generic profile
> +#
> +# Copyright (c) Siemens AG, 2020
> +#
> +# Authors:
> +#  Christian Storm <christian.storm@siemens.com>
> +#
> +# SPDX-License-Identifier: MIT
> +
> +KCONFIG_SNIPPETS = ""
> +
> +# The following function defines the kconfig snippet system
> +# with automatich debian dependency injection
> +#
> +# To define a feature set, the user has to define the following
> +# variable to an empty string:
> +#
> +# KFEATURE_featurename = ""
> +#
> +# Then, required additions to the variables can be defined:
> +#
> +# KFEATURE_featurename[KCONFIG_SNIPPETS] = "file://snippet-file-name.snippet"
> +# KFEATURE_featurename[SRC_URI] = "file://required-file.txt"
> +# KFEATURE_featurename[DEPENDS] = "deb-pkg1 deb-pkg2 deb-pkg3"
> +# KFEATURE_featurename[DEBIAN_DEPENDS] = "deb-pkg1"
> +# KFEATURE_featurename[BUILD_DEB_DEPENDS] = "deb-pkg1,deb-pkg2,deb-pkg3"
> +
> +# The 'KCONFIG_SNIPPETS' flag gives a list of URI entries, where only
> +# file:// is supported. These snippets are appended to the DEFCONFIG file.
> +#
> +# Features can depend on other features via the following mechanism:
> +#
> +# KFEATURE_DEPS[feature1] = "feature2"
> +
> +python () {
> +    requested_features = d.getVar("KFEATURES", True) or ""
> +
> +    features = set(requested_features.split())
> +    old_features = set()
> +    feature_deps = d.getVarFlags("KFEATURE_DEPS") or {}
> +    while old_features != features:
> +        diff_features = old_features.symmetric_difference(features)
> +        old_features = features.copy()
> +        for i in diff_features:
> +            features.update(feature_deps.get(i, "").split())
> +
> +    for f in sorted(features):
> +        bb.debug(2, "Feature: " + f)
> +        varname = "KFEATURE_" + f
> +        dummyvar = d.getVar(varname, False)
> +        if dummyvar == None:
> +            bb.error("Feature var " + f + " must be defined with needed flags.")
> +        else:
> +            feature_flags = d.getVarFlags(varname)
> +            for feature_varname in sorted(feature_flags):
> +                if feature_flags.get(feature_varname, "") != "":
> +                    sep = " "
> +
> +                    # Required to add KCONFIG_SNIPPETS to SRC_URI here,
> +                    # because 'SRC_URI += "${KCONFIG_SNIPPETS}"' would
> +                    # conflict with SRC_APT feature.
> +                    if feature_varname == "KCONFIG_SNIPPETS":
> +                        d.appendVar('SRC_URI',
> +                            " " + feature_flags[feature_varname].strip())
> +
> +                    # BUILD_DEP_DEPENDS and DEBIAN_DEPENDS is ',' separated
> +                    # Only add ',' if there is already something there
> +                    if feature_varname in ["BUILD_DEB_DEPENDS",
> +                                           "DEBIAN_DEPENDS"]:
> +                        sep = "," if d.getVar(feature_varname) else ""
> +
> +                    d.appendVar(feature_varname,
> +                        sep + feature_flags[feature_varname].strip())
> +}
> +
> +# DEFCONFIG must be a predefined bitbake variable and the corresponding file
> +# must exist in the WORKDIR.
> +# The resulting generated config is the same file suffixed with ".gen"
> +
> +do_prepare_build_prepend() {
> +        sh -x
> +        GENCONFIG="${WORKDIR}/${DEFCONFIG}".gen
> +        rm -f "$GENCONFIG"
> +        cp "${WORKDIR}/${DEFCONFIG}" "$GENCONFIG"
> +        for CONFIG_SNIPPET in $(echo "${KCONFIG_SNIPPETS}" | sed 's#file://##g')
> +        do
> +                cat ${WORKDIR}/$CONFIG_SNIPPET >> "$GENCONFIG"
> +        done
> +}
> diff --git a/classes/swupdate-config.bbclass b/classes/swupdate-config.bbclass
> new file mode 100644
> index 0000000..7ce51c5
> --- /dev/null
> +++ b/classes/swupdate-config.bbclass
> @@ -0,0 +1,76 @@
> +#
> +# CIP Core, generic profile
> +#
> +# Copyright (c) Siemens AG, 2020
> +#
> +# Authors:
> +#  Christian Storm <christian.storm@siemens.com>
> +#
> +# SPDX-License-Identifier: MIT
> +
> +# This class manages the config snippets together with their dependencies
> +# to build SWUpdate
> +
> +inherit kconfig-snippets
> +
> +BUILD_DEB_DEPENDS = " \
> +    zlib1g-dev, debhelper, libconfig-dev, libarchive-dev, \
> +    python-sphinx:native, dh-systemd, libsystemd-dev"
> +
> +KFEATURE_lua = ""
> +KFEATURE_lua[BUILD_DEB_DEPENDS] = "liblua5.3-dev"
> +KFEATURE_lua[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_lua.snippet"
> +
> +KFEATURE_luahandler = ""
> +KFEATURE_luahandler[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_luahandler.snippet"
> +KFEATURE_luahandler[SRC_URI] = "file://${SWUPDATE_LUASCRIPT}"
> +
> +KFEATURE_DEPS = ""
> +KFEATURE_DEPS[luahandler] = "lua"
> +
> +KFEATURE_efibootguard = ""
> +KFEATURE_efibootguard[BUILD_DEB_DEPENDS] = "efibootguard-dev"
> +KFEATURE_efibootguard[DEBIAN_DEPENDS] = "efibootguard-dev"
> +KFEATURE_efibootguard[DEPENDS] = "efibootguard-dev"
> +KFEATURE_efibootguard[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_efibootguard.snippet"
> +
> +KFEATURE_mtd = ""
> +KFEATURE_mtd[BUILD_DEB_DEPENDS] = "libmtd-dev"
> +KFEATURE_mtd[DEPENDS] = "mtd-utils"
> +KFEATURE_mtd[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_mtd.snippet"
> +
> +KFEATURE_ubi = ""
> +KFEATURE_ubi[BUILD_DEB_DEPENDS] = "libubi-dev"
> +KFEATURE_ubi[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_ubi.snippet"
> +
> +KFEATURE_DEPS[ubi] = "mtd"
> +
> +KFEATURE_u-boot = ""
> +KFEATURE_u-boot[BUILD_DEB_DEPENDS] = "u-boot-${MACHINE}-dev"
> +KFEATURE_u-boot[DEBIAN_DEPENDS] = "u-boot-tools"
> +KFEATURE_u-boot[DEPENDS] = "${U_BOOT}"
> +KFEATURE_u-boot[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_u-boot.snippet"
> +
> +SWUPDATE_LUASCRIPT ?= "swupdate_handlers.lua"
> +
> +def get_bootloader_featureset(d):
> +    bootloader = d.getVar("BOOTLOADER", True) or ""
> +    if bootloader == "efibootguard":
> +        return "efibootguard"
> +    if bootloader == "u-boot":
> +        return "u-boot"
> +    return ""
> +
> +SWUPDATE_KFEATURES ??= ""
> +KFEATURES = "${SWUPDATE_KFEATURES}"
> +KFEATURES += "${@get_bootloader_featureset(d)}"
> +
> +# Astonishingly, as an anonymous python function, BOOTLOADER is always None
> +# one time before it gets set. So the following must be a task.
> +python do_check_bootloader () {
> +    bootloader = d.getVar("BOOTLOADER", True) or "None"
> +    if not bootloader in ["efibootguard", "u-boot"]:
> +        bb.warn("swupdate: BOOTLOADER set to incompatible value: " + bootloader)
> +}
> +addtask check_bootloader before do_fetch
> +
> diff --git a/classes/swupdate-img.bbclass b/classes/swupdate-img.bbclass
> new file mode 100644
> index 0000000..a21d6ec
> --- /dev/null
> +++ b/classes/swupdate-img.bbclass
> @@ -0,0 +1,75 @@
> +#
> +# CIP Core, generic profile
> +#
> +# Copyright (c) Siemens AG, 2020
> +#
> +# Authors:
> +#  Christian Storm <christian.storm@siemens.com>
> +#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
> +#
> +# SPDX-License-Identifier: MIT
> +
> +SWU_IMAGE_FILE ?= "${PN}-${DISTRO}-${MACHINE}.swu"
> +SWU_DESCRIPTION_FILE ?= "sw-description"
> +SWU_ADDITIONAL_FILES ?= ""
> +SWU_SIGNED ?= ""
> +SWU_SIGNATURE_EXT ?= "sig"
> +SWU_SIGNATURE_TYPE ?= "rsa"
> +
> +IMAGER_INSTALL += "${@'openssl' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}"
> +
> +do_swupdate_image[stamp-extra-info] = "${DISTRO}-${MACHINE}"
> +do_swupdate_image[cleandirs] += "${WORKDIR}/swu"
> +do_swupdate_image() {
> +    rm -f '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
> +    cp '${WORKDIR}/${SWU_DESCRIPTION_FILE}' '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
> +
> +    # Create symlinks for files used in the update image
> +    for file in ${SWU_ADDITIONAL_FILES}; do
> +        if [ -e "${WORKDIR}/$file" ]; then
> +            ln -s "${WORKDIR}/$file" "${WORKDIR}/swu/$file"
> +        else
> +            ln -s "${DEPLOY_DIR_IMAGE}/$file" "${WORKDIR}/swu/$file"
> +        fi
> +    done
> +
> +    # Prepare for signing
> +    sign='${@'x' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}'
> +    if [ -n "$sign" ]; then
> +        image_do_mounts
> +        cp -f '${SIGN_KEY}' '${WORKDIR}/dev.key'
> +        test -e '${SIGN_CRT}' && cp -f '${SIGN_CRT}' '${WORKDIR}/dev.crt'
> +
> +        # Fill in file check sums
> +        for file in ${SWU_ADDITIONAL_FILES}; do
> +            sed -i "s:$file-sha256:$(sha256sum '${WORKDIR}/swu/'$file | cut -f 1 -d ' '):g" \
> +                '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
> +        done
> +    fi
> +
> +    cd "${WORKDIR}/swu"
> +    for file in '${SWU_DESCRIPTION_FILE}' ${SWU_ADDITIONAL_FILES}; do
> +        echo "$file"
> +        if [ -n "$sign" -a \
> +             '${SWU_DESCRIPTION_FILE}' = "$file" ]; then
> +            if [ "${SWU_SIGNATURE_TYPE}" = "rsa" ]; then
> +                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl dgst \
> +                    -sha256 -sign '${PP_WORK}/dev.key' \
> +                    '${PP_WORK}/swu/'"$file" \
> +                        > '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}'
> +            elif [ "${SWU_SIGNATURE_TYPE}" = "cms" ]; then
> +                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl cms \
> +                    -sign -in '${PP_WORK}/swu/'"$file" \
> +                    -out '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}' \
> +                    -signer '${PP_WORK}/dev.crt' \
> +                    -inkey '${PP_WORK}/dev.key' \
> +                    -outform DER -nosmimecap -binary
> +            fi
> +            echo "$file".'${SWU_SIGNATURE_EXT}'
> +        fi
> +    done | cpio -ovL -H crc \
> +        > '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
> +    cd -
> +}
> +
> +addtask swupdate_image before do_build after do_copy_boot_files do_install_imager_deps do_transform_template
> diff --git a/recipes-core/swupdate/files/debian/changelog.tmpl b/recipes-core/swupdate/files/debian/changelog.tmpl
> new file mode 100644
> index 0000000..81087d3
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/changelog.tmpl
> @@ -0,0 +1,6 @@
> +swupdate (${PV}) unstable; urgency=medium
> +
> +  * SWUpdate
> +
> + --  Christian Storm <christian.storm@siemens.com>  Thu, 31 Jan 2019 15:23:56 +0100
> +
> diff --git a/recipes-core/swupdate/files/debian/compat b/recipes-core/swupdate/files/debian/compat
> new file mode 100644
> index 0000000..b4de394
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/compat
> @@ -0,0 +1 @@
> +11
> diff --git a/recipes-core/swupdate/files/debian/control.tmpl b/recipes-core/swupdate/files/debian/control.tmpl
> new file mode 100644
> index 0000000..2b92850
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/control.tmpl
> @@ -0,0 +1,15 @@
> +Source: swupdate
> +Section: embedded
> +Priority: optional
> +Maintainer: Stefano Babic <sbabic@denx.de>
> +Build-Depends: ${BUILD_DEB_DEPENDS}
> +Standards-Version: 4.2.1
> +Homepage: http://sbabic.github.io/swupdate
> +
> +Package: swupdate
> +Architecture: any
> +Depends: ${DEBIAN_DEPENDS}
> +Description: reliable way to update an embedded system
> + This project is thought to help to update an embedded system from a storage media or from network.
> + However, it should be mainly considered as a framework, where further protocols or installers
> + (in SWUpdate they are called handlers) can be easily added to the application.
> diff --git a/recipes-core/swupdate/files/debian/copyright b/recipes-core/swupdate/files/debian/copyright
> new file mode 100644
> index 0000000..f920942
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/copyright
> @@ -0,0 +1,36 @@
> +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
> +Upstream-Name: swupdate
> +Maintainer: Stefano Babic <sbabic@denx.de>
> +Source: http://github.com/sbabic/swupdate
> +
> +Files: *
> +Copyright: 2014-2017 Stefano Babic <sbabic@denx.de>
> +
> +License: GPL-2 with OpenSSL exception
> + This package is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 2 of the License, or
> + (at your option) any later version.
> + .
> + In addition, as a special exception, the author of this
> + program gives permission to link the code of its
> + release with the OpenSSL project's "OpenSSL" library (or
> + with modified versions of it that use the same license as
> + the "OpenSSL" library), and distribute the linked
> + executables. You must obey the GNU General Public
> + License in all respects for all of the code used other
> + than "OpenSSL".  If you modify this file, you may extend
> + this exception to your version of the file, but you are
> + not obligated to do so.  If you do not wish to do so,
> + delete this exception statement from your version.
> + .
> + This package is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + GNU General Public License for more details.
> + .
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <https://www.gnu.org/licenses/>
> + .
> + On Debian systems, the complete text of the GNU General
> + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
> diff --git a/recipes-core/swupdate/files/debian/rules.tmpl b/recipes-core/swupdate/files/debian/rules.tmpl
> new file mode 100755
> index 0000000..54cca57
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/rules.tmpl
> @@ -0,0 +1,30 @@
> +#!/usr/bin/make -f
> +
> +ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
> +export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
> +export CC=$(DEB_HOST_GNU_TYPE)-gcc
> +export LD=$(DEB_HOST_GNU_TYPE)-gcc
> +endif
> +
> +export DH_VERBOSE = 1
> +
> +export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
> +
> +documentation: configure
> +	make man
> +
> +configure:
> +	make ${DEFCONFIG}
> +
> +build: documentation configure
> +	dh $@
> +
> +%:
> +	echo $@
> +	dh $@
> +
> +override_dh_installchangelogs:
> +	true
> +
> +override_dh_installdocs:
> +	true
> diff --git a/recipes-core/swupdate/files/debian/swupdate.examples b/recipes-core/swupdate/files/debian/swupdate.examples
> new file mode 100644
> index 0000000..c257b75
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/swupdate.examples
> @@ -0,0 +1,2 @@
> +examples/configuration
> +examples/description
> diff --git a/recipes-core/swupdate/files/debian/swupdate.install b/recipes-core/swupdate/files/debian/swupdate.install
> new file mode 100644
> index 0000000..8957cc6
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/swupdate.install
> @@ -0,0 +1,2 @@
> +swupdate usr/bin
> +swupdate.cfg /etc
> diff --git a/recipes-core/swupdate/files/debian/swupdate.manpages b/recipes-core/swupdate/files/debian/swupdate.manpages
> new file mode 100644
> index 0000000..c3438e0
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/swupdate.manpages
> @@ -0,0 +1,5 @@
> +doc/build/man/swupdate.1
> +doc/build/man/client.1
> +doc/build/man/sendtohawkbit.1
> +doc/build/man/hawkbitcfg.1
> +doc/build/man/progress.1
> diff --git a/recipes-core/swupdate/files/debian/swupdate.tmpfile b/recipes-core/swupdate/files/debian/swupdate.tmpfile
> new file mode 100644
> index 0000000..4743672
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/swupdate.tmpfile
> @@ -0,0 +1,2 @@
> +X /tmp/datadst
> +X /tmp/scripts
> diff --git a/recipes-core/swupdate/files/debian/watch b/recipes-core/swupdate/files/debian/watch
> new file mode 100644
> index 0000000..bc4c53e
> --- /dev/null
> +++ b/recipes-core/swupdate/files/debian/watch
> @@ -0,0 +1,12 @@
> +# Example watch control file for uscan
> +# Rename this file to "watch" and then you can run the "uscan" command
> +# to check for upstream updates and more.
> +# See uscan(1) for format
> +
> +# Compulsory line, this is a version 4 file
> +version=4
> +
> +# GitHub hosted projects
> +opts="filenamemangle="s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
> +   https://github.com/<user>/swupdate/tags \
> +   (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
> diff --git a/recipes-core/swupdate/files/postinst b/recipes-core/swupdate/files/postinst
> new file mode 100644
> index 0000000..f15ac10
> --- /dev/null
> +++ b/recipes-core/swupdate/files/postinst
> @@ -0,0 +1,2 @@
> +#!/bin/sh
> +deb-systemd-helper enable swupdate.socket || true
> diff --git a/recipes-core/swupdate/files/swupdate.cfg b/recipes-core/swupdate/files/swupdate.cfg
> new file mode 100644
> index 0000000..e0222f1
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate.cfg
> @@ -0,0 +1,6 @@
> +globals :
> +{
> +    verbose = true;
> +    loglevel = 10;
> +    syslog = false;
> +};
> diff --git a/recipes-core/swupdate/files/swupdate.service.example b/recipes-core/swupdate/files/swupdate.service.example
> new file mode 100644
> index 0000000..d0b821e
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate.service.example
> @@ -0,0 +1,11 @@
> +[Unit]
> +Description=SWUpdate daemon
> +Documentation=https://github.com/sbabic/swupdate
> +
> +[Service]
> +Type=simple
> +ExecStart=/usr/bin/swupdate -f /etc/swupdate.cfg
> +KillMode=mixed
> +
> +[Install]
> +WantedBy=multi-user.target
> diff --git a/recipes-core/swupdate/files/swupdate.socket.example b/recipes-core/swupdate/files/swupdate.socket.example
> new file mode 100644
> index 0000000..2b75671
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate.socket.example
> @@ -0,0 +1,11 @@
> +[Unit]
> +Description=SWUpdate socket listener
> +Documentation=https://github.com/sbabic/swupdate
> +Documentation=https://sbabic.github.io/swupdate
> +
> +[Socket]
> +ListenStream=/tmp/sockinstctrl
> +ListenStream=/tmp/swupdateprog
> +
> +[Install]
> +WantedBy=sockets.target
> diff --git a/recipes-core/swupdate/files/swupdate.socket.tmpl b/recipes-core/swupdate/files/swupdate.socket.tmpl
> new file mode 100644
> index 0000000..8e7fc1d
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate.socket.tmpl
> @@ -0,0 +1,13 @@
> +[Unit]
> +Description=SWUpdate socket listener
> +Documentation=https://github.com/sbabic/swupdate
> +Documentation=https://sbabic.github.io/swupdate
> +
> +[Socket]
> +SocketUser=${SWUPDATE_SOCKET_OWNER}
> +SocketGroup=root
> +ListenStream=/tmp/sockinstctrl
> +ListenStream=/tmp/swupdateprog
> +
> +[Install]
> +WantedBy=sockets.target
> diff --git a/recipes-core/swupdate/files/swupdate_defconfig b/recipes-core/swupdate/files/swupdate_defconfig
> new file mode 100644
> index 0000000..9ae7cb5
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_defconfig
> @@ -0,0 +1,83 @@
> +#
> +# Automatically generated file; DO NOT EDIT.
> +# Swupdate Configuration
> +#
> +CONFIG_HAVE_DOT_CONFIG=y
> +
> +#
> +# Swupdate Settings
> +#
> +
> +#
> +# General Configuration
> +#
> +# CONFIG_CURL is not set
> +# CONFIG_CURL_SSL is not set
> +CONFIG_SYSTEMD=y
> +CONFIG_SCRIPTS=y
> +# CONFIG_HW_COMPATIBILITY is not set
> +CONFIG_SW_VERSIONS_FILE="/etc/sw-versions"
> +
> +#
> +# Socket Paths
> +#
> +CONFIG_SOCKET_CTRL_PATH="/tmp/sockinstctrl"
> +CONFIG_SOCKET_PROGRESS_PATH="/tmp/swupdateprog"
> +CONFIG_SOCKET_REMOTE_HANDLER_DIRECTORY="/tmp/"
> +# CONFIG_MTD is not set
> +# CONFIG_LUA is not set
> +# CONFIG_LUAPKG is not set
> +# CONFIG_FEATURE_SYSLOG is not set
> +
> +#
> +# Build Options
> +#
> +CONFIG_CROSS_COMPILE=""
> +CONFIG_SYSROOT=""
> +CONFIG_EXTRA_CFLAGS=""
> +CONFIG_EXTRA_LDFLAGS=""
> +CONFIG_EXTRA_LDLIBS=""
> +
> +#
> +# Debugging Options
> +#
> +# CONFIG_DEBUG is not set
> +# CONFIG_WERROR is not set
> +# CONFIG_NOCLEANUP is not set
> +# CONFIG_BOOTLOADER_EBG is not set
> +# CONFIG_UBOOT is not set
> +# CONFIG_BOOTLOADER_NONE is not set
> +# CONFIG_BOOTLOADER_GRUB is not set
> +# CONFIG_DOWNLOAD is not set
> +# CONFIG_DOWNLOAD_SSL is not set
> +# CONFIG_CHANNEL_CURL is not set
> +# CONFIG_HASH_VERIFY=y
> +# CONFIG_SIGNED_IMAGES is not set
> +# CONFIG_ENCRYPTED_IMAGES is not set
> +# CONFIG_SURICATTA is not set
> +# CONFIG_WEBSERVER is not set
> +CONFIG_GUNZIP=y
> +
> +#
> +# Parser Features
> +#
> +CONFIG_LIBCONFIG=y
> +CONFIG_PARSERROOT=""
> +# CONFIG_JSON is not set
> +# CONFIG_LUAEXTERNAL is not set
> +# CONFIG_SETEXTPARSERNAME is not set
> +# CONFIG_SETSWDESCRIPTION is not set
> +
> +#
> +# Image Handlers
> +#
> +CONFIG_RAW=y
> +# CONFIG_LUASCRIPTHANDLER is not set
> +# CONFIG_SHELLSCRIPTHANDLER is not set
> +# CONFIG_HANDLER_IN_LUA is not set
> +# CONFIG_EMBEDDED_LUA_HANDLER is not set
> +# CONFIG_EMBEDDED_LUA_HANDLER_SOURCE is not set
> +CONFIG_ARCHIVE=y
> +# CONFIG_REMOTE_HANDLER is not set
> +# CONFIG_SWUFORWARDER_HANDLER is not set
> +# CONFIG_BOOTLOADERHANDLER is not set
> diff --git a/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
> new file mode 100644
> index 0000000..8e3688c
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
> @@ -0,0 +1,3 @@
> +CONFIG_BOOTLOADER_NONE=n
> +CONFIG_BOOTLOADER_EBG=y
> +CONFIG_BOOTLOADERHANDLER=y
> diff --git a/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
> new file mode 100644
> index 0000000..b39f9df
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
> @@ -0,0 +1,2 @@
> +CONFIG_LUA=y
> +CONFIG_LUAPKG="lua53"
> diff --git a/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
> new file mode 100644
> index 0000000..b4a2de8
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
> @@ -0,0 +1,4 @@
> +CONFIG_LUASCRIPTHANDLER=y
> +CONFIG_HANDLER_IN_LUA=y
> +CONFIG_EMBEDDED_LUA_HANDLER=y
> +CONFIG_EMBEDDED_LUA_HANDLER_SOURCE="swupdate_handlers.lua"
> diff --git a/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
> new file mode 100644
> index 0000000..eab98dd
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
> @@ -0,0 +1 @@
> +CONFIG_MTD=y
> diff --git a/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
> new file mode 100644
> index 0000000..6b5832a
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
> @@ -0,0 +1,3 @@
> +CONFIG_UBOOT=y
> +CONFIG_UBOOT_FWENV="/etc/fw_env.config"
> +CONFIG_BOOTLOADERHANDLER=y
> diff --git a/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
> new file mode 100644
> index 0000000..d1c7732
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
> @@ -0,0 +1,6 @@
> +CONFIG_UBIVOL=y
> +CONFIG_UBIATTACH=y
> +CONFIG_UBIBLACKLIST=""
> +CONFIG_UBIWHITELIST=""
> +CONFIG_UBIVIDOFFSET=0
> +CONFIG_CFI=y
> diff --git a/recipes-core/swupdate/files/swupdate_handlers.lua b/recipes-core/swupdate/files/swupdate_handlers.lua
> new file mode 100644
> index 0000000..c9b9962
> --- /dev/null
> +++ b/recipes-core/swupdate/files/swupdate_handlers.lua
> @@ -0,0 +1,449 @@
> +--[[
> +
> +    Round-robin Image and File Handler.
> +
> +    Copyright (C) 2019, Siemens AG
> +
> +    Author: Christian Storm <christian.storm@siemens.com>
> +
> +    SPDX-License-Identifier: GPL-2.0-or-later
> +
> +    An `sw-description` file using these handlers may look like:
> +        software =
> +        {
> +            version = "0.1.0";
> +            images: ({
> +                filename = "rootfs.ext4";
> +                device = "sda4,sda5";
> +                type = "roundrobin";
> +                compressed = false;
> +            });
> +            files: ({
> +                filename = "vmlinuz";
> +                path = "vmlinuz";
> +                type = "kernelfile";
> +                device = "sda2,sda3";
> +                filesystem = "vfat";
> +            },
> +            {
> +                filename = "initrd.img";
> +                path = "initrd.img";
> +                type = "kernelfile";
> +                device = "sda2,sda3";
> +                filesystem = "vfat";
> +            });
> +        }
> +
> +    The semantics is as follows: Instead of having a fixed target device,
> +    the 'roundrobin' image handler calculates the target device by parsing
> +    /proc/cmdline, matching the root=<device> kernel parameter against its
> +    'device' attribute's list of devices, and sets the actual target
> +    device to the next 'device' attribute list entry in a round-robin
> +    manner. The actual flashing is done via chain-calling another handler,
> +    defaulting to the "raw" handler.
> +
> +    The 'kernelfile' file handler reuses the 'roundrobin' handler's target
> +    device calculation by reading the actual target device from the same
> +    index into its 'device' attribute's list of devices. The actual placing
> +    of files into this partition is done via chain-calling another handler,
> +    defaulting to the "rawfile" handler.
> +
> +    In the above example, if /dev/sda4 is currently booted according to
> +    /proc/cmdline, /dev/sda5 will be flashed and the vmlinuz and initrd.img
> +    files will be placed on /dev/sda3. If /dev/sda5 is booted, /dev/sda4
> +    will be flashed and the vmlinuz and initrd.img files are placed on
> +    /dev/sda2.
> +    In addition to "classical" device nodes as in this example, partition
> +    UUIDs as reported, e.g., by `blkid -s PARTUUID` are also supported.
> +    UBI volumes are supported as well by specifying a CSV list of
> +    ubi<number>:<label> items.
> +
> +    Configuration is done via an INI-style configuration file located at
> +    /etc/swupdate.handler.ini or via compiled-in configuration (by
> +    embedding the Lua handler script into the SWUpdate binary via using
> +    CONFIG_EMBEDDED_LUA_HANDLER), the latter having precedence over the
> +    former. See the example configuration below.
> +    If uncommenting this example block, it will take precedence over any
> +    /etc/swupdate.handler.ini configuration file.
> +
> +    The chain-called handlers can either be specified in the configuration,
> +    i.e., a static run-time setting, or via the 'chainhandler' property of
> +    an 'image' or 'file' section in the sw-description, with the latter
> +    taking precedence over the former, e.g.,
> +        ...
> +        images: ({
> +                filename = "rootfs.ext4";
> +                device = "sda4,sda5";
> +                type = "roundrobin";
> +                properties: {
> +                    chainhandler = "myraw";
> +                };
> +            });
> +        ...
> +    Such a sw-description fragment will chain-call the imaginary "myraw"
> +    handler regardless of what's been configured in the compiled-in or the
> +    configuration file.
> +    When chain-calling the "rdiff_image" handler, its 'rdiffbase' property
> +    is subject to round-robin as well, i.e., the 'rdiffbase' property is
> +    expected to be a CSV list as for the 'device' property, and the actual
> +    'rdiffbase' property value is calculated following the same round-robin
> +    calculation mechanism stated above prior to chain-calling the actual
> +    "rdiff_image" handler, e.g.,
> +        images: ({
> +                filename = "rootfs.ext4";
> +                type = "roundrobin";
> +                device = "sda4,sda5";
> +                properties: {
> +                    chainhandler = "rdiff_image";
> +                    rdiffbase="sda1,sda2";
> +                };
> +            });
> +    will set the 'rdiffbase' property to /dev/sda2 (/dev/sda1) if /dev/sda4
> +    (/dev/sda5) is the currently booted root file system according to
> +    /proc/cmdline parsing.
> +
> +]]
> +
> +
> +local configuration = [[
> +[bootloader]
> +# Required: bootloader name, uboot and ebg currently supported.
> +name=ebg
> +# Required: bootloader-specific key-value pairs, e.g., for ebg:
> +kernelname=linux.signed.efi
> +# For relying on FAT labels, prefix bootlabels with 'L:', e.g., L:BOOT0.
> +# For using custom labels, i.e., relying on the contents of an EFILABEL
> +# file within the partition, prefix it with 'C:', e.g., C:BOOT0.
> +bootlabel={ "C:BOOT0:", "C:BOOT1:" }
> +
> +# Optional: handler to chain-call for the 'roundrobin' handler,
> +# defaulting to 'raw'
> +[roundrobin]
> +chainhandler=raw
> +
> +# Optional: handler to chain-call for the 'kernelfile' handler,
> +# defaulting to 'rawfile'
> +[kernelfile]
> +chainhandler=rawfile
> +]]
> +
> +-- Default configuration file, tried if no compiled-in config is available.
> +local cfgfile = "/etc/swupdate.handler.ini"
> +
> +-- Table holding the configuration.
> +local config = {}
> +
> +-- Mandatory configuration [section] and keys
> +local BOOTLOADERCFG = {
> +    ebg   = {
> +        bootloader = {"name", "bootlabel", "kernelname"}
> +    },
> +    -- TODO fill with mandatory U-Boot configuration
> +    uboot = {
> +        bootloader = {"name"}
> +    }
> +}
> +
> +-- enum-alikes to make code more readable
> +local BOOTLOADER = { EBG = "ebg", UBOOT = "uboot" }
> +local PARTTYPE   = { UUID = 1, PLAIN = 2, UBI = 3 }
> +
> +-- Target table describing the target device the image is to be/has been flashed to.
> +local rrtarget = {
> +    size = function(self)
> +        local _size = 0
> +        for index in pairs(self) do _size = _size + 1 end
> +        return _size - 1
> +    end
> +}
> +
> +-- Helper function parsing CSV fields of a struct img_type such as
> +-- the "device" fields or the "rdiffbase" property.
> +local get_device_list = function(device_node_csv_list)
> +    local device_list = {}
> +    for item in device_node_csv_list:gmatch("([^,]+)") do
> +        local device_node = item:gsub("/dev/", "")
> +        device_list[#device_list+1] = device_node
> +        device_list[device_node] = #device_list
> +    end
> +    return device_list
> +end
> +
> +-- Helper function to determine device node location.
> +local get_device_path = function(device_node)
> +    if device_node:match("ubi%d+:%S+") then
> +        return 0, device_node, PARTTYPE.UBI
> +    end
> +    local device_path = string.format("/dev/disk/by-partuuid/%s", device_node)
> +    local file = io.open(device_path, "rb" )
> +    if file then
> +        file:close()
> +        return 0, device_path, PARTTYPE.UUID
> +    end
> +    device_path = string.format("/dev/%s", device_node)
> +    file = io.open(device_path, "rb" )
> +    if file then
> +        file:close()
> +        return 0, device_path, PARTTYPE.PLAIN
> +    end
> +    swupdate.error(string.format("Cannot access target device node /dev/{,disk/by-partuuid}/%s", device_node))
> +    return 1, nil, nil
> +end
> +
> +-- Helper function parsing the INI-style configuration.
> +local get_config = function()
> +    -- Return configuration right away if it's already parsed.
> +    if config ~= nil and #config > 0 then
> +        return config
> +    end
> +
> +    -- Get configuration INI-style string.
> +    if not configuration then
> +        swupdate.trace(string.format("No compiled-in config found, trying %s", cfgfile))
> +        local file = io.open(cfgfile, "r" )
> +        if not file then
> +            swupdate.error(string.format("Cannot open config file %s", cfgfile))
> +            return nil
> +        end
> +        configuration = file:read("*a")
> +        file:close()
> +    end
> +    if configuration:sub(-1) ~= "\n" then
> +        configuration=configuration.."\n"
> +    end
> +
> +    -- Parse INI-style contents into config table.
> +    local sec, key, value
> +    for line in configuration:gmatch("(.-)\n") do
> +        if line:match("^%[([%w%p]+)%][%s]*") then
> +            sec = line:match("^%[([%w%p]+)%][%s]*")
> +            config[sec] = {}
> +        elseif sec then
> +            key, value = line:match("^([%w%p]-)=(.*)$")
> +            if key and value then
> +                if tonumber(value)  then value = tonumber(value) end
> +                if value == "true"  then value = true            end
> +                if value == "false" then value = false           end
> +                if value:sub(1,1) == "{" then
> +                    local _value = {}
> +                    for _key, _ in value:gmatch("\"(%S+)\"") do
> +                        table.insert(_value, _key)
> +                    end
> +                    value = _value
> +                end
> +                config[sec][key] = value
> +            else
> +                if not line:match("^$") and not line:match("^#") then
> +                    swupdate.warn(string.format("Syntax error, skipping '%s'", line))
> +                end
> +            end
> +        else
> +            swupdate.error(string.format("Syntax error. no [section] encountered."))
> +            return nil
> +        end
> +    end
> +
> +    -- Check config table for mandatory key existence.
> +    if config["bootloader"] == nil or config["bootloader"]["name"] == nil then
> +        swupdate.error(string.format("Syntax error. no [bootloader] encountered or name= missing therein."))
> +        return nil
> +    end
> +    local bcfg = BOOTLOADERCFG[config.bootloader.name]
> +    if not bcfg then
> +        swupdate.error(string.format("Bootloader unsupported, name=uboot|ebg missing in [bootloader]?."))
> +        return nil
> +    end
> +    for sec, _ in pairs(bcfg) do
> +        for _, key in pairs(bcfg[sec]) do
> +            if config[sec] == nil or config[sec][key] == nil then
> +                swupdate.error(string.format("Mandatory config key %s= in [%s] not found.", key, sec))
> +            end
> +        end
> +    end
> +
> +    return config
> +end
> +
> +-- Round-robin image handler for updating the root partition.
> +function handler_roundrobin(image)
> +    -- Read configuration.
> +    if not get_config() then
> +        swupdate.error("Cannot read configuration.")
> +        return 1
> +    end
> +
> +    -- Check if we can chain-call the handler.
> +    local chained_handler = "raw"
> +    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
> +        chained_handler = image.properties["chainhandler"]
> +    elseif config["roundrobin"] ~= nil and config["roundrobin"]["chainhandler"] ~= nil then
> +        chained_handler = config["roundrobin"]["chainhandler"]
> +    end
> +    if not swupdate.handler[chained_handler] then
> +        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution.", chained_handler))
> +        return 1
> +    end
> +
> +    -- Get device list for round-robin.
> +    local devices = get_device_list(image.device)
> +    if #devices < 2 then
> +        swupdate.error("Specify at least 2 devices in the device= property for 'roundrobin'.")
> +        return 1
> +    end
> +
> +    -- Check that rrtarget is unset, else a reboot may be pending.
> +    if rrtarget:size() > 0 then
> +        swupdate.warn("The 'roundrobin' handler has been run. Is a reboot pending?")
> +    end
> +
> +    -- Determine current root device.
> +    local file = io.open("/proc/cmdline", "r")
> +    if not file then
> +        swupdate.error("Cannot open /proc/cmdline.")
> +        return 1
> +    end
> +    local cmdline = file:read("*l")
> +    file:close()
> +
> +    local rootparam, rootdevice
> +    for item in cmdline:gmatch("%S+") do
> +        rootparam, rootdevice = item:match("(root=[%u=]*[/dev/]*(%S+))")
> +        if rootparam and rootdevice then break end
> +    end
> +    if not rootdevice then
> +      swupdate.error("Cannot determine current root device.")
> +      return 1
> +    end
> +    swupdate.info(string.format("Current root device is: %s", rootdevice))
> +
> +    if not devices[rootdevice] then
> +        swupdate.error(string.format("Current root device '%s' is not in round-robin root devices list: %s", rootdevice, image.device:gsub("/dev/", "")))
> +        return 1
> +    end
> +
> +    -- Perform round-robin calculation for target.
> +    local err
> +    rrtarget.index = devices[rootdevice] % #devices + 1
> +    rrtarget.device_node = devices[rrtarget.index]
> +    err, rrtarget.device_path, rrtarget.parttype = get_device_path(devices[rrtarget.index])
> +    if err ~= 0 then
> +        return 1
> +    end
> +    swupdate.info(string.format("Using '%s' as 'roundrobin' target via '%s' handler.", rrtarget.device_path, chained_handler))
> +
> +    -- If the chain-called handler is rdiff_image, adapt the rdiffbase property
> +    if chained_handler == "rdiff_image" then
> +        if image.properties ~= nil and image.properties["rdiffbase"] ~= nil then
> +            local rdiffbase_devices = get_device_list(image.properties["rdiffbase"])
> +            if #rdiffbase_devices < 2 then
> +                swupdate.error("Specify at least 2 devices in the rdiffbase= property for 'roundrobin'.")
> +                return 1
> +            end
> +            err, image.propierties["rdiffbase"], _ = get_device_path(rdiffbase_devices[rrtarget.index])
> +            if err ~= 0 then
> +                return 1
> +            end
> +            swupdate.info(string.format("Using device %s as rdiffbase.", image.properties["rdiffbase"]))
> +        else
> +            swupdate.error("Property 'rdiffbase' is missing in sw-description.")
> +            return 1
> +        end
> +    end
> +
> +    -- Actually flash the partition.
> +    local msg
> +    image.type = chained_handler
> +    image.device = rrtarget.device_path
> +    err, msg = swupdate.call_handler(chained_handler, image)
> +    if err ~= 0 then
> +        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
> +        return 1
> +    end
> +
> +    if config.bootloader.name == BOOTLOADER.EBG then
> +      if rootparam then
> +        local value = cmdline:gsub(
> +            rootparam:gsub("%-", "%%-"),
> +            string.format("root=%s%s",
> +                (rrtarget.parttype == PARTTYPE.PLAIN and "") or (rrtarget.parttype == PARTTYPE.UBI and "") or "PARTUUID=",
> +                 rrtarget.parttype == PARTTYPE.PLAIN and rrtarget.device_path or devices[rrtarget.index]
> +            )
> +        )
> +        swupdate.info(string.format("Setting EFI Bootguard environment: kernelparams=%s", value))
> +        swupdate.set_bootenv("kernelparams", value)
> +      end
> +    elseif config.bootloader.name == BOOTLOADER.UBOOT then
> +        -- Update U-Boot environment.
> +        swupdate.info(string.format("Setting U-Boot environment"))
> +        local value = rrtarget.index
> +        swupdate.set_bootenv("swupdpart", value);
> +    end
> +
> +    return 0
> +end
> +
> +-- File handler for updating kernel files.
> +function handler_kernelfile(image)
> +    -- Check if we can chain-call the handler.
> +    local chained_handler = "rawfile"
> +    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
> +        chained_handler = image.properties["chainhandler"]
> +    elseif config["kernelfile"] ~= nil and config["kernelfile"]["chainhandler"] ~= nil then
> +        chained_handler = config["kernelfile"]["chainhandler"]
> +    end
> +    if not swupdate.handler[chained_handler] then
> +        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution."), chained_handler)
> +        return 1
> +    end
> +
> +    -- Check that rrtarget is set, else the 'roundrobin' handler hasn't been run.
> +    if rrtarget:size() == 0 then
> +        swupdate.error("The 'roundrobin' handler hasn't been run.")
> +        swupdate.info("Place 'roundrobin' above 'kernelfile' in sw-description.")
> +        return 1
> +    end
> +
> +    -- Get device list for round-robin.
> +    local devices = get_device_list(image.device)
> +    if #devices < 2 then
> +        swupdate.error("Specify at least 2 devices in the device= property for 'kernelfile'.")
> +        return 1
> +    end
> +    if rrtarget.index > #devices then
> +        swupdate.error("Cannot map kernel partition to root partition.")
> +        return 1
> +    end
> +
> +    -- Perform round-robin indexing for target.
> +    local err
> +    err, image.device, _ = get_device_path(devices[rrtarget.index])
> +    if err ~= 0 then
> +        return 1
> +    end
> +    swupdate.info(string.format("Using '%s' as 'kernelfile' target via '%s' handler.", image.device, chained_handler))
> +
> +    -- Actually copy the 'kernelfile' files.
> +    local msg
> +    image.type = chained_handler
> +    err, msg = swupdate.call_handler(chained_handler, image)
> +    if err ~= 0 then
> +        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
> +        return 1
> +    end
> +
> +    if config.bootloader.name == BOOTLOADER.EBG then
> +        -- Update EFI Boot Guard environment: kernelfile
> +        local value = string.format("%s%s", config.bootloader.bootlabel[rrtarget.index], config.bootloader.kernelname)
> +        swupdate.info(string.format("Setting EFI Bootguard environment: kernelfile=%s", value))
> +        swupdate.set_bootenv("kernelfile", value)
> +    elseif config.bootloader.name == BOOTLOADER.UBOOT then
> +        -- Update U-Boot environment.
> +        swupdate.info(string.format("Setting U-Boot environment"))
> +        -- TODO
> +    end
> +
> +    return 0
> +end
> +
> +swupdate.register_handler("roundrobin", handler_roundrobin, swupdate.HANDLER_MASK.IMAGE_HANDLER)
> +swupdate.register_handler("kernelfile", handler_kernelfile, swupdate.HANDLER_MASK.FILE_HANDLER)
> diff --git a/recipes-core/swupdate/swupdate.bb b/recipes-core/swupdate/swupdate.bb
> new file mode 100644
> index 0000000..9c58f7d
> --- /dev/null
> +++ b/recipes-core/swupdate/swupdate.bb
> @@ -0,0 +1,54 @@
> +#
> +# CIP Core, generic profile
> +#
> +# Copyright (c) Siemens AG, 2020
> +#
> +# Authors:
> +#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
> +#
> +# SPDX-License-Identifier: MIT
> +
> +hDESCRIPTION = "swupdate utility for software updates"
> +HOMEPAGE= "https://github.com/sbabic/swupdate"
> +LICENSE = "GPL-2.0"
> +LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
> +
> +SRC_URI = "gitsm://code.siemens.com/mirror/swupdate.git;branch=master;protocol=https"

Internal mirror. You need to go back to upstream.

And do we actually need gitsm? It is not a mature feature of bitbake, 
thus generally discouraged.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux

[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4840): https://lists.cip-project.org/g/cip-dev/message/4840
Mute This Topic: https://lists.cip-project.org/mt/75102475/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard Quirin Gylstorff
@ 2020-06-26 13:37   ` Jan Kiszka
  2020-06-29  9:03     ` Quirin Gylstorff
  0 siblings, 1 reply; 22+ messages in thread
From: Jan Kiszka @ 2020-06-26 13:37 UTC (permalink / raw)
  To: Q. Gylstorff, cip-dev

[-- Attachment #1: Type: text/plain, Size: 481 bytes --]

On 25.06.20 15:21, Q. Gylstorff wrote:
> From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
> 
> Add the bootloader efibootguard for A/B partition update
> on x86 with EFI.
> 
> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
> ---
>   .../efibootguard/efibootguard_0.6-git+isar.bb |  46 +++++

I just released 0.7. Maybe you could update when preparing v2.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux

[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4841): https://lists.cip-project.org/g/cip-dev/message/4841
Mute This Topic: https://lists.cip-project.org/mt/75102473/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard
  2020-06-26 13:37   ` Jan Kiszka
@ 2020-06-29  9:03     ` Quirin Gylstorff
  0 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:03 UTC (permalink / raw)
  To: Jan Kiszka, cip-dev

[-- Attachment #1: Type: text/plain, Size: 467 bytes --]



On 6/26/20 3:37 PM, Jan Kiszka wrote:
> On 25.06.20 15:21, Q. Gylstorff wrote:
>> From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
>>
>> Add the bootloader efibootguard for A/B partition update
>> on x86 with EFI.
>>
>> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
>> ---
>>   .../efibootguard/efibootguard_0.6-git+isar.bb |  46 +++++
> 
> I just released 0.7. Maybe you could update when preparing v2.
> 
> Jan
> 

Sure

[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4849): https://lists.cip-project.org/g/cip-dev/message/4849
Mute This Topic: https://lists.cip-project.org/mt/75102473/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [cip-dev] [isar-cip-core RFC 3/4] recipes-core: add swupdate
  2020-06-26 13:05   ` Jan Kiszka
@ 2020-06-29  9:03     ` Quirin Gylstorff
  0 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:03 UTC (permalink / raw)
  To: Jan Kiszka, cip-dev

[-- Attachment #1: Type: text/plain, Size: 53414 bytes --]



On 6/26/20 3:05 PM, Jan Kiszka wrote:
> On 25.06.20 15:21, Q. Gylstorff wrote:
>> From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
>>
>> Add swupdate for A/B software updates. Currently the Round Robin
>> handler in lua supports efibootguard as bootloader. The u-boot
>> implementation is outstanding.
>>
>> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
>> ---
>>   classes/kconfig-snippets.bbclass              |  90 ++++
>>   classes/swupdate-config.bbclass               |  76 +++
>>   classes/swupdate-img.bbclass                  |  75 +++
>>   .../swupdate/files/debian/changelog.tmpl      |   6 +
>>   recipes-core/swupdate/files/debian/compat     |   1 +
>>   .../swupdate/files/debian/control.tmpl        |  15 +
>>   recipes-core/swupdate/files/debian/copyright  |  36 ++
>>   recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
>>   .../swupdate/files/debian/swupdate.examples   |   2 +
>>   .../swupdate/files/debian/swupdate.install    |   2 +
>>   .../swupdate/files/debian/swupdate.manpages   |   5 +
>>   .../swupdate/files/debian/swupdate.tmpfile    |   2 +
>>   recipes-core/swupdate/files/debian/watch      |  12 +
>>   recipes-core/swupdate/files/postinst          |   2 +
>>   recipes-core/swupdate/files/swupdate.cfg      |   6 +
>>   .../swupdate/files/swupdate.service.example   |  11 +
>>   .../swupdate/files/swupdate.socket.example    |  11 +
>>   .../swupdate/files/swupdate.socket.tmpl       |  13 +
>>   .../swupdate/files/swupdate_defconfig         |  83 ++++
>>   .../swupdate_defconfig_efibootguard.snippet   |   3 +
>>   .../files/swupdate_defconfig_lua.snippet      |   2 +
>>   .../swupdate_defconfig_luahandler.snippet     |   4 +
>>   .../files/swupdate_defconfig_mtd.snippet      |   1 +
>>   .../files/swupdate_defconfig_u-boot.snippet   |   3 +
>>   .../files/swupdate_defconfig_ubi.snippet      |   6 +
>>   .../swupdate/files/swupdate_handlers.lua      | 449 ++++++++++++++++++
>>   recipes-core/swupdate/swupdate.bb             |  54 +++
>>   27 files changed, 1000 insertions(+)
>>   create mode 100644 classes/kconfig-snippets.bbclass
>>   create mode 100644 classes/swupdate-config.bbclass
>>   create mode 100644 classes/swupdate-img.bbclass
>>   create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
>>   create mode 100644 recipes-core/swupdate/files/debian/compat
>>   create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
>>   create mode 100644 recipes-core/swupdate/files/debian/copyright
>>   create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
>>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
>>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
>>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
>>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
>>   create mode 100644 recipes-core/swupdate/files/debian/watch
>>   create mode 100644 recipes-core/swupdate/files/postinst
>>   create mode 100644 recipes-core/swupdate/files/swupdate.cfg
>>   create mode 100644 recipes-core/swupdate/files/swupdate.service.example
>>   create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
>>   create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
>>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
>>   create mode 100644 
>> recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
>>   create mode 100644 
>> recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
>>   create mode 100644 
>> recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
>>   create mode 100644 
>> recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
>>   create mode 100644 
>> recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
>>   create mode 100644 
>> recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
>>   create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
>>   create mode 100644 recipes-core/swupdate/swupdate.bb
>>
>> diff --git a/classes/kconfig-snippets.bbclass 
>> b/classes/kconfig-snippets.bbclass
>> new file mode 100644
>> index 0000000..d754654
>> --- /dev/null
>> +++ b/classes/kconfig-snippets.bbclass
>> @@ -0,0 +1,90 @@
>> +#
>> +# CIP Core, generic profile
>> +#
>> +# Copyright (c) Siemens AG, 2020
>> +#
>> +# Authors:
>> +#  Christian Storm <christian.storm@siemens.com>
>> +#
>> +# SPDX-License-Identifier: MIT
>> +
>> +KCONFIG_SNIPPETS = ""
>> +
>> +# The following function defines the kconfig snippet system
>> +# with automatich debian dependency injection
>> +#
>> +# To define a feature set, the user has to define the following
>> +# variable to an empty string:
>> +#
>> +# KFEATURE_featurename = ""
>> +#
>> +# Then, required additions to the variables can be defined:
>> +#
>> +# KFEATURE_featurename[KCONFIG_SNIPPETS] = 
>> "file://snippet-file-name.snippet"
>> +# KFEATURE_featurename[SRC_URI] = "file://required-file.txt"
>> +# KFEATURE_featurename[DEPENDS] = "deb-pkg1 deb-pkg2 deb-pkg3"
>> +# KFEATURE_featurename[DEBIAN_DEPENDS] = "deb-pkg1"
>> +# KFEATURE_featurename[BUILD_DEB_DEPENDS] = "deb-pkg1,deb-pkg2,deb-pkg3"
>> +
>> +# The 'KCONFIG_SNIPPETS' flag gives a list of URI entries, where only
>> +# file:// is supported. These snippets are appended to the DEFCONFIG 
>> file.
>> +#
>> +# Features can depend on other features via the following mechanism:
>> +#
>> +# KFEATURE_DEPS[feature1] = "feature2"
>> +
>> +python () {
>> +    requested_features = d.getVar("KFEATURES", True) or ""
>> +
>> +    features = set(requested_features.split())
>> +    old_features = set()
>> +    feature_deps = d.getVarFlags("KFEATURE_DEPS") or {}
>> +    while old_features != features:
>> +        diff_features = old_features.symmetric_difference(features)
>> +        old_features = features.copy()
>> +        for i in diff_features:
>> +            features.update(feature_deps.get(i, "").split())
>> +
>> +    for f in sorted(features):
>> +        bb.debug(2, "Feature: " + f)
>> +        varname = "KFEATURE_" + f
>> +        dummyvar = d.getVar(varname, False)
>> +        if dummyvar == None:
>> +            bb.error("Feature var " + f + " must be defined with 
>> needed flags.")
>> +        else:
>> +            feature_flags = d.getVarFlags(varname)
>> +            for feature_varname in sorted(feature_flags):
>> +                if feature_flags.get(feature_varname, "") != "":
>> +                    sep = " "
>> +
>> +                    # Required to add KCONFIG_SNIPPETS to SRC_URI here,
>> +                    # because 'SRC_URI += "${KCONFIG_SNIPPETS}"' would
>> +                    # conflict with SRC_APT feature.
>> +                    if feature_varname == "KCONFIG_SNIPPETS":
>> +                        d.appendVar('SRC_URI',
>> +                            " " + 
>> feature_flags[feature_varname].strip())
>> +
>> +                    # BUILD_DEP_DEPENDS and DEBIAN_DEPENDS is ',' 
>> separated
>> +                    # Only add ',' if there is already something there
>> +                    if feature_varname in ["BUILD_DEB_DEPENDS",
>> +                                           "DEBIAN_DEPENDS"]:
>> +                        sep = "," if d.getVar(feature_varname) else ""
>> +
>> +                    d.appendVar(feature_varname,
>> +                        sep + feature_flags[feature_varname].strip())
>> +}
>> +
>> +# DEFCONFIG must be a predefined bitbake variable and the 
>> corresponding file
>> +# must exist in the WORKDIR.
>> +# The resulting generated config is the same file suffixed with ".gen"
>> +
>> +do_prepare_build_prepend() {
>> +        sh -x
>> +        GENCONFIG="${WORKDIR}/${DEFCONFIG}".gen
>> +        rm -f "$GENCONFIG"
>> +        cp "${WORKDIR}/${DEFCONFIG}" "$GENCONFIG"
>> +        for CONFIG_SNIPPET in $(echo "${KCONFIG_SNIPPETS}" | sed 
>> 's#file://##g')
>> +        do
>> +                cat ${WORKDIR}/$CONFIG_SNIPPET >> "$GENCONFIG"
>> +        done
>> +}
>> diff --git a/classes/swupdate-config.bbclass 
>> b/classes/swupdate-config.bbclass
>> new file mode 100644
>> index 0000000..7ce51c5
>> --- /dev/null
>> +++ b/classes/swupdate-config.bbclass
>> @@ -0,0 +1,76 @@
>> +#
>> +# CIP Core, generic profile
>> +#
>> +# Copyright (c) Siemens AG, 2020
>> +#
>> +# Authors:
>> +#  Christian Storm <christian.storm@siemens.com>
>> +#
>> +# SPDX-License-Identifier: MIT
>> +
>> +# This class manages the config snippets together with their 
>> dependencies
>> +# to build SWUpdate
>> +
>> +inherit kconfig-snippets
>> +
>> +BUILD_DEB_DEPENDS = " \
>> +    zlib1g-dev, debhelper, libconfig-dev, libarchive-dev, \
>> +    python-sphinx:native, dh-systemd, libsystemd-dev"
>> +
>> +KFEATURE_lua = ""
>> +KFEATURE_lua[BUILD_DEB_DEPENDS] = "liblua5.3-dev"
>> +KFEATURE_lua[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_lua.snippet"
>> +
>> +KFEATURE_luahandler = ""
>> +KFEATURE_luahandler[KCONFIG_SNIPPETS] = 
>> "file://swupdate_defconfig_luahandler.snippet"
>> +KFEATURE_luahandler[SRC_URI] = "file://${SWUPDATE_LUASCRIPT}"
>> +
>> +KFEATURE_DEPS = ""
>> +KFEATURE_DEPS[luahandler] = "lua"
>> +
>> +KFEATURE_efibootguard = ""
>> +KFEATURE_efibootguard[BUILD_DEB_DEPENDS] = "efibootguard-dev"
>> +KFEATURE_efibootguard[DEBIAN_DEPENDS] = "efibootguard-dev"
>> +KFEATURE_efibootguard[DEPENDS] = "efibootguard-dev"
>> +KFEATURE_efibootguard[KCONFIG_SNIPPETS] = 
>> "file://swupdate_defconfig_efibootguard.snippet"
>> +
>> +KFEATURE_mtd = ""
>> +KFEATURE_mtd[BUILD_DEB_DEPENDS] = "libmtd-dev"
>> +KFEATURE_mtd[DEPENDS] = "mtd-utils"
>> +KFEATURE_mtd[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_mtd.snippet"
>> +
>> +KFEATURE_ubi = ""
>> +KFEATURE_ubi[BUILD_DEB_DEPENDS] = "libubi-dev"
>> +KFEATURE_ubi[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_ubi.snippet"
>> +
>> +KFEATURE_DEPS[ubi] = "mtd"
>> +
>> +KFEATURE_u-boot = ""
>> +KFEATURE_u-boot[BUILD_DEB_DEPENDS] = "u-boot-${MACHINE}-dev"
>> +KFEATURE_u-boot[DEBIAN_DEPENDS] = "u-boot-tools"
>> +KFEATURE_u-boot[DEPENDS] = "${U_BOOT}"
>> +KFEATURE_u-boot[KCONFIG_SNIPPETS] = 
>> "file://swupdate_defconfig_u-boot.snippet"
>> +
>> +SWUPDATE_LUASCRIPT ?= "swupdate_handlers.lua"
>> +
>> +def get_bootloader_featureset(d):
>> +    bootloader = d.getVar("BOOTLOADER", True) or ""
>> +    if bootloader == "efibootguard":
>> +        return "efibootguard"
>> +    if bootloader == "u-boot":
>> +        return "u-boot"
>> +    return ""
>> +
>> +SWUPDATE_KFEATURES ??= ""
>> +KFEATURES = "${SWUPDATE_KFEATURES}"
>> +KFEATURES += "${@get_bootloader_featureset(d)}"
>> +
>> +# Astonishingly, as an anonymous python function, BOOTLOADER is 
>> always None
>> +# one time before it gets set. So the following must be a task.
>> +python do_check_bootloader () {
>> +    bootloader = d.getVar("BOOTLOADER", True) or "None"
>> +    if not bootloader in ["efibootguard", "u-boot"]:
>> +        bb.warn("swupdate: BOOTLOADER set to incompatible value: " + 
>> bootloader)
>> +}
>> +addtask check_bootloader before do_fetch
>> +
>> diff --git a/classes/swupdate-img.bbclass b/classes/swupdate-img.bbclass
>> new file mode 100644
>> index 0000000..a21d6ec
>> --- /dev/null
>> +++ b/classes/swupdate-img.bbclass
>> @@ -0,0 +1,75 @@
>> +#
>> +# CIP Core, generic profile
>> +#
>> +# Copyright (c) Siemens AG, 2020
>> +#
>> +# Authors:
>> +#  Christian Storm <christian.storm@siemens.com>
>> +#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
>> +#
>> +# SPDX-License-Identifier: MIT
>> +
>> +SWU_IMAGE_FILE ?= "${PN}-${DISTRO}-${MACHINE}.swu"
>> +SWU_DESCRIPTION_FILE ?= "sw-description"
>> +SWU_ADDITIONAL_FILES ?= ""
>> +SWU_SIGNED ?= ""
>> +SWU_SIGNATURE_EXT ?= "sig"
>> +SWU_SIGNATURE_TYPE ?= "rsa"
>> +
>> +IMAGER_INSTALL += "${@'openssl' if 
>> bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}"
>> +
>> +do_swupdate_image[stamp-extra-info] = "${DISTRO}-${MACHINE}"
>> +do_swupdate_image[cleandirs] += "${WORKDIR}/swu"
>> +do_swupdate_image() {
>> +    rm -f '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
>> +    cp '${WORKDIR}/${SWU_DESCRIPTION_FILE}' 
>> '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
>> +
>> +    # Create symlinks for files used in the update image
>> +    for file in ${SWU_ADDITIONAL_FILES}; do
>> +        if [ -e "${WORKDIR}/$file" ]; then
>> +            ln -s "${WORKDIR}/$file" "${WORKDIR}/swu/$file"
>> +        else
>> +            ln -s "${DEPLOY_DIR_IMAGE}/$file" "${WORKDIR}/swu/$file"
>> +        fi
>> +    done
>> +
>> +    # Prepare for signing
>> +    sign='${@'x' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else 
>> ''}'
>> +    if [ -n "$sign" ]; then
>> +        image_do_mounts
>> +        cp -f '${SIGN_KEY}' '${WORKDIR}/dev.key'
>> +        test -e '${SIGN_CRT}' && cp -f '${SIGN_CRT}' 
>> '${WORKDIR}/dev.crt'
>> +
>> +        # Fill in file check sums
>> +        for file in ${SWU_ADDITIONAL_FILES}; do
>> +            sed -i "s:$file-sha256:$(sha256sum '${WORKDIR}/swu/'$file 
>> | cut -f 1 -d ' '):g" \
>> +                '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
>> +        done
>> +    fi
>> +
>> +    cd "${WORKDIR}/swu"
>> +    for file in '${SWU_DESCRIPTION_FILE}' ${SWU_ADDITIONAL_FILES}; do
>> +        echo "$file"
>> +        if [ -n "$sign" -a \
>> +             '${SWU_DESCRIPTION_FILE}' = "$file" ]; then
>> +            if [ "${SWU_SIGNATURE_TYPE}" = "rsa" ]; then
>> +                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl dgst \
>> +                    -sha256 -sign '${PP_WORK}/dev.key' \
>> +                    '${PP_WORK}/swu/'"$file" \
>> +                        > 
>> '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}'
>> +            elif [ "${SWU_SIGNATURE_TYPE}" = "cms" ]; then
>> +                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl cms \
>> +                    -sign -in '${PP_WORK}/swu/'"$file" \
>> +                    -out 
>> '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}' \
>> +                    -signer '${PP_WORK}/dev.crt' \
>> +                    -inkey '${PP_WORK}/dev.key' \
>> +                    -outform DER -nosmimecap -binary
>> +            fi
>> +            echo "$file".'${SWU_SIGNATURE_EXT}'
>> +        fi
>> +    done | cpio -ovL -H crc \
>> +        > '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
>> +    cd -
>> +}
>> +
>> +addtask swupdate_image before do_build after do_copy_boot_files 
>> do_install_imager_deps do_transform_template
>> diff --git a/recipes-core/swupdate/files/debian/changelog.tmpl 
>> b/recipes-core/swupdate/files/debian/changelog.tmpl
>> new file mode 100644
>> index 0000000..81087d3
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/changelog.tmpl
>> @@ -0,0 +1,6 @@
>> +swupdate (${PV}) unstable; urgency=medium
>> +
>> +  * SWUpdate
>> +
>> + --  Christian Storm <christian.storm@siemens.com>  Thu, 31 Jan 2019 
>> 15:23:56 +0100
>> +
>> diff --git a/recipes-core/swupdate/files/debian/compat 
>> b/recipes-core/swupdate/files/debian/compat
>> new file mode 100644
>> index 0000000..b4de394
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/compat
>> @@ -0,0 +1 @@
>> +11
>> diff --git a/recipes-core/swupdate/files/debian/control.tmpl 
>> b/recipes-core/swupdate/files/debian/control.tmpl
>> new file mode 100644
>> index 0000000..2b92850
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/control.tmpl
>> @@ -0,0 +1,15 @@
>> +Source: swupdate
>> +Section: embedded
>> +Priority: optional
>> +Maintainer: Stefano Babic <sbabic@denx.de>
>> +Build-Depends: ${BUILD_DEB_DEPENDS}
>> +Standards-Version: 4.2.1
>> +Homepage: http://sbabic.github.io/swupdate
>> +
>> +Package: swupdate
>> +Architecture: any
>> +Depends: ${DEBIAN_DEPENDS}
>> +Description: reliable way to update an embedded system
>> + This project is thought to help to update an embedded system from a 
>> storage media or from network.
>> + However, it should be mainly considered as a framework, where 
>> further protocols or installers
>> + (in SWUpdate they are called handlers) can be easily added to the 
>> application.
>> diff --git a/recipes-core/swupdate/files/debian/copyright 
>> b/recipes-core/swupdate/files/debian/copyright
>> new file mode 100644
>> index 0000000..f920942
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/copyright
>> @@ -0,0 +1,36 @@
>> +Format: 
>> https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
>> +Upstream-Name: swupdate
>> +Maintainer: Stefano Babic <sbabic@denx.de>
>> +Source: http://github.com/sbabic/swupdate
>> +
>> +Files: *
>> +Copyright: 2014-2017 Stefano Babic <sbabic@denx.de>
>> +
>> +License: GPL-2 with OpenSSL exception
>> + This package is free software; you can redistribute it and/or modify
>> + it under the terms of the GNU General Public License as published by
>> + the Free Software Foundation; either version 2 of the License, or
>> + (at your option) any later version.
>> + .
>> + In addition, as a special exception, the author of this
>> + program gives permission to link the code of its
>> + release with the OpenSSL project's "OpenSSL" library (or
>> + with modified versions of it that use the same license as
>> + the "OpenSSL" library), and distribute the linked
>> + executables. You must obey the GNU General Public
>> + License in all respects for all of the code used other
>> + than "OpenSSL".  If you modify this file, you may extend
>> + this exception to your version of the file, but you are
>> + not obligated to do so.  If you do not wish to do so,
>> + delete this exception statement from your version.
>> + .
>> + This package is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + GNU General Public License for more details.
>> + .
>> + You should have received a copy of the GNU General Public License
>> + along with this program. If not, see <https://www.gnu.org/licenses/>
>> + .
>> + On Debian systems, the complete text of the GNU General
>> + Public License version 2 can be found in 
>> "/usr/share/common-licenses/GPL-2".
>> diff --git a/recipes-core/swupdate/files/debian/rules.tmpl 
>> b/recipes-core/swupdate/files/debian/rules.tmpl
>> new file mode 100755
>> index 0000000..54cca57
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/rules.tmpl
>> @@ -0,0 +1,30 @@
>> +#!/usr/bin/make -f
>> +
>> +ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
>> +export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
>> +export CC=$(DEB_HOST_GNU_TYPE)-gcc
>> +export LD=$(DEB_HOST_GNU_TYPE)-gcc
>> +endif
>> +
>> +export DH_VERBOSE = 1
>> +
>> +export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
>> +
>> +documentation: configure
>> +    make man
>> +
>> +configure:
>> +    make ${DEFCONFIG}
>> +
>> +build: documentation configure
>> +    dh $@
>> +
>> +%:
>> +    echo $@
>> +    dh $@
>> +
>> +override_dh_installchangelogs:
>> +    true
>> +
>> +override_dh_installdocs:
>> +    true
>> diff --git a/recipes-core/swupdate/files/debian/swupdate.examples 
>> b/recipes-core/swupdate/files/debian/swupdate.examples
>> new file mode 100644
>> index 0000000..c257b75
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/swupdate.examples
>> @@ -0,0 +1,2 @@
>> +examples/configuration
>> +examples/description
>> diff --git a/recipes-core/swupdate/files/debian/swupdate.install 
>> b/recipes-core/swupdate/files/debian/swupdate.install
>> new file mode 100644
>> index 0000000..8957cc6
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/swupdate.install
>> @@ -0,0 +1,2 @@
>> +swupdate usr/bin
>> +swupdate.cfg /etc
>> diff --git a/recipes-core/swupdate/files/debian/swupdate.manpages 
>> b/recipes-core/swupdate/files/debian/swupdate.manpages
>> new file mode 100644
>> index 0000000..c3438e0
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/swupdate.manpages
>> @@ -0,0 +1,5 @@
>> +doc/build/man/swupdate.1
>> +doc/build/man/client.1
>> +doc/build/man/sendtohawkbit.1
>> +doc/build/man/hawkbitcfg.1
>> +doc/build/man/progress.1
>> diff --git a/recipes-core/swupdate/files/debian/swupdate.tmpfile 
>> b/recipes-core/swupdate/files/debian/swupdate.tmpfile
>> new file mode 100644
>> index 0000000..4743672
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/swupdate.tmpfile
>> @@ -0,0 +1,2 @@
>> +X /tmp/datadst
>> +X /tmp/scripts
>> diff --git a/recipes-core/swupdate/files/debian/watch 
>> b/recipes-core/swupdate/files/debian/watch
>> new file mode 100644
>> index 0000000..bc4c53e
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/debian/watch
>> @@ -0,0 +1,12 @@
>> +# Example watch control file for uscan
>> +# Rename this file to "watch" and then you can run the "uscan" command
>> +# to check for upstream updates and more.
>> +# See uscan(1) for format
>> +
>> +# Compulsory line, this is a version 4 file
>> +version=4
>> +
>> +# GitHub hosted projects
>> +opts="filenamemangle="s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" 
>> \
>> +   https://github.com/<user>/swupdate/tags \
>> +   (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
>> diff --git a/recipes-core/swupdate/files/postinst 
>> b/recipes-core/swupdate/files/postinst
>> new file mode 100644
>> index 0000000..f15ac10
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/postinst
>> @@ -0,0 +1,2 @@
>> +#!/bin/sh
>> +deb-systemd-helper enable swupdate.socket || true
>> diff --git a/recipes-core/swupdate/files/swupdate.cfg 
>> b/recipes-core/swupdate/files/swupdate.cfg
>> new file mode 100644
>> index 0000000..e0222f1
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate.cfg
>> @@ -0,0 +1,6 @@
>> +globals :
>> +{
>> +    verbose = true;
>> +    loglevel = 10;
>> +    syslog = false;
>> +};
>> diff --git a/recipes-core/swupdate/files/swupdate.service.example 
>> b/recipes-core/swupdate/files/swupdate.service.example
>> new file mode 100644
>> index 0000000..d0b821e
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate.service.example
>> @@ -0,0 +1,11 @@
>> +[Unit]
>> +Description=SWUpdate daemon
>> +Documentation=https://github.com/sbabic/swupdate
>> +
>> +[Service]
>> +Type=simple
>> +ExecStart=/usr/bin/swupdate -f /etc/swupdate.cfg
>> +KillMode=mixed
>> +
>> +[Install]
>> +WantedBy=multi-user.target
>> diff --git a/recipes-core/swupdate/files/swupdate.socket.example 
>> b/recipes-core/swupdate/files/swupdate.socket.example
>> new file mode 100644
>> index 0000000..2b75671
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate.socket.example
>> @@ -0,0 +1,11 @@
>> +[Unit]
>> +Description=SWUpdate socket listener
>> +Documentation=https://github.com/sbabic/swupdate
>> +Documentation=https://sbabic.github.io/swupdate
>> +
>> +[Socket]
>> +ListenStream=/tmp/sockinstctrl
>> +ListenStream=/tmp/swupdateprog
>> +
>> +[Install]
>> +WantedBy=sockets.target
>> diff --git a/recipes-core/swupdate/files/swupdate.socket.tmpl 
>> b/recipes-core/swupdate/files/swupdate.socket.tmpl
>> new file mode 100644
>> index 0000000..8e7fc1d
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate.socket.tmpl
>> @@ -0,0 +1,13 @@
>> +[Unit]
>> +Description=SWUpdate socket listener
>> +Documentation=https://github.com/sbabic/swupdate
>> +Documentation=https://sbabic.github.io/swupdate
>> +
>> +[Socket]
>> +SocketUser=${SWUPDATE_SOCKET_OWNER}
>> +SocketGroup=root
>> +ListenStream=/tmp/sockinstctrl
>> +ListenStream=/tmp/swupdateprog
>> +
>> +[Install]
>> +WantedBy=sockets.target
>> diff --git a/recipes-core/swupdate/files/swupdate_defconfig 
>> b/recipes-core/swupdate/files/swupdate_defconfig
>> new file mode 100644
>> index 0000000..9ae7cb5
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_defconfig
>> @@ -0,0 +1,83 @@
>> +#
>> +# Automatically generated file; DO NOT EDIT.
>> +# Swupdate Configuration
>> +#
>> +CONFIG_HAVE_DOT_CONFIG=y
>> +
>> +#
>> +# Swupdate Settings
>> +#
>> +
>> +#
>> +# General Configuration
>> +#
>> +# CONFIG_CURL is not set
>> +# CONFIG_CURL_SSL is not set
>> +CONFIG_SYSTEMD=y
>> +CONFIG_SCRIPTS=y
>> +# CONFIG_HW_COMPATIBILITY is not set
>> +CONFIG_SW_VERSIONS_FILE="/etc/sw-versions"
>> +
>> +#
>> +# Socket Paths
>> +#
>> +CONFIG_SOCKET_CTRL_PATH="/tmp/sockinstctrl"
>> +CONFIG_SOCKET_PROGRESS_PATH="/tmp/swupdateprog"
>> +CONFIG_SOCKET_REMOTE_HANDLER_DIRECTORY="/tmp/"
>> +# CONFIG_MTD is not set
>> +# CONFIG_LUA is not set
>> +# CONFIG_LUAPKG is not set
>> +# CONFIG_FEATURE_SYSLOG is not set
>> +
>> +#
>> +# Build Options
>> +#
>> +CONFIG_CROSS_COMPILE=""
>> +CONFIG_SYSROOT=""
>> +CONFIG_EXTRA_CFLAGS=""
>> +CONFIG_EXTRA_LDFLAGS=""
>> +CONFIG_EXTRA_LDLIBS=""
>> +
>> +#
>> +# Debugging Options
>> +#
>> +# CONFIG_DEBUG is not set
>> +# CONFIG_WERROR is not set
>> +# CONFIG_NOCLEANUP is not set
>> +# CONFIG_BOOTLOADER_EBG is not set
>> +# CONFIG_UBOOT is not set
>> +# CONFIG_BOOTLOADER_NONE is not set
>> +# CONFIG_BOOTLOADER_GRUB is not set
>> +# CONFIG_DOWNLOAD is not set
>> +# CONFIG_DOWNLOAD_SSL is not set
>> +# CONFIG_CHANNEL_CURL is not set
>> +# CONFIG_HASH_VERIFY=y
>> +# CONFIG_SIGNED_IMAGES is not set
>> +# CONFIG_ENCRYPTED_IMAGES is not set
>> +# CONFIG_SURICATTA is not set
>> +# CONFIG_WEBSERVER is not set
>> +CONFIG_GUNZIP=y
>> +
>> +#
>> +# Parser Features
>> +#
>> +CONFIG_LIBCONFIG=y
>> +CONFIG_PARSERROOT=""
>> +# CONFIG_JSON is not set
>> +# CONFIG_LUAEXTERNAL is not set
>> +# CONFIG_SETEXTPARSERNAME is not set
>> +# CONFIG_SETSWDESCRIPTION is not set
>> +
>> +#
>> +# Image Handlers
>> +#
>> +CONFIG_RAW=y
>> +# CONFIG_LUASCRIPTHANDLER is not set
>> +# CONFIG_SHELLSCRIPTHANDLER is not set
>> +# CONFIG_HANDLER_IN_LUA is not set
>> +# CONFIG_EMBEDDED_LUA_HANDLER is not set
>> +# CONFIG_EMBEDDED_LUA_HANDLER_SOURCE is not set
>> +CONFIG_ARCHIVE=y
>> +# CONFIG_REMOTE_HANDLER is not set
>> +# CONFIG_SWUFORWARDER_HANDLER is not set
>> +# CONFIG_BOOTLOADERHANDLER is not set
>> diff --git 
>> a/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet 
>> b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
>> new file mode 100644
>> index 0000000..8e3688c
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
>> @@ -0,0 +1,3 @@
>> +CONFIG_BOOTLOADER_NONE=n
>> +CONFIG_BOOTLOADER_EBG=y
>> +CONFIG_BOOTLOADERHANDLER=y
>> diff --git 
>> a/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet 
>> b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
>> new file mode 100644
>> index 0000000..b39f9df
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
>> @@ -0,0 +1,2 @@
>> +CONFIG_LUA=y
>> +CONFIG_LUAPKG="lua53"
>> diff --git 
>> a/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet 
>> b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
>> new file mode 100644
>> index 0000000..b4a2de8
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
>> @@ -0,0 +1,4 @@
>> +CONFIG_LUASCRIPTHANDLER=y
>> +CONFIG_HANDLER_IN_LUA=y
>> +CONFIG_EMBEDDED_LUA_HANDLER=y
>> +CONFIG_EMBEDDED_LUA_HANDLER_SOURCE="swupdate_handlers.lua"
>> diff --git 
>> a/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet 
>> b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
>> new file mode 100644
>> index 0000000..eab98dd
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
>> @@ -0,0 +1 @@
>> +CONFIG_MTD=y
>> diff --git 
>> a/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet 
>> b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
>> new file mode 100644
>> index 0000000..6b5832a
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
>> @@ -0,0 +1,3 @@
>> +CONFIG_UBOOT=y
>> +CONFIG_UBOOT_FWENV="/etc/fw_env.config"
>> +CONFIG_BOOTLOADERHANDLER=y
>> diff --git 
>> a/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet 
>> b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
>> new file mode 100644
>> index 0000000..d1c7732
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
>> @@ -0,0 +1,6 @@
>> +CONFIG_UBIVOL=y
>> +CONFIG_UBIATTACH=y
>> +CONFIG_UBIBLACKLIST=""
>> +CONFIG_UBIWHITELIST=""
>> +CONFIG_UBIVIDOFFSET=0
>> +CONFIG_CFI=y
>> diff --git a/recipes-core/swupdate/files/swupdate_handlers.lua 
>> b/recipes-core/swupdate/files/swupdate_handlers.lua
>> new file mode 100644
>> index 0000000..c9b9962
>> --- /dev/null
>> +++ b/recipes-core/swupdate/files/swupdate_handlers.lua
>> @@ -0,0 +1,449 @@
>> +--[[
>> +
>> +    Round-robin Image and File Handler.
>> +
>> +    Copyright (C) 2019, Siemens AG
>> +
>> +    Author: Christian Storm <christian.storm@siemens.com>
>> +
>> +    SPDX-License-Identifier: GPL-2.0-or-later
>> +
>> +    An `sw-description` file using these handlers may look like:
>> +        software =
>> +        {
>> +            version = "0.1.0";
>> +            images: ({
>> +                filename = "rootfs.ext4";
>> +                device = "sda4,sda5";
>> +                type = "roundrobin";
>> +                compressed = false;
>> +            });
>> +            files: ({
>> +                filename = "vmlinuz";
>> +                path = "vmlinuz";
>> +                type = "kernelfile";
>> +                device = "sda2,sda3";
>> +                filesystem = "vfat";
>> +            },
>> +            {
>> +                filename = "initrd.img";
>> +                path = "initrd.img";
>> +                type = "kernelfile";
>> +                device = "sda2,sda3";
>> +                filesystem = "vfat";
>> +            });
>> +        }
>> +
>> +    The semantics is as follows: Instead of having a fixed target 
>> device,
>> +    the 'roundrobin' image handler calculates the target device by 
>> parsing
>> +    /proc/cmdline, matching the root=<device> kernel parameter 
>> against its
>> +    'device' attribute's list of devices, and sets the actual target
>> +    device to the next 'device' attribute list entry in a round-robin
>> +    manner. The actual flashing is done via chain-calling another 
>> handler,
>> +    defaulting to the "raw" handler.
>> +
>> +    The 'kernelfile' file handler reuses the 'roundrobin' handler's 
>> target
>> +    device calculation by reading the actual target device from the same
>> +    index into its 'device' attribute's list of devices. The actual 
>> placing
>> +    of files into this partition is done via chain-calling another 
>> handler,
>> +    defaulting to the "rawfile" handler.
>> +
>> +    In the above example, if /dev/sda4 is currently booted according to
>> +    /proc/cmdline, /dev/sda5 will be flashed and the vmlinuz and 
>> initrd.img
>> +    files will be placed on /dev/sda3. If /dev/sda5 is booted, /dev/sda4
>> +    will be flashed and the vmlinuz and initrd.img files are placed on
>> +    /dev/sda2.
>> +    In addition to "classical" device nodes as in this example, 
>> partition
>> +    UUIDs as reported, e.g., by `blkid -s PARTUUID` are also supported.
>> +    UBI volumes are supported as well by specifying a CSV list of
>> +    ubi<number>:<label> items.
>> +
>> +    Configuration is done via an INI-style configuration file located at
>> +    /etc/swupdate.handler.ini or via compiled-in configuration (by
>> +    embedding the Lua handler script into the SWUpdate binary via using
>> +    CONFIG_EMBEDDED_LUA_HANDLER), the latter having precedence over the
>> +    former. See the example configuration below.
>> +    If uncommenting this example block, it will take precedence over any
>> +    /etc/swupdate.handler.ini configuration file.
>> +
>> +    The chain-called handlers can either be specified in the 
>> configuration,
>> +    i.e., a static run-time setting, or via the 'chainhandler' 
>> property of
>> +    an 'image' or 'file' section in the sw-description, with the latter
>> +    taking precedence over the former, e.g.,
>> +        ...
>> +        images: ({
>> +                filename = "rootfs.ext4";
>> +                device = "sda4,sda5";
>> +                type = "roundrobin";
>> +                properties: {
>> +                    chainhandler = "myraw";
>> +                };
>> +            });
>> +        ...
>> +    Such a sw-description fragment will chain-call the imaginary "myraw"
>> +    handler regardless of what's been configured in the compiled-in 
>> or the
>> +    configuration file.
>> +    When chain-calling the "rdiff_image" handler, its 'rdiffbase' 
>> property
>> +    is subject to round-robin as well, i.e., the 'rdiffbase' property is
>> +    expected to be a CSV list as for the 'device' property, and the 
>> actual
>> +    'rdiffbase' property value is calculated following the same 
>> round-robin
>> +    calculation mechanism stated above prior to chain-calling the actual
>> +    "rdiff_image" handler, e.g.,
>> +        images: ({
>> +                filename = "rootfs.ext4";
>> +                type = "roundrobin";
>> +                device = "sda4,sda5";
>> +                properties: {
>> +                    chainhandler = "rdiff_image";
>> +                    rdiffbase="sda1,sda2";
>> +                };
>> +            });
>> +    will set the 'rdiffbase' property to /dev/sda2 (/dev/sda1) if 
>> /dev/sda4
>> +    (/dev/sda5) is the currently booted root file system according to
>> +    /proc/cmdline parsing.
>> +
>> +]]
>> +
>> +
>> +local configuration = [[
>> +[bootloader]
>> +# Required: bootloader name, uboot and ebg currently supported.
>> +name=ebg
>> +# Required: bootloader-specific key-value pairs, e.g., for ebg:
>> +kernelname=linux.signed.efi
>> +# For relying on FAT labels, prefix bootlabels with 'L:', e.g., L:BOOT0.
>> +# For using custom labels, i.e., relying on the contents of an EFILABEL
>> +# file within the partition, prefix it with 'C:', e.g., C:BOOT0.
>> +bootlabel={ "C:BOOT0:", "C:BOOT1:" }
>> +
>> +# Optional: handler to chain-call for the 'roundrobin' handler,
>> +# defaulting to 'raw'
>> +[roundrobin]
>> +chainhandler=raw
>> +
>> +# Optional: handler to chain-call for the 'kernelfile' handler,
>> +# defaulting to 'rawfile'
>> +[kernelfile]
>> +chainhandler=rawfile
>> +]]
>> +
>> +-- Default configuration file, tried if no compiled-in config is 
>> available.
>> +local cfgfile = "/etc/swupdate.handler.ini"
>> +
>> +-- Table holding the configuration.
>> +local config = {}
>> +
>> +-- Mandatory configuration [section] and keys
>> +local BOOTLOADERCFG = {
>> +    ebg   = {
>> +        bootloader = {"name", "bootlabel", "kernelname"}
>> +    },
>> +    -- TODO fill with mandatory U-Boot configuration
>> +    uboot = {
>> +        bootloader = {"name"}
>> +    }
>> +}
>> +
>> +-- enum-alikes to make code more readable
>> +local BOOTLOADER = { EBG = "ebg", UBOOT = "uboot" }
>> +local PARTTYPE   = { UUID = 1, PLAIN = 2, UBI = 3 }
>> +
>> +-- Target table describing the target device the image is to be/has 
>> been flashed to.
>> +local rrtarget = {
>> +    size = function(self)
>> +        local _size = 0
>> +        for index in pairs(self) do _size = _size + 1 end
>> +        return _size - 1
>> +    end
>> +}
>> +
>> +-- Helper function parsing CSV fields of a struct img_type such as
>> +-- the "device" fields or the "rdiffbase" property.
>> +local get_device_list = function(device_node_csv_list)
>> +    local device_list = {}
>> +    for item in device_node_csv_list:gmatch("([^,]+)") do
>> +        local device_node = item:gsub("/dev/", "")
>> +        device_list[#device_list+1] = device_node
>> +        device_list[device_node] = #device_list
>> +    end
>> +    return device_list
>> +end
>> +
>> +-- Helper function to determine device node location.
>> +local get_device_path = function(device_node)
>> +    if device_node:match("ubi%d+:%S+") then
>> +        return 0, device_node, PARTTYPE.UBI
>> +    end
>> +    local device_path = string.format("/dev/disk/by-partuuid/%s", 
>> device_node)
>> +    local file = io.open(device_path, "rb" )
>> +    if file then
>> +        file:close()
>> +        return 0, device_path, PARTTYPE.UUID
>> +    end
>> +    device_path = string.format("/dev/%s", device_node)
>> +    file = io.open(device_path, "rb" )
>> +    if file then
>> +        file:close()
>> +        return 0, device_path, PARTTYPE.PLAIN
>> +    end
>> +    swupdate.error(string.format("Cannot access target device node 
>> /dev/{,disk/by-partuuid}/%s", device_node))
>> +    return 1, nil, nil
>> +end
>> +
>> +-- Helper function parsing the INI-style configuration.
>> +local get_config = function()
>> +    -- Return configuration right away if it's already parsed.
>> +    if config ~= nil and #config > 0 then
>> +        return config
>> +    end
>> +
>> +    -- Get configuration INI-style string.
>> +    if not configuration then
>> +        swupdate.trace(string.format("No compiled-in config found, 
>> trying %s", cfgfile))
>> +        local file = io.open(cfgfile, "r" )
>> +        if not file then
>> +            swupdate.error(string.format("Cannot open config file 
>> %s", cfgfile))
>> +            return nil
>> +        end
>> +        configuration = file:read("*a")
>> +        file:close()
>> +    end
>> +    if configuration:sub(-1) ~= "\n" then
>> +        configuration=configuration.."\n"
>> +    end
>> +
>> +    -- Parse INI-style contents into config table.
>> +    local sec, key, value
>> +    for line in configuration:gmatch("(.-)\n") do
>> +        if line:match("^%[([%w%p]+)%][%s]*") then
>> +            sec = line:match("^%[([%w%p]+)%][%s]*")
>> +            config[sec] = {}
>> +        elseif sec then
>> +            key, value = line:match("^([%w%p]-)=(.*)$")
>> +            if key and value then
>> +                if tonumber(value)  then value = tonumber(value) end
>> +                if value == "true"  then value = true            end
>> +                if value == "false" then value = false           end
>> +                if value:sub(1,1) == "{" then
>> +                    local _value = {}
>> +                    for _key, _ in value:gmatch("\"(%S+)\"") do
>> +                        table.insert(_value, _key)
>> +                    end
>> +                    value = _value
>> +                end
>> +                config[sec][key] = value
>> +            else
>> +                if not line:match("^$") and not line:match("^#") then
>> +                    swupdate.warn(string.format("Syntax error, 
>> skipping '%s'", line))
>> +                end
>> +            end
>> +        else
>> +            swupdate.error(string.format("Syntax error. no [section] 
>> encountered."))
>> +            return nil
>> +        end
>> +    end
>> +
>> +    -- Check config table for mandatory key existence.
>> +    if config["bootloader"] == nil or config["bootloader"]["name"] == 
>> nil then
>> +        swupdate.error(string.format("Syntax error. no [bootloader] 
>> encountered or name= missing therein."))
>> +        return nil
>> +    end
>> +    local bcfg = BOOTLOADERCFG[config.bootloader.name]
>> +    if not bcfg then
>> +        swupdate.error(string.format("Bootloader unsupported, 
>> name=uboot|ebg missing in [bootloader]?."))
>> +        return nil
>> +    end
>> +    for sec, _ in pairs(bcfg) do
>> +        for _, key in pairs(bcfg[sec]) do
>> +            if config[sec] == nil or config[sec][key] == nil then
>> +                swupdate.error(string.format("Mandatory config key 
>> %s= in [%s] not found.", key, sec))
>> +            end
>> +        end
>> +    end
>> +
>> +    return config
>> +end
>> +
>> +-- Round-robin image handler for updating the root partition.
>> +function handler_roundrobin(image)
>> +    -- Read configuration.
>> +    if not get_config() then
>> +        swupdate.error("Cannot read configuration.")
>> +        return 1
>> +    end
>> +
>> +    -- Check if we can chain-call the handler.
>> +    local chained_handler = "raw"
>> +    if image.properties ~= nil and image.properties["chainhandler"] 
>> ~= nil then
>> +        chained_handler = image.properties["chainhandler"]
>> +    elseif config["roundrobin"] ~= nil and 
>> config["roundrobin"]["chainhandler"] ~= nil then
>> +        chained_handler = config["roundrobin"]["chainhandler"]
>> +    end
>> +    if not swupdate.handler[chained_handler] then
>> +        swupdate.error(string.format("'%s' handler not available in 
>> SWUpdate distribution.", chained_handler))
>> +        return 1
>> +    end
>> +
>> +    -- Get device list for round-robin.
>> +    local devices = get_device_list(image.device)
>> +    if #devices < 2 then
>> +        swupdate.error("Specify at least 2 devices in the device= 
>> property for 'roundrobin'.")
>> +        return 1
>> +    end
>> +
>> +    -- Check that rrtarget is unset, else a reboot may be pending.
>> +    if rrtarget:size() > 0 then
>> +        swupdate.warn("The 'roundrobin' handler has been run. Is a 
>> reboot pending?")
>> +    end
>> +
>> +    -- Determine current root device.
>> +    local file = io.open("/proc/cmdline", "r")
>> +    if not file then
>> +        swupdate.error("Cannot open /proc/cmdline.")
>> +        return 1
>> +    end
>> +    local cmdline = file:read("*l")
>> +    file:close()
>> +
>> +    local rootparam, rootdevice
>> +    for item in cmdline:gmatch("%S+") do
>> +        rootparam, rootdevice = item:match("(root=[%u=]*[/dev/]*(%S+))")
>> +        if rootparam and rootdevice then break end
>> +    end
>> +    if not rootdevice then
>> +      swupdate.error("Cannot determine current root device.")
>> +      return 1
>> +    end
>> +    swupdate.info(string.format("Current root device is: %s", 
>> rootdevice))
>> +
>> +    if not devices[rootdevice] then
>> +        swupdate.error(string.format("Current root device '%s' is not 
>> in round-robin root devices list: %s", rootdevice, 
>> image.device:gsub("/dev/", "")))
>> +        return 1
>> +    end
>> +
>> +    -- Perform round-robin calculation for target.
>> +    local err
>> +    rrtarget.index = devices[rootdevice] % #devices + 1
>> +    rrtarget.device_node = devices[rrtarget.index]
>> +    err, rrtarget.device_path, rrtarget.parttype = 
>> get_device_path(devices[rrtarget.index])
>> +    if err ~= 0 then
>> +        return 1
>> +    end
>> +    swupdate.info(string.format("Using '%s' as 'roundrobin' target 
>> via '%s' handler.", rrtarget.device_path, chained_handler))
>> +
>> +    -- If the chain-called handler is rdiff_image, adapt the 
>> rdiffbase property
>> +    if chained_handler == "rdiff_image" then
>> +        if image.properties ~= nil and image.properties["rdiffbase"] 
>> ~= nil then
>> +            local rdiffbase_devices = 
>> get_device_list(image.properties["rdiffbase"])
>> +            if #rdiffbase_devices < 2 then
>> +                swupdate.error("Specify at least 2 devices in the 
>> rdiffbase= property for 'roundrobin'.")
>> +                return 1
>> +            end
>> +            err, image.propierties["rdiffbase"], _ = 
>> get_device_path(rdiffbase_devices[rrtarget.index])
>> +            if err ~= 0 then
>> +                return 1
>> +            end
>> +            swupdate.info(string.format("Using device %s as 
>> rdiffbase.", image.properties["rdiffbase"]))
>> +        else
>> +            swupdate.error("Property 'rdiffbase' is missing in 
>> sw-description.")
>> +            return 1
>> +        end
>> +    end
>> +
>> +    -- Actually flash the partition.
>> +    local msg
>> +    image.type = chained_handler
>> +    image.device = rrtarget.device_path
>> +    err, msg = swupdate.call_handler(chained_handler, image)
>> +    if err ~= 0 then
>> +        swupdate.error(string.format("Error chain-calling '%s' 
>> handler: %s", chained_handler, (msg or "")))
>> +        return 1
>> +    end
>> +
>> +    if config.bootloader.name == BOOTLOADER.EBG then
>> +      if rootparam then
>> +        local value = cmdline:gsub(
>> +            rootparam:gsub("%-", "%%-"),
>> +            string.format("root=%s%s",
>> +                (rrtarget.parttype == PARTTYPE.PLAIN and "") or 
>> (rrtarget.parttype == PARTTYPE.UBI and "") or "PARTUUID=",
>> +                 rrtarget.parttype == PARTTYPE.PLAIN and 
>> rrtarget.device_path or devices[rrtarget.index]
>> +            )
>> +        )
>> +        swupdate.info(string.format("Setting EFI Bootguard 
>> environment: kernelparams=%s", value))
>> +        swupdate.set_bootenv("kernelparams", value)
>> +      end
>> +    elseif config.bootloader.name == BOOTLOADER.UBOOT then
>> +        -- Update U-Boot environment.
>> +        swupdate.info(string.format("Setting U-Boot environment"))
>> +        local value = rrtarget.index
>> +        swupdate.set_bootenv("swupdpart", value);
>> +    end
>> +
>> +    return 0
>> +end
>> +
>> +-- File handler for updating kernel files.
>> +function handler_kernelfile(image)
>> +    -- Check if we can chain-call the handler.
>> +    local chained_handler = "rawfile"
>> +    if image.properties ~= nil and image.properties["chainhandler"] 
>> ~= nil then
>> +        chained_handler = image.properties["chainhandler"]
>> +    elseif config["kernelfile"] ~= nil and 
>> config["kernelfile"]["chainhandler"] ~= nil then
>> +        chained_handler = config["kernelfile"]["chainhandler"]
>> +    end
>> +    if not swupdate.handler[chained_handler] then
>> +        swupdate.error(string.format("'%s' handler not available in 
>> SWUpdate distribution."), chained_handler)
>> +        return 1
>> +    end
>> +
>> +    -- Check that rrtarget is set, else the 'roundrobin' handler 
>> hasn't been run.
>> +    if rrtarget:size() == 0 then
>> +        swupdate.error("The 'roundrobin' handler hasn't been run.")
>> +        swupdate.info("Place 'roundrobin' above 'kernelfile' in 
>> sw-description.")
>> +        return 1
>> +    end
>> +
>> +    -- Get device list for round-robin.
>> +    local devices = get_device_list(image.device)
>> +    if #devices < 2 then
>> +        swupdate.error("Specify at least 2 devices in the device= 
>> property for 'kernelfile'.")
>> +        return 1
>> +    end
>> +    if rrtarget.index > #devices then
>> +        swupdate.error("Cannot map kernel partition to root partition.")
>> +        return 1
>> +    end
>> +
>> +    -- Perform round-robin indexing for target.
>> +    local err
>> +    err, image.device, _ = get_device_path(devices[rrtarget.index])
>> +    if err ~= 0 then
>> +        return 1
>> +    end
>> +    swupdate.info(string.format("Using '%s' as 'kernelfile' target 
>> via '%s' handler.", image.device, chained_handler))
>> +
>> +    -- Actually copy the 'kernelfile' files.
>> +    local msg
>> +    image.type = chained_handler
>> +    err, msg = swupdate.call_handler(chained_handler, image)
>> +    if err ~= 0 then
>> +        swupdate.error(string.format("Error chain-calling '%s' 
>> handler: %s", chained_handler, (msg or "")))
>> +        return 1
>> +    end
>> +
>> +    if config.bootloader.name == BOOTLOADER.EBG then
>> +        -- Update EFI Boot Guard environment: kernelfile
>> +        local value = string.format("%s%s", 
>> config.bootloader.bootlabel[rrtarget.index], 
>> config.bootloader.kernelname)
>> +        swupdate.info(string.format("Setting EFI Bootguard 
>> environment: kernelfile=%s", value))
>> +        swupdate.set_bootenv("kernelfile", value)
>> +    elseif config.bootloader.name == BOOTLOADER.UBOOT then
>> +        -- Update U-Boot environment.
>> +        swupdate.info(string.format("Setting U-Boot environment"))
>> +        -- TODO
>> +    end
>> +
>> +    return 0
>> +end
>> +
>> +swupdate.register_handler("roundrobin", handler_roundrobin, 
>> swupdate.HANDLER_MASK.IMAGE_HANDLER)
>> +swupdate.register_handler("kernelfile", handler_kernelfile, 
>> swupdate.HANDLER_MASK.FILE_HANDLER)
>> diff --git a/recipes-core/swupdate/swupdate.bb 
>> b/recipes-core/swupdate/swupdate.bb
>> new file mode 100644
>> index 0000000..9c58f7d
>> --- /dev/null
>> +++ b/recipes-core/swupdate/swupdate.bb
>> @@ -0,0 +1,54 @@
>> +#
>> +# CIP Core, generic profile
>> +#
>> +# Copyright (c) Siemens AG, 2020
>> +#
>> +# Authors:
>> +#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
>> +#
>> +# SPDX-License-Identifier: MIT
>> +
>> +hDESCRIPTION = "swupdate utility for software updates"
>> +HOMEPAGE= "https://github.com/sbabic/swupdate"
>> +LICENSE = "GPL-2.0"
>> +LIC_FILES_CHKSUM = 
>> "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe" 
>>
>> +
>> +SRC_URI = 
>> "gitsm://code.siemens.com/mirror/swupdate.git;branch=master;protocol=https" 
>>
> 
> Internal mirror. You need to go back to upstream.
> 
> And do we actually need gitsm? It is not a mature feature of bitbake, 
> thus generally discouraged.
> 
> Jan
> 
I will fix that in v2

[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4850): https://lists.cip-project.org/g/cip-dev/message/4850
Mute This Topic: https://lists.cip-project.org/mt/75102475/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update
  2020-06-25 13:21 [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update Quirin Gylstorff
                   ` (3 preceding siblings ...)
  2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 4/4] wic: Add wks files for A/B Partition update Quirin Gylstorff
@ 2020-06-29  9:56 ` Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
                     ` (5 more replies)
  2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
  5 siblings, 6 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:56 UTC (permalink / raw)
  To: Jan.Kiszka, cip-dev; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 6198 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

This patchset adds efibootguard, swupdate to allow A/B updates in
cip-core. The update mechanism is currently only implemented for x86_64.

Changes V2:
 - update efibootguard to v0.7
 - add swdescription and kas option to build qemu-amd64 test image
 - swupdate set to upstream mirror and no longer use gitsm

Quirin Gylstorff (5):
  recipes-bsp: Add efibootguard
  patches: add libubootenv
  recipes-core: add swupdate
  wic: Add wks files for A/B Partition update
  swupdate: create swu file from wic image

 classes/extract-partition.bbclass             |  26 +
 classes/kconfig-snippets.bbclass              |  90 ++++
 classes/swupdate-config.bbclass               |  76 +++
 classes/swupdate-img.bbclass                  |  75 +++
 classes/wic-swu-img.bbclass                   |  20 +
 .../0001-u-boot-add-libubootenv.patch         | 169 +++++++
 kas-cip.yml                                   |   4 +
 kas/opt/ebg-swu.yml                           |  26 +
 kas/opt/qemu-swupdate.yml                     |  19 +
 .../efibootguard/efibootguard_0.7-git+isar.bb |  46 ++
 recipes-bsp/efibootguard/files/debian/compat  |   1 +
 .../efibootguard/files/debian/control.tmpl    |  20 +
 .../files/debian/efibootguard-dev.install     |   3 +
 .../files/debian/efibootguard.install         |   2 +
 recipes-bsp/efibootguard/files/debian/rules   |  21 +
 recipes-core/images/cip-core-image.bb         |  10 +
 recipes-core/images/files/sw-description.tmpl |  29 ++
 .../swupdate/files/debian/changelog.tmpl      |   6 +
 recipes-core/swupdate/files/debian/compat     |   1 +
 .../swupdate/files/debian/control.tmpl        |  15 +
 recipes-core/swupdate/files/debian/copyright  |  36 ++
 recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
 .../swupdate/files/debian/swupdate.examples   |   2 +
 .../swupdate/files/debian/swupdate.install    |   2 +
 .../swupdate/files/debian/swupdate.manpages   |   5 +
 .../swupdate/files/debian/swupdate.tmpfile    |   2 +
 recipes-core/swupdate/files/debian/watch      |  12 +
 recipes-core/swupdate/files/postinst          |   2 +
 recipes-core/swupdate/files/swupdate.cfg      |   6 +
 .../swupdate/files/swupdate.service.example   |  11 +
 .../swupdate/files/swupdate.socket.example    |  11 +
 .../swupdate/files/swupdate.socket.tmpl       |  13 +
 .../swupdate/files/swupdate_defconfig         |  83 ++++
 .../swupdate_defconfig_efibootguard.snippet   |   3 +
 .../files/swupdate_defconfig_lua.snippet      |   2 +
 .../swupdate_defconfig_luahandler.snippet     |   4 +
 .../files/swupdate_defconfig_mtd.snippet      |   1 +
 .../files/swupdate_defconfig_u-boot.snippet   |   3 +
 .../files/swupdate_defconfig_ubi.snippet      |   6 +
 .../swupdate/files/swupdate_handlers.lua      | 453 ++++++++++++++++++
 recipes-core/swupdate/swupdate.bb             |  54 +++
 .../wic/plugins/source/efibootguard-boot.py   | 162 +++++++
 .../wic/plugins/source/efibootguard-efi.py    | 102 ++++
 wic/ebg-sysparts.inc                          |   8 +
 wic/qemu-amd64-efibootguard.wks               |   5 +
 wic/simatic-ipc227e-efibootguard.wks          |   5 +
 wic/swupdate-partition.inc                    |   4 +
 47 files changed, 1686 insertions(+)
 create mode 100644 classes/extract-partition.bbclass
 create mode 100644 classes/kconfig-snippets.bbclass
 create mode 100644 classes/swupdate-config.bbclass
 create mode 100644 classes/swupdate-img.bbclass
 create mode 100644 classes/wic-swu-img.bbclass
 create mode 100644 isar-patches/0001-u-boot-add-libubootenv.patch
 create mode 100644 kas/opt/ebg-swu.yml
 create mode 100644 kas/opt/qemu-swupdate.yml
 create mode 100644 recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
 create mode 100644 recipes-bsp/efibootguard/files/debian/compat
 create mode 100644 recipes-bsp/efibootguard/files/debian/control.tmpl
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard.install
 create mode 100755 recipes-bsp/efibootguard/files/debian/rules
 create mode 100644 recipes-core/images/files/sw-description.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/compat
 create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/copyright
 create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
 create mode 100644 recipes-core/swupdate/files/debian/watch
 create mode 100644 recipes-core/swupdate/files/postinst
 create mode 100644 recipes-core/swupdate/files/swupdate.cfg
 create mode 100644 recipes-core/swupdate/files/swupdate.service.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
 create mode 100644 recipes-core/swupdate/swupdate.bb
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-boot.py
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-efi.py
 create mode 100644 wic/ebg-sysparts.inc
 create mode 100644 wic/qemu-amd64-efibootguard.wks
 create mode 100644 wic/simatic-ipc227e-efibootguard.wks
 create mode 100644 wic/swupdate-partition.inc

-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4852): https://lists.cip-project.org/g/cip-dev/message/4852
Mute This Topic: https://lists.cip-project.org/mt/75188184/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v2 1/5] recipes-bsp: Add efibootguard
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
@ 2020-06-29  9:56   ` Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 2/5] patches: add libubootenv Quirin Gylstorff
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:56 UTC (permalink / raw)
  To: Jan.Kiszka, cip-dev; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 15742 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add the bootloader efibootguard for A/B partition update
on x86 with EFI.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 .../efibootguard/efibootguard_0.7-git+isar.bb |  46 +++++
 recipes-bsp/efibootguard/files/debian/compat  |   1 +
 .../efibootguard/files/debian/control.tmpl    |  20 +++
 .../files/debian/efibootguard-dev.install     |   3 +
 .../files/debian/efibootguard.install         |   2 +
 recipes-bsp/efibootguard/files/debian/rules   |  21 +++
 .../wic/plugins/source/efibootguard-boot.py   | 162 ++++++++++++++++++
 .../wic/plugins/source/efibootguard-efi.py    | 102 +++++++++++
 8 files changed, 357 insertions(+)
 create mode 100644 recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
 create mode 100644 recipes-bsp/efibootguard/files/debian/compat
 create mode 100644 recipes-bsp/efibootguard/files/debian/control.tmpl
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard.install
 create mode 100755 recipes-bsp/efibootguard/files/debian/rules
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-boot.py
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-efi.py

diff --git a/recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb b/recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
new file mode 100644
index 0000000..4bdf76a
--- /dev/null
+++ b/recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
@@ -0,0 +1,46 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+DESCRIPTION = "efibootguard boot loader"
+DESCRIPTION_DEV = "efibootguard development library"
+HOMEPAGE = "https://github.com/siemens/efibootguard"
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
+MAINTAINER = "Jan Kiszka <jan.kiszka@siemens.com>"
+
+SRC_URI = "git://github.com/siemens/efibootguard.git;branch=master;protocol=https \
+           file://debian \
+          "
+
+S = "${WORKDIR}/git"
+
+SRCREV = "442e87bafb480ada2b9074f02350a30408d4cf9c"
+
+PROVIDES = "${PN}"
+PROVIDES += "${PN}-dev"
+
+BUILD_DEB_DEPENDS = "gnu-efi,libpci-dev,check,pkg-config,libc6-dev-i386"
+
+inherit dpkg
+
+TEMPLATE_FILES = "debian/control.tmpl"
+TEMPLATE_VARS += "DESCRIPTION_DEV BUILD_DEB_DEPENDS"
+
+do_prepare_build() {
+    cp -R ${WORKDIR}/debian ${S}
+    deb_add_changelog
+}
+
+dpkg_runbuild_append() {
+    install -m 0755 -d ${DEPLOY_DIR_IMAGE}
+    install -m 0755 ${S}/efibootguardx64.efi ${DEPLOY_DIR_IMAGE}/bootx64.efi
+    install -m 0755 ${S}/bg_setenv ${DEPLOY_DIR_IMAGE}/bg_setenv
+}
diff --git a/recipes-bsp/efibootguard/files/debian/compat b/recipes-bsp/efibootguard/files/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/recipes-bsp/efibootguard/files/debian/control.tmpl b/recipes-bsp/efibootguard/files/debian/control.tmpl
new file mode 100644
index 0000000..54b1994
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/control.tmpl
@@ -0,0 +1,20 @@
+Source: ${PN}
+Section: base
+Priority: optional
+Standards-Version: 3.9.6
+Build-Depends: ${BUILD_DEB_DEPENDS}
+Homepage: ${HOMEPAGE}
+Maintainer: ${MAINTAINER}
+
+Package: ${PN}
+Depends: ${shlibs:Depends}
+Section: base
+Architecture: ${DISTRO_ARCH}
+Priority: required
+Description: ${DESCRIPTION}
+
+Package: ${PN}-dev
+Section: base
+Architecture: ${DISTRO_ARCH}
+Priority: optional
+Description: ${DESCRIPTION_DEV}
diff --git a/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install b/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
new file mode 100644
index 0000000..7b45bd8
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
@@ -0,0 +1,3 @@
+include/ebgenv.h usr/include/efibootguard
+libebgenv.a usr/lib/x86_64-linux-gnu
+
diff --git a/recipes-bsp/efibootguard/files/debian/efibootguard.install b/recipes-bsp/efibootguard/files/debian/efibootguard.install
new file mode 100644
index 0000000..8a8d9d3
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/efibootguard.install
@@ -0,0 +1,2 @@
+bg_setenv usr/bin
+bg_printenv usr/bin
diff --git a/recipes-bsp/efibootguard/files/debian/rules b/recipes-bsp/efibootguard/files/debian/rules
new file mode 100755
index 0000000..82e9e0e
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/rules
@@ -0,0 +1,21 @@
+#!/usr/bin/make -f
+export DH_VERBOSE=1
+export DEB_BUILD_OPTIONS=hardening=-stackprotector
+export DPKG_EXPORT_BUILDFLAGS=1
+include /usr/share/dpkg/default.mk
+
+override_dh_auto_test:
+	# we do not run the tests; that avoids having to pull the fff submodule
+
+override_dh_auto_install:
+	# install using Debian's .install files rather than
+	# make install in order to have a proper package split.
+
+override_dh_installchangelogs:
+	# we're not interested in changelogs
+
+override_dh_installdocs:
+	# we're not interested in docs
+
+%:
+	dh $@ --with autoreconf
diff --git a/scripts/lib/wic/plugins/source/efibootguard-boot.py b/scripts/lib/wic/plugins/source/efibootguard-boot.py
new file mode 100644
index 0000000..38d2b2e
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/efibootguard-boot.py
@@ -0,0 +1,162 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Copyright (c) 2014, Intel Corporation.
+# Copyright (c) 2018, Siemens AG.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# DESCRIPTION
+# This implements the 'efibootguard-boot' source plugin class for 'wic'
+#
+# AUTHORS
+# Tom Zanussi <tom.zanussi (at] linux.intel.com>
+# Claudius Heine <ch (at] denx.de>
+# Andreas Reichel <andreas.reichel.ext (at] siemens.com>
+# Christian Storm <christian.storm (at] siemens.com>
+
+import os
+import fnmatch
+import sys
+import logging
+
+msger = logging.getLogger('wic')
+
+from wic.pluginbase import SourcePlugin
+from wic.utils.misc import exec_cmd, get_bitbake_var, BOOTDD_EXTRA_SPACE
+
+class EfibootguardBootPlugin(SourcePlugin):
+    """
+    Create EFI Boot Guard partition hosting the
+    environment file plus Kernel files.
+    """
+
+    name = 'efibootguard-boot'
+
+    @classmethod
+    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
+                             oe_builddir, deploy_dir, kernel_dir,
+                             rootfs_dir, native_sysroot):
+        """
+        Called to do the actual content population for a partition, i.e.,
+        populate an EFI Boot Guard environment partition plus Kernel files.
+        """
+
+        kernel_image = get_bitbake_var("KERNEL_IMAGE")
+        if not kernel_image:
+            msger.warning("KERNEL_IMAGE not set. Use default:")
+            kernel_image = "vmlinuz"
+        boot_image = kernel_image
+
+        initrd_image = get_bitbake_var("INITRD_IMAGE")
+        if not initrd_image:
+            msger.warning("INITRD_IMAGE not set\n")
+            initrd_image = "initrd.img"
+        bootloader = creator.ks.bootloader
+
+        deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
+        if not deploy_dir:
+            msger.error("DEPLOY_DIR_IMAGE not set, exiting\n")
+            sys.exit(1)
+        creator.deploy_dir = deploy_dir
+
+        wdog_timeout = get_bitbake_var("WDOG_TIMEOUT")
+        if not wdog_timeout:
+            msger.error("Specify watchdog timeout for \
+            efibootguard in local.conf with WDOG_TIMEOUT=")
+            exit(1)
+
+
+        boot_files = source_params.get("files", "").split(' ')
+        cmdline = bootloader.append
+        root_dev = source_params.get("root", None)
+        if not root_dev:
+            msger.error("Specify root in source params")
+            exit(1)
+            root_dev = root_dev.replace(":", "=")
+
+        cmdline += " root=%s rw" % root_dev
+        boot_files.append(kernel_image)
+        boot_files.append(initrd_image)
+        cmdline += "initrd=%s" % initrd_image if initrd_image else ""
+
+        part_rootfs_dir = "%s/disk/%s.%s" % (cr_workdir,
+                                             part.label, part.lineno)
+        create_dir_cmd = "install -d %s" % part_rootfs_dir
+        exec_cmd(create_dir_cmd)
+
+        cwd = os.getcwd()
+        os.chdir(part_rootfs_dir)
+        config_cmd = '%s/bg_setenv -f . -k "C:%s:%s" %s -r %s -w %s' \
+            % (
+                deploy_dir,
+                part.label.upper(),
+                boot_image,
+                '-a "%s"' % cmdline if cmdline else "",
+                source_params.get("revision", 1),
+                wdog_timeout
+            )
+        exec_cmd(config_cmd, True)
+        os.chdir(cwd)
+
+        boot_files = list(filter(None, boot_files))
+        for boot_file in boot_files:
+            if os.path.isfile("%s/%s" % (kernel_dir, kernel_image)):
+                install_cmd = "install -m 0644 %s/%s %s/%s" % \
+                    (kernel_dir, boot_file, part_rootfs_dir, boot_file)
+                exec_cmd(install_cmd)
+            else:
+                msger.error("file %s not found in directory %s",
+                            boot_file, kernel_dir)
+                exit(1)
+        cls._create_img(part_rootfs_dir, part, cr_workdir)
+
+    @classmethod
+    def _create_img(cls, part_rootfs_dir, part, cr_workdir):
+            # Write label as utf-16le to EFILABEL file
+        with open("%s/EFILABEL" % part_rootfs_dir, 'wb') as filedescriptor:
+            filedescriptor.write(part.label.upper().encode("utf-16le"))
+
+        du_cmd = "du --apparent-size -ks %s" % part_rootfs_dir
+        blocks = int(exec_cmd(du_cmd).split()[0])
+
+        extra_blocks = part.get_extra_block_count(blocks)
+        if extra_blocks < BOOTDD_EXTRA_SPACE:
+            extra_blocks = BOOTDD_EXTRA_SPACE
+
+        blocks += extra_blocks
+        blocks = blocks + (16 - (blocks % 16))
+
+        msger.debug("Added %d extra blocks to %s to get to %d total blocks",
+                    extra_blocks, part.mountpoint, blocks)
+
+        # dosfs image, created by mkdosfs
+        bootimg = "%s/%s.%s.img" % (cr_workdir, part.label, part.lineno)
+
+        dosfs_cmd = "mkdosfs -F 16 -S 512 -n %s -C %s %d" % \
+            (part.label.upper(), bootimg, blocks)
+        exec_cmd(dosfs_cmd)
+
+        mcopy_cmd = "mcopy -v -i %s -s %s/* ::/" % (bootimg, part_rootfs_dir)
+        exec_cmd(mcopy_cmd, True)
+
+        chmod_cmd = "chmod 644 %s" % bootimg
+        exec_cmd(chmod_cmd)
+
+        du_cmd = "du -Lbks %s" % bootimg
+        bootimg_size = int(exec_cmd(du_cmd).split()[0])
+
+        part.size = bootimg_size
+        part.source_file = bootimg
diff --git a/scripts/lib/wic/plugins/source/efibootguard-efi.py b/scripts/lib/wic/plugins/source/efibootguard-efi.py
new file mode 100644
index 0000000..5ee451f
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/efibootguard-efi.py
@@ -0,0 +1,102 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Copyright (c) 2014, Intel Corporation.
+# Copyright (c) 2018, Siemens AG.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# DESCRIPTION
+# This implements the 'efibootguard-efi' source plugin class for 'wic'
+#
+# AUTHORS
+# Tom Zanussi <tom.zanussi (at] linux.intel.com>
+# Claudius Heine <ch (at] denx.de>
+# Andreas Reichel <andreas.reichel.ext (at] siemens.com>
+# Christian Storm <christian.storm (at] siemens.com>
+
+import logging
+import os
+
+msger = logging.getLogger('wic')
+
+from wic.pluginbase import SourcePlugin
+from wic.utils.misc import exec_cmd, get_bitbake_var, BOOTDD_EXTRA_SPACE
+
+class EfibootguardEFIPlugin(SourcePlugin):
+    """
+    Create EFI bootloader partition containing the EFI Boot Guard Bootloader.
+    """
+
+    name = 'efibootguard-efi'
+
+    @classmethod
+    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
+                             oe_builddir, deploy_dir, kernel_dir,
+                             rootfs_dir, native_sysroot):
+        """
+        Called to do the actual content population for a partition, i.e.,
+        populate an EFI boot partition containing the EFI Boot Guard
+        bootloader binary.
+        """
+        deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
+        creator.deploy_dir = deploy_dir
+        bootloader_files = source_params.get("bootloader")
+        if not bootloader_files:
+            bootloader_files = "bootx64.efi"
+        bootloader_files = bootloader_files.split(' ')
+        part_rootfs_dir = "%s/disk/%s.%s" % (cr_workdir,
+                                             part.label,
+                                             part.lineno)
+        create_dir_cmd = "install -d %s/EFI/BOOT" % part_rootfs_dir
+        exec_cmd(create_dir_cmd)
+
+        for bootloader in bootloader_files:
+            cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (deploy_dir,
+                                                  bootloader,
+                                                  part_rootfs_dir,
+                                                  bootloader)
+            exec_cmd(cp_cmd, True)
+        du_cmd = "du --apparent-size -ks %s" % part_rootfs_dir
+        blocks = int(exec_cmd(du_cmd).split()[0])
+
+        extra_blocks = part.get_extra_block_count(blocks)
+        if extra_blocks < BOOTDD_EXTRA_SPACE:
+            extra_blocks = BOOTDD_EXTRA_SPACE
+        blocks += extra_blocks
+        blocks = blocks + (16 - (blocks % 16))
+
+        msger.debug("Added %d extra blocks to %s to get to %d total blocks",
+                    extra_blocks, part.mountpoint, blocks)
+
+        # dosfs image, created by mkdosfs
+        efi_part_image = "%s/%s.%s.img" % (cr_workdir, part.label, part.lineno)
+
+        dosfs_cmd = "mkdosfs -S 512 -n %s -C %s %d" % \
+            (part.label.upper(), efi_part_image, blocks)
+        exec_cmd(dosfs_cmd)
+
+        mcopy_cmd = "mcopy -v -i %s -s %s/* ::/" % \
+            (efi_part_image, part_rootfs_dir)
+        exec_cmd(mcopy_cmd, True)
+
+        chmod_cmd = "chmod 644 %s" % efi_part_image
+        exec_cmd(chmod_cmd)
+
+        du_cmd = "du -Lbks %s" % efi_part_image
+        efi_part_image_size = int(exec_cmd(du_cmd).split()[0])
+
+        part.size = efi_part_image_size
+        part.source_file = efi_part_image
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4853): https://lists.cip-project.org/g/cip-dev/message/4853
Mute This Topic: https://lists.cip-project.org/mt/75188185/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v2 2/5] patches: add libubootenv
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
@ 2020-06-29  9:56   ` Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 3/5] recipes-core: add swupdate Quirin Gylstorff
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:56 UTC (permalink / raw)
  To: Jan.Kiszka, cip-dev; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 7686 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

swupdate 2020.04 requires libubootenv as build dependency.

libubootenv is a library that provides a hardware independent
way to access to U-Boot environment. U-Boot has its default environment
compiled board-dependently and this means that tools to access the environment
are also board specific, too.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 .../0001-u-boot-add-libubootenv.patch         | 169 ++++++++++++++++++
 kas-cip.yml                                   |   4 +
 2 files changed, 173 insertions(+)
 create mode 100644 isar-patches/0001-u-boot-add-libubootenv.patch

diff --git a/isar-patches/0001-u-boot-add-libubootenv.patch b/isar-patches/0001-u-boot-add-libubootenv.patch
new file mode 100644
index 0000000..10a5b4a
--- /dev/null
+++ b/isar-patches/0001-u-boot-add-libubootenv.patch
@@ -0,0 +1,169 @@
+From 76897e89977f895495e21e37cb76f90392d55ef9 Mon Sep 17 00:00:00 2001
+From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
+Date: Fri, 19 Jun 2020 17:00:36 +0200
+Subject: [PATCH v2] u-boot: add libubootenv
+
+Add the new library libubootenv and remove fw_printenv and fw_setenv
+form u-boot-tools as the are now part of the new library.
+
+libubootenv is a library that provides a hardware independent
+way to access to U-Boot environment. U-Boot has its default environment
+compiled board-dependently and this means that tools to access the environment
+are also board specific, too.
+
+libubootenv conflicts with u-boot-tools from Debian 10
+as both try to install fw_printenv and fw_sentenv. This conflict is not
+part of the control file as it breaks the installation of custom u-boot-tools
+from the u-boot-sources.
+
+Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
+---
+ meta-isar/conf/machine/de0-nano-soc.conf      |  2 +-
+ .../libubootenv/files/debian/compat           |  1 +
+ .../libubootenv/files/debian/control.tmpl     | 15 +++++++++
+ .../libubootenv/files/debian/rules.tmpl       | 24 ++++++++++++++
+ .../libubootenv/libubootenv_0.2.bb            | 32 +++++++++++++++++++
+ .../files/debian/u-boot-tools.conffiles       |  1 -
+ .../u-boot/files/debian/u-boot-tools.install  |  2 --
+ .../u-boot/files/debian/u-boot-tools.links    |  1 -
+ 8 files changed, 73 insertions(+), 5 deletions(-)
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/compat
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+ create mode 100644 meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+ delete mode 100644 meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
+ delete mode 100644 meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
+
+diff --git a/meta-isar/conf/machine/de0-nano-soc.conf b/meta-isar/conf/machine/de0-nano-soc.conf
+index 3a2c009..6558d90 100644
+--- a/meta-isar/conf/machine/de0-nano-soc.conf
++++ b/meta-isar/conf/machine/de0-nano-soc.conf
+@@ -15,4 +15,4 @@ WKS_FILE ?= "de0-nano-soc.wks.in"
+ IMAGER_INSTALL += "u-boot-de0-nano-soc"
+ IMAGER_BUILD_DEPS += "u-boot-de0-nano-soc"
+ 
+-IMAGE_INSTALL += "u-boot-tools u-boot-script"
++IMAGE_INSTALL += "u-boot-tools libubootenv u-boot-script"
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/compat b/meta/recipes-bsp/libubootenv/files/debian/compat
+new file mode 100644
+index 0000000..b4de394
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/compat
+@@ -0,0 +1 @@
++11
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/control.tmpl b/meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+new file mode 100644
+index 0000000..fade69a
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+@@ -0,0 +1,15 @@
++Source: libubootenv
++Section: embedded
++Priority: optional
++Maintainer: Stefano Babic <sbabic@denx.de>
++Build-Depends: ${BUILD_DEB_DEPENDS}
++Standards-Version: 4.2.1
++Homepage: https://sbabic.github.io/libubootenv
++
++Package: libubootenv
++Architecture: any
++Depends: ${DEBIAN_DEPENDS}
++Description: libubootenv is a library that provides a hardware independent
++ way to access to U-Boot environment. U-Boot has its default environment
++ compiled board-dependently and this means that tools to access the environment
++ are also board specific, too.
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl b/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+new file mode 100644
+index 0000000..56ccd19
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+@@ -0,0 +1,24 @@
++#!/usr/bin/make -f
++
++ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
++export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
++export CC=$(DEB_HOST_GNU_TYPE)-gcc
++export LD=$(DEB_HOST_GNU_TYPE)-gcc
++endif
++
++export DH_VERBOSE = 1
++
++export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
++
++override_dh_auto_configure:
++	dh_auto_configure --
++
++%:
++	echo $@
++	dh $@
++
++override_dh_installchangelogs:
++	true
++
++override_dh_installdocs:
++	true
+diff --git a/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb b/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+new file mode 100644
+index 0000000..1be058c
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+@@ -0,0 +1,32 @@
++# libubootenv
++#
++# This software is a part of ISAR.
++# Copyright (c) Siemens AG, 2020
++#
++# SPDX-License-Identifier: MIT
++
++DESCRIPTION = "swupdate utility for software updates"
++HOMEPAGE= "https://github.com/sbabic/swupdate"
++LICENSE = "GPL-2.0"
++LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
++SRC_URI = "gitsm://github.com/sbabic/libubootenv.git;branch=master;protocol=https"
++
++SRCREV = "bf6ff631c0e38cede67268ceb8bf1383b5f8848e"
++
++BUILD_DEB_DEPENDS = "cmake, zlib1g-dev"
++
++SRC_URI += "file://debian"
++TEMPLATE_FILES = "debian/control.tmpl debian/rules.tmpl"
++TEMPLATE_VARS += "BUILD_DEB_DEPENDS DEFCONFIG DEBIAN_DEPENDS"
++
++
++inherit dpkg
++
++S = "${WORKDIR}/git"
++
++do_prepare_build() {
++        DEBDIR=${S}/debian
++        install -d ${DEBDIR}
++        cp -R ${WORKDIR}/debian ${S}
++        deb_add_changelog
++}
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
+deleted file mode 100644
+index d49a8fb..0000000
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
++++ /dev/null
+@@ -1 +0,0 @@
+-/etc/fw_env.config
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
+index d1ae3e0..2893b9a 100644
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
++++ b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
+@@ -1,5 +1,3 @@
+ tools/dumpimage		/usr/bin/
+-tools/env/fw_printenv	/usr/bin/
+ tools/mkenvimage	/usr/bin/
+ tools/mkimage		/usr/bin/
+-tools/env/fw_env.config	/etc
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
+deleted file mode 100644
+index 92f5a6c..0000000
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
++++ /dev/null
+@@ -1 +0,0 @@
+-/usr/bin/fw_printenv /usr/bin/fw_setenv
+-- 
+2.20.1
+
diff --git a/kas-cip.yml b/kas-cip.yml
index 019b31e..0da07db 100644
--- a/kas-cip.yml
+++ b/kas-cip.yml
@@ -22,6 +22,10 @@ repos:
     refspec: 351af175bc54a201c6f44307d4e998bd6c0afdb8
     layers:
       meta:
+    patches:
+      01-libubootenv:
+        path: isar-patches/0001-u-boot-add-libubootenv.patch
+        repo: cip-core
 
 bblayers_conf_header:
   standard: |
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4851): https://lists.cip-project.org/g/cip-dev/message/4851
Mute This Topic: https://lists.cip-project.org/mt/75188183/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v2 3/5] recipes-core: add swupdate
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 2/5] patches: add libubootenv Quirin Gylstorff
@ 2020-06-29  9:56   ` Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 4/5] wic: Add wks files for A/B Partition update Quirin Gylstorff
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:56 UTC (permalink / raw)
  To: Jan.Kiszka, cip-dev; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 45248 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add swupdate for A/B software updates. Currently the Round Robin
handler in lua supports efibootguard as bootloader. The u-boot
implementation is outstanding.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 classes/kconfig-snippets.bbclass              |  90 ++++
 classes/swupdate-config.bbclass               |  76 +++
 classes/swupdate-img.bbclass                  |  75 +++
 .../swupdate/files/debian/changelog.tmpl      |   6 +
 recipes-core/swupdate/files/debian/compat     |   1 +
 .../swupdate/files/debian/control.tmpl        |  15 +
 recipes-core/swupdate/files/debian/copyright  |  36 ++
 recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
 .../swupdate/files/debian/swupdate.examples   |   2 +
 .../swupdate/files/debian/swupdate.install    |   2 +
 .../swupdate/files/debian/swupdate.manpages   |   5 +
 .../swupdate/files/debian/swupdate.tmpfile    |   2 +
 recipes-core/swupdate/files/debian/watch      |  12 +
 recipes-core/swupdate/files/postinst          |   2 +
 recipes-core/swupdate/files/swupdate.cfg      |   6 +
 .../swupdate/files/swupdate.service.example   |  11 +
 .../swupdate/files/swupdate.socket.example    |  11 +
 .../swupdate/files/swupdate.socket.tmpl       |  13 +
 .../swupdate/files/swupdate_defconfig         |  83 ++++
 .../swupdate_defconfig_efibootguard.snippet   |   3 +
 .../files/swupdate_defconfig_lua.snippet      |   2 +
 .../swupdate_defconfig_luahandler.snippet     |   4 +
 .../files/swupdate_defconfig_mtd.snippet      |   1 +
 .../files/swupdate_defconfig_u-boot.snippet   |   3 +
 .../files/swupdate_defconfig_ubi.snippet      |   6 +
 .../swupdate/files/swupdate_handlers.lua      | 453 ++++++++++++++++++
 recipes-core/swupdate/swupdate.bb             |  54 +++
 27 files changed, 1004 insertions(+)
 create mode 100644 classes/kconfig-snippets.bbclass
 create mode 100644 classes/swupdate-config.bbclass
 create mode 100644 classes/swupdate-img.bbclass
 create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/compat
 create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/copyright
 create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
 create mode 100644 recipes-core/swupdate/files/debian/watch
 create mode 100644 recipes-core/swupdate/files/postinst
 create mode 100644 recipes-core/swupdate/files/swupdate.cfg
 create mode 100644 recipes-core/swupdate/files/swupdate.service.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
 create mode 100644 recipes-core/swupdate/swupdate.bb

diff --git a/classes/kconfig-snippets.bbclass b/classes/kconfig-snippets.bbclass
new file mode 100644
index 0000000..d754654
--- /dev/null
+++ b/classes/kconfig-snippets.bbclass
@@ -0,0 +1,90 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+KCONFIG_SNIPPETS = ""
+
+# The following function defines the kconfig snippet system
+# with automatich debian dependency injection
+#
+# To define a feature set, the user has to define the following
+# variable to an empty string:
+#
+# KFEATURE_featurename = ""
+#
+# Then, required additions to the variables can be defined:
+#
+# KFEATURE_featurename[KCONFIG_SNIPPETS] = "file://snippet-file-name.snippet"
+# KFEATURE_featurename[SRC_URI] = "file://required-file.txt"
+# KFEATURE_featurename[DEPENDS] = "deb-pkg1 deb-pkg2 deb-pkg3"
+# KFEATURE_featurename[DEBIAN_DEPENDS] = "deb-pkg1"
+# KFEATURE_featurename[BUILD_DEB_DEPENDS] = "deb-pkg1,deb-pkg2,deb-pkg3"
+
+# The 'KCONFIG_SNIPPETS' flag gives a list of URI entries, where only
+# file:// is supported. These snippets are appended to the DEFCONFIG file.
+#
+# Features can depend on other features via the following mechanism:
+#
+# KFEATURE_DEPS[feature1] = "feature2"
+
+python () {
+    requested_features = d.getVar("KFEATURES", True) or ""
+
+    features = set(requested_features.split())
+    old_features = set()
+    feature_deps = d.getVarFlags("KFEATURE_DEPS") or {}
+    while old_features != features:
+        diff_features = old_features.symmetric_difference(features)
+        old_features = features.copy()
+        for i in diff_features:
+            features.update(feature_deps.get(i, "").split())
+
+    for f in sorted(features):
+        bb.debug(2, "Feature: " + f)
+        varname = "KFEATURE_" + f
+        dummyvar = d.getVar(varname, False)
+        if dummyvar == None:
+            bb.error("Feature var " + f + " must be defined with needed flags.")
+        else:
+            feature_flags = d.getVarFlags(varname)
+            for feature_varname in sorted(feature_flags):
+                if feature_flags.get(feature_varname, "") != "":
+                    sep = " "
+
+                    # Required to add KCONFIG_SNIPPETS to SRC_URI here,
+                    # because 'SRC_URI += "${KCONFIG_SNIPPETS}"' would
+                    # conflict with SRC_APT feature.
+                    if feature_varname == "KCONFIG_SNIPPETS":
+                        d.appendVar('SRC_URI',
+                            " " + feature_flags[feature_varname].strip())
+
+                    # BUILD_DEP_DEPENDS and DEBIAN_DEPENDS is ',' separated
+                    # Only add ',' if there is already something there
+                    if feature_varname in ["BUILD_DEB_DEPENDS",
+                                           "DEBIAN_DEPENDS"]:
+                        sep = "," if d.getVar(feature_varname) else ""
+
+                    d.appendVar(feature_varname,
+                        sep + feature_flags[feature_varname].strip())
+}
+
+# DEFCONFIG must be a predefined bitbake variable and the corresponding file
+# must exist in the WORKDIR.
+# The resulting generated config is the same file suffixed with ".gen"
+
+do_prepare_build_prepend() {
+        sh -x
+        GENCONFIG="${WORKDIR}/${DEFCONFIG}".gen
+        rm -f "$GENCONFIG"
+        cp "${WORKDIR}/${DEFCONFIG}" "$GENCONFIG"
+        for CONFIG_SNIPPET in $(echo "${KCONFIG_SNIPPETS}" | sed 's#file://##g')
+        do
+                cat ${WORKDIR}/$CONFIG_SNIPPET >> "$GENCONFIG"
+        done
+}
diff --git a/classes/swupdate-config.bbclass b/classes/swupdate-config.bbclass
new file mode 100644
index 0000000..7ce51c5
--- /dev/null
+++ b/classes/swupdate-config.bbclass
@@ -0,0 +1,76 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+# This class manages the config snippets together with their dependencies
+# to build SWUpdate
+
+inherit kconfig-snippets
+
+BUILD_DEB_DEPENDS = " \
+    zlib1g-dev, debhelper, libconfig-dev, libarchive-dev, \
+    python-sphinx:native, dh-systemd, libsystemd-dev"
+
+KFEATURE_lua = ""
+KFEATURE_lua[BUILD_DEB_DEPENDS] = "liblua5.3-dev"
+KFEATURE_lua[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_lua.snippet"
+
+KFEATURE_luahandler = ""
+KFEATURE_luahandler[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_luahandler.snippet"
+KFEATURE_luahandler[SRC_URI] = "file://${SWUPDATE_LUASCRIPT}"
+
+KFEATURE_DEPS = ""
+KFEATURE_DEPS[luahandler] = "lua"
+
+KFEATURE_efibootguard = ""
+KFEATURE_efibootguard[BUILD_DEB_DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[DEBIAN_DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_efibootguard.snippet"
+
+KFEATURE_mtd = ""
+KFEATURE_mtd[BUILD_DEB_DEPENDS] = "libmtd-dev"
+KFEATURE_mtd[DEPENDS] = "mtd-utils"
+KFEATURE_mtd[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_mtd.snippet"
+
+KFEATURE_ubi = ""
+KFEATURE_ubi[BUILD_DEB_DEPENDS] = "libubi-dev"
+KFEATURE_ubi[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_ubi.snippet"
+
+KFEATURE_DEPS[ubi] = "mtd"
+
+KFEATURE_u-boot = ""
+KFEATURE_u-boot[BUILD_DEB_DEPENDS] = "u-boot-${MACHINE}-dev"
+KFEATURE_u-boot[DEBIAN_DEPENDS] = "u-boot-tools"
+KFEATURE_u-boot[DEPENDS] = "${U_BOOT}"
+KFEATURE_u-boot[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_u-boot.snippet"
+
+SWUPDATE_LUASCRIPT ?= "swupdate_handlers.lua"
+
+def get_bootloader_featureset(d):
+    bootloader = d.getVar("BOOTLOADER", True) or ""
+    if bootloader == "efibootguard":
+        return "efibootguard"
+    if bootloader == "u-boot":
+        return "u-boot"
+    return ""
+
+SWUPDATE_KFEATURES ??= ""
+KFEATURES = "${SWUPDATE_KFEATURES}"
+KFEATURES += "${@get_bootloader_featureset(d)}"
+
+# Astonishingly, as an anonymous python function, BOOTLOADER is always None
+# one time before it gets set. So the following must be a task.
+python do_check_bootloader () {
+    bootloader = d.getVar("BOOTLOADER", True) or "None"
+    if not bootloader in ["efibootguard", "u-boot"]:
+        bb.warn("swupdate: BOOTLOADER set to incompatible value: " + bootloader)
+}
+addtask check_bootloader before do_fetch
+
diff --git a/classes/swupdate-img.bbclass b/classes/swupdate-img.bbclass
new file mode 100644
index 0000000..a21d6ec
--- /dev/null
+++ b/classes/swupdate-img.bbclass
@@ -0,0 +1,75 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+SWU_IMAGE_FILE ?= "${PN}-${DISTRO}-${MACHINE}.swu"
+SWU_DESCRIPTION_FILE ?= "sw-description"
+SWU_ADDITIONAL_FILES ?= ""
+SWU_SIGNED ?= ""
+SWU_SIGNATURE_EXT ?= "sig"
+SWU_SIGNATURE_TYPE ?= "rsa"
+
+IMAGER_INSTALL += "${@'openssl' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}"
+
+do_swupdate_image[stamp-extra-info] = "${DISTRO}-${MACHINE}"
+do_swupdate_image[cleandirs] += "${WORKDIR}/swu"
+do_swupdate_image() {
+    rm -f '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
+    cp '${WORKDIR}/${SWU_DESCRIPTION_FILE}' '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
+
+    # Create symlinks for files used in the update image
+    for file in ${SWU_ADDITIONAL_FILES}; do
+        if [ -e "${WORKDIR}/$file" ]; then
+            ln -s "${WORKDIR}/$file" "${WORKDIR}/swu/$file"
+        else
+            ln -s "${DEPLOY_DIR_IMAGE}/$file" "${WORKDIR}/swu/$file"
+        fi
+    done
+
+    # Prepare for signing
+    sign='${@'x' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}'
+    if [ -n "$sign" ]; then
+        image_do_mounts
+        cp -f '${SIGN_KEY}' '${WORKDIR}/dev.key'
+        test -e '${SIGN_CRT}' && cp -f '${SIGN_CRT}' '${WORKDIR}/dev.crt'
+
+        # Fill in file check sums
+        for file in ${SWU_ADDITIONAL_FILES}; do
+            sed -i "s:$file-sha256:$(sha256sum '${WORKDIR}/swu/'$file | cut -f 1 -d ' '):g" \
+                '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
+        done
+    fi
+
+    cd "${WORKDIR}/swu"
+    for file in '${SWU_DESCRIPTION_FILE}' ${SWU_ADDITIONAL_FILES}; do
+        echo "$file"
+        if [ -n "$sign" -a \
+             '${SWU_DESCRIPTION_FILE}' = "$file" ]; then
+            if [ "${SWU_SIGNATURE_TYPE}" = "rsa" ]; then
+                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl dgst \
+                    -sha256 -sign '${PP_WORK}/dev.key' \
+                    '${PP_WORK}/swu/'"$file" \
+                        > '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}'
+            elif [ "${SWU_SIGNATURE_TYPE}" = "cms" ]; then
+                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl cms \
+                    -sign -in '${PP_WORK}/swu/'"$file" \
+                    -out '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}' \
+                    -signer '${PP_WORK}/dev.crt' \
+                    -inkey '${PP_WORK}/dev.key' \
+                    -outform DER -nosmimecap -binary
+            fi
+            echo "$file".'${SWU_SIGNATURE_EXT}'
+        fi
+    done | cpio -ovL -H crc \
+        > '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
+    cd -
+}
+
+addtask swupdate_image before do_build after do_copy_boot_files do_install_imager_deps do_transform_template
diff --git a/recipes-core/swupdate/files/debian/changelog.tmpl b/recipes-core/swupdate/files/debian/changelog.tmpl
new file mode 100644
index 0000000..81087d3
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/changelog.tmpl
@@ -0,0 +1,6 @@
+swupdate (${PV}) unstable; urgency=medium
+
+  * SWUpdate
+
+ --  Christian Storm <christian.storm@siemens.com>  Thu, 31 Jan 2019 15:23:56 +0100
+
diff --git a/recipes-core/swupdate/files/debian/compat b/recipes-core/swupdate/files/debian/compat
new file mode 100644
index 0000000..b4de394
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/compat
@@ -0,0 +1 @@
+11
diff --git a/recipes-core/swupdate/files/debian/control.tmpl b/recipes-core/swupdate/files/debian/control.tmpl
new file mode 100644
index 0000000..2b92850
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/control.tmpl
@@ -0,0 +1,15 @@
+Source: swupdate
+Section: embedded
+Priority: optional
+Maintainer: Stefano Babic <sbabic@denx.de>
+Build-Depends: ${BUILD_DEB_DEPENDS}
+Standards-Version: 4.2.1
+Homepage: http://sbabic.github.io/swupdate
+
+Package: swupdate
+Architecture: any
+Depends: ${DEBIAN_DEPENDS}
+Description: reliable way to update an embedded system
+ This project is thought to help to update an embedded system from a storage media or from network.
+ However, it should be mainly considered as a framework, where further protocols or installers
+ (in SWUpdate they are called handlers) can be easily added to the application.
diff --git a/recipes-core/swupdate/files/debian/copyright b/recipes-core/swupdate/files/debian/copyright
new file mode 100644
index 0000000..f920942
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/copyright
@@ -0,0 +1,36 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: swupdate
+Maintainer: Stefano Babic <sbabic@denx.de>
+Source: http://github.com/sbabic/swupdate
+
+Files: *
+Copyright: 2014-2017 Stefano Babic <sbabic@denx.de>
+
+License: GPL-2 with OpenSSL exception
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ In addition, as a special exception, the author of this
+ program gives permission to link the code of its
+ release with the OpenSSL project's "OpenSSL" library (or
+ with modified versions of it that use the same license as
+ the "OpenSSL" library), and distribute the linked
+ executables. You must obey the GNU General Public
+ License in all respects for all of the code used other
+ than "OpenSSL".  If you modify this file, you may extend
+ this exception to your version of the file, but you are
+ not obligated to do so.  If you do not wish to do so,
+ delete this exception statement from your version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
diff --git a/recipes-core/swupdate/files/debian/rules.tmpl b/recipes-core/swupdate/files/debian/rules.tmpl
new file mode 100755
index 0000000..54cca57
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/rules.tmpl
@@ -0,0 +1,30 @@
+#!/usr/bin/make -f
+
+ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
+export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
+export CC=$(DEB_HOST_GNU_TYPE)-gcc
+export LD=$(DEB_HOST_GNU_TYPE)-gcc
+endif
+
+export DH_VERBOSE = 1
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
+
+documentation: configure
+	make man
+
+configure:
+	make ${DEFCONFIG}
+
+build: documentation configure
+	dh $@
+
+%:
+	echo $@
+	dh $@
+
+override_dh_installchangelogs:
+	true
+
+override_dh_installdocs:
+	true
diff --git a/recipes-core/swupdate/files/debian/swupdate.examples b/recipes-core/swupdate/files/debian/swupdate.examples
new file mode 100644
index 0000000..c257b75
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.examples
@@ -0,0 +1,2 @@
+examples/configuration
+examples/description
diff --git a/recipes-core/swupdate/files/debian/swupdate.install b/recipes-core/swupdate/files/debian/swupdate.install
new file mode 100644
index 0000000..8957cc6
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.install
@@ -0,0 +1,2 @@
+swupdate usr/bin
+swupdate.cfg /etc
diff --git a/recipes-core/swupdate/files/debian/swupdate.manpages b/recipes-core/swupdate/files/debian/swupdate.manpages
new file mode 100644
index 0000000..c3438e0
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.manpages
@@ -0,0 +1,5 @@
+doc/build/man/swupdate.1
+doc/build/man/client.1
+doc/build/man/sendtohawkbit.1
+doc/build/man/hawkbitcfg.1
+doc/build/man/progress.1
diff --git a/recipes-core/swupdate/files/debian/swupdate.tmpfile b/recipes-core/swupdate/files/debian/swupdate.tmpfile
new file mode 100644
index 0000000..4743672
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.tmpfile
@@ -0,0 +1,2 @@
+X /tmp/datadst
+X /tmp/scripts
diff --git a/recipes-core/swupdate/files/debian/watch b/recipes-core/swupdate/files/debian/watch
new file mode 100644
index 0000000..bc4c53e
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/watch
@@ -0,0 +1,12 @@
+# Example watch control file for uscan
+# Rename this file to "watch" and then you can run the "uscan" command
+# to check for upstream updates and more.
+# See uscan(1) for format
+
+# Compulsory line, this is a version 4 file
+version=4
+
+# GitHub hosted projects
+opts="filenamemangle="s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
+   https://github.com/<user>/swupdate/tags \
+   (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
diff --git a/recipes-core/swupdate/files/postinst b/recipes-core/swupdate/files/postinst
new file mode 100644
index 0000000..f15ac10
--- /dev/null
+++ b/recipes-core/swupdate/files/postinst
@@ -0,0 +1,2 @@
+#!/bin/sh
+deb-systemd-helper enable swupdate.socket || true
diff --git a/recipes-core/swupdate/files/swupdate.cfg b/recipes-core/swupdate/files/swupdate.cfg
new file mode 100644
index 0000000..e0222f1
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.cfg
@@ -0,0 +1,6 @@
+globals :
+{
+    verbose = true;
+    loglevel = 10;
+    syslog = false;
+};
diff --git a/recipes-core/swupdate/files/swupdate.service.example b/recipes-core/swupdate/files/swupdate.service.example
new file mode 100644
index 0000000..d0b821e
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.service.example
@@ -0,0 +1,11 @@
+[Unit]
+Description=SWUpdate daemon
+Documentation=https://github.com/sbabic/swupdate
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/swupdate -f /etc/swupdate.cfg
+KillMode=mixed
+
+[Install]
+WantedBy=multi-user.target
diff --git a/recipes-core/swupdate/files/swupdate.socket.example b/recipes-core/swupdate/files/swupdate.socket.example
new file mode 100644
index 0000000..2b75671
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.socket.example
@@ -0,0 +1,11 @@
+[Unit]
+Description=SWUpdate socket listener
+Documentation=https://github.com/sbabic/swupdate
+Documentation=https://sbabic.github.io/swupdate
+
+[Socket]
+ListenStream=/tmp/sockinstctrl
+ListenStream=/tmp/swupdateprog
+
+[Install]
+WantedBy=sockets.target
diff --git a/recipes-core/swupdate/files/swupdate.socket.tmpl b/recipes-core/swupdate/files/swupdate.socket.tmpl
new file mode 100644
index 0000000..8e7fc1d
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.socket.tmpl
@@ -0,0 +1,13 @@
+[Unit]
+Description=SWUpdate socket listener
+Documentation=https://github.com/sbabic/swupdate
+Documentation=https://sbabic.github.io/swupdate
+
+[Socket]
+SocketUser=${SWUPDATE_SOCKET_OWNER}
+SocketGroup=root
+ListenStream=/tmp/sockinstctrl
+ListenStream=/tmp/swupdateprog
+
+[Install]
+WantedBy=sockets.target
diff --git a/recipes-core/swupdate/files/swupdate_defconfig b/recipes-core/swupdate/files/swupdate_defconfig
new file mode 100644
index 0000000..9ae7cb5
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig
@@ -0,0 +1,83 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Swupdate Configuration
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Swupdate Settings
+#
+
+#
+# General Configuration
+#
+# CONFIG_CURL is not set
+# CONFIG_CURL_SSL is not set
+CONFIG_SYSTEMD=y
+CONFIG_SCRIPTS=y
+# CONFIG_HW_COMPATIBILITY is not set
+CONFIG_SW_VERSIONS_FILE="/etc/sw-versions"
+
+#
+# Socket Paths
+#
+CONFIG_SOCKET_CTRL_PATH="/tmp/sockinstctrl"
+CONFIG_SOCKET_PROGRESS_PATH="/tmp/swupdateprog"
+CONFIG_SOCKET_REMOTE_HANDLER_DIRECTORY="/tmp/"
+# CONFIG_MTD is not set
+# CONFIG_LUA is not set
+# CONFIG_LUAPKG is not set
+# CONFIG_FEATURE_SYSLOG is not set
+
+#
+# Build Options
+#
+CONFIG_CROSS_COMPILE=""
+CONFIG_SYSROOT=""
+CONFIG_EXTRA_CFLAGS=""
+CONFIG_EXTRA_LDFLAGS=""
+CONFIG_EXTRA_LDLIBS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_WERROR is not set
+# CONFIG_NOCLEANUP is not set
+# CONFIG_BOOTLOADER_EBG is not set
+# CONFIG_UBOOT is not set
+# CONFIG_BOOTLOADER_NONE is not set
+# CONFIG_BOOTLOADER_GRUB is not set
+# CONFIG_DOWNLOAD is not set
+# CONFIG_DOWNLOAD_SSL is not set
+# CONFIG_CHANNEL_CURL is not set
+# CONFIG_HASH_VERIFY=y
+# CONFIG_SIGNED_IMAGES is not set
+# CONFIG_ENCRYPTED_IMAGES is not set
+# CONFIG_SURICATTA is not set
+# CONFIG_WEBSERVER is not set
+CONFIG_GUNZIP=y
+
+#
+# Parser Features
+#
+CONFIG_LIBCONFIG=y
+CONFIG_PARSERROOT=""
+# CONFIG_JSON is not set
+# CONFIG_LUAEXTERNAL is not set
+# CONFIG_SETEXTPARSERNAME is not set
+# CONFIG_SETSWDESCRIPTION is not set
+
+#
+# Image Handlers
+#
+CONFIG_RAW=y
+# CONFIG_LUASCRIPTHANDLER is not set
+# CONFIG_SHELLSCRIPTHANDLER is not set
+# CONFIG_HANDLER_IN_LUA is not set
+# CONFIG_EMBEDDED_LUA_HANDLER is not set
+# CONFIG_EMBEDDED_LUA_HANDLER_SOURCE is not set
+CONFIG_ARCHIVE=y
+# CONFIG_REMOTE_HANDLER is not set
+# CONFIG_SWUFORWARDER_HANDLER is not set
+# CONFIG_BOOTLOADERHANDLER is not set
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
new file mode 100644
index 0000000..8e3688c
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
@@ -0,0 +1,3 @@
+CONFIG_BOOTLOADER_NONE=n
+CONFIG_BOOTLOADER_EBG=y
+CONFIG_BOOTLOADERHANDLER=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
new file mode 100644
index 0000000..b39f9df
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
@@ -0,0 +1,2 @@
+CONFIG_LUA=y
+CONFIG_LUAPKG="lua53"
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
new file mode 100644
index 0000000..b4a2de8
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
@@ -0,0 +1,4 @@
+CONFIG_LUASCRIPTHANDLER=y
+CONFIG_HANDLER_IN_LUA=y
+CONFIG_EMBEDDED_LUA_HANDLER=y
+CONFIG_EMBEDDED_LUA_HANDLER_SOURCE="swupdate_handlers.lua"
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
new file mode 100644
index 0000000..eab98dd
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
@@ -0,0 +1 @@
+CONFIG_MTD=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
new file mode 100644
index 0000000..6b5832a
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
@@ -0,0 +1,3 @@
+CONFIG_UBOOT=y
+CONFIG_UBOOT_FWENV="/etc/fw_env.config"
+CONFIG_BOOTLOADERHANDLER=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
new file mode 100644
index 0000000..d1c7732
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
@@ -0,0 +1,6 @@
+CONFIG_UBIVOL=y
+CONFIG_UBIATTACH=y
+CONFIG_UBIBLACKLIST=""
+CONFIG_UBIWHITELIST=""
+CONFIG_UBIVIDOFFSET=0
+CONFIG_CFI=y
diff --git a/recipes-core/swupdate/files/swupdate_handlers.lua b/recipes-core/swupdate/files/swupdate_handlers.lua
new file mode 100644
index 0000000..f2ecc54
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_handlers.lua
@@ -0,0 +1,453 @@
+--[[
+
+    Round-robin Image and File Handler.
+
+    Copyright (C) 2019, Siemens AG
+
+    Author: Christian Storm <christian.storm@siemens.com>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+
+    An `sw-description` file using these handlers may look like:
+        software =
+        {
+            version = "0.1.0";
+            images: ({
+                filename = "rootfs.ext4";
+                device = "sda4,sda5";
+                type = "roundrobin";
+                compressed = false;
+            });
+            files: ({
+                filename = "vmlinuz";
+                path = "vmlinuz";
+                type = "kernelfile";
+                device = "sda2,sda3";
+                filesystem = "vfat";
+            },
+            {
+                filename = "initrd.img";
+                path = "initrd.img";
+                type = "kernelfile";
+                device = "sda2,sda3";
+                filesystem = "vfat";
+            });
+        }
+
+    The semantics is as follows: Instead of having a fixed target device,
+    the 'roundrobin' image handler calculates the target device by parsing
+    /proc/cmdline, matching the root=<device> kernel parameter against its
+    'device' attribute's list of devices, and sets the actual target
+    device to the next 'device' attribute list entry in a round-robin
+    manner. The actual flashing is done via chain-calling another handler,
+    defaulting to the "raw" handler.
+
+    The 'kernelfile' file handler reuses the 'roundrobin' handler's target
+    device calculation by reading the actual target device from the same
+    index into its 'device' attribute's list of devices. The actual placing
+    of files into this partition is done via chain-calling another handler,
+    defaulting to the "rawfile" handler.
+
+    In the above example, if /dev/sda4 is currently booted according to
+    /proc/cmdline, /dev/sda5 will be flashed and the vmlinuz and initrd.img
+    files will be placed on /dev/sda3. If /dev/sda5 is booted, /dev/sda4
+    will be flashed and the vmlinuz and initrd.img files are placed on
+    /dev/sda2.
+    In addition to "classical" device nodes as in this example, partition
+    UUIDs as reported, e.g., by `blkid -s PARTUUID` are also supported.
+    UBI volumes are supported as well by specifying a CSV list of
+    ubi<number>:<label> items.
+
+    Configuration is done via an INI-style configuration file located at
+    /etc/swupdate.handler.ini or via compiled-in configuration (by
+    embedding the Lua handler script into the SWUpdate binary via using
+    CONFIG_EMBEDDED_LUA_HANDLER), the latter having precedence over the
+    former. See the example configuration below.
+    If uncommenting this example block, it will take precedence over any
+    /etc/swupdate.handler.ini configuration file.
+
+    The chain-called handlers can either be specified in the configuration,
+    i.e., a static run-time setting, or via the 'chainhandler' property of
+    an 'image' or 'file' section in the sw-description, with the latter
+    taking precedence over the former, e.g.,
+        ...
+        images: ({
+                filename = "rootfs.ext4";
+                device = "sda4,sda5";
+                type = "roundrobin";
+                properties: {
+                    chainhandler = "myraw";
+                };
+            });
+        ...
+    Such a sw-description fragment will chain-call the imaginary "myraw"
+    handler regardless of what's been configured in the compiled-in or the
+    configuration file.
+    When chain-calling the "rdiff_image" handler, its 'rdiffbase' property
+    is subject to round-robin as well, i.e., the 'rdiffbase' property is
+    expected to be a CSV list as for the 'device' property, and the actual
+    'rdiffbase' property value is calculated following the same round-robin
+    calculation mechanism stated above prior to chain-calling the actual
+    "rdiff_image" handler, e.g.,
+        images: ({
+                filename = "rootfs.ext4";
+                type = "roundrobin";
+                device = "sda4,sda5";
+                properties: {
+                    chainhandler = "rdiff_image";
+                    rdiffbase="sda1,sda2";
+                };
+            });
+    will set the 'rdiffbase' property to /dev/sda2 (/dev/sda1) if /dev/sda4
+    (/dev/sda5) is the currently booted root file system according to
+    /proc/cmdline parsing.
+
+]]
+
+
+local configuration = [[
+[bootloader]
+# Required: bootloader name, uboot and ebg currently supported.
+name=ebg
+# Required: bootloader-specific key-value pairs, e.g., for ebg:
+kernelname=linux.signed.efi
+# For relying on FAT labels, prefix bootlabels with 'L:', e.g., L:BOOT0.
+# For using custom labels, i.e., relying on the contents of an EFILABEL
+# file within the partition, prefix it with 'C:', e.g., C:BOOT0.
+bootlabel={ "C:BOOT0:", "C:BOOT1:" }
+
+# Optional: handler to chain-call for the 'roundrobin' handler,
+# defaulting to 'raw'
+[roundrobin]
+chainhandler=raw
+
+# Optional: handler to chain-call for the 'kernelfile' handler,
+# defaulting to 'rawfile'
+[kernelfile]
+chainhandler=rawfile
+]]
+
+-- Default configuration file, tried if no compiled-in config is available.
+local cfgfile = "/etc/swupdate.handler.ini"
+
+-- Table holding the configuration.
+local config = {}
+
+-- Mandatory configuration [section] and keys
+local BOOTLOADERCFG = {
+    ebg   = {
+        bootloader = {"name", "bootlabel", "kernelname"}
+    },
+    -- TODO fill with mandatory U-Boot configuration
+    uboot = {
+        bootloader = {"name"}
+    }
+}
+
+-- enum-alikes to make code more readable
+local BOOTLOADER = { EBG = "ebg", UBOOT = "uboot" }
+local PARTTYPE   = { UUID = 1, PLAIN = 2, UBI = 3 }
+
+-- Target table describing the target device the image is to be/has been flashed to.
+local rrtarget = {
+    size = function(self)
+        local _size = 0
+        for index in pairs(self) do _size = _size + 1 end
+        return _size - 1
+    end
+}
+
+-- Helper function parsing CSV fields of a struct img_type such as
+-- the "device" fields or the "rdiffbase" property.
+local get_device_list = function(device_node_csv_list)
+    local device_list = {}
+    for item in device_node_csv_list:gmatch("([^,]+)") do
+        local device_node = item:gsub("/dev/", "")
+        device_list[#device_list+1] = device_node
+        device_list[device_node] = #device_list
+    end
+    return device_list
+end
+
+-- Helper function to determine device node location.
+local get_device_path = function(device_node)
+    if device_node:match("ubi%d+:%S+") then
+        return 0, device_node, PARTTYPE.UBI
+    end
+    local device_path = string.format("/dev/disk/by-partuuid/%s", device_node)
+    local file = io.open(device_path, "rb" )
+    if file then
+        file:close()
+        return 0, device_path, PARTTYPE.UUID
+    end
+    device_path = string.format("/dev/%s", device_node)
+    file = io.open(device_path, "rb" )
+    if file then
+        file:close()
+        return 0, device_path, PARTTYPE.PLAIN
+    end
+    swupdate.error(string.format("Cannot access target device node /dev/{,disk/by-partuuid}/%s", device_node))
+    return 1, nil, nil
+end
+
+-- Helper function parsing the INI-style configuration.
+local get_config = function()
+    -- Return configuration right away if it's already parsed.
+    if config ~= nil and #config > 0 then
+        return config
+    end
+
+    -- Get configuration INI-style string.
+    if not configuration then
+        swupdate.trace(string.format("No compiled-in config found, trying %s", cfgfile))
+        local file = io.open(cfgfile, "r" )
+        if not file then
+            swupdate.error(string.format("Cannot open config file %s", cfgfile))
+            return nil
+        end
+        configuration = file:read("*a")
+        file:close()
+    end
+    if configuration:sub(-1) ~= "\n" then
+        configuration=configuration.."\n"
+    end
+
+    -- Parse INI-style contents into config table.
+    local sec, key, value
+    for line in configuration:gmatch("(.-)\n") do
+        if line:match("^%[([%w%p]+)%][%s]*") then
+            sec = line:match("^%[([%w%p]+)%][%s]*")
+            config[sec] = {}
+        elseif sec then
+            key, value = line:match("^([%w%p]-)=(.*)$")
+            if key and value then
+                if tonumber(value)  then value = tonumber(value) end
+                if value == "true"  then value = true            end
+                if value == "false" then value = false           end
+                if value:sub(1,1) == "{" then
+                    local _value = {}
+                    for _key, _ in value:gmatch("\"(%S+)\"") do
+                        table.insert(_value, _key)
+                    end
+                    value = _value
+                end
+                config[sec][key] = value
+            else
+                if not line:match("^$") and not line:match("^#") then
+                    swupdate.warn(string.format("Syntax error, skipping '%s'", line))
+                end
+            end
+        else
+            swupdate.error(string.format("Syntax error. no [section] encountered."))
+            return nil
+        end
+    end
+
+    -- Check config table for mandatory key existence.
+    if config["bootloader"] == nil or config["bootloader"]["name"] == nil then
+        swupdate.error(string.format("Syntax error. no [bootloader] encountered or name= missing therein."))
+        return nil
+    end
+    local bcfg = BOOTLOADERCFG[config.bootloader.name]
+    if not bcfg then
+        swupdate.error(string.format("Bootloader unsupported, name=uboot|ebg missing in [bootloader]?."))
+        return nil
+    end
+    for sec, _ in pairs(bcfg) do
+        for _, key in pairs(bcfg[sec]) do
+            if config[sec] == nil or config[sec][key] == nil then
+                swupdate.error(string.format("Mandatory config key %s= in [%s] not found.", key, sec))
+            end
+        end
+    end
+
+    return config
+end
+
+-- Round-robin image handler for updating the root partition.
+function handler_roundrobin(image)
+    -- Read configuration.
+    if not get_config() then
+        swupdate.error("Cannot read configuration.")
+        return 1
+    end
+
+    -- Check if we can chain-call the handler.
+    local chained_handler = "raw"
+    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
+        chained_handler = image.properties["chainhandler"]
+    elseif config["roundrobin"] ~= nil and config["roundrobin"]["chainhandler"] ~= nil then
+        chained_handler = config["roundrobin"]["chainhandler"]
+    end
+    if not swupdate.handler[chained_handler] then
+        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution.", chained_handler))
+        return 1
+    end
+
+    -- Get device list for round-robin.
+    local devices = get_device_list(image.device)
+    if #devices < 2 then
+        swupdate.error("Specify at least 2 devices in the device= property for 'roundrobin'.")
+        return 1
+    end
+
+    -- Check that rrtarget is unset, else a reboot may be pending.
+    if rrtarget:size() > 0 then
+        swupdate.warn("The 'roundrobin' handler has been run. Is a reboot pending?")
+    end
+
+    -- Determine current root device.
+    local file = io.open("/proc/cmdline", "r")
+    if not file then
+        swupdate.error("Cannot open /proc/cmdline.")
+        return 1
+    end
+    local cmdline = file:read("*l")
+    file:close()
+
+    local rootparam, rootdevice
+    for item in cmdline:gmatch("%S+") do
+        rootparam, rootdevice = item:match("(root=[%u=]*[/dev/]*(%S+))")
+        if rootparam and rootdevice then break end
+    end
+    if not rootdevice then
+        -- Use findmnt to get the rootdev
+      rootdevice = io.popen('findmnt -nl / -o PARTUUID'):read("*l")
+      if not rootdevice then
+        swupdate.error("Cannot determine current root device.")
+        return 1
+      end
+    end
+    swupdate.info(string.format("Current root device is: %s", rootdevice))
+
+    if not devices[rootdevice] then
+        swupdate.error(string.format("Current root device '%s' is not in round-robin root devices list: %s", rootdevice, image.device:gsub("/dev/", "")))
+        return 1
+    end
+
+    -- Perform round-robin calculation for target.
+    local err
+    rrtarget.index = devices[rootdevice] % #devices + 1
+    rrtarget.device_node = devices[rrtarget.index]
+    err, rrtarget.device_path, rrtarget.parttype = get_device_path(devices[rrtarget.index])
+    if err ~= 0 then
+        return 1
+    end
+    swupdate.info(string.format("Using '%s' as 'roundrobin' target via '%s' handler.", rrtarget.device_path, chained_handler))
+
+    -- If the chain-called handler is rdiff_image, adapt the rdiffbase property
+    if chained_handler == "rdiff_image" then
+        if image.properties ~= nil and image.properties["rdiffbase"] ~= nil then
+            local rdiffbase_devices = get_device_list(image.properties["rdiffbase"])
+            if #rdiffbase_devices < 2 then
+                swupdate.error("Specify at least 2 devices in the rdiffbase= property for 'roundrobin'.")
+                return 1
+            end
+            err, image.propierties["rdiffbase"], _ = get_device_path(rdiffbase_devices[rrtarget.index])
+            if err ~= 0 then
+                return 1
+            end
+            swupdate.info(string.format("Using device %s as rdiffbase.", image.properties["rdiffbase"]))
+        else
+            swupdate.error("Property 'rdiffbase' is missing in sw-description.")
+            return 1
+        end
+    end
+
+    -- Actually flash the partition.
+    local msg
+    image.type = chained_handler
+    image.device = rrtarget.device_path
+    err, msg = swupdate.call_handler(chained_handler, image)
+    if err ~= 0 then
+        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
+        return 1
+    end
+
+    if config.bootloader.name == BOOTLOADER.EBG then
+      if rootparam then
+        local value = cmdline:gsub(
+            rootparam:gsub("%-", "%%-"),
+            string.format("root=%s%s",
+                (rrtarget.parttype == PARTTYPE.PLAIN and "") or (rrtarget.parttype == PARTTYPE.UBI and "") or "PARTUUID=",
+                 rrtarget.parttype == PARTTYPE.PLAIN and rrtarget.device_path or devices[rrtarget.index]
+            )
+        )
+        swupdate.info(string.format("Setting EFI Bootguard environment: kernelparams=%s", value))
+        swupdate.set_bootenv("kernelparams", value)
+      end
+    elseif config.bootloader.name == BOOTLOADER.UBOOT then
+        -- Update U-Boot environment.
+        swupdate.info(string.format("Setting U-Boot environment"))
+        local value = rrtarget.index
+        swupdate.set_bootenv("swupdpart", value);
+    end
+
+    return 0
+end
+
+-- File handler for updating kernel files.
+function handler_kernelfile(image)
+    -- Check if we can chain-call the handler.
+    local chained_handler = "rawfile"
+    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
+        chained_handler = image.properties["chainhandler"]
+    elseif config["kernelfile"] ~= nil and config["kernelfile"]["chainhandler"] ~= nil then
+        chained_handler = config["kernelfile"]["chainhandler"]
+    end
+    if not swupdate.handler[chained_handler] then
+        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution."), chained_handler)
+        return 1
+    end
+
+    -- Check that rrtarget is set, else the 'roundrobin' handler hasn't been run.
+    if rrtarget:size() == 0 then
+        swupdate.error("The 'roundrobin' handler hasn't been run.")
+        swupdate.info("Place 'roundrobin' above 'kernelfile' in sw-description.")
+        return 1
+    end
+
+    -- Get device list for round-robin.
+    local devices = get_device_list(image.device)
+    if #devices < 2 then
+        swupdate.error("Specify at least 2 devices in the device= property for 'kernelfile'.")
+        return 1
+    end
+    if rrtarget.index > #devices then
+        swupdate.error("Cannot map kernel partition to root partition.")
+        return 1
+    end
+
+    -- Perform round-robin indexing for target.
+    local err
+    err, image.device, _ = get_device_path(devices[rrtarget.index])
+    if err ~= 0 then
+        return 1
+    end
+    swupdate.info(string.format("Using '%s' as 'kernelfile' target via '%s' handler.", image.device, chained_handler))
+
+    -- Actually copy the 'kernelfile' files.
+    local msg
+    image.type = chained_handler
+    err, msg = swupdate.call_handler(chained_handler, image)
+    if err ~= 0 then
+        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
+        return 1
+    end
+
+    if config.bootloader.name == BOOTLOADER.EBG then
+        -- Update EFI Boot Guard environment: kernelfile
+        local value = string.format("%s%s", config.bootloader.bootlabel[rrtarget.index], config.bootloader.kernelname)
+        swupdate.info(string.format("Setting EFI Bootguard environment: kernelfile=%s", value))
+        swupdate.set_bootenv("kernelfile", value)
+    elseif config.bootloader.name == BOOTLOADER.UBOOT then
+        -- Update U-Boot environment.
+        swupdate.info(string.format("Setting U-Boot environment"))
+        -- TODO
+    end
+
+    return 0
+end
+
+swupdate.register_handler("roundrobin", handler_roundrobin, swupdate.HANDLER_MASK.IMAGE_HANDLER)
+swupdate.register_handler("kernelfile", handler_kernelfile, swupdate.HANDLER_MASK.FILE_HANDLER)
diff --git a/recipes-core/swupdate/swupdate.bb b/recipes-core/swupdate/swupdate.bb
new file mode 100644
index 0000000..95cf73a
--- /dev/null
+++ b/recipes-core/swupdate/swupdate.bb
@@ -0,0 +1,54 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+hDESCRIPTION = "swupdate utility for software updates"
+HOMEPAGE= "https://github.com/sbabic/swupdate"
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
+
+SRC_URI = "git://github.com/sbabic/swupdate.git;branch=master;protocol=https"
+
+SRCREV = "1a6dfbb5a0be978ac1a159758e278ab4d44167e2"
+PV = "2020.4-git+isar"
+
+DEFCONFIG := "swupdate_defconfig"
+
+SRC_URI += "file://debian \
+            file://${DEFCONFIG} \
+            file://${PN}.cfg"
+
+DEPENDS += "libubootenv"
+
+DEBIAN_DEPENDS = "${shlibs:Depends}, ${misc:Depends}"
+
+inherit dpkg
+inherit swupdate-config
+
+KFEATURES += "luahandler"
+
+S = "${WORKDIR}/git"
+
+TEMPLATE_FILES = "debian/changelog.tmpl debian/control.tmpl debian/rules.tmpl"
+TEMPLATE_VARS += "BUILD_DEB_DEPENDS DEFCONFIG DEBIAN_DEPENDS"
+
+do_prepare_build() {
+        DEBDIR=${S}/debian
+        cp -R ${WORKDIR}/debian ${S}
+
+        install -m 0644 ${WORKDIR}/${PN}.cfg ${S}/swupdate.cfg
+        install -m 0644 ${WORKDIR}/${DEFCONFIG}.gen ${S}/configs/${DEFCONFIG}
+
+        if ! grep -q "configs/${DEFCONFIG}" ${S}/.gitignore
+        then
+                echo "configs/${DEFCONFIG}" >> ${S}/.gitignore
+        fi
+        # luahandler
+        install -m 0644 ${WORKDIR}/${SWUPDATE_LUASCRIPT} ${S}
+}
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4855): https://lists.cip-project.org/g/cip-dev/message/4855
Mute This Topic: https://lists.cip-project.org/mt/75188187/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v2 4/5] wic: Add wks files for A/B Partition update
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
                     ` (2 preceding siblings ...)
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 3/5] recipes-core: add swupdate Quirin Gylstorff
@ 2020-06-29  9:56   ` Quirin Gylstorff
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 5/5] swupdate: create swu file from wic image Quirin Gylstorff
  2020-07-29 17:07   ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Jan Kiszka
  5 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:56 UTC (permalink / raw)
  To: Jan.Kiszka, cip-dev; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 3692 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add wks for:
- simatic-ipc227e
- qemu-amd64

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 kas/opt/ebg-swu.yml                  | 26 ++++++++++++++++++++++++++
 wic/ebg-sysparts.inc                 |  8 ++++++++
 wic/qemu-amd64-efibootguard.wks      |  5 +++++
 wic/simatic-ipc227e-efibootguard.wks |  5 +++++
 wic/swupdate-partition.inc           |  4 ++++
 5 files changed, 48 insertions(+)
 create mode 100644 kas/opt/ebg-swu.yml
 create mode 100644 wic/ebg-sysparts.inc
 create mode 100644 wic/qemu-amd64-efibootguard.wks
 create mode 100644 wic/simatic-ipc227e-efibootguard.wks
 create mode 100644 wic/swupdate-partition.inc

diff --git a/kas/opt/ebg-swu.yml b/kas/opt/ebg-swu.yml
new file mode 100644
index 0000000..5b39730
--- /dev/null
+++ b/kas/opt/ebg-swu.yml
@@ -0,0 +1,26 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+header:
+  version: 8
+
+local_conf_header:
+  swupdate: |
+    IMAGE_INSTALL_append = " swupdate efibootguard"
+    BOOTLOADER = "efibootguard"
+
+  efibootguard: |
+    WDOG_TIMEOUT = "0"
+    WICVARS += "WDOG_TIMEOUT"
+
+  wic: |
+    IMAGE_TYPE = "wic-img"
+    WKS_FILE = "${MACHINE}-${BOOTLOADER}.wks"
diff --git a/wic/ebg-sysparts.inc b/wic/ebg-sysparts.inc
new file mode 100644
index 0000000..dea99e8
--- /dev/null
+++ b/wic/ebg-sysparts.inc
@@ -0,0 +1,8 @@
+# default partition layout EFI Boot Guard usage
+
+# EFI partition containing efibootguard bootloader binary
+part --source efibootguard-efi  --ondisk sda --size 16M --extra-space 0 --overhead-factor 1 --label efi   --align 1024 --part-type=EF00 --active
+
+# EFI Boot Guard environment/config partitions plus Kernel files
+part --source efibootguard-boot --ondisk sda --size 32M --extra-space 0 --overhead-factor 1 --label BOOT0 --align 1024 --part-type=0700 --sourceparams "revision=2,root=PARTUUID:fedcba98-7654-3210-cafe-5e0710000001"
+part --source efibootguard-boot --ondisk sda --size 32M --extra-space 0 --overhead-factor 1 --label BOOT1 --align 1024 --part-type=0700 --sourceparams "revision=1,root=PARTUUID:fedcba98-7654-3210-cafe-5e0710000002"
diff --git a/wic/qemu-amd64-efibootguard.wks b/wic/qemu-amd64-efibootguard.wks
new file mode 100644
index 0000000..3cd7360
--- /dev/null
+++ b/wic/qemu-amd64-efibootguard.wks
@@ -0,0 +1,5 @@
+# short-description: Qemu-amd64 with Efibootguard and SWUpdate
+# long-description: Disk image for qemu-amd64 with EFI Boot Guard and SWUpdate
+
+include ebg-sysparts.inc
+include swupdate-partition.inc
diff --git a/wic/simatic-ipc227e-efibootguard.wks b/wic/simatic-ipc227e-efibootguard.wks
new file mode 100644
index 0000000..74446d3
--- /dev/null
+++ b/wic/simatic-ipc227e-efibootguard.wks
@@ -0,0 +1,5 @@
+# short-description: Simatic-ipc227e with EFI Boot Guard and SWUpdate
+# long-description: Disk image for Simatic-ipc227e with EFI Boot Guard and SWUpdate
+
+include ebg-sysparts.inc
+include swupdate-partition.inc
diff --git a/wic/swupdate-partition.inc b/wic/swupdate-partition.inc
new file mode 100644
index 0000000..15fbe80
--- /dev/null
+++ b/wic/swupdate-partition.inc
@@ -0,0 +1,4 @@
+part --source rootfs --uuid "fedcba98-7654-3210-cafe-5e0710000001" --size 1000M   --extra-space 128M --overhead-factor 1 --label systema --align 1024 --fstype=ext4
+part  --source rootfs --uuid "fedcba98-7654-3210-cafe-5e0710000002" --size 1000M   --extra-space 128M --overhead-factor 1 --label systemb --align 1024 --fstype=ext4
+
+bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 rootwait earlyprintk"
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4854): https://lists.cip-project.org/g/cip-dev/message/4854
Mute This Topic: https://lists.cip-project.org/mt/75188186/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v2 5/5] swupdate: create swu file from wic image
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
                     ` (3 preceding siblings ...)
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 4/5] wic: Add wks files for A/B Partition update Quirin Gylstorff
@ 2020-06-29  9:56   ` Quirin Gylstorff
  2020-07-29 17:07   ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Jan Kiszka
  5 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-06-29  9:56 UTC (permalink / raw)
  To: Jan.Kiszka, cip-dev; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 4537 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Create a swu file for swupdate to update devices in the field.
This is done in the same step as the complete image build
to avoid diverging images.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 classes/extract-partition.bbclass             | 26 +++++++++++++++++
 classes/wic-swu-img.bbclass                   | 20 +++++++++++++
 kas/opt/qemu-swupdate.yml                     | 19 ++++++++++++
 recipes-core/images/cip-core-image.bb         | 10 +++++++
 recipes-core/images/files/sw-description.tmpl | 29 +++++++++++++++++++
 5 files changed, 104 insertions(+)
 create mode 100644 classes/extract-partition.bbclass
 create mode 100644 classes/wic-swu-img.bbclass
 create mode 100644 kas/opt/qemu-swupdate.yml
 create mode 100644 recipes-core/images/files/sw-description.tmpl

diff --git a/classes/extract-partition.bbclass b/classes/extract-partition.bbclass
new file mode 100644
index 0000000..e9de8fc
--- /dev/null
+++ b/classes/extract-partition.bbclass
@@ -0,0 +1,26 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+SOURCE_IMAGE_FILE ?= "${WIC_IMAGE_FILE}"
+EXTRACT_PARTITIONS ?= "img4"
+
+do_extract_partition () {
+    for PARTITION in ${EXTRACT_PARTITIONS}; do
+        rm -f ${DEPLOY_DIR_IMAGE}/${PARTITION}.gz
+        PART_START=$(fdisk -lu ${SOURCE_IMAGE_FILE} | grep ${PARTITION} | awk '{ print $2 }'  )
+        PART_END=$(fdisk -lu ${SOURCE_IMAGE_FILE} | grep ${PARTITION} | awk '{ print $3 }'  )
+        PART_COUNT=$(expr ${PART_END} - ${PART_START} + 1 )
+
+        dd if=${SOURCE_IMAGE_FILE} of=${DEPLOY_DIR_IMAGE}/${PARTITION} bs=512 skip=${PART_START} count=${PART_COUNT}
+
+        gzip ${DEPLOY_DIR_IMAGE}/${PARTITION}
+    done
+}
diff --git a/classes/wic-swu-img.bbclass b/classes/wic-swu-img.bbclass
new file mode 100644
index 0000000..c8532ba
--- /dev/null
+++ b/classes/wic-swu-img.bbclass
@@ -0,0 +1,20 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+
+inherit wic-img
+inherit extract-partition
+inherit swupdate-img
+
+SOURCE_IMAGE_FILE = "${WIC_IMAGE_FILE}"
+
+addtask do_extract_partition after do_wic_image
+addtask do_swupdate_image after do_extract_partition
diff --git a/kas/opt/qemu-swupdate.yml b/kas/opt/qemu-swupdate.yml
new file mode 100644
index 0000000..99b4547
--- /dev/null
+++ b/kas/opt/qemu-swupdate.yml
@@ -0,0 +1,19 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+
+header:
+  version: 8
+
+local_conf_header:
+  qemu-wic: |
+    IMAGE_TYPE ?= "wic-swu-img"
+    WKS_FILE = "qemu-amd64-${BOOTLOADER}.wks"
diff --git a/recipes-core/images/cip-core-image.bb b/recipes-core/images/cip-core-image.bb
index 9ee4b25..4dfc983 100644
--- a/recipes-core/images/cip-core-image.bb
+++ b/recipes-core/images/cip-core-image.bb
@@ -17,3 +17,13 @@ DESCRIPTION = "CIP Core image"
 IMAGE_INSTALL += "customizations"
 # for cip-testing
 IMAGE_INSTALL += "ltp-full"
+
+# for swupdate
+EXTRACT_PARTITIONS = "img4"
+ROOTFS_PARTITION_NAME="img4.gz"
+
+SRC_URI += "file://sw-description.tmpl"
+TEMPLATE_FILES += "sw-description.tmpl"
+TEMPLATE_VARS += "PN ROOTFS_PARTITION_NAME"
+
+SWU_ADDITIONAL_FILES += "linux.signed.efi ${ROOTFS_PARTITION_NAME}"
diff --git a/recipes-core/images/files/sw-description.tmpl b/recipes-core/images/files/sw-description.tmpl
new file mode 100644
index 0000000..bef1984
--- /dev/null
+++ b/recipes-core/images/files/sw-description.tmpl
@@ -0,0 +1,29 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+software =
+{
+    version = "0.2";
+    name = "ebsy secure boot update"
+    images: ({
+            filename = "${EXTRACTED_PARTITION_NAME}";
+            device = "fedcba98-7654-3210-cafe-5e0710000001,fedcba98-7654-3210-cafe-5e0710000002";
+            type = "roundrobin";
+            compressed = true;
+            filesystem = "ext4";
+    });
+    files: ({
+            filename = "linux.signed.efi";
+            path = "linux.signed.efi";
+            type = "kernelfile";
+            device = "sda2,sda3";
+            filesystem = "vfat";
+    })
+}
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4856): https://lists.cip-project.org/g/cip-dev/message/4856
Mute This Topic: https://lists.cip-project.org/mt/75188188/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v3 0/5] A/B Rootfs update with software update
  2020-06-25 13:21 [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update Quirin Gylstorff
                   ` (4 preceding siblings ...)
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
@ 2020-07-24 14:52 ` Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
                     ` (4 more replies)
  5 siblings, 5 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-07-24 14:52 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 6290 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

This patchset adds efibootguard, swupdate to allow A/B updates in
cip-core. The update mechanism is currently only implemented for x86_64.

Changes V2:
 - update efibootguard to v0.7
 - add swdescription and kas option to build qemu-amd64 test image
 - swupdate set to upstream mirror and no longer use gitsm

Changes V3:

 - change image type for ebg-swu to generate a swu image during build
 - remove qemu-swupdate as it is no longer needed
 - add swdescription file for updating without secureboot


Quirin Gylstorff (5):
  recipes-bsp: Add efibootguard
  patches: add libubootenv
  recipes-core: add swupdate
  wic: Add wks files for A/B Partition update
  swupdate: create swu file from wic image

 classes/extract-partition.bbclass             |  26 +
 classes/kconfig-snippets.bbclass              |  90 ++++
 classes/swupdate-config.bbclass               |  76 +++
 classes/swupdate-img.bbclass                  |  75 +++
 classes/wic-swu-img.bbclass                   |  20 +
 .../0001-u-boot-add-libubootenv.patch         | 169 +++++++
 kas-cip.yml                                   |   4 +
 kas/opt/ebg-swu.yml                           |  26 +
 .../efibootguard/efibootguard_0.7-git+isar.bb |  46 ++
 recipes-bsp/efibootguard/files/debian/compat  |   1 +
 .../efibootguard/files/debian/control.tmpl    |  20 +
 .../files/debian/efibootguard-dev.install     |   3 +
 .../files/debian/efibootguard.install         |   2 +
 recipes-bsp/efibootguard/files/debian/rules   |  21 +
 recipes-core/images/cip-core-image.bb         |  10 +
 recipes-core/images/files/sw-description.tmpl |  37 ++
 .../swupdate/files/debian/changelog.tmpl      |   6 +
 recipes-core/swupdate/files/debian/compat     |   1 +
 .../swupdate/files/debian/control.tmpl        |  15 +
 recipes-core/swupdate/files/debian/copyright  |  36 ++
 recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
 .../swupdate/files/debian/swupdate.examples   |   2 +
 .../swupdate/files/debian/swupdate.install    |   2 +
 .../swupdate/files/debian/swupdate.manpages   |   5 +
 .../swupdate/files/debian/swupdate.tmpfile    |   2 +
 recipes-core/swupdate/files/debian/watch      |  12 +
 recipes-core/swupdate/files/postinst          |   2 +
 recipes-core/swupdate/files/swupdate.cfg      |   6 +
 .../swupdate/files/swupdate.service.example   |  11 +
 .../swupdate/files/swupdate.socket.example    |  11 +
 .../swupdate/files/swupdate.socket.tmpl       |  13 +
 .../swupdate/files/swupdate_defconfig         |  83 ++++
 .../swupdate_defconfig_efibootguard.snippet   |   3 +
 .../files/swupdate_defconfig_lua.snippet      |   2 +
 .../swupdate_defconfig_luahandler.snippet     |   4 +
 .../files/swupdate_defconfig_mtd.snippet      |   1 +
 .../files/swupdate_defconfig_u-boot.snippet   |   3 +
 .../files/swupdate_defconfig_ubi.snippet      |   6 +
 .../swupdate/files/swupdate_handlers.lua      | 453 ++++++++++++++++++
 recipes-core/swupdate/swupdate.bb             |  54 +++
 .../wic/plugins/source/efibootguard-boot.py   | 162 +++++++
 .../wic/plugins/source/efibootguard-efi.py    | 102 ++++
 wic/ebg-sysparts.inc                          |   8 +
 wic/qemu-amd64-efibootguard.wks               |   5 +
 wic/simatic-ipc227e-efibootguard.wks          |   5 +
 wic/swupdate-partition.inc                    |   4 +
 46 files changed, 1675 insertions(+)
 create mode 100644 classes/extract-partition.bbclass
 create mode 100644 classes/kconfig-snippets.bbclass
 create mode 100644 classes/swupdate-config.bbclass
 create mode 100644 classes/swupdate-img.bbclass
 create mode 100644 classes/wic-swu-img.bbclass
 create mode 100644 isar-patches/0001-u-boot-add-libubootenv.patch
 create mode 100644 kas/opt/ebg-swu.yml
 create mode 100644 recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
 create mode 100644 recipes-bsp/efibootguard/files/debian/compat
 create mode 100644 recipes-bsp/efibootguard/files/debian/control.tmpl
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard.install
 create mode 100755 recipes-bsp/efibootguard/files/debian/rules
 create mode 100644 recipes-core/images/files/sw-description.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/compat
 create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/copyright
 create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
 create mode 100644 recipes-core/swupdate/files/debian/watch
 create mode 100644 recipes-core/swupdate/files/postinst
 create mode 100644 recipes-core/swupdate/files/swupdate.cfg
 create mode 100644 recipes-core/swupdate/files/swupdate.service.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
 create mode 100644 recipes-core/swupdate/swupdate.bb
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-boot.py
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-efi.py
 create mode 100644 wic/ebg-sysparts.inc
 create mode 100644 wic/qemu-amd64-efibootguard.wks
 create mode 100644 wic/simatic-ipc227e-efibootguard.wks
 create mode 100644 wic/swupdate-partition.inc

-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4997): https://lists.cip-project.org/g/cip-dev/message/4997
Mute This Topic: https://lists.cip-project.org/mt/75767664/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v3 1/5] recipes-bsp: Add efibootguard
  2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
@ 2020-07-24 14:52   ` Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 2/5] patches: add libubootenv Quirin Gylstorff
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-07-24 14:52 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 15742 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add the bootloader efibootguard for A/B partition update
on x86 with EFI.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 .../efibootguard/efibootguard_0.7-git+isar.bb |  46 +++++
 recipes-bsp/efibootguard/files/debian/compat  |   1 +
 .../efibootguard/files/debian/control.tmpl    |  20 +++
 .../files/debian/efibootguard-dev.install     |   3 +
 .../files/debian/efibootguard.install         |   2 +
 recipes-bsp/efibootguard/files/debian/rules   |  21 +++
 .../wic/plugins/source/efibootguard-boot.py   | 162 ++++++++++++++++++
 .../wic/plugins/source/efibootguard-efi.py    | 102 +++++++++++
 8 files changed, 357 insertions(+)
 create mode 100644 recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
 create mode 100644 recipes-bsp/efibootguard/files/debian/compat
 create mode 100644 recipes-bsp/efibootguard/files/debian/control.tmpl
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
 create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard.install
 create mode 100755 recipes-bsp/efibootguard/files/debian/rules
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-boot.py
 create mode 100644 scripts/lib/wic/plugins/source/efibootguard-efi.py

diff --git a/recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb b/recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
new file mode 100644
index 0000000..4bdf76a
--- /dev/null
+++ b/recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
@@ -0,0 +1,46 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+DESCRIPTION = "efibootguard boot loader"
+DESCRIPTION_DEV = "efibootguard development library"
+HOMEPAGE = "https://github.com/siemens/efibootguard"
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
+MAINTAINER = "Jan Kiszka <jan.kiszka@siemens.com>"
+
+SRC_URI = "git://github.com/siemens/efibootguard.git;branch=master;protocol=https \
+           file://debian \
+          "
+
+S = "${WORKDIR}/git"
+
+SRCREV = "442e87bafb480ada2b9074f02350a30408d4cf9c"
+
+PROVIDES = "${PN}"
+PROVIDES += "${PN}-dev"
+
+BUILD_DEB_DEPENDS = "gnu-efi,libpci-dev,check,pkg-config,libc6-dev-i386"
+
+inherit dpkg
+
+TEMPLATE_FILES = "debian/control.tmpl"
+TEMPLATE_VARS += "DESCRIPTION_DEV BUILD_DEB_DEPENDS"
+
+do_prepare_build() {
+    cp -R ${WORKDIR}/debian ${S}
+    deb_add_changelog
+}
+
+dpkg_runbuild_append() {
+    install -m 0755 -d ${DEPLOY_DIR_IMAGE}
+    install -m 0755 ${S}/efibootguardx64.efi ${DEPLOY_DIR_IMAGE}/bootx64.efi
+    install -m 0755 ${S}/bg_setenv ${DEPLOY_DIR_IMAGE}/bg_setenv
+}
diff --git a/recipes-bsp/efibootguard/files/debian/compat b/recipes-bsp/efibootguard/files/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/recipes-bsp/efibootguard/files/debian/control.tmpl b/recipes-bsp/efibootguard/files/debian/control.tmpl
new file mode 100644
index 0000000..54b1994
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/control.tmpl
@@ -0,0 +1,20 @@
+Source: ${PN}
+Section: base
+Priority: optional
+Standards-Version: 3.9.6
+Build-Depends: ${BUILD_DEB_DEPENDS}
+Homepage: ${HOMEPAGE}
+Maintainer: ${MAINTAINER}
+
+Package: ${PN}
+Depends: ${shlibs:Depends}
+Section: base
+Architecture: ${DISTRO_ARCH}
+Priority: required
+Description: ${DESCRIPTION}
+
+Package: ${PN}-dev
+Section: base
+Architecture: ${DISTRO_ARCH}
+Priority: optional
+Description: ${DESCRIPTION_DEV}
diff --git a/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install b/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
new file mode 100644
index 0000000..7b45bd8
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
@@ -0,0 +1,3 @@
+include/ebgenv.h usr/include/efibootguard
+libebgenv.a usr/lib/x86_64-linux-gnu
+
diff --git a/recipes-bsp/efibootguard/files/debian/efibootguard.install b/recipes-bsp/efibootguard/files/debian/efibootguard.install
new file mode 100644
index 0000000..8a8d9d3
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/efibootguard.install
@@ -0,0 +1,2 @@
+bg_setenv usr/bin
+bg_printenv usr/bin
diff --git a/recipes-bsp/efibootguard/files/debian/rules b/recipes-bsp/efibootguard/files/debian/rules
new file mode 100755
index 0000000..82e9e0e
--- /dev/null
+++ b/recipes-bsp/efibootguard/files/debian/rules
@@ -0,0 +1,21 @@
+#!/usr/bin/make -f
+export DH_VERBOSE=1
+export DEB_BUILD_OPTIONS=hardening=-stackprotector
+export DPKG_EXPORT_BUILDFLAGS=1
+include /usr/share/dpkg/default.mk
+
+override_dh_auto_test:
+	# we do not run the tests; that avoids having to pull the fff submodule
+
+override_dh_auto_install:
+	# install using Debian's .install files rather than
+	# make install in order to have a proper package split.
+
+override_dh_installchangelogs:
+	# we're not interested in changelogs
+
+override_dh_installdocs:
+	# we're not interested in docs
+
+%:
+	dh $@ --with autoreconf
diff --git a/scripts/lib/wic/plugins/source/efibootguard-boot.py b/scripts/lib/wic/plugins/source/efibootguard-boot.py
new file mode 100644
index 0000000..38d2b2e
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/efibootguard-boot.py
@@ -0,0 +1,162 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Copyright (c) 2014, Intel Corporation.
+# Copyright (c) 2018, Siemens AG.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# DESCRIPTION
+# This implements the 'efibootguard-boot' source plugin class for 'wic'
+#
+# AUTHORS
+# Tom Zanussi <tom.zanussi (at] linux.intel.com>
+# Claudius Heine <ch (at] denx.de>
+# Andreas Reichel <andreas.reichel.ext (at] siemens.com>
+# Christian Storm <christian.storm (at] siemens.com>
+
+import os
+import fnmatch
+import sys
+import logging
+
+msger = logging.getLogger('wic')
+
+from wic.pluginbase import SourcePlugin
+from wic.utils.misc import exec_cmd, get_bitbake_var, BOOTDD_EXTRA_SPACE
+
+class EfibootguardBootPlugin(SourcePlugin):
+    """
+    Create EFI Boot Guard partition hosting the
+    environment file plus Kernel files.
+    """
+
+    name = 'efibootguard-boot'
+
+    @classmethod
+    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
+                             oe_builddir, deploy_dir, kernel_dir,
+                             rootfs_dir, native_sysroot):
+        """
+        Called to do the actual content population for a partition, i.e.,
+        populate an EFI Boot Guard environment partition plus Kernel files.
+        """
+
+        kernel_image = get_bitbake_var("KERNEL_IMAGE")
+        if not kernel_image:
+            msger.warning("KERNEL_IMAGE not set. Use default:")
+            kernel_image = "vmlinuz"
+        boot_image = kernel_image
+
+        initrd_image = get_bitbake_var("INITRD_IMAGE")
+        if not initrd_image:
+            msger.warning("INITRD_IMAGE not set\n")
+            initrd_image = "initrd.img"
+        bootloader = creator.ks.bootloader
+
+        deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
+        if not deploy_dir:
+            msger.error("DEPLOY_DIR_IMAGE not set, exiting\n")
+            sys.exit(1)
+        creator.deploy_dir = deploy_dir
+
+        wdog_timeout = get_bitbake_var("WDOG_TIMEOUT")
+        if not wdog_timeout:
+            msger.error("Specify watchdog timeout for \
+            efibootguard in local.conf with WDOG_TIMEOUT=")
+            exit(1)
+
+
+        boot_files = source_params.get("files", "").split(' ')
+        cmdline = bootloader.append
+        root_dev = source_params.get("root", None)
+        if not root_dev:
+            msger.error("Specify root in source params")
+            exit(1)
+            root_dev = root_dev.replace(":", "=")
+
+        cmdline += " root=%s rw" % root_dev
+        boot_files.append(kernel_image)
+        boot_files.append(initrd_image)
+        cmdline += "initrd=%s" % initrd_image if initrd_image else ""
+
+        part_rootfs_dir = "%s/disk/%s.%s" % (cr_workdir,
+                                             part.label, part.lineno)
+        create_dir_cmd = "install -d %s" % part_rootfs_dir
+        exec_cmd(create_dir_cmd)
+
+        cwd = os.getcwd()
+        os.chdir(part_rootfs_dir)
+        config_cmd = '%s/bg_setenv -f . -k "C:%s:%s" %s -r %s -w %s' \
+            % (
+                deploy_dir,
+                part.label.upper(),
+                boot_image,
+                '-a "%s"' % cmdline if cmdline else "",
+                source_params.get("revision", 1),
+                wdog_timeout
+            )
+        exec_cmd(config_cmd, True)
+        os.chdir(cwd)
+
+        boot_files = list(filter(None, boot_files))
+        for boot_file in boot_files:
+            if os.path.isfile("%s/%s" % (kernel_dir, kernel_image)):
+                install_cmd = "install -m 0644 %s/%s %s/%s" % \
+                    (kernel_dir, boot_file, part_rootfs_dir, boot_file)
+                exec_cmd(install_cmd)
+            else:
+                msger.error("file %s not found in directory %s",
+                            boot_file, kernel_dir)
+                exit(1)
+        cls._create_img(part_rootfs_dir, part, cr_workdir)
+
+    @classmethod
+    def _create_img(cls, part_rootfs_dir, part, cr_workdir):
+            # Write label as utf-16le to EFILABEL file
+        with open("%s/EFILABEL" % part_rootfs_dir, 'wb') as filedescriptor:
+            filedescriptor.write(part.label.upper().encode("utf-16le"))
+
+        du_cmd = "du --apparent-size -ks %s" % part_rootfs_dir
+        blocks = int(exec_cmd(du_cmd).split()[0])
+
+        extra_blocks = part.get_extra_block_count(blocks)
+        if extra_blocks < BOOTDD_EXTRA_SPACE:
+            extra_blocks = BOOTDD_EXTRA_SPACE
+
+        blocks += extra_blocks
+        blocks = blocks + (16 - (blocks % 16))
+
+        msger.debug("Added %d extra blocks to %s to get to %d total blocks",
+                    extra_blocks, part.mountpoint, blocks)
+
+        # dosfs image, created by mkdosfs
+        bootimg = "%s/%s.%s.img" % (cr_workdir, part.label, part.lineno)
+
+        dosfs_cmd = "mkdosfs -F 16 -S 512 -n %s -C %s %d" % \
+            (part.label.upper(), bootimg, blocks)
+        exec_cmd(dosfs_cmd)
+
+        mcopy_cmd = "mcopy -v -i %s -s %s/* ::/" % (bootimg, part_rootfs_dir)
+        exec_cmd(mcopy_cmd, True)
+
+        chmod_cmd = "chmod 644 %s" % bootimg
+        exec_cmd(chmod_cmd)
+
+        du_cmd = "du -Lbks %s" % bootimg
+        bootimg_size = int(exec_cmd(du_cmd).split()[0])
+
+        part.size = bootimg_size
+        part.source_file = bootimg
diff --git a/scripts/lib/wic/plugins/source/efibootguard-efi.py b/scripts/lib/wic/plugins/source/efibootguard-efi.py
new file mode 100644
index 0000000..5ee451f
--- /dev/null
+++ b/scripts/lib/wic/plugins/source/efibootguard-efi.py
@@ -0,0 +1,102 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Copyright (c) 2014, Intel Corporation.
+# Copyright (c) 2018, Siemens AG.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# DESCRIPTION
+# This implements the 'efibootguard-efi' source plugin class for 'wic'
+#
+# AUTHORS
+# Tom Zanussi <tom.zanussi (at] linux.intel.com>
+# Claudius Heine <ch (at] denx.de>
+# Andreas Reichel <andreas.reichel.ext (at] siemens.com>
+# Christian Storm <christian.storm (at] siemens.com>
+
+import logging
+import os
+
+msger = logging.getLogger('wic')
+
+from wic.pluginbase import SourcePlugin
+from wic.utils.misc import exec_cmd, get_bitbake_var, BOOTDD_EXTRA_SPACE
+
+class EfibootguardEFIPlugin(SourcePlugin):
+    """
+    Create EFI bootloader partition containing the EFI Boot Guard Bootloader.
+    """
+
+    name = 'efibootguard-efi'
+
+    @classmethod
+    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
+                             oe_builddir, deploy_dir, kernel_dir,
+                             rootfs_dir, native_sysroot):
+        """
+        Called to do the actual content population for a partition, i.e.,
+        populate an EFI boot partition containing the EFI Boot Guard
+        bootloader binary.
+        """
+        deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
+        creator.deploy_dir = deploy_dir
+        bootloader_files = source_params.get("bootloader")
+        if not bootloader_files:
+            bootloader_files = "bootx64.efi"
+        bootloader_files = bootloader_files.split(' ')
+        part_rootfs_dir = "%s/disk/%s.%s" % (cr_workdir,
+                                             part.label,
+                                             part.lineno)
+        create_dir_cmd = "install -d %s/EFI/BOOT" % part_rootfs_dir
+        exec_cmd(create_dir_cmd)
+
+        for bootloader in bootloader_files:
+            cp_cmd = "cp %s/%s %s/EFI/BOOT/%s" % (deploy_dir,
+                                                  bootloader,
+                                                  part_rootfs_dir,
+                                                  bootloader)
+            exec_cmd(cp_cmd, True)
+        du_cmd = "du --apparent-size -ks %s" % part_rootfs_dir
+        blocks = int(exec_cmd(du_cmd).split()[0])
+
+        extra_blocks = part.get_extra_block_count(blocks)
+        if extra_blocks < BOOTDD_EXTRA_SPACE:
+            extra_blocks = BOOTDD_EXTRA_SPACE
+        blocks += extra_blocks
+        blocks = blocks + (16 - (blocks % 16))
+
+        msger.debug("Added %d extra blocks to %s to get to %d total blocks",
+                    extra_blocks, part.mountpoint, blocks)
+
+        # dosfs image, created by mkdosfs
+        efi_part_image = "%s/%s.%s.img" % (cr_workdir, part.label, part.lineno)
+
+        dosfs_cmd = "mkdosfs -S 512 -n %s -C %s %d" % \
+            (part.label.upper(), efi_part_image, blocks)
+        exec_cmd(dosfs_cmd)
+
+        mcopy_cmd = "mcopy -v -i %s -s %s/* ::/" % \
+            (efi_part_image, part_rootfs_dir)
+        exec_cmd(mcopy_cmd, True)
+
+        chmod_cmd = "chmod 644 %s" % efi_part_image
+        exec_cmd(chmod_cmd)
+
+        du_cmd = "du -Lbks %s" % efi_part_image
+        efi_part_image_size = int(exec_cmd(du_cmd).split()[0])
+
+        part.size = efi_part_image_size
+        part.source_file = efi_part_image
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4999): https://lists.cip-project.org/g/cip-dev/message/4999
Mute This Topic: https://lists.cip-project.org/mt/75767666/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v3 2/5] patches: add libubootenv
  2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
@ 2020-07-24 14:52   ` Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 3/5] recipes-core: add swupdate Quirin Gylstorff
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-07-24 14:52 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 7686 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

swupdate 2020.04 requires libubootenv as build dependency.

libubootenv is a library that provides a hardware independent
way to access to U-Boot environment. U-Boot has its default environment
compiled board-dependently and this means that tools to access the environment
are also board specific, too.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 .../0001-u-boot-add-libubootenv.patch         | 169 ++++++++++++++++++
 kas-cip.yml                                   |   4 +
 2 files changed, 173 insertions(+)
 create mode 100644 isar-patches/0001-u-boot-add-libubootenv.patch

diff --git a/isar-patches/0001-u-boot-add-libubootenv.patch b/isar-patches/0001-u-boot-add-libubootenv.patch
new file mode 100644
index 0000000..10a5b4a
--- /dev/null
+++ b/isar-patches/0001-u-boot-add-libubootenv.patch
@@ -0,0 +1,169 @@
+From 76897e89977f895495e21e37cb76f90392d55ef9 Mon Sep 17 00:00:00 2001
+From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
+Date: Fri, 19 Jun 2020 17:00:36 +0200
+Subject: [PATCH v2] u-boot: add libubootenv
+
+Add the new library libubootenv and remove fw_printenv and fw_setenv
+form u-boot-tools as the are now part of the new library.
+
+libubootenv is a library that provides a hardware independent
+way to access to U-Boot environment. U-Boot has its default environment
+compiled board-dependently and this means that tools to access the environment
+are also board specific, too.
+
+libubootenv conflicts with u-boot-tools from Debian 10
+as both try to install fw_printenv and fw_sentenv. This conflict is not
+part of the control file as it breaks the installation of custom u-boot-tools
+from the u-boot-sources.
+
+Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
+---
+ meta-isar/conf/machine/de0-nano-soc.conf      |  2 +-
+ .../libubootenv/files/debian/compat           |  1 +
+ .../libubootenv/files/debian/control.tmpl     | 15 +++++++++
+ .../libubootenv/files/debian/rules.tmpl       | 24 ++++++++++++++
+ .../libubootenv/libubootenv_0.2.bb            | 32 +++++++++++++++++++
+ .../files/debian/u-boot-tools.conffiles       |  1 -
+ .../u-boot/files/debian/u-boot-tools.install  |  2 --
+ .../u-boot/files/debian/u-boot-tools.links    |  1 -
+ 8 files changed, 73 insertions(+), 5 deletions(-)
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/compat
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+ create mode 100644 meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+ create mode 100644 meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+ delete mode 100644 meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
+ delete mode 100644 meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
+
+diff --git a/meta-isar/conf/machine/de0-nano-soc.conf b/meta-isar/conf/machine/de0-nano-soc.conf
+index 3a2c009..6558d90 100644
+--- a/meta-isar/conf/machine/de0-nano-soc.conf
++++ b/meta-isar/conf/machine/de0-nano-soc.conf
+@@ -15,4 +15,4 @@ WKS_FILE ?= "de0-nano-soc.wks.in"
+ IMAGER_INSTALL += "u-boot-de0-nano-soc"
+ IMAGER_BUILD_DEPS += "u-boot-de0-nano-soc"
+ 
+-IMAGE_INSTALL += "u-boot-tools u-boot-script"
++IMAGE_INSTALL += "u-boot-tools libubootenv u-boot-script"
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/compat b/meta/recipes-bsp/libubootenv/files/debian/compat
+new file mode 100644
+index 0000000..b4de394
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/compat
+@@ -0,0 +1 @@
++11
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/control.tmpl b/meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+new file mode 100644
+index 0000000..fade69a
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/control.tmpl
+@@ -0,0 +1,15 @@
++Source: libubootenv
++Section: embedded
++Priority: optional
++Maintainer: Stefano Babic <sbabic@denx.de>
++Build-Depends: ${BUILD_DEB_DEPENDS}
++Standards-Version: 4.2.1
++Homepage: https://sbabic.github.io/libubootenv
++
++Package: libubootenv
++Architecture: any
++Depends: ${DEBIAN_DEPENDS}
++Description: libubootenv is a library that provides a hardware independent
++ way to access to U-Boot environment. U-Boot has its default environment
++ compiled board-dependently and this means that tools to access the environment
++ are also board specific, too.
+diff --git a/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl b/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+new file mode 100644
+index 0000000..56ccd19
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/files/debian/rules.tmpl
+@@ -0,0 +1,24 @@
++#!/usr/bin/make -f
++
++ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
++export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
++export CC=$(DEB_HOST_GNU_TYPE)-gcc
++export LD=$(DEB_HOST_GNU_TYPE)-gcc
++endif
++
++export DH_VERBOSE = 1
++
++export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
++
++override_dh_auto_configure:
++	dh_auto_configure --
++
++%:
++	echo $@
++	dh $@
++
++override_dh_installchangelogs:
++	true
++
++override_dh_installdocs:
++	true
+diff --git a/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb b/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+new file mode 100644
+index 0000000..1be058c
+--- /dev/null
++++ b/meta/recipes-bsp/libubootenv/libubootenv_0.2.bb
+@@ -0,0 +1,32 @@
++# libubootenv
++#
++# This software is a part of ISAR.
++# Copyright (c) Siemens AG, 2020
++#
++# SPDX-License-Identifier: MIT
++
++DESCRIPTION = "swupdate utility for software updates"
++HOMEPAGE= "https://github.com/sbabic/swupdate"
++LICENSE = "GPL-2.0"
++LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
++SRC_URI = "gitsm://github.com/sbabic/libubootenv.git;branch=master;protocol=https"
++
++SRCREV = "bf6ff631c0e38cede67268ceb8bf1383b5f8848e"
++
++BUILD_DEB_DEPENDS = "cmake, zlib1g-dev"
++
++SRC_URI += "file://debian"
++TEMPLATE_FILES = "debian/control.tmpl debian/rules.tmpl"
++TEMPLATE_VARS += "BUILD_DEB_DEPENDS DEFCONFIG DEBIAN_DEPENDS"
++
++
++inherit dpkg
++
++S = "${WORKDIR}/git"
++
++do_prepare_build() {
++        DEBDIR=${S}/debian
++        install -d ${DEBDIR}
++        cp -R ${WORKDIR}/debian ${S}
++        deb_add_changelog
++}
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
+deleted file mode 100644
+index d49a8fb..0000000
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.conffiles
++++ /dev/null
+@@ -1 +0,0 @@
+-/etc/fw_env.config
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
+index d1ae3e0..2893b9a 100644
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
++++ b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.install
+@@ -1,5 +1,3 @@
+ tools/dumpimage		/usr/bin/
+-tools/env/fw_printenv	/usr/bin/
+ tools/mkenvimage	/usr/bin/
+ tools/mkimage		/usr/bin/
+-tools/env/fw_env.config	/etc
+diff --git a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links b/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
+deleted file mode 100644
+index 92f5a6c..0000000
+--- a/meta/recipes-bsp/u-boot/files/debian/u-boot-tools.links
++++ /dev/null
+@@ -1 +0,0 @@
+-/usr/bin/fw_printenv /usr/bin/fw_setenv
+-- 
+2.20.1
+
diff --git a/kas-cip.yml b/kas-cip.yml
index 019b31e..0da07db 100644
--- a/kas-cip.yml
+++ b/kas-cip.yml
@@ -22,6 +22,10 @@ repos:
     refspec: 351af175bc54a201c6f44307d4e998bd6c0afdb8
     layers:
       meta:
+    patches:
+      01-libubootenv:
+        path: isar-patches/0001-u-boot-add-libubootenv.patch
+        repo: cip-core
 
 bblayers_conf_header:
   standard: |
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#4998): https://lists.cip-project.org/g/cip-dev/message/4998
Mute This Topic: https://lists.cip-project.org/mt/75767665/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v3 3/5] recipes-core: add swupdate
  2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 2/5] patches: add libubootenv Quirin Gylstorff
@ 2020-07-24 14:52   ` Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 4/5] wic: Add wks files for A/B Partition update Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 5/5] swupdate: create swu file from wic image Quirin Gylstorff
  4 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-07-24 14:52 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 45248 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add swupdate for A/B software updates. Currently the Round Robin
handler in lua supports efibootguard as bootloader. The u-boot
implementation is outstanding.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 classes/kconfig-snippets.bbclass              |  90 ++++
 classes/swupdate-config.bbclass               |  76 +++
 classes/swupdate-img.bbclass                  |  75 +++
 .../swupdate/files/debian/changelog.tmpl      |   6 +
 recipes-core/swupdate/files/debian/compat     |   1 +
 .../swupdate/files/debian/control.tmpl        |  15 +
 recipes-core/swupdate/files/debian/copyright  |  36 ++
 recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
 .../swupdate/files/debian/swupdate.examples   |   2 +
 .../swupdate/files/debian/swupdate.install    |   2 +
 .../swupdate/files/debian/swupdate.manpages   |   5 +
 .../swupdate/files/debian/swupdate.tmpfile    |   2 +
 recipes-core/swupdate/files/debian/watch      |  12 +
 recipes-core/swupdate/files/postinst          |   2 +
 recipes-core/swupdate/files/swupdate.cfg      |   6 +
 .../swupdate/files/swupdate.service.example   |  11 +
 .../swupdate/files/swupdate.socket.example    |  11 +
 .../swupdate/files/swupdate.socket.tmpl       |  13 +
 .../swupdate/files/swupdate_defconfig         |  83 ++++
 .../swupdate_defconfig_efibootguard.snippet   |   3 +
 .../files/swupdate_defconfig_lua.snippet      |   2 +
 .../swupdate_defconfig_luahandler.snippet     |   4 +
 .../files/swupdate_defconfig_mtd.snippet      |   1 +
 .../files/swupdate_defconfig_u-boot.snippet   |   3 +
 .../files/swupdate_defconfig_ubi.snippet      |   6 +
 .../swupdate/files/swupdate_handlers.lua      | 453 ++++++++++++++++++
 recipes-core/swupdate/swupdate.bb             |  54 +++
 27 files changed, 1004 insertions(+)
 create mode 100644 classes/kconfig-snippets.bbclass
 create mode 100644 classes/swupdate-config.bbclass
 create mode 100644 classes/swupdate-img.bbclass
 create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/compat
 create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/copyright
 create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
 create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
 create mode 100644 recipes-core/swupdate/files/debian/watch
 create mode 100644 recipes-core/swupdate/files/postinst
 create mode 100644 recipes-core/swupdate/files/swupdate.cfg
 create mode 100644 recipes-core/swupdate/files/swupdate.service.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
 create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
 create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
 create mode 100644 recipes-core/swupdate/swupdate.bb

diff --git a/classes/kconfig-snippets.bbclass b/classes/kconfig-snippets.bbclass
new file mode 100644
index 0000000..d754654
--- /dev/null
+++ b/classes/kconfig-snippets.bbclass
@@ -0,0 +1,90 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+KCONFIG_SNIPPETS = ""
+
+# The following function defines the kconfig snippet system
+# with automatich debian dependency injection
+#
+# To define a feature set, the user has to define the following
+# variable to an empty string:
+#
+# KFEATURE_featurename = ""
+#
+# Then, required additions to the variables can be defined:
+#
+# KFEATURE_featurename[KCONFIG_SNIPPETS] = "file://snippet-file-name.snippet"
+# KFEATURE_featurename[SRC_URI] = "file://required-file.txt"
+# KFEATURE_featurename[DEPENDS] = "deb-pkg1 deb-pkg2 deb-pkg3"
+# KFEATURE_featurename[DEBIAN_DEPENDS] = "deb-pkg1"
+# KFEATURE_featurename[BUILD_DEB_DEPENDS] = "deb-pkg1,deb-pkg2,deb-pkg3"
+
+# The 'KCONFIG_SNIPPETS' flag gives a list of URI entries, where only
+# file:// is supported. These snippets are appended to the DEFCONFIG file.
+#
+# Features can depend on other features via the following mechanism:
+#
+# KFEATURE_DEPS[feature1] = "feature2"
+
+python () {
+    requested_features = d.getVar("KFEATURES", True) or ""
+
+    features = set(requested_features.split())
+    old_features = set()
+    feature_deps = d.getVarFlags("KFEATURE_DEPS") or {}
+    while old_features != features:
+        diff_features = old_features.symmetric_difference(features)
+        old_features = features.copy()
+        for i in diff_features:
+            features.update(feature_deps.get(i, "").split())
+
+    for f in sorted(features):
+        bb.debug(2, "Feature: " + f)
+        varname = "KFEATURE_" + f
+        dummyvar = d.getVar(varname, False)
+        if dummyvar == None:
+            bb.error("Feature var " + f + " must be defined with needed flags.")
+        else:
+            feature_flags = d.getVarFlags(varname)
+            for feature_varname in sorted(feature_flags):
+                if feature_flags.get(feature_varname, "") != "":
+                    sep = " "
+
+                    # Required to add KCONFIG_SNIPPETS to SRC_URI here,
+                    # because 'SRC_URI += "${KCONFIG_SNIPPETS}"' would
+                    # conflict with SRC_APT feature.
+                    if feature_varname == "KCONFIG_SNIPPETS":
+                        d.appendVar('SRC_URI',
+                            " " + feature_flags[feature_varname].strip())
+
+                    # BUILD_DEP_DEPENDS and DEBIAN_DEPENDS is ',' separated
+                    # Only add ',' if there is already something there
+                    if feature_varname in ["BUILD_DEB_DEPENDS",
+                                           "DEBIAN_DEPENDS"]:
+                        sep = "," if d.getVar(feature_varname) else ""
+
+                    d.appendVar(feature_varname,
+                        sep + feature_flags[feature_varname].strip())
+}
+
+# DEFCONFIG must be a predefined bitbake variable and the corresponding file
+# must exist in the WORKDIR.
+# The resulting generated config is the same file suffixed with ".gen"
+
+do_prepare_build_prepend() {
+        sh -x
+        GENCONFIG="${WORKDIR}/${DEFCONFIG}".gen
+        rm -f "$GENCONFIG"
+        cp "${WORKDIR}/${DEFCONFIG}" "$GENCONFIG"
+        for CONFIG_SNIPPET in $(echo "${KCONFIG_SNIPPETS}" | sed 's#file://##g')
+        do
+                cat ${WORKDIR}/$CONFIG_SNIPPET >> "$GENCONFIG"
+        done
+}
diff --git a/classes/swupdate-config.bbclass b/classes/swupdate-config.bbclass
new file mode 100644
index 0000000..7ce51c5
--- /dev/null
+++ b/classes/swupdate-config.bbclass
@@ -0,0 +1,76 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+# This class manages the config snippets together with their dependencies
+# to build SWUpdate
+
+inherit kconfig-snippets
+
+BUILD_DEB_DEPENDS = " \
+    zlib1g-dev, debhelper, libconfig-dev, libarchive-dev, \
+    python-sphinx:native, dh-systemd, libsystemd-dev"
+
+KFEATURE_lua = ""
+KFEATURE_lua[BUILD_DEB_DEPENDS] = "liblua5.3-dev"
+KFEATURE_lua[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_lua.snippet"
+
+KFEATURE_luahandler = ""
+KFEATURE_luahandler[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_luahandler.snippet"
+KFEATURE_luahandler[SRC_URI] = "file://${SWUPDATE_LUASCRIPT}"
+
+KFEATURE_DEPS = ""
+KFEATURE_DEPS[luahandler] = "lua"
+
+KFEATURE_efibootguard = ""
+KFEATURE_efibootguard[BUILD_DEB_DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[DEBIAN_DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[DEPENDS] = "efibootguard-dev"
+KFEATURE_efibootguard[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_efibootguard.snippet"
+
+KFEATURE_mtd = ""
+KFEATURE_mtd[BUILD_DEB_DEPENDS] = "libmtd-dev"
+KFEATURE_mtd[DEPENDS] = "mtd-utils"
+KFEATURE_mtd[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_mtd.snippet"
+
+KFEATURE_ubi = ""
+KFEATURE_ubi[BUILD_DEB_DEPENDS] = "libubi-dev"
+KFEATURE_ubi[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_ubi.snippet"
+
+KFEATURE_DEPS[ubi] = "mtd"
+
+KFEATURE_u-boot = ""
+KFEATURE_u-boot[BUILD_DEB_DEPENDS] = "u-boot-${MACHINE}-dev"
+KFEATURE_u-boot[DEBIAN_DEPENDS] = "u-boot-tools"
+KFEATURE_u-boot[DEPENDS] = "${U_BOOT}"
+KFEATURE_u-boot[KCONFIG_SNIPPETS] = "file://swupdate_defconfig_u-boot.snippet"
+
+SWUPDATE_LUASCRIPT ?= "swupdate_handlers.lua"
+
+def get_bootloader_featureset(d):
+    bootloader = d.getVar("BOOTLOADER", True) or ""
+    if bootloader == "efibootguard":
+        return "efibootguard"
+    if bootloader == "u-boot":
+        return "u-boot"
+    return ""
+
+SWUPDATE_KFEATURES ??= ""
+KFEATURES = "${SWUPDATE_KFEATURES}"
+KFEATURES += "${@get_bootloader_featureset(d)}"
+
+# Astonishingly, as an anonymous python function, BOOTLOADER is always None
+# one time before it gets set. So the following must be a task.
+python do_check_bootloader () {
+    bootloader = d.getVar("BOOTLOADER", True) or "None"
+    if not bootloader in ["efibootguard", "u-boot"]:
+        bb.warn("swupdate: BOOTLOADER set to incompatible value: " + bootloader)
+}
+addtask check_bootloader before do_fetch
+
diff --git a/classes/swupdate-img.bbclass b/classes/swupdate-img.bbclass
new file mode 100644
index 0000000..a21d6ec
--- /dev/null
+++ b/classes/swupdate-img.bbclass
@@ -0,0 +1,75 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Christian Storm <christian.storm@siemens.com>
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+SWU_IMAGE_FILE ?= "${PN}-${DISTRO}-${MACHINE}.swu"
+SWU_DESCRIPTION_FILE ?= "sw-description"
+SWU_ADDITIONAL_FILES ?= ""
+SWU_SIGNED ?= ""
+SWU_SIGNATURE_EXT ?= "sig"
+SWU_SIGNATURE_TYPE ?= "rsa"
+
+IMAGER_INSTALL += "${@'openssl' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}"
+
+do_swupdate_image[stamp-extra-info] = "${DISTRO}-${MACHINE}"
+do_swupdate_image[cleandirs] += "${WORKDIR}/swu"
+do_swupdate_image() {
+    rm -f '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
+    cp '${WORKDIR}/${SWU_DESCRIPTION_FILE}' '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
+
+    # Create symlinks for files used in the update image
+    for file in ${SWU_ADDITIONAL_FILES}; do
+        if [ -e "${WORKDIR}/$file" ]; then
+            ln -s "${WORKDIR}/$file" "${WORKDIR}/swu/$file"
+        else
+            ln -s "${DEPLOY_DIR_IMAGE}/$file" "${WORKDIR}/swu/$file"
+        fi
+    done
+
+    # Prepare for signing
+    sign='${@'x' if bb.utils.to_boolean(d.getVar('SWU_SIGNED')) else ''}'
+    if [ -n "$sign" ]; then
+        image_do_mounts
+        cp -f '${SIGN_KEY}' '${WORKDIR}/dev.key'
+        test -e '${SIGN_CRT}' && cp -f '${SIGN_CRT}' '${WORKDIR}/dev.crt'
+
+        # Fill in file check sums
+        for file in ${SWU_ADDITIONAL_FILES}; do
+            sed -i "s:$file-sha256:$(sha256sum '${WORKDIR}/swu/'$file | cut -f 1 -d ' '):g" \
+                '${WORKDIR}/swu/${SWU_DESCRIPTION_FILE}'
+        done
+    fi
+
+    cd "${WORKDIR}/swu"
+    for file in '${SWU_DESCRIPTION_FILE}' ${SWU_ADDITIONAL_FILES}; do
+        echo "$file"
+        if [ -n "$sign" -a \
+             '${SWU_DESCRIPTION_FILE}' = "$file" ]; then
+            if [ "${SWU_SIGNATURE_TYPE}" = "rsa" ]; then
+                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl dgst \
+                    -sha256 -sign '${PP_WORK}/dev.key' \
+                    '${PP_WORK}/swu/'"$file" \
+                        > '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}'
+            elif [ "${SWU_SIGNATURE_TYPE}" = "cms" ]; then
+                sudo chroot ${BUILDCHROOT_DIR} /usr/bin/openssl cms \
+                    -sign -in '${PP_WORK}/swu/'"$file" \
+                    -out '${WORKDIR}/swu/'"$file".'${SWU_SIGNATURE_EXT}' \
+                    -signer '${PP_WORK}/dev.crt' \
+                    -inkey '${PP_WORK}/dev.key' \
+                    -outform DER -nosmimecap -binary
+            fi
+            echo "$file".'${SWU_SIGNATURE_EXT}'
+        fi
+    done | cpio -ovL -H crc \
+        > '${DEPLOY_DIR_IMAGE}/${SWU_IMAGE_FILE}'
+    cd -
+}
+
+addtask swupdate_image before do_build after do_copy_boot_files do_install_imager_deps do_transform_template
diff --git a/recipes-core/swupdate/files/debian/changelog.tmpl b/recipes-core/swupdate/files/debian/changelog.tmpl
new file mode 100644
index 0000000..81087d3
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/changelog.tmpl
@@ -0,0 +1,6 @@
+swupdate (${PV}) unstable; urgency=medium
+
+  * SWUpdate
+
+ --  Christian Storm <christian.storm@siemens.com>  Thu, 31 Jan 2019 15:23:56 +0100
+
diff --git a/recipes-core/swupdate/files/debian/compat b/recipes-core/swupdate/files/debian/compat
new file mode 100644
index 0000000..b4de394
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/compat
@@ -0,0 +1 @@
+11
diff --git a/recipes-core/swupdate/files/debian/control.tmpl b/recipes-core/swupdate/files/debian/control.tmpl
new file mode 100644
index 0000000..2b92850
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/control.tmpl
@@ -0,0 +1,15 @@
+Source: swupdate
+Section: embedded
+Priority: optional
+Maintainer: Stefano Babic <sbabic@denx.de>
+Build-Depends: ${BUILD_DEB_DEPENDS}
+Standards-Version: 4.2.1
+Homepage: http://sbabic.github.io/swupdate
+
+Package: swupdate
+Architecture: any
+Depends: ${DEBIAN_DEPENDS}
+Description: reliable way to update an embedded system
+ This project is thought to help to update an embedded system from a storage media or from network.
+ However, it should be mainly considered as a framework, where further protocols or installers
+ (in SWUpdate they are called handlers) can be easily added to the application.
diff --git a/recipes-core/swupdate/files/debian/copyright b/recipes-core/swupdate/files/debian/copyright
new file mode 100644
index 0000000..f920942
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/copyright
@@ -0,0 +1,36 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: swupdate
+Maintainer: Stefano Babic <sbabic@denx.de>
+Source: http://github.com/sbabic/swupdate
+
+Files: *
+Copyright: 2014-2017 Stefano Babic <sbabic@denx.de>
+
+License: GPL-2 with OpenSSL exception
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ In addition, as a special exception, the author of this
+ program gives permission to link the code of its
+ release with the OpenSSL project's "OpenSSL" library (or
+ with modified versions of it that use the same license as
+ the "OpenSSL" library), and distribute the linked
+ executables. You must obey the GNU General Public
+ License in all respects for all of the code used other
+ than "OpenSSL".  If you modify this file, you may extend
+ this exception to your version of the file, but you are
+ not obligated to do so.  If you do not wish to do so,
+ delete this exception statement from your version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
diff --git a/recipes-core/swupdate/files/debian/rules.tmpl b/recipes-core/swupdate/files/debian/rules.tmpl
new file mode 100755
index 0000000..54cca57
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/rules.tmpl
@@ -0,0 +1,30 @@
+#!/usr/bin/make -f
+
+ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
+export CROSS_COMPILE=$(DEB_HOST_GNU_TYPE)-
+export CC=$(DEB_HOST_GNU_TYPE)-gcc
+export LD=$(DEB_HOST_GNU_TYPE)-gcc
+endif
+
+export DH_VERBOSE = 1
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
+
+documentation: configure
+	make man
+
+configure:
+	make ${DEFCONFIG}
+
+build: documentation configure
+	dh $@
+
+%:
+	echo $@
+	dh $@
+
+override_dh_installchangelogs:
+	true
+
+override_dh_installdocs:
+	true
diff --git a/recipes-core/swupdate/files/debian/swupdate.examples b/recipes-core/swupdate/files/debian/swupdate.examples
new file mode 100644
index 0000000..c257b75
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.examples
@@ -0,0 +1,2 @@
+examples/configuration
+examples/description
diff --git a/recipes-core/swupdate/files/debian/swupdate.install b/recipes-core/swupdate/files/debian/swupdate.install
new file mode 100644
index 0000000..8957cc6
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.install
@@ -0,0 +1,2 @@
+swupdate usr/bin
+swupdate.cfg /etc
diff --git a/recipes-core/swupdate/files/debian/swupdate.manpages b/recipes-core/swupdate/files/debian/swupdate.manpages
new file mode 100644
index 0000000..c3438e0
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.manpages
@@ -0,0 +1,5 @@
+doc/build/man/swupdate.1
+doc/build/man/client.1
+doc/build/man/sendtohawkbit.1
+doc/build/man/hawkbitcfg.1
+doc/build/man/progress.1
diff --git a/recipes-core/swupdate/files/debian/swupdate.tmpfile b/recipes-core/swupdate/files/debian/swupdate.tmpfile
new file mode 100644
index 0000000..4743672
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/swupdate.tmpfile
@@ -0,0 +1,2 @@
+X /tmp/datadst
+X /tmp/scripts
diff --git a/recipes-core/swupdate/files/debian/watch b/recipes-core/swupdate/files/debian/watch
new file mode 100644
index 0000000..bc4c53e
--- /dev/null
+++ b/recipes-core/swupdate/files/debian/watch
@@ -0,0 +1,12 @@
+# Example watch control file for uscan
+# Rename this file to "watch" and then you can run the "uscan" command
+# to check for upstream updates and more.
+# See uscan(1) for format
+
+# Compulsory line, this is a version 4 file
+version=4
+
+# GitHub hosted projects
+opts="filenamemangle="s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
+   https://github.com/<user>/swupdate/tags \
+   (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
diff --git a/recipes-core/swupdate/files/postinst b/recipes-core/swupdate/files/postinst
new file mode 100644
index 0000000..f15ac10
--- /dev/null
+++ b/recipes-core/swupdate/files/postinst
@@ -0,0 +1,2 @@
+#!/bin/sh
+deb-systemd-helper enable swupdate.socket || true
diff --git a/recipes-core/swupdate/files/swupdate.cfg b/recipes-core/swupdate/files/swupdate.cfg
new file mode 100644
index 0000000..e0222f1
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.cfg
@@ -0,0 +1,6 @@
+globals :
+{
+    verbose = true;
+    loglevel = 10;
+    syslog = false;
+};
diff --git a/recipes-core/swupdate/files/swupdate.service.example b/recipes-core/swupdate/files/swupdate.service.example
new file mode 100644
index 0000000..d0b821e
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.service.example
@@ -0,0 +1,11 @@
+[Unit]
+Description=SWUpdate daemon
+Documentation=https://github.com/sbabic/swupdate
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/swupdate -f /etc/swupdate.cfg
+KillMode=mixed
+
+[Install]
+WantedBy=multi-user.target
diff --git a/recipes-core/swupdate/files/swupdate.socket.example b/recipes-core/swupdate/files/swupdate.socket.example
new file mode 100644
index 0000000..2b75671
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.socket.example
@@ -0,0 +1,11 @@
+[Unit]
+Description=SWUpdate socket listener
+Documentation=https://github.com/sbabic/swupdate
+Documentation=https://sbabic.github.io/swupdate
+
+[Socket]
+ListenStream=/tmp/sockinstctrl
+ListenStream=/tmp/swupdateprog
+
+[Install]
+WantedBy=sockets.target
diff --git a/recipes-core/swupdate/files/swupdate.socket.tmpl b/recipes-core/swupdate/files/swupdate.socket.tmpl
new file mode 100644
index 0000000..8e7fc1d
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate.socket.tmpl
@@ -0,0 +1,13 @@
+[Unit]
+Description=SWUpdate socket listener
+Documentation=https://github.com/sbabic/swupdate
+Documentation=https://sbabic.github.io/swupdate
+
+[Socket]
+SocketUser=${SWUPDATE_SOCKET_OWNER}
+SocketGroup=root
+ListenStream=/tmp/sockinstctrl
+ListenStream=/tmp/swupdateprog
+
+[Install]
+WantedBy=sockets.target
diff --git a/recipes-core/swupdate/files/swupdate_defconfig b/recipes-core/swupdate/files/swupdate_defconfig
new file mode 100644
index 0000000..9ae7cb5
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig
@@ -0,0 +1,83 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Swupdate Configuration
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Swupdate Settings
+#
+
+#
+# General Configuration
+#
+# CONFIG_CURL is not set
+# CONFIG_CURL_SSL is not set
+CONFIG_SYSTEMD=y
+CONFIG_SCRIPTS=y
+# CONFIG_HW_COMPATIBILITY is not set
+CONFIG_SW_VERSIONS_FILE="/etc/sw-versions"
+
+#
+# Socket Paths
+#
+CONFIG_SOCKET_CTRL_PATH="/tmp/sockinstctrl"
+CONFIG_SOCKET_PROGRESS_PATH="/tmp/swupdateprog"
+CONFIG_SOCKET_REMOTE_HANDLER_DIRECTORY="/tmp/"
+# CONFIG_MTD is not set
+# CONFIG_LUA is not set
+# CONFIG_LUAPKG is not set
+# CONFIG_FEATURE_SYSLOG is not set
+
+#
+# Build Options
+#
+CONFIG_CROSS_COMPILE=""
+CONFIG_SYSROOT=""
+CONFIG_EXTRA_CFLAGS=""
+CONFIG_EXTRA_LDFLAGS=""
+CONFIG_EXTRA_LDLIBS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_WERROR is not set
+# CONFIG_NOCLEANUP is not set
+# CONFIG_BOOTLOADER_EBG is not set
+# CONFIG_UBOOT is not set
+# CONFIG_BOOTLOADER_NONE is not set
+# CONFIG_BOOTLOADER_GRUB is not set
+# CONFIG_DOWNLOAD is not set
+# CONFIG_DOWNLOAD_SSL is not set
+# CONFIG_CHANNEL_CURL is not set
+# CONFIG_HASH_VERIFY=y
+# CONFIG_SIGNED_IMAGES is not set
+# CONFIG_ENCRYPTED_IMAGES is not set
+# CONFIG_SURICATTA is not set
+# CONFIG_WEBSERVER is not set
+CONFIG_GUNZIP=y
+
+#
+# Parser Features
+#
+CONFIG_LIBCONFIG=y
+CONFIG_PARSERROOT=""
+# CONFIG_JSON is not set
+# CONFIG_LUAEXTERNAL is not set
+# CONFIG_SETEXTPARSERNAME is not set
+# CONFIG_SETSWDESCRIPTION is not set
+
+#
+# Image Handlers
+#
+CONFIG_RAW=y
+# CONFIG_LUASCRIPTHANDLER is not set
+# CONFIG_SHELLSCRIPTHANDLER is not set
+# CONFIG_HANDLER_IN_LUA is not set
+# CONFIG_EMBEDDED_LUA_HANDLER is not set
+# CONFIG_EMBEDDED_LUA_HANDLER_SOURCE is not set
+CONFIG_ARCHIVE=y
+# CONFIG_REMOTE_HANDLER is not set
+# CONFIG_SWUFORWARDER_HANDLER is not set
+# CONFIG_BOOTLOADERHANDLER is not set
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
new file mode 100644
index 0000000..8e3688c
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
@@ -0,0 +1,3 @@
+CONFIG_BOOTLOADER_NONE=n
+CONFIG_BOOTLOADER_EBG=y
+CONFIG_BOOTLOADERHANDLER=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
new file mode 100644
index 0000000..b39f9df
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
@@ -0,0 +1,2 @@
+CONFIG_LUA=y
+CONFIG_LUAPKG="lua53"
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
new file mode 100644
index 0000000..b4a2de8
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
@@ -0,0 +1,4 @@
+CONFIG_LUASCRIPTHANDLER=y
+CONFIG_HANDLER_IN_LUA=y
+CONFIG_EMBEDDED_LUA_HANDLER=y
+CONFIG_EMBEDDED_LUA_HANDLER_SOURCE="swupdate_handlers.lua"
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
new file mode 100644
index 0000000..eab98dd
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
@@ -0,0 +1 @@
+CONFIG_MTD=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
new file mode 100644
index 0000000..6b5832a
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
@@ -0,0 +1,3 @@
+CONFIG_UBOOT=y
+CONFIG_UBOOT_FWENV="/etc/fw_env.config"
+CONFIG_BOOTLOADERHANDLER=y
diff --git a/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
new file mode 100644
index 0000000..d1c7732
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
@@ -0,0 +1,6 @@
+CONFIG_UBIVOL=y
+CONFIG_UBIATTACH=y
+CONFIG_UBIBLACKLIST=""
+CONFIG_UBIWHITELIST=""
+CONFIG_UBIVIDOFFSET=0
+CONFIG_CFI=y
diff --git a/recipes-core/swupdate/files/swupdate_handlers.lua b/recipes-core/swupdate/files/swupdate_handlers.lua
new file mode 100644
index 0000000..f2ecc54
--- /dev/null
+++ b/recipes-core/swupdate/files/swupdate_handlers.lua
@@ -0,0 +1,453 @@
+--[[
+
+    Round-robin Image and File Handler.
+
+    Copyright (C) 2019, Siemens AG
+
+    Author: Christian Storm <christian.storm@siemens.com>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+
+    An `sw-description` file using these handlers may look like:
+        software =
+        {
+            version = "0.1.0";
+            images: ({
+                filename = "rootfs.ext4";
+                device = "sda4,sda5";
+                type = "roundrobin";
+                compressed = false;
+            });
+            files: ({
+                filename = "vmlinuz";
+                path = "vmlinuz";
+                type = "kernelfile";
+                device = "sda2,sda3";
+                filesystem = "vfat";
+            },
+            {
+                filename = "initrd.img";
+                path = "initrd.img";
+                type = "kernelfile";
+                device = "sda2,sda3";
+                filesystem = "vfat";
+            });
+        }
+
+    The semantics is as follows: Instead of having a fixed target device,
+    the 'roundrobin' image handler calculates the target device by parsing
+    /proc/cmdline, matching the root=<device> kernel parameter against its
+    'device' attribute's list of devices, and sets the actual target
+    device to the next 'device' attribute list entry in a round-robin
+    manner. The actual flashing is done via chain-calling another handler,
+    defaulting to the "raw" handler.
+
+    The 'kernelfile' file handler reuses the 'roundrobin' handler's target
+    device calculation by reading the actual target device from the same
+    index into its 'device' attribute's list of devices. The actual placing
+    of files into this partition is done via chain-calling another handler,
+    defaulting to the "rawfile" handler.
+
+    In the above example, if /dev/sda4 is currently booted according to
+    /proc/cmdline, /dev/sda5 will be flashed and the vmlinuz and initrd.img
+    files will be placed on /dev/sda3. If /dev/sda5 is booted, /dev/sda4
+    will be flashed and the vmlinuz and initrd.img files are placed on
+    /dev/sda2.
+    In addition to "classical" device nodes as in this example, partition
+    UUIDs as reported, e.g., by `blkid -s PARTUUID` are also supported.
+    UBI volumes are supported as well by specifying a CSV list of
+    ubi<number>:<label> items.
+
+    Configuration is done via an INI-style configuration file located at
+    /etc/swupdate.handler.ini or via compiled-in configuration (by
+    embedding the Lua handler script into the SWUpdate binary via using
+    CONFIG_EMBEDDED_LUA_HANDLER), the latter having precedence over the
+    former. See the example configuration below.
+    If uncommenting this example block, it will take precedence over any
+    /etc/swupdate.handler.ini configuration file.
+
+    The chain-called handlers can either be specified in the configuration,
+    i.e., a static run-time setting, or via the 'chainhandler' property of
+    an 'image' or 'file' section in the sw-description, with the latter
+    taking precedence over the former, e.g.,
+        ...
+        images: ({
+                filename = "rootfs.ext4";
+                device = "sda4,sda5";
+                type = "roundrobin";
+                properties: {
+                    chainhandler = "myraw";
+                };
+            });
+        ...
+    Such a sw-description fragment will chain-call the imaginary "myraw"
+    handler regardless of what's been configured in the compiled-in or the
+    configuration file.
+    When chain-calling the "rdiff_image" handler, its 'rdiffbase' property
+    is subject to round-robin as well, i.e., the 'rdiffbase' property is
+    expected to be a CSV list as for the 'device' property, and the actual
+    'rdiffbase' property value is calculated following the same round-robin
+    calculation mechanism stated above prior to chain-calling the actual
+    "rdiff_image" handler, e.g.,
+        images: ({
+                filename = "rootfs.ext4";
+                type = "roundrobin";
+                device = "sda4,sda5";
+                properties: {
+                    chainhandler = "rdiff_image";
+                    rdiffbase="sda1,sda2";
+                };
+            });
+    will set the 'rdiffbase' property to /dev/sda2 (/dev/sda1) if /dev/sda4
+    (/dev/sda5) is the currently booted root file system according to
+    /proc/cmdline parsing.
+
+]]
+
+
+local configuration = [[
+[bootloader]
+# Required: bootloader name, uboot and ebg currently supported.
+name=ebg
+# Required: bootloader-specific key-value pairs, e.g., for ebg:
+kernelname=linux.signed.efi
+# For relying on FAT labels, prefix bootlabels with 'L:', e.g., L:BOOT0.
+# For using custom labels, i.e., relying on the contents of an EFILABEL
+# file within the partition, prefix it with 'C:', e.g., C:BOOT0.
+bootlabel={ "C:BOOT0:", "C:BOOT1:" }
+
+# Optional: handler to chain-call for the 'roundrobin' handler,
+# defaulting to 'raw'
+[roundrobin]
+chainhandler=raw
+
+# Optional: handler to chain-call for the 'kernelfile' handler,
+# defaulting to 'rawfile'
+[kernelfile]
+chainhandler=rawfile
+]]
+
+-- Default configuration file, tried if no compiled-in config is available.
+local cfgfile = "/etc/swupdate.handler.ini"
+
+-- Table holding the configuration.
+local config = {}
+
+-- Mandatory configuration [section] and keys
+local BOOTLOADERCFG = {
+    ebg   = {
+        bootloader = {"name", "bootlabel", "kernelname"}
+    },
+    -- TODO fill with mandatory U-Boot configuration
+    uboot = {
+        bootloader = {"name"}
+    }
+}
+
+-- enum-alikes to make code more readable
+local BOOTLOADER = { EBG = "ebg", UBOOT = "uboot" }
+local PARTTYPE   = { UUID = 1, PLAIN = 2, UBI = 3 }
+
+-- Target table describing the target device the image is to be/has been flashed to.
+local rrtarget = {
+    size = function(self)
+        local _size = 0
+        for index in pairs(self) do _size = _size + 1 end
+        return _size - 1
+    end
+}
+
+-- Helper function parsing CSV fields of a struct img_type such as
+-- the "device" fields or the "rdiffbase" property.
+local get_device_list = function(device_node_csv_list)
+    local device_list = {}
+    for item in device_node_csv_list:gmatch("([^,]+)") do
+        local device_node = item:gsub("/dev/", "")
+        device_list[#device_list+1] = device_node
+        device_list[device_node] = #device_list
+    end
+    return device_list
+end
+
+-- Helper function to determine device node location.
+local get_device_path = function(device_node)
+    if device_node:match("ubi%d+:%S+") then
+        return 0, device_node, PARTTYPE.UBI
+    end
+    local device_path = string.format("/dev/disk/by-partuuid/%s", device_node)
+    local file = io.open(device_path, "rb" )
+    if file then
+        file:close()
+        return 0, device_path, PARTTYPE.UUID
+    end
+    device_path = string.format("/dev/%s", device_node)
+    file = io.open(device_path, "rb" )
+    if file then
+        file:close()
+        return 0, device_path, PARTTYPE.PLAIN
+    end
+    swupdate.error(string.format("Cannot access target device node /dev/{,disk/by-partuuid}/%s", device_node))
+    return 1, nil, nil
+end
+
+-- Helper function parsing the INI-style configuration.
+local get_config = function()
+    -- Return configuration right away if it's already parsed.
+    if config ~= nil and #config > 0 then
+        return config
+    end
+
+    -- Get configuration INI-style string.
+    if not configuration then
+        swupdate.trace(string.format("No compiled-in config found, trying %s", cfgfile))
+        local file = io.open(cfgfile, "r" )
+        if not file then
+            swupdate.error(string.format("Cannot open config file %s", cfgfile))
+            return nil
+        end
+        configuration = file:read("*a")
+        file:close()
+    end
+    if configuration:sub(-1) ~= "\n" then
+        configuration=configuration.."\n"
+    end
+
+    -- Parse INI-style contents into config table.
+    local sec, key, value
+    for line in configuration:gmatch("(.-)\n") do
+        if line:match("^%[([%w%p]+)%][%s]*") then
+            sec = line:match("^%[([%w%p]+)%][%s]*")
+            config[sec] = {}
+        elseif sec then
+            key, value = line:match("^([%w%p]-)=(.*)$")
+            if key and value then
+                if tonumber(value)  then value = tonumber(value) end
+                if value == "true"  then value = true            end
+                if value == "false" then value = false           end
+                if value:sub(1,1) == "{" then
+                    local _value = {}
+                    for _key, _ in value:gmatch("\"(%S+)\"") do
+                        table.insert(_value, _key)
+                    end
+                    value = _value
+                end
+                config[sec][key] = value
+            else
+                if not line:match("^$") and not line:match("^#") then
+                    swupdate.warn(string.format("Syntax error, skipping '%s'", line))
+                end
+            end
+        else
+            swupdate.error(string.format("Syntax error. no [section] encountered."))
+            return nil
+        end
+    end
+
+    -- Check config table for mandatory key existence.
+    if config["bootloader"] == nil or config["bootloader"]["name"] == nil then
+        swupdate.error(string.format("Syntax error. no [bootloader] encountered or name= missing therein."))
+        return nil
+    end
+    local bcfg = BOOTLOADERCFG[config.bootloader.name]
+    if not bcfg then
+        swupdate.error(string.format("Bootloader unsupported, name=uboot|ebg missing in [bootloader]?."))
+        return nil
+    end
+    for sec, _ in pairs(bcfg) do
+        for _, key in pairs(bcfg[sec]) do
+            if config[sec] == nil or config[sec][key] == nil then
+                swupdate.error(string.format("Mandatory config key %s= in [%s] not found.", key, sec))
+            end
+        end
+    end
+
+    return config
+end
+
+-- Round-robin image handler for updating the root partition.
+function handler_roundrobin(image)
+    -- Read configuration.
+    if not get_config() then
+        swupdate.error("Cannot read configuration.")
+        return 1
+    end
+
+    -- Check if we can chain-call the handler.
+    local chained_handler = "raw"
+    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
+        chained_handler = image.properties["chainhandler"]
+    elseif config["roundrobin"] ~= nil and config["roundrobin"]["chainhandler"] ~= nil then
+        chained_handler = config["roundrobin"]["chainhandler"]
+    end
+    if not swupdate.handler[chained_handler] then
+        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution.", chained_handler))
+        return 1
+    end
+
+    -- Get device list for round-robin.
+    local devices = get_device_list(image.device)
+    if #devices < 2 then
+        swupdate.error("Specify at least 2 devices in the device= property for 'roundrobin'.")
+        return 1
+    end
+
+    -- Check that rrtarget is unset, else a reboot may be pending.
+    if rrtarget:size() > 0 then
+        swupdate.warn("The 'roundrobin' handler has been run. Is a reboot pending?")
+    end
+
+    -- Determine current root device.
+    local file = io.open("/proc/cmdline", "r")
+    if not file then
+        swupdate.error("Cannot open /proc/cmdline.")
+        return 1
+    end
+    local cmdline = file:read("*l")
+    file:close()
+
+    local rootparam, rootdevice
+    for item in cmdline:gmatch("%S+") do
+        rootparam, rootdevice = item:match("(root=[%u=]*[/dev/]*(%S+))")
+        if rootparam and rootdevice then break end
+    end
+    if not rootdevice then
+        -- Use findmnt to get the rootdev
+      rootdevice = io.popen('findmnt -nl / -o PARTUUID'):read("*l")
+      if not rootdevice then
+        swupdate.error("Cannot determine current root device.")
+        return 1
+      end
+    end
+    swupdate.info(string.format("Current root device is: %s", rootdevice))
+
+    if not devices[rootdevice] then
+        swupdate.error(string.format("Current root device '%s' is not in round-robin root devices list: %s", rootdevice, image.device:gsub("/dev/", "")))
+        return 1
+    end
+
+    -- Perform round-robin calculation for target.
+    local err
+    rrtarget.index = devices[rootdevice] % #devices + 1
+    rrtarget.device_node = devices[rrtarget.index]
+    err, rrtarget.device_path, rrtarget.parttype = get_device_path(devices[rrtarget.index])
+    if err ~= 0 then
+        return 1
+    end
+    swupdate.info(string.format("Using '%s' as 'roundrobin' target via '%s' handler.", rrtarget.device_path, chained_handler))
+
+    -- If the chain-called handler is rdiff_image, adapt the rdiffbase property
+    if chained_handler == "rdiff_image" then
+        if image.properties ~= nil and image.properties["rdiffbase"] ~= nil then
+            local rdiffbase_devices = get_device_list(image.properties["rdiffbase"])
+            if #rdiffbase_devices < 2 then
+                swupdate.error("Specify at least 2 devices in the rdiffbase= property for 'roundrobin'.")
+                return 1
+            end
+            err, image.propierties["rdiffbase"], _ = get_device_path(rdiffbase_devices[rrtarget.index])
+            if err ~= 0 then
+                return 1
+            end
+            swupdate.info(string.format("Using device %s as rdiffbase.", image.properties["rdiffbase"]))
+        else
+            swupdate.error("Property 'rdiffbase' is missing in sw-description.")
+            return 1
+        end
+    end
+
+    -- Actually flash the partition.
+    local msg
+    image.type = chained_handler
+    image.device = rrtarget.device_path
+    err, msg = swupdate.call_handler(chained_handler, image)
+    if err ~= 0 then
+        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
+        return 1
+    end
+
+    if config.bootloader.name == BOOTLOADER.EBG then
+      if rootparam then
+        local value = cmdline:gsub(
+            rootparam:gsub("%-", "%%-"),
+            string.format("root=%s%s",
+                (rrtarget.parttype == PARTTYPE.PLAIN and "") or (rrtarget.parttype == PARTTYPE.UBI and "") or "PARTUUID=",
+                 rrtarget.parttype == PARTTYPE.PLAIN and rrtarget.device_path or devices[rrtarget.index]
+            )
+        )
+        swupdate.info(string.format("Setting EFI Bootguard environment: kernelparams=%s", value))
+        swupdate.set_bootenv("kernelparams", value)
+      end
+    elseif config.bootloader.name == BOOTLOADER.UBOOT then
+        -- Update U-Boot environment.
+        swupdate.info(string.format("Setting U-Boot environment"))
+        local value = rrtarget.index
+        swupdate.set_bootenv("swupdpart", value);
+    end
+
+    return 0
+end
+
+-- File handler for updating kernel files.
+function handler_kernelfile(image)
+    -- Check if we can chain-call the handler.
+    local chained_handler = "rawfile"
+    if image.properties ~= nil and image.properties["chainhandler"] ~= nil then
+        chained_handler = image.properties["chainhandler"]
+    elseif config["kernelfile"] ~= nil and config["kernelfile"]["chainhandler"] ~= nil then
+        chained_handler = config["kernelfile"]["chainhandler"]
+    end
+    if not swupdate.handler[chained_handler] then
+        swupdate.error(string.format("'%s' handler not available in SWUpdate distribution."), chained_handler)
+        return 1
+    end
+
+    -- Check that rrtarget is set, else the 'roundrobin' handler hasn't been run.
+    if rrtarget:size() == 0 then
+        swupdate.error("The 'roundrobin' handler hasn't been run.")
+        swupdate.info("Place 'roundrobin' above 'kernelfile' in sw-description.")
+        return 1
+    end
+
+    -- Get device list for round-robin.
+    local devices = get_device_list(image.device)
+    if #devices < 2 then
+        swupdate.error("Specify at least 2 devices in the device= property for 'kernelfile'.")
+        return 1
+    end
+    if rrtarget.index > #devices then
+        swupdate.error("Cannot map kernel partition to root partition.")
+        return 1
+    end
+
+    -- Perform round-robin indexing for target.
+    local err
+    err, image.device, _ = get_device_path(devices[rrtarget.index])
+    if err ~= 0 then
+        return 1
+    end
+    swupdate.info(string.format("Using '%s' as 'kernelfile' target via '%s' handler.", image.device, chained_handler))
+
+    -- Actually copy the 'kernelfile' files.
+    local msg
+    image.type = chained_handler
+    err, msg = swupdate.call_handler(chained_handler, image)
+    if err ~= 0 then
+        swupdate.error(string.format("Error chain-calling '%s' handler: %s", chained_handler, (msg or "")))
+        return 1
+    end
+
+    if config.bootloader.name == BOOTLOADER.EBG then
+        -- Update EFI Boot Guard environment: kernelfile
+        local value = string.format("%s%s", config.bootloader.bootlabel[rrtarget.index], config.bootloader.kernelname)
+        swupdate.info(string.format("Setting EFI Bootguard environment: kernelfile=%s", value))
+        swupdate.set_bootenv("kernelfile", value)
+    elseif config.bootloader.name == BOOTLOADER.UBOOT then
+        -- Update U-Boot environment.
+        swupdate.info(string.format("Setting U-Boot environment"))
+        -- TODO
+    end
+
+    return 0
+end
+
+swupdate.register_handler("roundrobin", handler_roundrobin, swupdate.HANDLER_MASK.IMAGE_HANDLER)
+swupdate.register_handler("kernelfile", handler_kernelfile, swupdate.HANDLER_MASK.FILE_HANDLER)
diff --git a/recipes-core/swupdate/swupdate.bb b/recipes-core/swupdate/swupdate.bb
new file mode 100644
index 0000000..95cf73a
--- /dev/null
+++ b/recipes-core/swupdate/swupdate.bb
@@ -0,0 +1,54 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+hDESCRIPTION = "swupdate utility for software updates"
+HOMEPAGE= "https://github.com/sbabic/swupdate"
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://${LAYERDIR_isar}/licenses/COPYING.GPLv2;md5=751419260aa954499f7abaabaa882bbe"
+
+SRC_URI = "git://github.com/sbabic/swupdate.git;branch=master;protocol=https"
+
+SRCREV = "1a6dfbb5a0be978ac1a159758e278ab4d44167e2"
+PV = "2020.4-git+isar"
+
+DEFCONFIG := "swupdate_defconfig"
+
+SRC_URI += "file://debian \
+            file://${DEFCONFIG} \
+            file://${PN}.cfg"
+
+DEPENDS += "libubootenv"
+
+DEBIAN_DEPENDS = "${shlibs:Depends}, ${misc:Depends}"
+
+inherit dpkg
+inherit swupdate-config
+
+KFEATURES += "luahandler"
+
+S = "${WORKDIR}/git"
+
+TEMPLATE_FILES = "debian/changelog.tmpl debian/control.tmpl debian/rules.tmpl"
+TEMPLATE_VARS += "BUILD_DEB_DEPENDS DEFCONFIG DEBIAN_DEPENDS"
+
+do_prepare_build() {
+        DEBDIR=${S}/debian
+        cp -R ${WORKDIR}/debian ${S}
+
+        install -m 0644 ${WORKDIR}/${PN}.cfg ${S}/swupdate.cfg
+        install -m 0644 ${WORKDIR}/${DEFCONFIG}.gen ${S}/configs/${DEFCONFIG}
+
+        if ! grep -q "configs/${DEFCONFIG}" ${S}/.gitignore
+        then
+                echo "configs/${DEFCONFIG}" >> ${S}/.gitignore
+        fi
+        # luahandler
+        install -m 0644 ${WORKDIR}/${SWUPDATE_LUASCRIPT} ${S}
+}
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#5002): https://lists.cip-project.org/g/cip-dev/message/5002
Mute This Topic: https://lists.cip-project.org/mt/75767669/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v3 4/5] wic: Add wks files for A/B Partition update
  2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
                     ` (2 preceding siblings ...)
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 3/5] recipes-core: add swupdate Quirin Gylstorff
@ 2020-07-24 14:52   ` Quirin Gylstorff
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 5/5] swupdate: create swu file from wic image Quirin Gylstorff
  4 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-07-24 14:52 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 3692 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Add wks for:
- simatic-ipc227e
- qemu-amd64

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 kas/opt/ebg-swu.yml                  | 26 ++++++++++++++++++++++++++
 wic/ebg-sysparts.inc                 |  8 ++++++++
 wic/qemu-amd64-efibootguard.wks      |  5 +++++
 wic/simatic-ipc227e-efibootguard.wks |  5 +++++
 wic/swupdate-partition.inc           |  4 ++++
 5 files changed, 48 insertions(+)
 create mode 100644 kas/opt/ebg-swu.yml
 create mode 100644 wic/ebg-sysparts.inc
 create mode 100644 wic/qemu-amd64-efibootguard.wks
 create mode 100644 wic/simatic-ipc227e-efibootguard.wks
 create mode 100644 wic/swupdate-partition.inc

diff --git a/kas/opt/ebg-swu.yml b/kas/opt/ebg-swu.yml
new file mode 100644
index 0000000..5b39730
--- /dev/null
+++ b/kas/opt/ebg-swu.yml
@@ -0,0 +1,26 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+header:
+  version: 8
+
+local_conf_header:
+  swupdate: |
+    IMAGE_INSTALL_append = " swupdate efibootguard"
+    BOOTLOADER = "efibootguard"
+
+  efibootguard: |
+    WDOG_TIMEOUT = "0"
+    WICVARS += "WDOG_TIMEOUT"
+
+  wic: |
+    IMAGE_TYPE = "wic-img"
+    WKS_FILE = "${MACHINE}-${BOOTLOADER}.wks"
diff --git a/wic/ebg-sysparts.inc b/wic/ebg-sysparts.inc
new file mode 100644
index 0000000..dea99e8
--- /dev/null
+++ b/wic/ebg-sysparts.inc
@@ -0,0 +1,8 @@
+# default partition layout EFI Boot Guard usage
+
+# EFI partition containing efibootguard bootloader binary
+part --source efibootguard-efi  --ondisk sda --size 16M --extra-space 0 --overhead-factor 1 --label efi   --align 1024 --part-type=EF00 --active
+
+# EFI Boot Guard environment/config partitions plus Kernel files
+part --source efibootguard-boot --ondisk sda --size 32M --extra-space 0 --overhead-factor 1 --label BOOT0 --align 1024 --part-type=0700 --sourceparams "revision=2,root=PARTUUID:fedcba98-7654-3210-cafe-5e0710000001"
+part --source efibootguard-boot --ondisk sda --size 32M --extra-space 0 --overhead-factor 1 --label BOOT1 --align 1024 --part-type=0700 --sourceparams "revision=1,root=PARTUUID:fedcba98-7654-3210-cafe-5e0710000002"
diff --git a/wic/qemu-amd64-efibootguard.wks b/wic/qemu-amd64-efibootguard.wks
new file mode 100644
index 0000000..3cd7360
--- /dev/null
+++ b/wic/qemu-amd64-efibootguard.wks
@@ -0,0 +1,5 @@
+# short-description: Qemu-amd64 with Efibootguard and SWUpdate
+# long-description: Disk image for qemu-amd64 with EFI Boot Guard and SWUpdate
+
+include ebg-sysparts.inc
+include swupdate-partition.inc
diff --git a/wic/simatic-ipc227e-efibootguard.wks b/wic/simatic-ipc227e-efibootguard.wks
new file mode 100644
index 0000000..74446d3
--- /dev/null
+++ b/wic/simatic-ipc227e-efibootguard.wks
@@ -0,0 +1,5 @@
+# short-description: Simatic-ipc227e with EFI Boot Guard and SWUpdate
+# long-description: Disk image for Simatic-ipc227e with EFI Boot Guard and SWUpdate
+
+include ebg-sysparts.inc
+include swupdate-partition.inc
diff --git a/wic/swupdate-partition.inc b/wic/swupdate-partition.inc
new file mode 100644
index 0000000..15fbe80
--- /dev/null
+++ b/wic/swupdate-partition.inc
@@ -0,0 +1,4 @@
+part --source rootfs --uuid "fedcba98-7654-3210-cafe-5e0710000001" --size 1000M   --extra-space 128M --overhead-factor 1 --label systema --align 1024 --fstype=ext4
+part  --source rootfs --uuid "fedcba98-7654-3210-cafe-5e0710000002" --size 1000M   --extra-space 128M --overhead-factor 1 --label systemb --align 1024 --fstype=ext4
+
+bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 rootwait earlyprintk"
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#5000): https://lists.cip-project.org/g/cip-dev/message/5000
Mute This Topic: https://lists.cip-project.org/mt/75767667/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [cip-dev] [isar-cip-core PATCH v3 5/5] swupdate: create swu file from wic image
  2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
                     ` (3 preceding siblings ...)
  2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 4/5] wic: Add wks files for A/B Partition update Quirin Gylstorff
@ 2020-07-24 14:52   ` Quirin Gylstorff
  4 siblings, 0 replies; 22+ messages in thread
From: Quirin Gylstorff @ 2020-07-24 14:52 UTC (permalink / raw)
  To: cip-dev, Jan.Kiszka; +Cc: Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 4589 bytes --]

From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

Create a swu file for swupdate to update devices in the field.
This is done in the same step as the complete image build
to avoid diverging images.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 classes/extract-partition.bbclass             | 26 +++++++++++++
 classes/wic-swu-img.bbclass                   | 20 ++++++++++
 kas/opt/ebg-swu.yml                           |  4 +-
 recipes-core/images/cip-core-image.bb         | 10 +++++
 recipes-core/images/files/sw-description.tmpl | 37 +++++++++++++++++++
 5 files changed, 95 insertions(+), 2 deletions(-)
 create mode 100644 classes/extract-partition.bbclass
 create mode 100644 classes/wic-swu-img.bbclass
 create mode 100644 recipes-core/images/files/sw-description.tmpl

diff --git a/classes/extract-partition.bbclass b/classes/extract-partition.bbclass
new file mode 100644
index 0000000..e9de8fc
--- /dev/null
+++ b/classes/extract-partition.bbclass
@@ -0,0 +1,26 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+SOURCE_IMAGE_FILE ?= "${WIC_IMAGE_FILE}"
+EXTRACT_PARTITIONS ?= "img4"
+
+do_extract_partition () {
+    for PARTITION in ${EXTRACT_PARTITIONS}; do
+        rm -f ${DEPLOY_DIR_IMAGE}/${PARTITION}.gz
+        PART_START=$(fdisk -lu ${SOURCE_IMAGE_FILE} | grep ${PARTITION} | awk '{ print $2 }'  )
+        PART_END=$(fdisk -lu ${SOURCE_IMAGE_FILE} | grep ${PARTITION} | awk '{ print $3 }'  )
+        PART_COUNT=$(expr ${PART_END} - ${PART_START} + 1 )
+
+        dd if=${SOURCE_IMAGE_FILE} of=${DEPLOY_DIR_IMAGE}/${PARTITION} bs=512 skip=${PART_START} count=${PART_COUNT}
+
+        gzip ${DEPLOY_DIR_IMAGE}/${PARTITION}
+    done
+}
diff --git a/classes/wic-swu-img.bbclass b/classes/wic-swu-img.bbclass
new file mode 100644
index 0000000..c8532ba
--- /dev/null
+++ b/classes/wic-swu-img.bbclass
@@ -0,0 +1,20 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+
+inherit wic-img
+inherit extract-partition
+inherit swupdate-img
+
+SOURCE_IMAGE_FILE = "${WIC_IMAGE_FILE}"
+
+addtask do_extract_partition after do_wic_image
+addtask do_swupdate_image after do_extract_partition
diff --git a/kas/opt/ebg-swu.yml b/kas/opt/ebg-swu.yml
index 5b39730..304fa4d 100644
--- a/kas/opt/ebg-swu.yml
+++ b/kas/opt/ebg-swu.yml
@@ -22,5 +22,5 @@ local_conf_header:
     WICVARS += "WDOG_TIMEOUT"
 
   wic: |
-    IMAGE_TYPE = "wic-img"
-    WKS_FILE = "${MACHINE}-${BOOTLOADER}.wks"
+    IMAGE_TYPE = "wic-swu-img"
+    WKS_FILE ?= "${MACHINE}-${BOOTLOADER}.wks"
diff --git a/recipes-core/images/cip-core-image.bb b/recipes-core/images/cip-core-image.bb
index 9ee4b25..b1ed491 100644
--- a/recipes-core/images/cip-core-image.bb
+++ b/recipes-core/images/cip-core-image.bb
@@ -17,3 +17,13 @@ DESCRIPTION = "CIP Core image"
 IMAGE_INSTALL += "customizations"
 # for cip-testing
 IMAGE_INSTALL += "ltp-full"
+
+# for swupdate
+EXTRACT_PARTITIONS = "img4"
+ROOTFS_PARTITION_NAME="img4.gz"
+
+SRC_URI += "file://sw-description.tmpl"
+TEMPLATE_FILES += "sw-description.tmpl"
+TEMPLATE_VARS += "PN ROOTFS_PARTITION_NAME KERNEL_IMAGE INITRD_IMAGE"
+
+SWU_ADDITIONAL_FILES += "${INITRD_IMAGE} ${KERNEL_IMAGE} ${ROOTFS_PARTITION_NAME}"
diff --git a/recipes-core/images/files/sw-description.tmpl b/recipes-core/images/files/sw-description.tmpl
new file mode 100644
index 0000000..4d32f6f
--- /dev/null
+++ b/recipes-core/images/files/sw-description.tmpl
@@ -0,0 +1,37 @@
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+software =
+{
+    version = "0.2";
+    name = "cip software update"
+    images: ({
+            filename = "${ROOTFS_PARTITION_NAME}";
+            device = "fedcba98-7654-3210-cafe-5e0710000001,fedcba98-7654-3210-cafe-5e0710000002";
+            type = "roundrobin";
+            compressed = true;
+            filesystem = "ext4";
+    });
+    files: ({
+            filename = "${KERNEL_IMAGE}";
+            path = "vmlinuz";
+            type = "kernelfile";
+            device = "sda2,sda3";
+            filesystem = "vfat";
+    },
+    {
+            filename = "${INITRD_IMAGE}";
+            path = "initrd.img";
+            type = "kernelfile";
+            device = "sda2,sda3";
+            filesystem = "vfat";
+    });
+}
+
-- 
2.20.1


[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#5001): https://lists.cip-project.org/g/cip-dev/message/5001
Mute This Topic: https://lists.cip-project.org/mt/75767668/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update
  2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
                     ` (4 preceding siblings ...)
  2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 5/5] swupdate: create swu file from wic image Quirin Gylstorff
@ 2020-07-29 17:07   ` Jan Kiszka
  5 siblings, 0 replies; 22+ messages in thread
From: Jan Kiszka @ 2020-07-29 17:07 UTC (permalink / raw)
  To: cip-dev, Quirin Gylstorff

[-- Attachment #1: Type: text/plain, Size: 6862 bytes --]

On 29.06.20 11:56, Quirin Gylstorff wrote:
> From: Quirin Gylstorff <quirin.gylstorff@siemens.com>
> 
> This patchset adds efibootguard, swupdate to allow A/B updates in
> cip-core. The update mechanism is currently only implemented for x86_64.
> 
> Changes V2:
>   - update efibootguard to v0.7
>   - add swdescription and kas option to build qemu-amd64 test image
>   - swupdate set to upstream mirror and no longer use gitsm
> 
> Quirin Gylstorff (5):
>    recipes-bsp: Add efibootguard
>    patches: add libubootenv
>    recipes-core: add swupdate
>    wic: Add wks files for A/B Partition update
>    swupdate: create swu file from wic image
> 
>   classes/extract-partition.bbclass             |  26 +
>   classes/kconfig-snippets.bbclass              |  90 ++++
>   classes/swupdate-config.bbclass               |  76 +++
>   classes/swupdate-img.bbclass                  |  75 +++
>   classes/wic-swu-img.bbclass                   |  20 +
>   .../0001-u-boot-add-libubootenv.patch         | 169 +++++++
>   kas-cip.yml                                   |   4 +
>   kas/opt/ebg-swu.yml                           |  26 +
>   kas/opt/qemu-swupdate.yml                     |  19 +
>   .../efibootguard/efibootguard_0.7-git+isar.bb |  46 ++
>   recipes-bsp/efibootguard/files/debian/compat  |   1 +
>   .../efibootguard/files/debian/control.tmpl    |  20 +
>   .../files/debian/efibootguard-dev.install     |   3 +
>   .../files/debian/efibootguard.install         |   2 +
>   recipes-bsp/efibootguard/files/debian/rules   |  21 +
>   recipes-core/images/cip-core-image.bb         |  10 +
>   recipes-core/images/files/sw-description.tmpl |  29 ++
>   .../swupdate/files/debian/changelog.tmpl      |   6 +
>   recipes-core/swupdate/files/debian/compat     |   1 +
>   .../swupdate/files/debian/control.tmpl        |  15 +
>   recipes-core/swupdate/files/debian/copyright  |  36 ++
>   recipes-core/swupdate/files/debian/rules.tmpl |  30 ++
>   .../swupdate/files/debian/swupdate.examples   |   2 +
>   .../swupdate/files/debian/swupdate.install    |   2 +
>   .../swupdate/files/debian/swupdate.manpages   |   5 +
>   .../swupdate/files/debian/swupdate.tmpfile    |   2 +
>   recipes-core/swupdate/files/debian/watch      |  12 +
>   recipes-core/swupdate/files/postinst          |   2 +
>   recipes-core/swupdate/files/swupdate.cfg      |   6 +
>   .../swupdate/files/swupdate.service.example   |  11 +
>   .../swupdate/files/swupdate.socket.example    |  11 +
>   .../swupdate/files/swupdate.socket.tmpl       |  13 +
>   .../swupdate/files/swupdate_defconfig         |  83 ++++
>   .../swupdate_defconfig_efibootguard.snippet   |   3 +
>   .../files/swupdate_defconfig_lua.snippet      |   2 +
>   .../swupdate_defconfig_luahandler.snippet     |   4 +
>   .../files/swupdate_defconfig_mtd.snippet      |   1 +
>   .../files/swupdate_defconfig_u-boot.snippet   |   3 +
>   .../files/swupdate_defconfig_ubi.snippet      |   6 +
>   .../swupdate/files/swupdate_handlers.lua      | 453 ++++++++++++++++++
>   recipes-core/swupdate/swupdate.bb             |  54 +++
>   .../wic/plugins/source/efibootguard-boot.py   | 162 +++++++
>   .../wic/plugins/source/efibootguard-efi.py    | 102 ++++
>   wic/ebg-sysparts.inc                          |   8 +
>   wic/qemu-amd64-efibootguard.wks               |   5 +
>   wic/simatic-ipc227e-efibootguard.wks          |   5 +
>   wic/swupdate-partition.inc                    |   4 +
>   47 files changed, 1686 insertions(+)
>   create mode 100644 classes/extract-partition.bbclass
>   create mode 100644 classes/kconfig-snippets.bbclass
>   create mode 100644 classes/swupdate-config.bbclass
>   create mode 100644 classes/swupdate-img.bbclass
>   create mode 100644 classes/wic-swu-img.bbclass
>   create mode 100644 isar-patches/0001-u-boot-add-libubootenv.patch
>   create mode 100644 kas/opt/ebg-swu.yml
>   create mode 100644 kas/opt/qemu-swupdate.yml
>   create mode 100644 recipes-bsp/efibootguard/efibootguard_0.7-git+isar.bb
>   create mode 100644 recipes-bsp/efibootguard/files/debian/compat
>   create mode 100644 recipes-bsp/efibootguard/files/debian/control.tmpl
>   create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard-dev.install
>   create mode 100644 recipes-bsp/efibootguard/files/debian/efibootguard.install
>   create mode 100755 recipes-bsp/efibootguard/files/debian/rules
>   create mode 100644 recipes-core/images/files/sw-description.tmpl
>   create mode 100644 recipes-core/swupdate/files/debian/changelog.tmpl
>   create mode 100644 recipes-core/swupdate/files/debian/compat
>   create mode 100644 recipes-core/swupdate/files/debian/control.tmpl
>   create mode 100644 recipes-core/swupdate/files/debian/copyright
>   create mode 100755 recipes-core/swupdate/files/debian/rules.tmpl
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.examples
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.install
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.manpages
>   create mode 100644 recipes-core/swupdate/files/debian/swupdate.tmpfile
>   create mode 100644 recipes-core/swupdate/files/debian/watch
>   create mode 100644 recipes-core/swupdate/files/postinst
>   create mode 100644 recipes-core/swupdate/files/swupdate.cfg
>   create mode 100644 recipes-core/swupdate/files/swupdate.service.example
>   create mode 100644 recipes-core/swupdate/files/swupdate.socket.example
>   create mode 100644 recipes-core/swupdate/files/swupdate.socket.tmpl
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_efibootguard.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_lua.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_luahandler.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_mtd.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_u-boot.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_defconfig_ubi.snippet
>   create mode 100644 recipes-core/swupdate/files/swupdate_handlers.lua
>   create mode 100644 recipes-core/swupdate/swupdate.bb
>   create mode 100644 scripts/lib/wic/plugins/source/efibootguard-boot.py
>   create mode 100644 scripts/lib/wic/plugins/source/efibootguard-efi.py
>   create mode 100644 wic/ebg-sysparts.inc
>   create mode 100644 wic/qemu-amd64-efibootguard.wks
>   create mode 100644 wic/simatic-ipc227e-efibootguard.wks
>   create mode 100644 wic/swupdate-partition.inc
> 

Thanks, applied to next. The secure boot series is on hold due to 
conflict. When you update it, please also make sure that at least one 
target covering as much as possible of your code is built via CI.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux

[-- Attachment #2: Type: text/plain, Size: 419 bytes --]

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#5051): https://lists.cip-project.org/g/cip-dev/message/5051
Mute This Topic: https://lists.cip-project.org/mt/75188184/4520388
Group Owner: cip-dev+owner@lists.cip-project.org
Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129055/727948398/xyzzy  [cip-dev@archiver.kernel.org]
-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2020-07-29 17:07 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-25 13:21 [cip-dev] [isar-cip-core RFC 0/4] A/B Rootfs update with software update Quirin Gylstorff
2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 1/4] recipes-bsp: Add efibootguard Quirin Gylstorff
2020-06-26 13:37   ` Jan Kiszka
2020-06-29  9:03     ` Quirin Gylstorff
2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 2/4] patches: add libubootenv Quirin Gylstorff
2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 3/4] recipes-core: add swupdate Quirin Gylstorff
2020-06-26 13:05   ` Jan Kiszka
2020-06-29  9:03     ` Quirin Gylstorff
2020-06-25 13:21 ` [cip-dev] [isar-cip-core RFC 4/4] wic: Add wks files for A/B Partition update Quirin Gylstorff
2020-06-29  9:56 ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Quirin Gylstorff
2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 2/5] patches: add libubootenv Quirin Gylstorff
2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 3/5] recipes-core: add swupdate Quirin Gylstorff
2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 4/5] wic: Add wks files for A/B Partition update Quirin Gylstorff
2020-06-29  9:56   ` [cip-dev] [isar-cip-core PATCH v2 5/5] swupdate: create swu file from wic image Quirin Gylstorff
2020-07-29 17:07   ` [cip-dev] [isar-cip-core PATCH v2 0/5] A/B Rootfs update with software update Jan Kiszka
2020-07-24 14:52 ` [cip-dev] [isar-cip-core PATCH v3 " Quirin Gylstorff
2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 1/5] recipes-bsp: Add efibootguard Quirin Gylstorff
2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 2/5] patches: add libubootenv Quirin Gylstorff
2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 3/5] recipes-core: add swupdate Quirin Gylstorff
2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 4/5] wic: Add wks files for A/B Partition update Quirin Gylstorff
2020-07-24 14:52   ` [cip-dev] [isar-cip-core PATCH v3 5/5] swupdate: create swu file from wic image Quirin Gylstorff

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.