You are not logged in.

#1 2026-01-08 16:17:37

ectospasm
Member
Registered: 2015-08-28
Posts: 302

[SOLVED] ThinkPad with Secure Boot

SOLVED: See comment below for what I found and how I fixed it.

I have an X1 Carbon 11gen running Arch Linux, and about a year ago I upgraded the firmware using LVFS fwupd, and somehow that broke the TPM2 from being able to automatically unlock my LUKS2 container containing my root volume.  It took me about six months to fix it (in the meantime I'd enter my LUKS2 passphrase).  I tried several things to fix it, including enable systemd-boot (I had not beenusing a bootloader before, just having the EFI boot my signed UKI directly with Secure Boot, EDIT:  set up by kernel-install with ukify).  Turns out the problem was a stale PCR policy JSON I had set up as part of the troubleshooting. 

So I tried deleting systemd-boot with `bootctl remove`, and now I can't get it to boot into Arch.  I'm using sbctl to sign the UKI and set up Secure Boot.  But the Lenovo logo just keeps appearing, going away briefly, and then eventually prompting for the firmware admin password.  I've tried clearing all keys in the BIOS menu, enabling Setup Mode, enrolling the existing keys including the Microsoft Third Party Certificates, but it won't boot the UKI.

I did have to remove the systemd-boot files from the efivars, but as far as I can tell I'm now doing everything right.

I've checked with `sbctl status` after `sbctl enroll-keys  --microsoft`, and it properly says that Setup Mode is disabled (but so is Secure Boot).

After enrollment, I reinstall the kernel, and `sbctl verify` shows everything is signed.  When I reboot into the BIOS menu, it Says Secure Boot is enabled.

Do I have to run systemd-cryptenroll again?  That's something I haven't tried yet.

Last edited by ectospasm (2026-01-09 14:19:28)

Offline

#2 2026-01-08 21:56:06

ectospasm
Member
Registered: 2015-08-28
Posts: 302

Re: [SOLVED] ThinkPad with Secure Boot

EDIT:  See the next reply, using sbctl bundles will be deprecated.



The Solution:
The fix involved switching from kernel-install to sbctl for UKI management and utilizing the UEFI Fallback path to ensure boot reliability without cluttering the NVRAM.

1. The Boot Path (UEFI Fallback)
Instead of relying on fragile efibootmgr entries, I configured the system to use the UEFI "Fallback" executable path (/EFI/BOOT/BOOTX64.EFI). The ThinkPad firmware is hardcoded to boot this file if no other entries exist.

2. Fixing mkinitcpio Presets
My mkinitcpio was trying to generate a UKI directly, which conflicted with sbctl's bundling process. I reverted the preset to generate a standard initramfs image so sbctl could consume it.

File: /etc/mkinitcpio.d/linux.preset

# Disable direct UKI generation here
# default_uki="/efi/Linux/..."
# Enable standard image generation
default_image="/boot/initramfs-linux.img"


3. Fixing Kernel Command Line (sd-encrypt)
I use the systemd hook (sd-encrypt). The command line syntax is strict: it does not use the UUID= prefix for the LUKS mapper, and it cannot handle double quotes.

File: /etc/kernel/cmdline

# Correct syntax for systemd hook:
rd.luks.name=<RAW-LUKS-UUID>=top root=/dev/mapper/top rootflags=subvol=/root rw

(Note: No quotes around the parameters, and rd.luks.name takes the UUID directly without the UUID= prefix).

4. Automation with sbctl bundle
I masked the standard kernel-install hooks and set up sbctl to automatically bundle, sign, and install the UKI to the fallback path on every kernel update.

# 1. Mask conflicting hooks
ln -sf /dev/null /etc/pacman.d/hooks/90-mkinitcpio-install.hook

# 2. Create the permanent bundle
sbctl bundle --save \
  --kernel-img /boot/vmlinuz-linux-zen \
  --initramfs /boot/initramfs-linux.img \
  --intel-ucode /boot/intel-ucode.img \
  --cmdline /etc/kernel/cmdline \
  /efi/EFI/BOOT/BOOTX64.EFI

# 3. Generate the signed UKI
sbctl generate-bundles

5. TPM Enrollment
Once successfully booted, I re-enrolled the TPM keys against PCR 7 (Secure Boot) and PCR 0 (Firmware).

systemd-cryptenroll --wipe-slot=tpm2 /dev/nvme0n1p2
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7

Outcome:
The system now boots seamlessly from the Lenovo logo to the login prompt with no manual password entry and no intermediate bootloader menu.

---

Helper Script for Future Updates
Since X1 Carbon BIOS updates change PCR 0 and trip the TPM, I created a simple wrapper to re-enroll the keys quickly after a firmware update.

File: /usr/local/bin/tpm-fix

#!/bin/bash

# Configuration
DRIVE_DEVICE="/dev/nvme0n1p2"  # Your LUKS partition
PCRS="0+7"                     # PCR 0 (Firmware) and 7 (Secure Boot)

echo "[-] Wiping old TPM2 slot..."
sudo systemd-cryptenroll "$DRIVE_DEVICE" --wipe-slot=tpm2

echo "[-] Enrolling new measurements (PCRs: $PCRS)..."
sudo systemd-cryptenroll "$DRIVE_DEVICE" --tpm2-device=auto --tpm2-pcrs="$PCRS"

if [ $? -eq 0 ]; then
    echo "[+] Success! TPM updated."
else
    echo "[!] Error updating TPM."
fi

DISCLAIMER:  I worked with Google Gemini (I have a subscription to Pro) to arrive to the solution, and above is the summary Gemini drafted for me.

Last edited by ectospasm (Yesterday 15:52:20)

Offline

#3 2026-01-08 22:06:06

system72
Member
Registered: 2025-11-22
Posts: 469
Website

Re: [SOLVED] ThinkPad with Secure Boot

uh yeah.. maybe dont do that

man sbctl wrote:

BUNDLES
       Note: This is being deprecated. Please move to dracut/mkinitcpio/ukify.

       Normally, only the kernel is signed with your secure boot keys. This means the kernel command
       line and initramfs can be changed without possibility of verification.

       Bundles are EFI executables which pack all three (initramfs, kernel and cmdline) into a
       single file which is easy to sign. Avoiding any unsigned files during boot makes the whole
       process more tamper-proof.

       When a bundle is generated, its configuration is stored into the bundle database (see FILES).
       Subsequent executions of sbctl generate-bundles will rebuild these bundles, so you don’t need
       to re-specify all parameters after each system update.

       Tip: systemd-boot will automatically show entries for any bundles found in
       esp/EFI/Linux/*.efi.

see the warning

Last edited by system72 (2026-01-08 22:06:37)

Offline

#4 2026-01-09 14:33:39

ectospasm
Member
Registered: 2015-08-28
Posts: 302

Re: [SOLVED] ThinkPad with Secure Boot

Ahh, OK.  Does Foxboron have a date when the bundle functionality will be removed (causing my current setup to fail)?

I don't know when I'll have a chance to go back to kernel-install and ukify, since I can't afford to break my laptop for the next several weeks.

Offline

#5 Yesterday 16:25:57

ectospasm
Member
Registered: 2015-08-28
Posts: 302

Re: [SOLVED] ThinkPad with Secure Boot

Secure Boot without a Bootloader (systemd-stub + ukify)

I recently moved my X1 Carbon Gen 11 to a fully automated "Bootloader-less" Secure Boot setup. It uses the BIOS fallback path directly, managing everything via kernel-install and ukify.

1. The Strategy

  • No GRUB/systemd-boot: The firmware boots /EFI/BOOT/BOOTX64.EFI directly.

  • Keys: Managed by sbctl, but symlinked to /etc/kernel/ for standard discovery.

  • Builder: ukify builds and signs the Unified Kernel Image (UKI).

  • Installer: A custom script moves the signed UKI to the fallback path.

2. Configuration

Symlink the Keys
Instead of pointing configs to /var/lib/sbctl, I symlinked them to where ukify expects them:

ln -s /var/lib/sbctl/keys/db.key /etc/kernel/secure-boot-privaye-key.pem
ln -s /var/lib/sbctl/keys/db.pem /etc/kernel/secure-boot-certificate.pem

/etc/kernel/install.conf
Tells Arch to use the modern UKI layout and ukify tool.

layout=uki
initrd_generator=mkinitcpio
uki_generator=ukify

/etc/kernel/uki.conf
Configures the build. Note that I specify systemd-sbsign as the tool.

[UKI]
Microcode=/boot/intel-ucode.img
SecureBootSigningTool=systemd-sbsign
SecureBootPrivateKey=/etc/kernel/secure-boot-private-key.pem
SecureBootCertificate=/etc/kernel/secure-boot-certificate.pem
SignKernel=true
# Keys are symlinks to the sbctl created key/crt

/etc/mkinitcpio.d/linux-zen.preset
Ensure mkinitcpio builds a standard image, not a UKI (avoids double-builds).

#default_uki=... (Make sure this is commented out)
default_image="/boot/initramfs-linux-zen.img"

3. The Install Script
/etc/kernel/install.d/99-fallback.install
This script moves the generated UKI to the magic fallback path so the BIOS finds it automatically.

#!/bin/bash
COMMAND="$1"; KERNEL_VERSION="$2"
if [ "$COMMAND" = "add" ]; then
    TARGET_DIR="/efi/EFI/Linux"
    # Find the freshest signed UKI
    SIGNED_UKI=$(find "$TARGET_DIR" -name "*${KERNEL_VERSION}*.efi" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" ")
    
    if [ -f "$SIGNED_UKI" ]; then
        mkdir -p /efi/EFI/BOOT
        # Move to prevent NVRAM clutter
        mv -f "$SIGNED_UKI" /efi/EFI/BOOT/BOOTX64.EFI
        rmdir "$TARGET_DIR" --ignore-fail-on-non-empty 2>/dev/null
    fi
fi

4. Hook Management
Finally, ensure kernel-install is the only manager running.

# Enable kernel-install
rm /etc/pacman.d/hooks/90-kernel-install.hook 2>/dev/null

# Disable direct mkinitcpio (handled by kernel-install now)
ln -sf /dev/null /etc/pacman.d/hooks/90-mkinitcpio-install.hook
ln -sf /dev/null /etc/pacman.d/hooks/60-mkinitcpio-remove.hook

# Disable sbctl's internal signing (handled by ukify now)
ln -sf /dev/null /etc/pacman.d/hooks/sbctl.hook

Again, I worked with Gemini to arrive at the solution, and asked it to provide the summary above.

Last edited by ectospasm (Yesterday 16:27:18)

Offline

Board footer

Powered by FluxBB