我的电脑由于下面这个帖子中描述的问题,需要覆盖原有的ACPI DSDT表来解决。
目前我只有在关闭安全启动的情况下才能覆盖成功,但这对于双系统用户不够友好。
覆盖DSDT有下面几种可行的办法:
-
建立 /kernel/firmware/acpi/*.aml 并使用 cpio 工具生成未压缩存档 acpi_override,grub 配置中,在原先的initrd之前导入 acpi_override(方法一)
-
创建 initramfs_tools 的钩子,打包成一个 initrd.img(方法二,ai给的方案,目前在用)
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
# 检查我们的源目录是否存在
if [ ! -d /etc/acpi/override ]; then
exit 0
fi
# 在initramfs内部创建内核期望的目标目录
# ${DESTDIR} 是指向正在构建的initramfs临时根目录的变量
mkdir -p "${DESTDIR}/kernel/firmware/acpi"
# 将我们的ACPI文件复制到initramfs内部的正确位置
cp /etc/acpi/override/*.aml "${DESTDIR}/kernel/firmware/acpi/"
echo "ACPI override table(s) copied to initramfs."
- 直接把 DSDT.aml 放在 /boot 下,给grub加命令
acpi /boot/DSDT.aml(方法三)
我已经尝试过 AI 给的方案:导入自签名的 MOK.der 到 shim 中,并把签名文件 DSDT.aml.sig 和 DSDT.aml 放置在 initramfs 的正确位置上。但似乎安全启动下,内核在最早期启动阶段会把 .sig 文件当成 ACPI 表解析(然后报 `Unknown signature`),并且会直接拒绝我的 ACPI DSDT 表,不检查 MOK keyring。
[ 0.003605] ACPI: ACPI OVERRIDE: Unknown signature [kernel/firmware/acpi/DSDT.aml.sig]
[ 0.003621] ACPI: DSDT ACPI table found in initrd [kernel/firmware/acpi/DSDT.aml][0x12a61]
[ 0.003624] Lockdown: swapper: modifying ACPI tables is restricted; see man kernel_lockdown.7
[ 0.003625] ACPI: kernel is locked down, ignoring table override
[ 0.003627] ACPI: Early table checksum verification disabled
下面是内核对应的源代码:
// at drivers/acpi/tables.c
void __init acpi_table_upgrade(void)
{
...
for (no = 0; no < NR_ACPI_INITRD_TABLES; no++) {
file = find_cpio_data(cpio_path, data, size, &offset);
if (!file.data)
break;
data += offset;
size -= offset;
if (file.size < sizeof(struct acpi_table_header)) {
pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
cpio_path, file.name);
continue;
}
table = file.data;
for (sig = 0; sig < ARRAY_SIZE(table_sigs); sig++)
if (!memcmp(table->signature, table_sigs[sig], 4))
break;
if (sig >= ARRAY_SIZE(table_sigs)) {
pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
cpio_path, file.name);
continue;
}
if (file.size != table->length) {
pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
cpio_path, file.name);
continue;
}
if (acpi_table_checksum(file.data, table->length)) {
pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
cpio_path, file.name);
continue;
}
pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
table->signature, cpio_path, file.name, table->length);
all_tables_size += table->length;
acpi_initrd_files[table_nr].data = file.data;
acpi_initrd_files[table_nr].size = file.size;
table_nr++;
}
if (table_nr == 0)
return;
if (security_locked_down(LOCKDOWN_ACPI_TABLES)) {
pr_notice("kernel is locked down, ignoring table override\n");
return;
}
...
}
kernel_lockdown.7提到:
Only validly signed modules/binaries may be loaded, and these features may be disabled or restricted
• The overriding of ACPI tables.
• The use of ACPI error injection.
• The specification of the ACPI RDSP address.
• The use of ACPI custom methods.
所以在开启安全启动(即内核启用 lockdown 功能)的情况下,内核估计是不能读取我的 DSDT.aml 来覆写了对吗?我有没有别的方法解决呢,能否从 grub 入手,或者修改并编译内核?但是我真的不希望魔改内核……对编译内核也不是很熟悉。