diff mbox series

[meta-oe,v1,2/3] classes: add discoverable disk image class

Message ID 20250531110022.3843938-3-johannes.schneider@leica-geosystems.com
State Under Review
Headers show
Series add support for building "system extension images" | expand

Commit Message

SCHNEIDER Johannes May 31, 2025, 11 a.m. UTC
Add a class to build discoverable disk images [1] through
systemd-repart(-native).

Note that systemd >= 256 is required for '--private-key-source'

The class was adapted from a patch [2] floating upstream.

Link: [1]: https://uapi-group.org/specifications/specs/discoverable_disk_image/
Link: [2]: https://lists.openembedded.org/g/openembedded-core/message/198724
Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 .../classes/discoverable-disk-image.bbclass   | 132 ++++++++++++++++++
 1 file changed, 132 insertions(+)
 create mode 100644 meta-oe/classes/discoverable-disk-image.bbclass
diff mbox series

Patch

diff --git a/meta-oe/classes/discoverable-disk-image.bbclass b/meta-oe/classes/discoverable-disk-image.bbclass
new file mode 100644
index 0000000000..e601bf452f
--- /dev/null
+++ b/meta-oe/classes/discoverable-disk-image.bbclass
@@ -0,0 +1,132 @@ 
+##
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+#
+# Discoverable Disk Image (DDI)
+#
+# "DDIs (Discoverable Disk Images) are self-describing file system
+# images that follow the DPS ( Discoverable Partitions Specification),
+# wrapped in a GPT partition table, that may contain root (or /usr/)
+# filesystems for bootable OS images, system extensions, configuration
+# extensions, portable services, containers and more, and shall be
+# protected by signed dm-verity all combined into one. They are
+# designed to be composable and stackable, and provide security by
+# default."
+# https://uapi-group.org/specifications/specs/discoverable_disk_image/
+# https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.image-policy.html
+
+# To be able to use discoverable-disk-images with a
+# root-verity-sig or usr-verity-sig configuration:
+# - systemd needs to include the PACKAGECONFIG 'cryptsetup', and
+# - the kernel needs the following features enabled:
+#   CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
+#   CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING=y
+#   CONFIG_EROFS_FS=y
+#   CONFIG_EROFS_FS_XATTR=y
+#   CONFIG_EROFS_FS_ZIP=y
+#   CONFIG_EROFS_FS_ZIP_LZMA=y
+#   CONFIG_INTEGRITY_SIGNATURE=y
+#   CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+#   CONFIG_INTEGRITY_PLATFORM_KEYRING=y
+#   CONFIG_SYSTEM_BLACKLIST_KEYRING=y
+#   CONFIG_SYSTEM_BLACKLIST_HASH_LIST=""
+#   CONFIG_SIGNATURE=y
+
+# To sign DDIs, a key and certificate need to be provided by setting
+# the variables:
+#   REPART_PRIVATE_KEY
+#     private key so sign the verity-hash
+#   REPART_PRIVATE_KEY_SOURCE
+#     optional, can be "engine:pkcs11" when using a (soft)hsm
+#   REPART_CERTIFICATE
+#     corresponding public certificate, in .pem format
+#
+
+# For signature verification, systemd-sysext expects the matching
+# certificate to reside in /etc/verity.d as PEM formated .crt file.
+#
+# To enforce loading of only signed extension images, an appropriate
+# image policy has to be passed to systemd-sysext, e.g.:
+# systemd-sysext --image-policy='root=signed+absent:usr=signed+absent:=unused+absent' merge
+
+# 'systemd-dissect' can be used to inspect, manually mount, ... a DDI.
+
+inherit image
+
+IMAGE_FSTYPES = "ddi"
+
+DEPENDS += " \
+    systemd-repart-native \
+    erofs-utils-native \
+    openssl-native \
+"
+
+# systemd-repart --make-ddi takes one of "sysext", "confext" or "portable",
+# which it then takes and looks up definitions in the host os; which we need
+# to divert to the sysroot-native by setting '--definitions=' instead.
+#
+REPART_DDI_TYPE ?= "sysext"
+
+REPART_DDI_EXTENSION ?= "ddi"
+
+# systemd-repart creates temporary directoryies under /var/tmp/.#repartXXXXXXX/,
+# to estimate partition size etc. Since files are copied there from the image/rootfs
+# folder - which are owned by pseudo-root - this temporary location has to be
+# added to the directories handled by pseudo; otherwise calls to e.g.
+# fchown(0,0) inside systemd git/src/shared/copy.c end up failing.
+PSEUDO_INCLUDE_PATHS .= ",/var/tmp/"
+
+oe_image_systemd_repart_make_ddi() {
+
+    local additional_args=""
+
+    if [ -n "${REPART_PRIVATE_KEY}" ]
+    then
+        if [ -n "${REPART_PRIVATE_KEY_SOURCE}" ]
+        then
+            additional_args="$additional_args --private-key-source=${REPART_PRIVATE_KEY_SOURCE}"
+        fi
+        additional_args="$additional_args --private-key=${REPART_PRIVATE_KEY}"
+    fi
+
+    if [ -n "${REPART_CERTIFICATE}" ]
+    then
+        additional_args="$additional_args --certificate=${REPART_CERTIFICATE}"
+    fi
+
+    # map architectures to systemd's expected values
+    local systemd_arch="${TARGET_ARCH}"
+    case "${systemd_arch}" in
+        aarch64)
+        systemd_arch=arm64
+        ;;
+        x86_64)
+        systemd_arch=x86-64
+        ;;
+    esac
+
+    # prepare system-repart configuration
+    mkdir -p ${B}/definitions.repart.d
+    cp ${STAGING_LIBDIR_NATIVE}/systemd/repart/definitions/${REPART_DDI_TYPE}.repart.d/* ${B}/definitions.repart.d/
+    # enable erofs compression
+    sed -i "/^Compression/d" ${B}/definitions.repart.d/10-root.conf
+    echo "Compression=lzma\nCompressionLevel=3" >> ${B}/definitions.repart.d/10-root.conf
+    # disable verity signature partition creation, if no key is provided
+    if [ -z "${REPART_PRIVATE_KEY}" ]; then
+        rm ${B}/definitions.repart.d/30-root-verity-sig.conf
+    fi
+
+    systemd-repart \
+        --definitions="${B}/definitions.repart.d/" \
+        --copy-source="${IMAGE_ROOTFS}" \
+        --empty=create --size=auto --dry-run=no --offline=yes \
+        --architecture="${systemd_arch}" \
+        --json=pretty --no-pager $additional_args \
+        "${IMGDEPLOYDIR}/${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${REPART_DDI_EXTENSION}"
+}
+
+IMAGE_CMD:ddi = "oe_image_systemd_repart_make_ddi"
+do_image_ddi[deptask] += "do_unpack"