生成 UKI 镜像
这部分需要先去 BIOS 关闭安全启动!!
删除 GRUB 引导程序
sudo rm -rf /boot/efi/*
sudo dnf remove grub2\* --setopt=protected_packages=
配置 kernel-install
这里也可以使用 ukify
sudo vim /etc/kernel/install.conf
layout=uki
uki_generator=dracut
由于默认生成的 efi 文件包含随机字符,不利于 Direct Boot,这里需要固定 efi 文件名称
sudo cp /usr/lib/kernel/install.d/90-uki-copy.install /etc/kernel/install.d/
sudo vim /etc/kernel/install.d/90-uki-copy.install
这里添加了 UKI_FALLBACK_FILE
, 留一份原来的内核备用
#!/usr/bin/sh
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# systemd is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with systemd; If not, see <https://www.gnu.org/licenses/>.
set -e
COMMAND="${1:?}"
KERNEL_VERSION="${2:?}"
# shellcheck disable=SC2034
ENTRY_DIR_ABS="$3"
KERNEL_IMAGE="$4"
BOOT_ROOT="$KERNEL_INSTALL_BOOT_ROOT"
UKI_DIR="$BOOT_ROOT/EFI/Linux"
UKI_FILE="$UKI_DIR/fedora-linux.efi"
UKI_FALLBACK_FILE="$UKI_DIR/fedora-linux-fallback.efi"
# If there is a UKI named uki.efi on the staging area use that, if not use what
# was passed in as $KERNEL_IMAGE but insist it has a .efi extension
if [ -f "$KERNEL_INSTALL_STAGING_AREA/uki.efi" ]; then
install -m 0644 "$UKI_FILE" "$UKI_FALLBACK_FILE"
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_INSTALL_STAGING_AREA/uki.efi as $UKI_FILE"
install -m 0644 "$KERNEL_INSTALL_STAGING_AREA/uki.efi" "$UKI_FILE" || {
echo "Error: could not copy '$KERNEL_INSTALL_STAGING_AREA/uki.efi' to '$UKI_FILE'." >&2
exit 1
}
elif [ -n "$KERNEL_IMAGE" ]; then
[ -f "$KERNEL_IMAGE" ] || {
echo "Error: UKI '$KERNEL_IMAGE' not a file." >&2
exit 1
}
[ "$KERNEL_IMAGE" != "${KERNEL_IMAGE%*.efi}.efi" ] && {
echo "Error: $KERNEL_IMAGE is missing .efi suffix." >&2
exit 1
}
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_IMAGE as $UKI_FILE"
install -m 0644 "$KERNEL_IMAGE" "$UKI_FILE" || {
echo "Error: could not copy '$KERNEL_IMAGE' to '$UKI_FILE'." >&2
exit 1
}
else
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "No UKI available. Nothing to do."
exit 0
fi
chown root:root "$UKI_FILE" || :
exit 0
更改 dracut 配置
由于 dracut 默认并不会读取 /etc/kernel/cmdline
中的内核参数,这里需要修改,保证 dracut 能读取到内核参数
sudo vim /etc/dracut.conf
kernel_cmdline="$(cat /etc/kernel/cmdline)"
生成 UKI 镜像
sudo kernel-install add-all -v
如果没报错应该就成功了
设置启动项
sudo efibootmgr --create --disk /dev/sdX --part partition_number --label "Fedora" --loader '\EFI\Linux\fedora-linux.efi' --unicode
启用安全启动
安装 sbctl
sudo dnf copr enable chenxiaolong/sbctl
sudo dnf install sbctl
创建密钥
sudo sbctl create-keys
将密钥导入BIOS
这部分的操作可能导致设备变砖!!
导入前 BIOS 需要启用 Setup Mode,具体参考 example enrollment
Option ROM
cp /sys/kernel/security/tpm0/binary_bios_measurements eventlog
tpm2_eventlog eventlog | grep "BOOT_SERVICES_DRIVER"
EventType: EV_EFI_BOOT_SERVICES_DRIVER
输出包含 BOOT_SERVICES_DRIVER
表明电脑包含 Option ROM,不可以直接 enroll,否则会导致变砖
导入Microsoft Corporation UEFI CA 2011
证书
sudo sbctl enroll-keys -m
如果不想导入微软的证书可以使用 TPM eventlog
读取校验值后手动导入
sudo sbctl enroll-keys -t
没有 Option ROM 的电脑直接 enroll 即可
sudo sbctl enroll-keys
修改 install 文件
sbctl 默认会签名包含随机字符的 UKI 镜像,不修改会报 not exist 错误
sudo cp /usr/lib/kernel/install.d/91-sbctl.install /etc/kernel/install.d/
sudo vim /etc/kernel/install.d/91-sbctl.install
这里固定了 IMAGE_FILE
,并删掉了 remove 部分,毕竟不需要清理内核了
#!/usr/bin/sh
# This file is part of sbctl.
COMMAND="$1"
KERNEL_VERSION="$2"
ENTRY_DIR_ABS="$3"
# shellcheck disable=SC2034 # Unused variables left for readability
KERNEL_IMAGE="$4"
IMAGE_FILE="$ENTRY_DIR_ABS/linux"
IMAGE_FALLBACK_FILE="$ENTRY_DIR_ABS/linux"
if [ "$KERNEL_INSTALL_LAYOUT" = "uki" ]; then
UKI_DIR="$KERNEL_INSTALL_BOOT_ROOT/EFI/Linux"
IMAGE_FILE="$UKI_DIR/fedora-linux.efi"
IMAGE_FALLBACK_FILE="$UKI_DIR/fedora-linux-fallback.efi"
fi
case "$COMMAND" in
add)
printf 'sbctl: Signing kernel %s\n' "$IMAGE_FILE"
# exit without error if keys don't exist
# https://github.com/Foxboron/sbctl/issues/187
if ! [ "$(sbctl setup --print-state --json | awk '/installed/ { gsub(/,$/,"",$2); print $2 }')" = "true" ]; then
echo "Secureboot key directory doesn't exist, not signing!"
exit 0
fi
sbctl sign "$IMAGE_FILE" 1>/dev/null
sbctl sign "$IMAGE_FALLBACK_FILE" 1>/dev/null
;;
esac
之后每次内核更新都会重新签名
重新生成 UKI 镜像并签名
sudo kernel-install add-all -v