Is there some odd initramfs limitation that requires explicitly
calling out /usr/bin/busybox throughout the whole script?

Surely echo atleast can be relied on to be built into the shell or PATH.


On Mon, Mar 2, 2026 at 12:07 PM Shiva Tripathi via
lists.yoctoproject.org <[email protected]>
wrote:
>
> Add ti-encrypted-boot-initramfs for LUKS encryption with TPM-sealed
> keys. This provides full disk encryption using dm-crypt with keys
> sealed by firmware TPM (fTPM) running in OP-TEE and stored in eMMC RPMB.
>
> The initramfs includes:
> - Custom init script for in-place LUKS encryption on first boot
> - TPM key sealing/unsealing using persistent handle 0x81080001
> - Support for cryptsetup, tpm2-tools, and OP-TEE client
> - Automatic filesystem resize after encryption
>
> ti-encrypted-boot-initramfs builds when MACHINE_FEATURES contains
> 'luks-encryption'.
>
> Signed-off-by: Shiva Tripathi <[email protected]>
> ---
>  .../initramfs-ti-encrypted-init/files/init    | 324 ++++++++++++++++++
>  .../initramfs-ti-encrypted-init_1.0.bb        |  30 ++
>  .../initramfs/ti-encrypted-boot-initramfs.bb  |  50 +++
>  3 files changed, 404 insertions(+)
>  create mode 100644 
> meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init
>  create mode 100644 
> meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb
>  create mode 100644 
> meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb
>
> diff --git 
> a/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init 
> b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init
> new file mode 100644
> index 00000000..6675b6ed
> --- /dev/null
> +++ b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init
> @@ -0,0 +1,324 @@
> +#!/usr/bin/busybox sh
> +# TI SDK initramfs init script with LUKS2 + fTPM encryption support
> +
> +# Mount essential filesystems
> +/usr/bin/busybox echo "Initializing system..."
> +/usr/bin/busybox mount -t proc proc /proc
> +/usr/bin/busybox mount -t sysfs sysfs /sys
> +/usr/bin/busybox mount -t devtmpfs devtmpfs /dev
> +
> +# Configuration
> +BOOT_DEV="/dev/mmcblk1p1"           # Boot partition (FAT, unencrypted)
> +ROOT_DEV="/dev/mmcblk1p2"           # Root partition (will be encrypted)
> +CRYPT_NAME="root_crypt"
> +CRYPT_DEV="/dev/mapper/${CRYPT_NAME}"
> +BOOT_MNT="/boot_part"
> +TPM_PRIMARY_CTX="/tmp/tpm_primary.ctx"
> +TPM_KEY_PRIV="/tmp/tpm_key.priv"
> +TPM_KEY_PUB="/tmp/tpm_key.pub"
> +TPM_KEY_CTX="/tmp/tpm_key.ctx"
> +TPM2_HANDLE="0x81080001"            # TPM persistent handle for LUKS key
> +ENCRYPTION_MARKER="${BOOT_MNT}/.encryption_in_progress"
> +
> +# Wait for MMC device to appear (up to 10 seconds)
> +/usr/bin/busybox echo "Waiting for storage device..."
> +for i in 1 2 3 4 5 6 7 8 9 10; do
> +    if [ -b "${ROOT_DEV}" ]; then
> +        break
> +    fi
> +    /usr/bin/busybox sleep 1
> +done
> +
> +# Check if root device exists
> +if [ ! -b "${ROOT_DEV}" ]; then
> +    /usr/bin/busybox echo "ERROR: Storage device not found!"
> +    /usr/bin/busybox sh
> +fi
> +
> +# Mount boot partition
> +/usr/bin/busybox echo "Mounting boot partition..."
> +/usr/bin/busybox mkdir -p "${BOOT_MNT}"
> +if ! /usr/bin/busybox mount "${BOOT_DEV}" "${BOOT_MNT}"; then
> +    /usr/bin/busybox echo "ERROR: Failed to mount boot partition!"
> +    /usr/bin/busybox echo "Attempting standard boot..."
> +    /usr/bin/busybox mkdir -p /newroot
> +    /usr/bin/busybox mount "${ROOT_DEV}" /newroot
> +    exec /usr/sbin/switch_root /newroot /sbin/init
> +fi
> +
> +# Initialize fTPM in OP-TEE
> +/usr/bin/busybox echo "Initializing secure hardware(fTPM)..."
> +
> +# Start TEE supplicant (required for fTPM TA to work)
> +if [ -x /usr/sbin/tee-supplicant ]; then
> +    /usr/sbin/tee-supplicant -d &
> +    TEE_SUPPLICANT_PID=$!
> +    /usr/bin/busybox sleep 5
> +else
> +    /usr/bin/busybox echo "Warning: Trusted execution environment not 
> available"
> +fi
> +
> +# Load fTPM kernel module
> +if ! /sbin/modprobe tpm_ftpm_tee; then
> +    /usr/bin/busybox echo "Warning: TPM module failed to load"
> +fi
> +
> +# Wait for TPM device (up to 10 seconds)
> +for i in 1 2 3 4 5 6 7 8 9 10; do
> +    if [ -c /dev/tpmrm0 ]; then
> +        break
> +    fi
> +    /usr/bin/busybox sleep 1
> +done
> +
> +# Check if TPM is available
> +TPM_AVAILABLE=0
> +if [ -c /dev/tpmrm0 ]; then
> +    TPM_AVAILABLE=1
> +    export TPM2TOOLS_TCTI="device:/dev/tpmrm0"
> +else
> +    /usr/bin/busybox echo "Warning: fTPM not available - encryption will be 
> skipped"
> +    if [ -n "${TEE_SUPPLICANT_PID}" ]; then
> +        /usr/bin/busybox kill "${TEE_SUPPLICANT_PID}" 2>/dev/null
> +    fi
> +fi
> +
> +# Function: Generate 32-byte random key using TPM RNG
> +generate_random_key() {
> +    if [ $TPM_AVAILABLE -eq 1 ]; then
> +        /usr/bin/tpm2_getrandom --hex 32
> +    else
> +        /usr/bin/busybox echo "ERROR: TPM not available for key generation"
> +        return 1
> +    fi
> +}
> +
> +# Function: Seal data with TPM and store in persistent handle
> +tpm_seal_key() {
> +    local KEY_DATA="$1"
> +
> +    if [ $TPM_AVAILABLE -eq 0 ]; then
> +        /usr/bin/busybox echo "ERROR: TPM not available for sealing"
> +        return 1
> +    fi
> +
> +    # Create primary key in owner hierarchy
> +    /usr/bin/tpm2_createprimary -C o -c "${TPM_PRIMARY_CTX}" -Q || return 1
> +
> +    # Create sealed object
> +    /usr/bin/busybox echo -n "${KEY_DATA}" | \
> +        /usr/bin/tpm2_create -C "${TPM_PRIMARY_CTX}" \
> +        -u "${TPM_KEY_PUB}" -r "${TPM_KEY_PRIV}" \
> +        -i- -Q || return 1
> +
> +    # Load sealed object into TPM
> +    /usr/bin/tpm2_load -C "${TPM_PRIMARY_CTX}" \
> +        -u "${TPM_KEY_PUB}" -r "${TPM_KEY_PRIV}" \
> +        -c "${TPM_KEY_CTX}" -Q || return 1
> +
> +    # Make key persistent at handle (stored in TPM NV RAM - RPMB)
> +    /usr/bin/tpm2_evictcontrol -C o -c "${TPM_KEY_CTX}" "${TPM2_HANDLE}" || 
> return 1
> +
> +    return 0
> +}
> +
> +# Function: Unseal data from TPM persistent handle
> +tpm_unseal_key() {
> +    if [ $TPM_AVAILABLE -eq 0 ]; then
> +        /usr/bin/busybox echo "ERROR: TPM not available for unsealing" >&2
> +        return 1
> +    fi
> +
> +    # Check if persistent handle exists
> +    if ! /usr/bin/tpm2_getcap handles-persistent | grep -q "${TPM2_HANDLE}"; 
> then
> +        /usr/bin/busybox echo "ERROR: TPM persistent handle not found" >&2
> +        return 1
> +    fi
> +
> +    # Unseal key directly from persistent handle
> +    /usr/bin/tpm2_unseal -c "${TPM2_HANDLE}" || return 1
> +
> +    return 0
> +}
> +
> +# Function: Perform in-place LUKS encryption (first boot)
> +encrypt_root_filesystem() {
> +    /usr/bin/busybox echo "=========================================="
> +    /usr/bin/busybox echo "First boot: Encrypting root filesystem"
> +    /usr/bin/busybox echo "=========================================="
> +
> +    # Set marker to track encryption progress
> +    /usr/bin/busybox touch "${ENCRYPTION_MARKER}"
> +    /usr/bin/busybox sync
> +
> +    # Generate random encryption key using TPM RNG
> +    /usr/bin/busybox echo "Generating encryption key..."
> +    LUKS_KEY=$(generate_random_key)
> +
> +    if [ -z "${LUKS_KEY}" ]; then
> +        /usr/bin/busybox echo "ERROR: Failed to generate encryption key"
> +        /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}"
> +        return 1
> +    fi
> +
> +    # Seal key with TPM before encryption starts
> +    /usr/bin/busybox echo "Securing key with TPM..."
> +    if ! tpm_seal_key "${LUKS_KEY}"; then
> +        /usr/bin/busybox echo "ERROR: Failed to secure key"
> +        /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}"
> +        return 1
> +    fi
> +
> +    # Filesystem check before encryption
> +    /usr/bin/busybox echo "Checking filesystem integrity..."
> +    /usr/sbin/e2fsck -f -y "${ROOT_DEV}"
> +    E2FSCK_RET=$?
> +    if [ ${E2FSCK_RET} -ge 4 ]; then
> +        /usr/bin/busybox echo "ERROR: Filesystem check failed"
> +        /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}"
> +        return 1
> +    fi
> +
> +    # Shrink filesystem before encryption to leave room for LUKS header
> +    /usr/bin/busybox echo "Preparing filesystem for encryption..."
> +    /usr/sbin/resize2fs "${ROOT_DEV}" 368M || {
> +        /usr/bin/busybox echo "ERROR: Failed to prepare filesystem"
> +        /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}"
> +        return 1
> +    }
> +
> +    # Perform in-place encryption
> +    /usr/bin/busybox echo "=========================================="
> +    /usr/bin/busybox echo "Encrypting filesystem..."
> +    /usr/bin/busybox echo "This will take several minutes."
> +    /usr/bin/busybox echo "DO NOT POWER OFF THE DEVICE!"
> +    /usr/bin/busybox echo "=========================================="
> +
> +    /usr/bin/busybox echo -n "${LUKS_KEY}" | \
> +        /usr/sbin/cryptsetup reencrypt --encrypt \
> +        --type luks2 \
> +        --cipher aes-xts-plain64 \
> +        --key-size 256 \
> +        --hash sha256 \
> +        --reduce-device-size 32M \
> +        --key-file - \
> +        "${ROOT_DEV}" || {
> +        /usr/bin/busybox echo "ERROR: Encryption failed"
> +        /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}"
> +        return 1
> +    }
> +
> +    /usr/bin/busybox echo "=========================================="
> +    /usr/bin/busybox echo "Encryption completed successfully!"
> +    /usr/bin/busybox echo "=========================================="
> +
> +    # Remove encryption marker
> +    /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}"
> +    /usr/bin/busybox sync
> +
> +    # Unlock the newly encrypted device
> +    /usr/bin/busybox echo "Activating encrypted filesystem..."
> +    /usr/bin/busybox echo -n "${LUKS_KEY}" | \
> +        /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" 
> --key-file - || {
> +        /usr/bin/busybox echo "ERROR: Failed to activate encrypted 
> filesystem"
> +        return 1
> +    }
> +
> +    # Resize filesystem to fit the encrypted device
> +    /usr/bin/busybox echo "Optimizing filesystem..."
> +    /usr/sbin/resize2fs -f "${CRYPT_DEV}" || {
> +        /usr/bin/busybox echo "ERROR: Failed to optimize filesystem"
> +        return 1
> +    }
> +
> +    # Verify filesystem after resize
> +    /usr/sbin/e2fsck -f -y "${CRYPT_DEV}" || {
> +        /usr/bin/busybox echo "WARNING: Filesystem verification had issues, 
> but continuing"
> +    }
> +    return 0
> +}
> +
> +# Function: Unlock encrypted root filesystem (subsequent boots)
> +unlock_encrypted_root() {
> +    /usr/bin/busybox echo "Unlocking encrypted filesystem..."
> +
> +    # Unseal key from TPM persistent handle
> +    LUKS_KEY=$(tpm_unseal_key)
> +
> +    if [ -z "${LUKS_KEY}" ]; then
> +        /usr/bin/busybox echo "ERROR: Failed to retrieve encryption key from 
> TPM"
> +        /usr/bin/busybox echo "Attempting passphrase fallback..."
> +
> +        # Try to unlock with passphrase (interactive)
> +        /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" || {
> +            /usr/bin/busybox echo "ERROR: Failed to unlock encrypted 
> filesystem"
> +            /usr/bin/busybox sh
> +        }
> +    else
> +        # Unlock with unsealed key
> +        /usr/bin/busybox echo -n "${LUKS_KEY}" | \
> +            /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" 
> --key-file - || {
> +            /usr/bin/busybox echo "ERROR: Failed to unlock with TPM key"
> +            /usr/bin/busybox sh
> +        }
> +    fi
> +
> +    /usr/bin/busybox echo "Encrypted filesystem unlocked"
> +}
> +
> +# Main boot logic
> +/usr/bin/busybox echo "Checking filesystem encryption status..."
> +
> +# Check if device is LUKS encrypted
> +if /usr/sbin/cryptsetup isLuks "${ROOT_DEV}"; then
> +    /usr/bin/busybox echo "Filesystem is encrypted"
> +    unlock_encrypted_root
> +    MOUNT_DEV="${CRYPT_DEV}"
> +else
> +    /usr/bin/busybox echo "Filesystem is not encrypted"
> +
> +    # Check if encryption is enabled and TPM is available
> +    if [ $TPM_AVAILABLE -eq 1 ]; then
> +        # Check for encryption marker (resume interrupted encryption)
> +        if [ -f "${ENCRYPTION_MARKER}" ]; then
> +            /usr/bin/busybox echo "Resuming interrupted encryption..."
> +            if ! encrypt_root_filesystem; then
> +                /usr/bin/busybox echo "ERROR: Failed to resume encryption"
> +                /usr/bin/busybox echo "Booting without encryption..."
> +                MOUNT_DEV="${ROOT_DEV}"
> +            else
> +                MOUNT_DEV="${CRYPT_DEV}"
> +            fi
> +        else
> +            # First boot - perform encryption
> +            if encrypt_root_filesystem; then
> +                MOUNT_DEV="${CRYPT_DEV}"
> +            else
> +                /usr/bin/busybox echo "ERROR: Encryption failed - booting 
> without encryption"
> +                MOUNT_DEV="${ROOT_DEV}"
> +            fi
> +        fi
> +    else
> +        /usr/bin/busybox echo "TPM not available - skipping encryption"
> +        MOUNT_DEV="${ROOT_DEV}"
> +    fi
> +fi
> +
> +# Unmount boot partition before switching root
> +/usr/bin/busybox umount "${BOOT_MNT}"
> +
> +# Mount root filesystem (encrypted or unencrypted)
> +/usr/bin/busybox echo "Mounting root filesystem..."
> +/usr/bin/busybox mkdir -p /newroot
> +/usr/bin/busybox mount "${MOUNT_DEV}" /newroot || {
> +    /usr/bin/busybox echo "ERROR: Failed to mount root filesystem!"
> +    /usr/bin/busybox sh
> +}
> +
> +/usr/bin/busybox echo "Boot complete"
> +
> +# Clean up tmpfs
> +/usr/bin/busybox rm -f "${TPM_PRIMARY_CTX}" "${TPM_KEY_PUB}" 
> "${TPM_KEY_PRIV}" "${TPM_KEY_CTX}"
> +
> +# Switch to real root
> +exec /usr/sbin/switch_root /newroot /sbin/init
> diff --git 
> a/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb 
> b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb
> new file mode 100644
> index 00000000..7da878f7
> --- /dev/null
> +++ b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb
> @@ -0,0 +1,30 @@
> +SUMMARY = "TI encrypted boot initramfs init script"
> +DESCRIPTION = "Custom /init script for encrypted boot with fTPM + LUKS 
> support"
> +
> +LICENSE = "MIT"
> +LIC_FILES_CHKSUM = 
> "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
> +
> +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}/files:"
> +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
> +
> +SRC_URI = "file://init"
> +
> +S = "${WORKDIR}/sources"
> +UNPACKDIR = "${WORKDIR}"
> +
> +# This recipe must run in the initramfs context
> +inherit allarch
> +
> +do_install() {
> +    # Install /init script to root of initramfs
> +    install -m 0755 ${UNPACKDIR}/init ${D}/init
> +}
> +
> +# Package the /init file
> +FILES:${PN} = "/init"
> +
> +# Runtime dependencies
> +RDEPENDS:${PN} = "busybox cryptsetup tpm2-tools tpm2-tss optee-client 
> e2fsprogs-e2fsck e2fsprogs-resize2fs util-linux-blkid"
> +
> +# This package must be included in initramfs
> +PACKAGE_ARCH = "${MACHINE_ARCH}"
> diff --git a/meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb 
> b/meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb
> new file mode 100644
> index 00000000..314499db
> --- /dev/null
> +++ b/meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb
> @@ -0,0 +1,50 @@
> +SUMMARY = "TI encrypted boot initramfs image"
> +
> +DESCRIPTION = "Minimal initramfs image with dm-crypt/fTPM support for 
> encrypted root filesystem. \
> +This initramfs provides LUKS encryption with TPM-sealed keys stored in RPMB."
> +
> +LICENSE = "MIT"
> +
> +# Only build this when luks-encryption feature is enabled
> +COMPATIBLE_MACHINE = "null"
> +COMPATIBLE_MACHINE:k3 = "${@bb.utils.contains('MACHINE_FEATURES', 
> 'luks-encryption', '.*', 'null', d)}"
> +
> +INITRAMFS_FSTYPES = "cpio.gz"
> +
> +IMAGE_NAME = "ti-encrypted-boot-initramfs"
> +
> +export IMAGE_BASENAME = "${IMAGE_NAME}"
> +
> +# Install our custom init script and dependencies
> +PACKAGE_INSTALL = "\
> +    initramfs-ti-encrypted-init \
> +    busybox \
> +    base-passwd \
> +    kmod \
> +    cryptsetup \
> +    tpm2-tools \
> +    tpm2-tss \
> +    libtss2-tcti-device \
> +    optee-client \
> +    util-linux-blkid \
> +    e2fsprogs-e2fsck \
> +    e2fsprogs-resize2fs \
> +    kernel-module-tpm-ftpm-tee \
> +    ${ROOTFS_BOOTSTRAP_INSTALL} \
> +"
> +
> +# Ensure the initramfs only contains the bare minimum
> +IMAGE_FEATURES = ""
> +IMAGE_LINGUAS = ""
> +
> +# Exclude kernel image from initramfs
> +PACKAGE_EXCLUDE = "kernel-image-*"
> +
> +IMAGE_FSTYPES = "${INITRAMFS_FSTYPES}"
> +IMAGE_NAME_SUFFIX ?= ""
> +IMAGE_ROOTFS_SIZE = "16384"
> +IMAGE_ROOTFS_EXTRA_SPACE = "0"
> +
> +BAD_RECOMMENDATIONS += "busybox-syslog"
> +
> +inherit image
> --
> 2.34.1
>
>
> 
>


-- 
Jonathan Cormier
Senior Software Engineer

Office:  315.425.4045 x222

http://www.CriticalLink.com
6712 Brooklawn Parkway, Syracuse, NY 13211
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#19631): 
https://lists.yoctoproject.org/g/meta-ti/message/19631
Mute This Topic: https://lists.yoctoproject.org/mt/118097473/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/meta-ti/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to