diff --git a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc index d6ae80adf..748728579 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc @@ -25,6 +25,7 @@ SRC_URI = " \ file://install_linux_fw_sd.txt \ file://install_linux_fw_usb.txt \ ${@oe.utils.conditional('UBOOT_HAS_FASTBOOT', 'true', 'file://install_linux_fw_uuu.sh', '', d)} \ + ${@oe.utils.vartrue('DUALBOOT_ENABLED', 'file://altboot.txt', '', d)} \ " BOOTLOADER_IMAGE_RECIPE ?= "u-boot" @@ -184,6 +185,11 @@ do_deploy:append() { sed -e "${TF_BOOTSCRIPT_SEDFILTER}" ${WORKDIR}/boot.txt > ${TMP_BOOTSCR} mkimage -T script -n bootscript -C none -d ${TMP_BOOTSCR} ${DEPLOYDIR}/boot.scr + # Alternate boot script for dualboot + if [ "${DUALBOOT_ENABLED}" = "true" ]; then + mkimage -T script -n "Alternate bootscript" -C none -d ${WORKDIR}/altboot.txt ${DEPLOYDIR}/altboot.scr + fi + # Sign the scripts if [ "${TRUSTFENCE_SIGN}" = "1" ]; then export CONFIG_SIGN_KEYS_PATH="${TRUSTFENCE_SIGN_KEYS_PATH}" @@ -194,6 +200,13 @@ do_deploy:append() { TMP_SIGNED_BOOTSCR="$(mktemp ${WORKDIR}/bootscr-signed.XXXXXX)" trustfence-sign-artifact.sh -p "${DIGI_FAMILY}" -b "${DEPLOYDIR}/boot.scr" "${TMP_SIGNED_BOOTSCR}" mv "${TMP_SIGNED_BOOTSCR}" "${DEPLOYDIR}/boot.scr" + + if [ "${DUALBOOT_ENABLED}" = "true" ]; then + # Sign boot script + TMP_SIGNED_BOOTSCR="$(mktemp ${WORKDIR}/altboot-signed.XXXXXX)" + trustfence-sign-artifact.sh -p "${DIGI_FAMILY}" -b "${DEPLOYDIR}/altboot.scr" "${TMP_SIGNED_BOOTSCR}" + mv "${TMP_SIGNED_BOOTSCR}" "${DEPLOYDIR}/altboot.scr" + fi fi rm -f ${TMP_BOOTSCR} } diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6/altboot.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6/altboot.txt new file mode 100644 index 000000000..29172875b --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6/altboot.txt @@ -0,0 +1,37 @@ +# +# U-Boot bootscript for altbootcmd (dual boot fallback after retries) +# + +# After an upgrade, active_system has changed. U-Boot tries to boot this system +# for a number of tries. If the limit is reached, altbootcmd is run instead. +# This is the script that it will run. It has to: +# * switch back to previous system +# * reset the firmware update flag +# * run the regular boot command + +if test "${dualboot}" = "yes" && test "${upgrade_available}" = "1"; then + echo "## Update failed; Rolling back to previous version." + if test "${active_system}" = "linux_a"; then + setenv active_system linux_b + part number mmc ${mmcbootdev} linux_b linux_b_index + setexpr mmcpart ${linux_b_index} + # Save the partition index on variable rootfs_b_index + part number mmc ${mmcbootdev} rootfs_b rootfs_b_index + # Save the rootfs_b UUID into mmcroot_b + part uuid mmc ${mmcbootdev}:${rootfs_b_index} mmcroot_b + setenv mmcroot PARTUUID=${mmcroot_b} + else + setenv active_system linux_a + part number mmc ${mmcbootdev} linux_a linux_a_index + setexpr mmcpart ${linux_a_index} + # Save the partition index on variable rootfs_a_index + part number mmc ${mmcbootdev} rootfs_a rootfs_a_index + # Save the rootfs_a UUID into mmcroot_a + part uuid mmc ${mmcbootdev}:${rootfs_a_index} mmcroot_a + setenv mmcroot PARTUUID=${mmcroot_a} + fi + setenv upgrade_available + setenv bootcount 0 + saveenv +fi +run bootcmd diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/altboot.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/altboot.txt new file mode 100644 index 000000000..3d8abc1cb --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/altboot.txt @@ -0,0 +1,29 @@ +# +# U-Boot bootscript for altbootcmd (dual boot fallback after retries) +# + +# After an upgrade, active_system has changed. U-Boot tries to boot this system +# for a number of tries. If the limit is reached, altbootcmd is run instead. +# This is the script that it will run. It has to: +# * switch back to previous system +# * reset the firmware update flag +# * run the regular boot command + +if test "${dualboot}" = "yes" && test "${upgrade_available}" = "1"; then + echo "## Update failed; Rolling back to previous version." + if test "${active_system}" = "linux_a"; then + setenv active_system linux_b + setenv mtdbootpart ${active_system} + setenv mtdrootfspart ${rootfsvol_b} + setenv rootfsvol ${rootfsvol_b} + else + setenv active_system linux_a + setenv mtdbootpart ${active_system} + setenv mtdrootfspart ${rootfsvol_a} + setenv rootfsvol ${rootfsvol_a} + fi + setenv upgrade_available + setenv bootcount 0 + saveenv +fi +run bootcmd diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/altboot.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/altboot.txt new file mode 100644 index 000000000..29172875b --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/altboot.txt @@ -0,0 +1,37 @@ +# +# U-Boot bootscript for altbootcmd (dual boot fallback after retries) +# + +# After an upgrade, active_system has changed. U-Boot tries to boot this system +# for a number of tries. If the limit is reached, altbootcmd is run instead. +# This is the script that it will run. It has to: +# * switch back to previous system +# * reset the firmware update flag +# * run the regular boot command + +if test "${dualboot}" = "yes" && test "${upgrade_available}" = "1"; then + echo "## Update failed; Rolling back to previous version." + if test "${active_system}" = "linux_a"; then + setenv active_system linux_b + part number mmc ${mmcbootdev} linux_b linux_b_index + setexpr mmcpart ${linux_b_index} + # Save the partition index on variable rootfs_b_index + part number mmc ${mmcbootdev} rootfs_b rootfs_b_index + # Save the rootfs_b UUID into mmcroot_b + part uuid mmc ${mmcbootdev}:${rootfs_b_index} mmcroot_b + setenv mmcroot PARTUUID=${mmcroot_b} + else + setenv active_system linux_a + part number mmc ${mmcbootdev} linux_a linux_a_index + setexpr mmcpart ${linux_a_index} + # Save the partition index on variable rootfs_a_index + part number mmc ${mmcbootdev} rootfs_a rootfs_a_index + # Save the rootfs_a UUID into mmcroot_a + part uuid mmc ${mmcbootdev}:${rootfs_a_index} mmcroot_a + setenv mmcroot PARTUUID=${mmcroot_a} + fi + setenv upgrade_available + setenv bootcount 0 + saveenv +fi +run bootcmd diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/altboot.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/altboot.txt new file mode 100644 index 000000000..29172875b --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/altboot.txt @@ -0,0 +1,37 @@ +# +# U-Boot bootscript for altbootcmd (dual boot fallback after retries) +# + +# After an upgrade, active_system has changed. U-Boot tries to boot this system +# for a number of tries. If the limit is reached, altbootcmd is run instead. +# This is the script that it will run. It has to: +# * switch back to previous system +# * reset the firmware update flag +# * run the regular boot command + +if test "${dualboot}" = "yes" && test "${upgrade_available}" = "1"; then + echo "## Update failed; Rolling back to previous version." + if test "${active_system}" = "linux_a"; then + setenv active_system linux_b + part number mmc ${mmcbootdev} linux_b linux_b_index + setexpr mmcpart ${linux_b_index} + # Save the partition index on variable rootfs_b_index + part number mmc ${mmcbootdev} rootfs_b rootfs_b_index + # Save the rootfs_b UUID into mmcroot_b + part uuid mmc ${mmcbootdev}:${rootfs_b_index} mmcroot_b + setenv mmcroot PARTUUID=${mmcroot_b} + else + setenv active_system linux_a + part number mmc ${mmcbootdev} linux_a linux_a_index + setexpr mmcpart ${linux_a_index} + # Save the partition index on variable rootfs_a_index + part number mmc ${mmcbootdev} rootfs_a rootfs_a_index + # Save the rootfs_a UUID into mmcroot_a + part uuid mmc ${mmcbootdev}:${rootfs_a_index} mmcroot_a + setenv mmcroot PARTUUID=${mmcroot_a} + fi + setenv upgrade_available + setenv bootcount 0 + saveenv +fi +run bootcmd diff --git a/meta-digi-dey/classes/dualboot.bbclass b/meta-digi-dey/classes/dualboot.bbclass new file mode 100644 index 000000000..78a3d8421 --- /dev/null +++ b/meta-digi-dey/classes/dualboot.bbclass @@ -0,0 +1,29 @@ +# Adds DualBoot configuration +# +# To use it add the following line to conf/local.conf: +# +# INHERIT += "dualboot" +# + +DUALBOOT_ENABLED ?= "true" + +# U-Boot altboot script +BOOT_SCRIPTS += "altboot.scr:altboot.scr" + +# Dual boot partition names for eMMC or MTD +BOOT_DEV_NAME_A ?= "${@bb.utils.contains('STORAGE_MEDIA', 'mmc', '/dev/mmcblk0p1', 'linux_a', d)}" +BOOT_DEV_NAME_B ?= "${@bb.utils.contains('STORAGE_MEDIA', 'mmc', '/dev/mmcblk0p2', 'linux_b', d)}" +ROOTFS_DEV_NAME_A ?= "${@bb.utils.contains('STORAGE_MEDIA', 'mmc', '/dev/mmcblk0p3', 'rootfs_a', d)}" +ROOTFS_DEV_NAME_B ?= "${@bb.utils.contains('STORAGE_MEDIA', 'mmc', '/dev/mmcblk0p4', 'rootfs_b', d)}" + +fill_description_dualboot () { + sed -i -e "s,##BOOTIMG_NAME##,${IMG_NAME}-${MACHINE}${BOOTFS_EXT},g" "${WORKDIR}/sw-description-dualboot" + sed -i -e "s,##BOOT_DEV_A##,${BOOT_DEV_NAME_A},g" "${WORKDIR}/sw-description-dualboot" + sed -i -e "s,##BOOT_DEV_B##,${BOOT_DEV_NAME_B},g" "${WORKDIR}/sw-description-dualboot" + sed -i -e "s,##ROOTIMG_NAME##,${IMG_NAME}-${MACHINE}${ROOTFS_EXT},g" "${WORKDIR}/sw-description-dualboot" + sed -i -e "s,##ROOTFS_DEV_A##,${ROOTFS_DEV_NAME_A},g" "${WORKDIR}/sw-description-dualboot" + sed -i -e "s,##ROOTFS_DEV_B##,${ROOTFS_DEV_NAME_B},g" "${WORKDIR}/sw-description-dualboot" + sed -i -e "s,##SW_VERSION##,${SOFTWARE_VERSION},g" "${WORKDIR}/sw-description-dualboot" + # Overwrite the sw-description with the dualboot version + mv ${WORKDIR}/sw-description-dualboot ${WORKDIR}/sw-description +} \ No newline at end of file diff --git a/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb b/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb index 462e03795..02d1bebc3 100644 --- a/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb +++ b/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb @@ -36,6 +36,7 @@ RDEPENDS:${PN} = "\ connectcore-demo-example \ cloudconnector \ cryptodev-module \ + ${@oe.utils.vartrue('DUALBOOT_ENABLED', 'dualboot', 'recovery-utils', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'firmwared', '',d)} \ ${@bb.utils.contains("MACHINE_FEATURES", "keyboard", "${VIRTUAL-RUNTIME_keymaps}", "", d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '', bb.utils.contains("MACHINE_FEATURES", "rtc", "${VIRTUAL-RUNTIME_base-utils-hwclock}", "", d), d)} \ @@ -51,7 +52,6 @@ RDEPENDS:${PN} = "\ networkmanager-nmcli \ os-release \ ${@bb.utils.contains('MACHINE_FEATURES', 'pci', 'pciutils', '',d)} \ - recovery-utils \ sysinfo \ ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'system-monitor', '',d)} \ usbutils \ diff --git a/meta-digi-dey/recipes-digi/cloudconnector/cloudconnector/0001-cc.conf-pre-set-for-dual-boot-mode.patch b/meta-digi-dey/recipes-digi/cloudconnector/cloudconnector/0001-cc.conf-pre-set-for-dual-boot-mode.patch new file mode 100644 index 000000000..2150182ca --- /dev/null +++ b/meta-digi-dey/recipes-digi/cloudconnector/cloudconnector/0001-cc.conf-pre-set-for-dual-boot-mode.patch @@ -0,0 +1,48 @@ +From: Hector Palacios +Date: Thu, 8 Jul 2021 09:43:50 +0200 +Subject: [PATCH] cc.conf: pre-set for dual boot mode + +- Change default firmware download path to external media + '/home/root/'. +- Remove '/mnt/update' virtual directory. +- Enable dual boot mode. + +Signed-off-by: Hector Palacios +--- + app/cfg_files/cc.conf | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/app/cfg_files/cc.conf b/app/cfg_files/cc.conf +index 7018efb..bff9332 100644 +--- a/app/cfg_files/cc.conf ++++ b/app/cfg_files/cc.conf +@@ -99,27 +99,22 @@ virtual-dirs + vdir { + name = "tmp" + path = "/tmp" + } + +- vdir { +- name = "update" +- path = "/mnt/update" +- } +- + vdir { + name = "media" + path = "/run/media" + } + } + + # Firmware Download Path: Absolute path to download the firmware packages from + # the cloud. It must be an existing directory. +-firmware_download_path = /mnt/update ++firmware_download_path = /home/root + + # Enable dualboot support +-dualboot = false ++dualboot = true + + # Enables on the fly firmware update support + on_the_fly = false + + #=============================================================================== diff --git a/meta-digi-dey/recipes-digi/cloudconnector/cloudconnector_git.bb b/meta-digi-dey/recipes-digi/cloudconnector/cloudconnector_git.bb index 9c7dadb8a..2614073b5 100644 --- a/meta-digi-dey/recipes-digi/cloudconnector/cloudconnector_git.bb +++ b/meta-digi-dey/recipes-digi/cloudconnector/cloudconnector_git.bb @@ -19,6 +19,7 @@ SRC_URI = " \ ${CC_GIT_URI};branch=${SRCBRANCH} \ file://cloud-connector-init \ file://cloud-connector.service \ + ${@oe.utils.vartrue('DUALBOOT_ENABLED', 'file://0001-cc.conf-pre-set-for-dual-boot-mode.patch', '', d)} \ " S = "${WORKDIR}/git" diff --git a/meta-digi-dey/recipes-digi/dualboot/dualboot.bb b/meta-digi-dey/recipes-digi/dualboot/dualboot.bb new file mode 100644 index 000000000..6afd29dab --- /dev/null +++ b/meta-digi-dey/recipes-digi/dualboot/dualboot.bb @@ -0,0 +1,84 @@ +# Copyright (C) 2021 Digi International Inc. + +SUMMARY = "Digi Embedded Yocto Dual boot support" +SECTION = "base" +LICENSE = "GPL-2.0-only" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6" + + +# When building a TrustFence enabled rootfs, we need the TrustFence PKI tree to +# be already generated in order to copy the public key. Forcing a dependency with +# 'virtual/kernel' ensures that the keys are already generated as they are needed to sign the +# kernel artifacts. +DEPENDS += "${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'virtual/kernel openssl-native', '', d)}" + +SRC_URI = " \ + file://dualboot-init \ + file://firmware-update-dual.sh \ + file://firmware-update-check.service \ + file://on-the-fly-swap-partition.sh \ +" + +S = "${WORKDIR}" + +inherit systemd update-rc.d + +do_install() { + install -d ${D}${sysconfdir}/init.d/ + install -m 0755 ${WORKDIR}/dualboot-init ${D}${sysconfdir}/dualboot-init + ln -sf /etc/dualboot-init ${D}${sysconfdir}/init.d/dualboot-init + + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/firmware-update-dual.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/on-the-fly-swap-partition.sh ${D}${bindir} + + install -d ${D}${systemd_unitdir}/system/ + install -m 0644 ${WORKDIR}/firmware-update-check.service ${D}${systemd_unitdir}/system/ + + # If Trustfence is enabled, copy the public key that is going to be used into the + # initramfs '/etc/ssl/certs' folder in order to verify swupdate packages. + if [ "${TRUSTFENCE_SIGN}" = "1" ]; then + # Retrieve the key index to use. + KEY_INDEX="0" + if [ -n "${TRUSTFENCE_KEY_INDEX}" ]; then + KEY_INDEX="${TRUSTFENCE_KEY_INDEX}" + fi + KEY_INDEX_1=$(expr ${KEY_INDEX} + 1) + + # Find the certificate to use. + if [ "${TRUSTFENCE_SIGN_MODE}" = "HAB" ]; then + CERT_IMG="$(echo ${TRUSTFENCE_SIGN_KEYS_PATH}/crts/IMG${KEY_INDEX_1}*crt.pem)" + elif [ "${TRUSTFENCE_SIGN_MODE}" = "AHAB" ]; then + CERT_IMG="$(echo ${TRUSTFENCE_SIGN_KEYS_PATH}/crts/SRK${KEY_INDEX_1}*_ca_crt.pem)" + else + bberror "Unkown TRUSTFENCE_SIGN_MODE value" + exit 1 + fi + + # Extract the public key from the certificate. + install -d ${D}${sysconfdir}/ssl/certs + openssl x509 -pubkey -noout -in "${CERT_IMG}" > ${D}${sysconfdir}/ssl/certs/key.pub + fi +} + +FILES:${PN} += " \ + ${sysconfdir}/dualboot-init \ + ${sysconfdir}/init.d/dualboot-init \ + ${bindir}/firmware-update-dual.sh \ + ${bindir}/on-the-fly-swap-partition.sh \ + ${systemd_unitdir}/system/firmware-update-check.service \ + ${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', '${sysconfdir}/ssl/certs/key.pub', '', d)} \ +" + +INITSCRIPT_NAME = "dualboot-init" +INITSCRIPT_PARAMS = "start 19 2 3 4 5 . stop 21 0 1 6 ." + +SYSTEMD_SERVICE = "firmware-update-check.service" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +# Add swupdate into the rootfs for dual boot support +RDEPENDS_${PN}-init = " \ + swupdate \ + trustfence-tool \ +" diff --git a/meta-digi-dey/recipes-digi/dualboot/dualboot/dualboot-init b/meta-digi-dey/recipes-digi/dualboot/dualboot/dualboot-init new file mode 100644 index 000000000..d134b01e7 --- /dev/null +++ b/meta-digi-dey/recipes-digi/dualboot/dualboot/dualboot-init @@ -0,0 +1,56 @@ +#!/bin/sh +#=============================================================================== +# +# Copyright (C) 2021 by Digi International Inc. +# 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. +# +# +# !Description: Verifies successful boot +# +#=============================================================================== + +dualboot_init () { + ACTIVE_SYSTEM="$(fw_printenv -n active_system 2>/dev/null)" + if [ -z "${ACTIVE_SYSTEM}" ]; then + if grep -qs environment /proc/mtd; then + MTD_BOOT_PART="$(fw_printenv -n mtdbootpart 2>/dev/null)" + fw_setenv active_system "${MTD_BOOT_PART}" + else + BOOT_PART="$(fw_printenv -n mmcpart 2>/dev/null)" + BOOT_DEV="$(fw_printenv -n mmcbootdev 2>/dev/null)" + CURRENT_PART="$(ls -l /dev/disk/by-partlabel/ | grep -i mmcblk${BOOT_DEV}p${BOOT_PART} | awk '{print $9}')" + fw_setenv active_system "${CURRENT_PART}" + fi + fi + + ISUPGRADING="$(fw_printenv -n upgrade_available 2>/dev/null)" + + if [ "$ISUPGRADING" = "1" ]; then + BOOTCOUNT="$(fw_printenv -n bootcount 2>/dev/null)" + if [ "${BOOTCOUNT}" -lt 3 ]; then + fw_setenv upgrade_available + fw_setenv bootcount 0 + fi + fi +} + +case "$1" in + start) + echo -n "Starting dualboot check: " + dualboot_init + echo "done." + ;; + stop) + ;; + restart) + $0 start + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 + ;; +esac diff --git a/meta-digi-dey/recipes-digi/dualboot/dualboot/firmware-update-check.service b/meta-digi-dey/recipes-digi/dualboot/dualboot/firmware-update-check.service new file mode 100755 index 000000000..d1970780b --- /dev/null +++ b/meta-digi-dey/recipes-digi/dualboot/dualboot/firmware-update-check.service @@ -0,0 +1,12 @@ +[Unit] +Description=Verify if fw update was successful +After=default.target + +[Service] +Type=simple +RemainAfterExit=no +ExecStart=/etc/dualboot-init start +TimeoutStartSec=0 + +[Install] +WantedBy=default.target diff --git a/meta-digi-dey/recipes-digi/dualboot/dualboot/firmware-update-dual.sh b/meta-digi-dey/recipes-digi/dualboot/dualboot/firmware-update-dual.sh new file mode 100755 index 000000000..5ff8e8b51 --- /dev/null +++ b/meta-digi-dey/recipes-digi/dualboot/dualboot/firmware-update-dual.sh @@ -0,0 +1,149 @@ +#!/bin/sh +#=============================================================================== +# +# update-firmware-dual.sh +# +# Copyright (C) 2021 by Digi International Inc. +# 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. +# +# +# !Description: Dual boot firmware update script +# +#=============================================================================== + +SCRIPTNAME="$(basename $(readlink -f ${0}))" +VERBOSE="" +PUBLIC_KEY="/etc/ssl/certs/key.pub" +ACTIVE_SYSTEM="$(fw_printenv -n active_system 2>/dev/null)" + +## Local functions +usage() { + cat <.swu + + -a Show currently active system + -v Enable verbosity + -h Show this help + +EOF +} + +show_active_system() { + if [ "${ACTIVE_SYSTEM}" = "linux_a" ]; then + echo "Active system is A" + else + echo "Active system is B" + fi +} + +while :; do + case $1 in + -a|--active) show_active_system;exit + ;; + -v|--verbose) VERBOSE="-v" + ;; + -h|--help) usage;exit + ;; + *) UPDATE_FILE="${1}" + break + ;; + esac + shift +done + +# Check update file parameter. +if [ -z "${UPDATE_FILE}" ]; then + echo "[ERROR] Update file not specified" + exit +fi + +PARTTABLE="/proc/mtd" +MTDINDEX="$(sed -ne "s/\(^mtd[0-9]\+\):.*\.*/\1/g;T;p" ${PARTTABLE} 2>/dev/null)" + +if [ -z "${MTDINDEX}" ]; then + # Get Boot partition device and index. + BOOT_PART="$(fw_printenv -n mmcpart 2>/dev/null)" + BOOT_DEV="$(fw_printenv -n mmcbootdev 2>/dev/null)" + + # Get current partition information so we can + # determine where to flash the images. + if [ "${ACTIVE_SYSTEM}" = "linux_a" ]; then + echo "Current system is A; Updating system on B" + KERNELBOOT="linux_b" + ROOTFS="rootfs_b" + IMAGE_SET="mmc,secondary" + else + echo "Current system is B; Updating system on A" + KERNELBOOT="linux_a" + ROOTFS="rootfs_a" + IMAGE_SET="mmc,primary" + fi + + # get boot partition index + MMC_PART="$(ls -l /dev/disk/by-partlabel/ | grep -i ${KERNELBOOT} | awk '{print $11}' | sed -e 's/[../mmcblkp]//g' -e 's/^.//')" + + # search rootfs UUID + MMCROOT_PART="$(ls -l /dev/disk/by-partlabel/ | grep -i ${ROOTFS} | awk '{print $11}' | sed -e 's/[../mmcblkp]//g' -e 's/^.//')" + PART_UUID="$(ls -l /dev/disk/by-partuuid/ | grep -i mmcblk${BOOT_DEV}p${MMCROOT_PART} | awk '{print $9}')" + + echo "" + echo "Updating '${IMAGE_SET}' image set from '${UPDATE_FILE}'..." + echo "" + + # Execute the update. + swupdate ${VERBOSE} -i "${UPDATE_FILE}" -e "${IMAGE_SET}" + if [ "$?" = "0" ]; then + fw_setenv mmcroot PARTUUID=${PART_UUID} + fw_setenv mmcpart ${MMC_PART} + fw_setenv active_system ${KERNELBOOT} + fw_setenv bootcount 0 + echo "Firmware update finished; Rebooting system." + reboot -f + else + echo "[ERROR] $? There was an error performing the update" + fi +else + # Get current partition information so we can + # determine where to flash the images. + if [ "${ACTIVE_SYSTEM}" = "linux_a" ]; then + echo "Current system is A; Updating system on B" + KERNELBOOT="linux_b" + ROOTFS="rootfs_b" + IMAGE_SET="mtd,secondary" + else + echo "Current system is B; Updating system on A" + KERNELBOOT="linux_a" + ROOTFS="rootfs_a" + IMAGE_SET="mtd,primary" + fi + + echo "" + echo "Updating '${IMAGE_SET}' image set from '${UPDATE_FILE}'..." + echo "" + + # Umount the partition before the update. + umount /mnt/${KERNELBOOT} + + # Execute the update. + if [ -f "${PUBLIC_KEY}" ]; then + swupdate ${VERBOSE} -i "${UPDATE_FILE}" -e "${IMAGE_SET}" -k "${PUBLIC_KEY}" + else + swupdate ${VERBOSE} -i "${UPDATE_FILE}" -e "${IMAGE_SET}" + fi + if [ "$?" = "0" ]; then + fw_setenv mtdbootpart ${KERNELBOOT} + fw_setenv mtdrootfspart ${ROOTFS} + fw_setenv rootfsvol ${ROOTFS} + fw_setenv active_system ${KERNELBOOT} + fw_setenv bootcount 0 + echo "Firmware update finished; Rebooting system." + reboot -f + else + echo "[ERROR] $? There was an error performing the update" + fi +fi diff --git a/meta-digi-dey/recipes-digi/dualboot/dualboot/on-the-fly-swap-partition.sh b/meta-digi-dey/recipes-digi/dualboot/dualboot/on-the-fly-swap-partition.sh new file mode 100644 index 000000000..83d1f586a --- /dev/null +++ b/meta-digi-dey/recipes-digi/dualboot/dualboot/on-the-fly-swap-partition.sh @@ -0,0 +1,48 @@ +#!/bin/sh +#=============================================================================== +# +# on-the-fly-swap-partition.sh +# +# Copyright (C) 2021-2022 by Digi International Inc. +# 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. +# +# +# !Description: On the fly script to swap active partition +# +#=============================================================================== + +ACTIVE_SYSTEM="$(fw_printenv -n active_system 2>/dev/null)" + +# Get current partition information so we can +# determine where to flash the images. +if [ "${ACTIVE_SYSTEM}" = "linux_a" ]; then + KERNELBOOT="linux_b" + ROOTFS="rootfs_b" +else + KERNELBOOT="linux_a" + ROOTFS="rootfs_a" +fi +if grep -qs environment /proc/mtd; then + fw_setenv mtdbootpart ${KERNELBOOT} + fw_setenv mtdrootfspart ${ROOTFS} + fw_setenv rootfsvol ${ROOTFS} + fw_setenv active_system ${KERNELBOOT} +else + # Get Boot partition device and index. + BOOT_DEV="$(fw_printenv -n mmcbootdev 2>/dev/null)" + + # get boot partition index + MMC_PART="$(ls -l /dev/disk/by-partlabel/ | grep -i ${KERNELBOOT} | awk '{print $11}' | sed -e 's/[../mmcblkp]//g' -e 's/^.//')" + + # search rootfs UUID + MMCROOT_PART="$(ls -l /dev/disk/by-partlabel/ | grep -i ${ROOTFS} | awk '{print $11}' | sed -e 's/[../mmcblkp]//g' -e 's/^.//')" + PART_UUID="$(ls -l /dev/disk/by-partuuid/ | grep -i mmcblk${BOOT_DEV}p${MMCROOT_PART} | awk '{print $9}')" + + fw_setenv mmcroot PARTUUID=${PART_UUID} + fw_setenv mmcpart ${MMC_PART} + fw_setenv active_system ${KERNELBOOT} +fi diff --git a/meta-digi-dey/recipes-digi/swu-images/files/sw-description-dualboot b/meta-digi-dey/recipes-digi/swu-images/files/sw-description-dualboot new file mode 100644 index 000000000..4822d93b9 --- /dev/null +++ b/meta-digi-dey/recipes-digi/swu-images/files/sw-description-dualboot @@ -0,0 +1,107 @@ +software = +{ + version = "##SW_VERSION##"; + + mmc = { + primary: { + images: ( + { + filename = "##BOOTIMG_NAME##"; + device = "##BOOT_DEV_A##"; + type = "raw"; + sha256 = "@##BOOTIMG_NAME##"; + installed-directly = true; + }, + { + filename = "##ROOTIMG_NAME##"; + device = "##ROOTFS_DEV_A##"; + type = "raw"; + sha256 = "@##ROOTIMG_NAME##"; + compressed = "zlib"; + installed-directly = true; + } + ); + uboot: ( + { + name = "upgrade_available"; + value = "1"; + } + ); + } + secondary: { + images: ( + { + filename = "##BOOTIMG_NAME##"; + device = "##BOOT_DEV_B##"; + type = "raw"; + sha256 = "@##BOOTIMG_NAME##"; + installed-directly = true; + }, + { + filename = "##ROOTIMG_NAME##"; + device = "##ROOTFS_DEV_B##"; + type = "raw"; + sha256 = "@##ROOTIMG_NAME##"; + compressed = "zlib"; + installed-directly = true; + } + ); + uboot: ( + { + name = "upgrade_available"; + value = "1"; + } + ); + } + }; + mtd = { + primary: { + images: ( + { + filename = "##BOOTIMG_NAME##"; + volume = "##BOOT_DEV_A##"; + type = "ubivol"; + sha256 = "@##BOOTIMG_NAME##"; + installed-directly = true; + }, + { + filename = "##ROOTIMG_NAME##"; + volume = "##ROOTFS_DEV_A##"; + type = "ubivol"; + sha256 = "@##ROOTIMG_NAME##"; + installed-directly = true; + } + ); + uboot: ( + { + name = "upgrade_available"; + value = "1"; + } + ); + } + secondary: { + images: ( + { + filename = "##BOOTIMG_NAME##"; + volume = "##BOOT_DEV_B##"; + type = "ubivol"; + sha256 = "@##BOOTIMG_NAME##"; + installed-directly = true; + }, + { + filename = "##ROOTIMG_NAME##"; + volume = "##ROOTFS_DEV_B##"; + type = "ubivol"; + sha256 = "@##ROOTIMG_NAME##"; + installed-directly = true; + } + ); + uboot: ( + { + name = "upgrade_available"; + value = "1"; + } + ); + } + }; +} diff --git a/meta-digi-dey/recipes-digi/swu-images/swu.inc b/meta-digi-dey/recipes-digi/swu-images/swu.inc index ffd4afe77..2ca61daf1 100644 --- a/meta-digi-dey/recipes-digi/swu-images/swu.inc +++ b/meta-digi-dey/recipes-digi/swu-images/swu.inc @@ -10,7 +10,9 @@ SRC_URI = " \ file://sw-description-uboot \ file://swupdate_uboot_nand.sh \ file://swupdate_uboot_mmc.sh \ + ${@oe.utils.vartrue('DUALBOOT_ENABLED', 'file://sw-description-dualboot', '', d)} \ " + inherit swupdate IMAGE_DEPENDS = "${@get_baseimg_pn(d)}" @@ -50,7 +52,8 @@ def get_baseimg_pn(d): file_name = d.getVar('PN', True) return file_name[:file_name.find("-swu")] -do_unpack[postfuncs] += "fill_description" +# Call regular substitution or dualboot substitution +do_unpack[postfuncs] += "${@oe.utils.vartrue('DUALBOOT_ENABLED', 'fill_description_dualboot', 'fill_description', d)}" fill_description() { if [ "${SWUPDATE_UBOOTIMG}" = "true" ]; then