【求助】开启安全启动,如何覆写DSDT表?

我的电脑由于下面这个帖子中描述的问题,需要覆盖原有的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 入手,或者修改并编译内核?但是我真的不希望魔改内核……对编译内核也不是很熟悉。

从grub文档来看使用安全启动的时候acpi覆写功能也会被禁用,所以可能这些路径都是堵死的。

可能只能改内核把这段检查关掉了。