diff --git a/.gitmodules b/.gitmodules index adb667a..e531f44 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,3 +18,7 @@ path = layers/meta-efibootguard url = ssh://git@bitbucket.gad.local:7999/ico/meta-efibootguard.git branch = coreos/master +[submodule "layers/meta-swupdate"] + path = layers/meta-swupdate + url = ssh://git@bitbucket.gad.local:7999/ico/meta-swupdate.git + branch = kirkstone diff --git a/layers/meta-belden-coreos/classes/coreos-image-swupdate.bbclass b/layers/meta-belden-coreos/classes/coreos-image-swupdate.bbclass new file mode 100644 index 0000000..901a4c1 --- /dev/null +++ b/layers/meta-belden-coreos/classes/coreos-image-swupdate.bbclass @@ -0,0 +1,34 @@ +# This class generate the swu file needed by swupdate +# This should not be used directly but via coreos-image.bbclass + +# This is made to work with our default boot flow, so it depends on the output +# of coreos-image-uki.bbclass. Other boot flow are not supported by CoreOS. + +# Swupdate image generation +# ============================================================================== + +# Machine using MBR override this value, see legacy-mbr-disk.inc +COREOS_DISK_PARTLABEL_LOOKUP_DIRECTORY ??= "/dev/disk/by-partlabel" + +IMAGE_FSTYPES:append = " ext4.zst" +python () { + image = d.getVar('IMAGE_BASENAME') + d.setVarFlag("SWUPDATE_IMAGES_FSTYPES", image, ".ext4.zst") +} + +inherit swupdate-image + +# Ensure than variable used in the sw-description files are watched for change +do_swuimage[vardeps] += "COREOS_KERNEL0_FILENAME COREOS_KERNEL1_FILENAME EFIBOOTGUARD_TIMEOUT COREOS_DISK_PARTLABEL_LOOKUP_DIRECTORY" +do_swuimage[deptask] += "do_bundle_uki" +SWUPDATE_IMAGES += "${COREOS_KERNEL0_NAME} ${COREOS_KERNEL1_NAME}" + +python () { + kernel0 = d.getVar('COREOS_KERNEL0_NAME') + kernel1 = d.getVar('COREOS_KERNEL1_NAME') + kernelext = d.getVar('COREOS_KERNEL_EXT') + d.setVarFlag("SWUPDATE_IMAGES_FSTYPES", kernel0, kernelext) + d.setVarFlag("SWUPDATE_IMAGES_FSTYPES", kernel1, kernelext) +} + +FILESEXTRAPATHS:append := ":${COREOS_ROOT}/layers/meta-belden-coreos/files" diff --git a/layers/meta-belden-coreos/classes/coreos-image.bbclass b/layers/meta-belden-coreos/classes/coreos-image.bbclass index fb7e07a..024c3fc 100644 --- a/layers/meta-belden-coreos/classes/coreos-image.bbclass +++ b/layers/meta-belden-coreos/classes/coreos-image.bbclass @@ -14,6 +14,8 @@ FEATURE_PACKAGES_networkmanager = "networkmanager networkmanager-nmcli" FEATURE_PACKAGES_networkmanager-dev-tools = "networkmanager-nmtui" FEATURE_PACKAGES_networkmanager-cockpit = "cockpit-networkmanager" +FEATURE_PACKAGES_swupdate = "swupdate swupdate-client swupdate-lua" + # The cockpit feature automatically install the corresponding # *-cockpit FEATURES_PACKAGES for any image features FEATURE_PACKAGES_cockpit = "packagegroup-coreos-cockpit ${@get_feature_packages_with_suffix('cockpit', d)}" @@ -90,8 +92,10 @@ IMAGE_ROOTFS_EXTRA_SPACE:append = " ${@bb.utils.contains('DISTRO_FEATURES', 'sys # ============================================================================== COREOS_IMAGE_GENERATE_UKI ??= "${@bb.utils.contains('COMBINED_FEATURES', 'efi', '1', '0', d)}" +COREOS_IMAGE_GENERATE_SWU ??= "${@bb.utils.contains('IMAGE_FEATURES', 'swupdate', '1', '0', d)}" # Support for Unified Kernel Image and Swupdate are optional COREOS_IMAGE_EXTRACLASSES ??= "" COREOS_IMAGE_EXTRACLASSES:append = "${@' coreos-image-uki' if d.getVar('COREOS_IMAGE_GENERATE_UKI') == '1' else ''}" +COREOS_IMAGE_EXTRACLASSES:append = "${@' coreos-image-swupdate' if d.getVar('COREOS_IMAGE_GENERATE_SWU') == '1' else ''}" inherit ${COREOS_IMAGE_EXTRACLASSES} diff --git a/layers/meta-belden-coreos/files/sw-description b/layers/meta-belden-coreos/files/sw-description new file mode 100644 index 0000000..7ad1225 --- /dev/null +++ b/layers/meta-belden-coreos/files/sw-description @@ -0,0 +1,89 @@ +software = +{ + version = "@@DISTRO_VERSION@@"; + @@MACHINE@@ = { + hardware-compatibility: ["1.0"]; + stable = { + copy0 = { + images: ( + { + filename = "@@PN@@-@@MACHINE@@.ext4.zst"; + compressed = "zstd"; + installed-directly = true; + # partlabel are stored inside the GPT partition table. + # The partition table is flashed only once and never updated + device = "@@COREOS_DISK_PARTLABEL_LOOKUP_DIRECTORY@@/platform0"; + type = "raw"; + sha256 = "$swupdate_get_sha256(@@PN@@-@@MACHINE@@.ext4.zst)"; + } + ); + + files: ( + { + filename = "@@COREOS_KERNEL0_FILENAME@@"; + path = "/KERNEL.EFI"; + device = "@@COREOS_DISK_PARTLABEL_LOOKUP_DIRECTORY@@/boot0"; + filesystem = "vfat"; + sha256 = "$swupdate_get_sha256(@@COREOS_KERNEL0_FILENAME@@)"; + } + ); + + bootenv: ( + { + name = "kernelparams"; + value = "root=PARTLABEL=platform0 @@WKS_KERNEL_ARGS@@"; + }, + { + name = "watchdog_timeout_sec"; + value = "@@EFIBOOTGUARD_TIMEOUT@@"; + }, + { + name = "kernelfile"; + value = "C:BOOT0:KERNEL.EFI"; + + } + ); + } + + copy1 = { + images: ( + { + filename = "@@PN@@-@@MACHINE@@.ext4.zst"; + compressed = "zstd"; + installed-directly = true; + # partlabel are stored inside the GPT partition table. + # The partition table is flashed only once and never updated + device = "@@COREOS_DISK_PARTLABEL_LOOKUP_DIRECTORY@@/platform1"; + type = "raw"; + sha256 = "$swupdate_get_sha256(@@PN@@-@@MACHINE@@.ext4.zst)"; + } + ); + + files: ( + { + filename = "@@COREOS_KERNEL1_FILENAME@@"; + path = "/KERNEL.EFI"; + device = "@@COREOS_DISK_PARTLABEL_LOOKUP_DIRECTORY@@/boot1"; + filesystem = "vfat"; + sha256 = "$swupdate_get_sha256(@@COREOS_KERNEL1_FILENAME@@)"; + } + ); + bootenv: ( + { + name = "kernelparams"; + value = "root=PARTLABEL=platform1 @@WKS_KERNEL_ARGS@@"; + }, + { + name = "watchdog_timeout_sec"; + value = "@@EFIBOOTGUARD_TIMEOUT@@"; + }, + { + name = "kernelfile"; + value = "C:BOOT1:KERNEL.EFI"; + + } + ); + } + } + } +} diff --git a/layers/meta-belden-coreos/recipes-core/images/coreos-image-full-cmdline.bb b/layers/meta-belden-coreos/recipes-core/images/coreos-image-full-cmdline.bb index c2e9e63..21f6690 100644 --- a/layers/meta-belden-coreos/recipes-core/images/coreos-image-full-cmdline.bb +++ b/layers/meta-belden-coreos/recipes-core/images/coreos-image-full-cmdline.bb @@ -3,5 +3,5 @@ functionality installed." inherit coreos-image -IMAGE_FEATURES += "ssh-server podman dev-tools cockpit networkmanager" -IMAGE_INSTALL:append = " packagegroup-core-full-cmdline" +IMAGE_FEATURES += "ssh-server podman dev-tools cockpit networkmanager swupdate" +IMAGE_INSTALL:append = " packagegroup-core-full-cmdline swupdate-www" diff --git a/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/defconfig b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/defconfig new file mode 100644 index 0000000..e8c5086 --- /dev/null +++ b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/defconfig @@ -0,0 +1,22 @@ +CONFIG_HW_COMPATIBILITY=y +CONFIG_HW_COMPATIBILITY_FILE="/etc/hwrevision" +CONFIG_SW_VERSIONS_FILE="/etc/sw-versions" +# CONFIG_MTD is not set +# CONFIG_BOOTLOADER_NONE is not set +CONFIG_ARCHIVE=y +CONFIG_ZSTD=y +CONFIG_BOOTLOADER_EBG=y +BOOTLOADER_DEFAULT_EBG=y +CONFIG_BOOTLOADERHANDLER=y +CONFIG_HASH_VERIFY=y +CONFIG_WEBSERVER=y +CONFIG_MONGOOSESSL=y +CONFIG_SSL_IMPL_OPENSSL=y +CONFIG_LUA=y +CONFIG_LUASCRIPTHANDLER=y +CONFIG_RAW=y +CONFIG_SHELLSCRIPTHANDLER=y +CONFIG_SYSTEMD=y +CONFIG_UPDATE_STATE_CHOICE_BOOTLOADER=y +CONFIG_UPDATE_STATE_BOOTLOADER="ustate" +CONFIG_LIBCONFIG=y diff --git a/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/sw-collections-config.sh b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/sw-collections-config.sh new file mode 100644 index 0000000..1238e9b --- /dev/null +++ b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/sw-collections-config.sh @@ -0,0 +1,39 @@ +# Get the root partition device +# ============================================================================== + +ROOT_PART=$(swupdate -g) +echo "Root partition is ${ROOT_PART}" + +# Get the partition label of the root partition +# ============================================================================== + +DISK_DEVICE_NAME=$(lsblk -ndo pkname "${ROOT_PART}") +DISK_PARTITION_TYPE=$(lsblk -dno PTTYPE "/dev/${DISK_DEVICE_NAME}") + +echo "Root partition is on device ${DISK_DEVICE_NAME} - type ${DISK_PARTITION_TYPE}" + +# Use partlabel for GPT disk, as it's more reliable than the filesystem label +# Fallback to label for legacy DOS/MBR disk +if [ "${DISK_PARTITION_TYPE}" == "gpt" ]; then + ROOT_PARTLABEL=$(lsblk -dno PARTLABEL "${ROOT_PART}") +else + echo "Using MBR disk is less reliable than GPT disk!" + ROOT_PARTLABEL=$(lsblk -dno LABEL "${ROOT_PART}") +fi + +echo "Root partition label is ${ROOT_PARTLABEL}" + +case $ROOT_PARTLABEL in + platform0 ) + echo "We are running copy0 -> Use copy1 in the SWU file" + SWUPDATE_ARGS="${SWUPDATE_ARGS} -e stable,copy1" + ;; + platform1 ) + echo "We are running copy1 -> Use copy0 in the SWU file" + SWUPDATE_ARGS="${SWUPDATE_ARGS} -e stable,copy0" + ;; + * ) + >&2 echo "Root partition label ${ROOT_PARTLABEL} is invalid" + exit 1 + ;; +esac diff --git a/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/webserver-config.sh b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/webserver-config.sh new file mode 100644 index 0000000..795f1cf --- /dev/null +++ b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate/webserver-config.sh @@ -0,0 +1 @@ +SWUPDATE_WEBSERVER_ARGS="-r /usr/share/swupdate-www -p 8080" diff --git a/layers/meta-belden-coreos/recipes-support/swupdate/swupdate_%.bbappend b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate_%.bbappend new file mode 100644 index 0000000..f962dac --- /dev/null +++ b/layers/meta-belden-coreos/recipes-support/swupdate/swupdate_%.bbappend @@ -0,0 +1,28 @@ +# File in the swupdate subdirectory of this recipe should overwrite the +# same file in meta-swupdate +FILESEXTRAPATHS:prepend := "${THISDIR}/swupdate:" +RDEPENDS:${PN}:append = " efibootguard" + +SRC_URI += " \ + file://webserver-config.sh \ + file://sw-collections-config.sh \ +" +wwwdir = "/usr/share/swupdate-www" + +FILES:${PN} += " \ + ${SWUPDATE_SW_VERSIONS_FILE} \ + ${SWUPDATE_HW_COMPATIBILITY_FILE} \ +" + +FILES:${PN}-www += " \ + ${libdir}/swupdate/conf.d/webserver-config.sh \ + ${libdir}/swupdate/conf.d/sw-collections-config.sh \ +" + +do_install:append() { + # Probably replace revision with the value of the device tree + install -m 755 ${WORKDIR}/webserver-config.sh ${D}${libdir}/swupdate/conf.d/ + + install -m 755 ${WORKDIR}/sw-collections-config.sh ${D}${libdir}/swupdate/conf.d/ + echo "${MACHINE} 1.0" > ${D}${SWUPDATE_HW_COMPATIBILITY_FILE} +} \ No newline at end of file diff --git a/layers/meta-swupdate b/layers/meta-swupdate new file mode 160000 index 0000000..f27a63f --- /dev/null +++ b/layers/meta-swupdate @@ -0,0 +1 @@ +Subproject commit f27a63f42d124676a07401462b1c4a64f38b768b diff --git a/templates/bblayers.conf.sample b/templates/bblayers.conf.sample index b937f91..ccc0dc2 100644 --- a/templates/bblayers.conf.sample +++ b/templates/bblayers.conf.sample @@ -17,4 +17,6 @@ BBLAYERS ?= " \ ##COREOS_LAYERSDIR##/meta-openembedded/meta-python \ ##COREOS_LAYERSDIR##/meta-openembedded/meta-webserver \ ##COREOS_LAYERSDIR##/meta-virtualization \ + ##COREOS_LAYERSDIR##/meta-efibootguard \ + ##COREOS_LAYERSDIR##/meta-swupdate \ "