Fehlerhafte ACPI Tabellen für Tagesalarm korrigieren
Geschrieben von Andreas am 15. Oktober 2022
Um meinen TV-PC mal wieder etwas zu erneuern habe ich ein gebrauchtes GA-N3160TN Mainboard erstanden. Das ist zwar schon etwas älter aber durch den Celeron N3160 sehr stromsparend und ausreichend leistungsstark. (Mainboard, RAM und SSD brauchen im Betrieb weniger Strom als eine Fritzbox, deren Netzteil passt hervorrangend als Stromversorgung)
Leider schaffen es auch höherwertige Hersteller anscheinend nicht mehr ein vernünftig angepasstes BIOS für Ihre Mainboards zu erstellen, so meldet der Linux Kernel dann auch beim Boot, das die RTC nur 24-Stunden Alarme kann:
$ dmesg | grep rtc_cmos
[ 1.063278] rtc_cmos 00:00: RTC can wake from S4
[ 1.063870] rtc_cmos 00:00: registered as rtc0
[ 1.064262] rtc_cmos 00:00: setting system clock to 2022-10-09T14:46:21 UTC (1665326781)
[ 1.064325] rtc_cmos 00:00: alarms up to one day, y3k, 242 bytes nvram
Für einen TV-PC ist das suboptimal. Eigentlich können alle Intel Chipsätze mit integrierter RTC auch sogenannte Tagesalarme, also Aufwachen bis 30 Tage in die Zukunft. Da der Linux Kernel die Information zu den Fähigkeiten der RTC aus der FADT ACPI Tabelle holt, kann man das Problem durch Patchen dieser Tabelle lösen.
FADT Patchen¶
Zunächst einmal werden die dafür notendigen Tools installiert:
$ apt install acpica-tools
Der nächste Schritt ist es dann die ACPI tabellen auszulesen und zu dekompilieren:
$ mkdir acpi
$ cd acpi
$ acpidump >acpidump
$ acpixtract -a acpidump
Intel ACPI Component Architecture
ACPI Binary Table Extraction Utility version 20200925
Copyright (c) 2000 - 2020 Intel Corporation
MCFG - 60 bytes written (0x0000003C) - mcfg.dat
APIC - 132 bytes written (0x00000084) - apic.dat
SSDT - 656 bytes written (0x00000290) - ssdt1.dat
UEFI - 66 bytes written (0x00000042) - uefi.dat
DSDT - 53903 bytes written (0x0000D28F) - dsdt.dat
LPIT - 260 bytes written (0x00000104) - lpit.dat
SSDT - 378 bytes written (0x0000017A) - ssdt2.dat
FACP - 268 bytes written (0x0000010C) - facp.dat
FPDT - 68 bytes written (0x00000044) - fpdt.dat
SSDT - 1891 bytes written (0x00000763) - ssdt3.dat
CSRT - 332 bytes written (0x0000014C) - csrt.dat
FIDT - 156 bytes written (0x0000009C) - fidt.dat
FACS - 64 bytes written (0x00000040) - facs.dat
SSDT - 1621 bytes written (0x00000655) - ssdt4.dat
SSDT - 141 bytes written (0x0000008D) - ssdt5.dat
SSDT - 933 bytes written (0x000003A5) - ssdt6.dat
SSDT - 351 bytes written (0x0000015F) - ssdt7.dat
$ iasl -d *.dat
Die ACPI Tabellen können nun mit einem einfachen Editor bearbeitet werden. Die RTC Eigenschaften werden in der FADT bzw FACP Tabelle beschrieben. Es müssen zwei Felder in der Tabelle angepasst werden:
Die
Oem Revision
der Tabelle muss erhöht werden unddas
RTC Day Alarm Index
Feld muss auf den Wert „0D
“ geändert werden
/*
* Intel ACPI Component Architecture
* AML/ASL+ Disassembler version 20200925 (64-bit version)
* Copyright (c) 2000 - 2020 Intel Corporation
*
* Disassembly of facp.dat, Sat Oct 15 13:59:47 2022
*
* ACPI Data Table [FACP]
*
* Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue
*/
[000h 0000 4] Signature : "FACP" [Fixed ACPI Description Table (FADT)]
[004h 0004 4] Table Length : 0000010C
[008h 0008 1] Revision : 05
[009h 0009 1] Checksum : 39
[00Ah 0010 6] Oem ID : "ALASKA"
[010h 0016 8] Oem Table ID : "A M I "
[018h 0024 4] Oem Revision : 0107200A
...
[06Ah 0106 1] RTC Day Alarm Index : 0D
...
Das kann man mit einem beliebigen Editor erledigen. Danach wird die FACP wieder compiliert:
$ iasl -sa facp.dsl
Intel ACPI Component Architecture
ASL+ Optimizing Compiler/Disassembler version 20200925
Copyright (c) 2000 - 2020 Intel Corporation
Table Input: facp.dsl - 10104 bytes 148 fields 178 source lines
Binary Output: facp.aml - 268 bytes
Compilation successful. 0 Errors, 0 Warnings, 0 Remarks
Kernel neue Tabelle unterschieben¶
Im zweiten Schritt wird dem Kernel die neue Tabelle untergeschoben, d.h. der Kernel soll statt der originalen die neue gepatchte Tabelle verwenden. Das ist relativ einfach möglich, wenn man initrds zum booten benutzt. Es wird dazu einfach eine weitere initrd vor die „normale“ initrd gepackt.
Entsprechend der Kernel Dokumentation [1] wird diese zunächst wie folgt erstellt:
$ mkdir -p kernel/firmware/acpi
$ cp facp.dsl kernel/firmware/acpi/
$ find kernel | cpio -H newc --create >/boot/initrd.img-acpi
Danach hab ich ein hook-Script für die initramfs-tools erstellt, welches automatisch die gepatchte initrd voranstellt:
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
prepend_earlyinitramfs /boot/initrd.img-acpi
Diese Datei muss dann noch als ausführbar markiert werden und dann kann die initrd neu erstellt werden:
$ chmod +x /etc/initramfs-tools/hooks/patch-acpi
$ update-initramfs -c -k all
Danach muss neu gebootet werden und die RTC sollte nun auch Tagesalarme unterstützen:
$ dmesg | grep rtc_cmos
[ 1.042898] rtc_cmos 00:00: RTC can wake from S4
[ 1.044270] rtc_cmos 00:00: registered as rtc0
[ 1.044710] rtc_cmos 00:00: setting system clock to 2022-10-15T12:34:06 UTC (1665837246)
[ 1.044868] rtc_cmos 00:00: alarms up to one month, y3k, 242 bytes nvram
Links