diff --git a/layers/meta-balena-raspberrypi/recipes-core/images/balena-image-bootloader-initramfs.bbappend b/layers/meta-balena-raspberrypi/recipes-core/images/balena-image-bootloader-initramfs.bbappend new file mode 100644 index 000000000..11cd5548b --- /dev/null +++ b/layers/meta-balena-raspberrypi/recipes-core/images/balena-image-bootloader-initramfs.bbappend @@ -0,0 +1 @@ +PACKAGE_INSTALL:append:raspberrypi4-64 = " initramfs-module-kexec-pi4-fwgpio" diff --git a/layers/meta-balena-raspberrypi/recipes-core/images/balena-image-initramfs.bbappend b/layers/meta-balena-raspberrypi/recipes-core/images/balena-image-initramfs.bbappend index fa281e31d..40f5e5831 100644 --- a/layers/meta-balena-raspberrypi/recipes-core/images/balena-image-initramfs.bbappend +++ b/layers/meta-balena-raspberrypi/recipes-core/images/balena-image-initramfs.bbappend @@ -1,2 +1,4 @@ PACKAGE_INSTALL:remove:revpi = "initramfs-module-migrate" + +PACKAGE_INSTALL:append:raspberrypicm4-ioboard-sb = " initramfs-module-kexec-pi4-fwgpio" IMAGE_ROOTFS_MAXSIZE:raspberrypicm4-ioboard-sb = "51200" diff --git a/layers/meta-balena-raspberrypi/recipes-core/initrdscripts/files/kexec_pi4_fwgpio b/layers/meta-balena-raspberrypi/recipes-core/initrdscripts/files/kexec_pi4_fwgpio new file mode 100644 index 000000000..09ba86873 --- /dev/null +++ b/layers/meta-balena-raspberrypi/recipes-core/initrdscripts/files/kexec_pi4_fwgpio @@ -0,0 +1,68 @@ +#!/bin/sh + +# shellcheck disable=SC1091 +. /usr/libexec/os-helpers-logging + +kexec_pi4_fwgpio_enabled() { + if [ "$bootparam_balena_stage2" = "true" ]; then + return 0 + fi + + if [ -n "$bootparam_balena_pi4_fwgpio" ]; then + return 0 + fi + + return 1 +} + +kexec_pi4_fwgpio_run() { + # Find the wifi/bt device labelled "mmcnr" in the device tree + WIFI_DT_NODE="mmcnr" + WIFI_SYSFS_PATH="$(find /sys/bus/platform/devices -name "*.${WIFI_DT_NODE}")" + + # Exactly one device should match, but let's be defensive + if [ "$(echo "${WIFI_SYSFS_PATH}" | wc -l)" -gt 1 ]; then + warn "Multiple '${WIFI_DT_NODE}' devices found, will use the first one" + WIFI_SYSFS_PATH="$(echo "${WIFI_SYSFS_PATH}" | head -n 1)" + fi + + # readlink here, because the driver unbinds as we manipulate the GPIOs + WIFI_DRIVER_DIR="$(readlink -f "${WIFI_SYSFS_PATH}/driver")" + WIFI_DEV="$(basename "${WIFI_SYSFS_PATH}")" + + GPIO_SYSFS_DIR="/sys/class/gpio" + + FW_GPIO_BASE="504" + BT_ON="0" + WL_ON="1" + + NEED_RESET="0" + CURRENT_STATE="0" + for PIN in "${BT_ON}" "${WL_ON}"; do + GPIO=$["${FW_GPIO_BASE}" + "${PIN}"] + echo "${GPIO}" > "${GPIO_SYSFS_DIR}/export" + PIN_VALUE="$(cat "${GPIO_SYSFS_DIR}/gpio${GPIO}/value")" + + if [ "$bootparam_balena_stage2" = "true" ]; then + CURRENT_STATE=$["${CURRENT_STATE}" | ("${PIN_VALUE}" << "${PIN}")] + elif [ -n "$bootparam_balena_pi4_fwgpio" ]; then + NEW_VALUE=$[("$bootparam_balena_pi4_fwgpio" >> "${PIN}") & 1] + echo "${NEW_VALUE}" > "${GPIO_SYSFS_DIR}/gpio${GPIO}/value" + + if [ "${PIN_VALUE}" != "${NEW_VALUE}" ]; then + NEED_RESET="1" + fi + fi + + echo "${GPIO}" > "${GPIO_SYSFS_DIR}/unexport" + done + + if [ "${NEED_RESET}" = "1" ]; then + echo -n "${WIFI_DEV}" > "${WIFI_DRIVER_DIR}/unbind" + echo -n "${WIFI_DEV}" > "${WIFI_DRIVER_DIR}/bind" + fi + + if [ "$bootparam_balena_stage2" = "true" ]; then + export KEXEC_EXTRA_ARGS="${KEXEC_EXTRA_ARGS} balena_pi4_fwgpio=${CURRENT_STATE}" + fi +} diff --git a/layers/meta-balena-raspberrypi/recipes-core/initrdscripts/initramfs-framework_%.bbappend b/layers/meta-balena-raspberrypi/recipes-core/initrdscripts/initramfs-framework_%.bbappend index e0ab5d99d..02182b112 100644 --- a/layers/meta-balena-raspberrypi/recipes-core/initrdscripts/initramfs-framework_%.bbappend +++ b/layers/meta-balena-raspberrypi/recipes-core/initrdscripts/initramfs-framework_%.bbappend @@ -2,8 +2,14 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI:append = " \ file://cryptsetup-rpi \ + file://kexec_pi4_fwgpio \ " +PACKAGES:append = " initramfs-module-kexec-pi4-fwgpio" +SUMMARY:initramfs-module-kexec-pi4-fwgpio = "Hook necessary to persist the value of Pi4/CM4 firmware GPIOs after kexec" +RDEPENDS:initramfs-module-kexec-pi4-fwgpio = "initramfs-module-kexec" +FILES:initramfs-module-kexec-pi4-fwgpio = "/init.d/73-kexec_pi4_fwgpio" + PACKAGES:remove:revpi = "initramfs-module-migrate" do_install:append:revpi() { rm -f ${D}/init.d/92-migrate @@ -11,8 +17,11 @@ do_install:append:revpi() { do_install:append() { install -d ${D}/init.d + install -m 0755 ${WORKDIR}/cryptsetup-rpi ${D}/init.d/72-cryptsetup sed -i -e "s/@@BALENA_NONENC_BOOT_LABEL@@/${BALENA_NONENC_BOOT_LABEL}/g" ${D}/init.d/72-cryptsetup + + install -m 0755 ${WORKDIR}/kexec_pi4_fwgpio ${D}/init.d/73-kexec_pi4_fwgpio } RDEPENDS:initramfs-module-cryptsetup:append = " os-helpers-otp gnupg"