Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Fixing the DSDT of an Asus P8Z68V-Pro
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
christoph_peter_s
Tux's lil' helper
Tux's lil' helper


Joined: 30 Nov 2015
Posts: 108

PostPosted: Tue Jun 18, 2019 12:42 pm    Post subject: Fixing the DSDT of an Asus P8Z68V-Pro Reply with quote

After having fixed some rotten tubes of the water cooling system, I wanted to reuse an Asus P8Z68V-Pro carrying an i7-3770K and 32GB RAM as a Gentoo based workstation. The box had served as my main Windoze box for quite some time - so I never realized, how badly Asus messed up the bios of that mainboard. The issue is this: whenever I enable Wake-on-Lan (which I badly deserve as the box has been moved to my basement compartment), the unit will no longer be able to be switched-off. Whenever issuing a shutdown command, the box does switch-off - and power-up again after a one or two seconds.

After a lot of searching, I found a thread on exactly that malfunction on an Asus H87I-Plus board in an Arch-Linux forum (see: https://bbs.archlinux.org/viewtopic.php?id=173648). As this was virtually the only piece of information I could find after a lot of searching, and as things are always a bit different for Gentoo (and to give something back to the great Gentoo community), I decided to write this small tutorial, on how to fix the issue.


Background information

The bios of a mainboard contains lists, which describe the individual hardware sitting on the board as well as the information on how to access it. A good chunk of this information is then handed over to the booting operating system, which during boot enables one piece after another. In order to allow different OS to boot, the information is expected to be formatted according to well defined standards. There are however to notable exceptions: one is Apple, which supplies a bundled set of hard- and software, which is difficult to break apart - and in fact, it is not too simple to build an Hackintosh...
The other notable exception is Microsoft, which uses to deliberately incorporate subtle nuances to accepted standards in their products, which nearly achieve interoperability - but in fact they are designed to do not. One of these spoiled implementations is the M$ way of implementing the Intel ACPI Source Language, iASL for short, which is the basic means to describe the mainboards hardware in a set of tables. The most cumbersome one is the Differentiated System Description Table DSDT. Background information can be found here: https://www.coreboot.org/ACPI and here: https://acpica.org/documentation. Also there is a community, which deals with the hacking of tuned bioses to re-enable crippled features of popular non-high end mainboards. It is not too complicated stuff - but it is a bit of reading. Also one whishes to have a flash programmer at hand, when really fixing the bios. But this would be an overkill for the given issue... As You will see later, we can cope with our issue in a less intrusive way.
It is worthwhile to note, that Linux seemed to face issues with crappy bios implementation since its very beginning. So it did conceive an elegant means on how to deal with it: it offers an mechanism, to replace a buggy DSDT on the fly during the boot-up process, either by compiling a DSDT copy into the kernel, or by loading one early in the boot process from a give file location. I have chosen the latter approach, as I did not manage to make the first one working.
On a technical level I should add, that the term ACPI Source Language, commonly referred to as ASL, is the human readable hardware description. Within the bios a compiled version of it is used, the ACPI Machine Language AML. Compilation and decompilation is performed by the a compiler, in our case by the open source Intel ACPI Soure Language compiler. An informative, but outdated wiki article is here: https://forums.gentoo.org/viewtopic-t-122145-start-0.html (but I wasn't aware of this, besides: it is _really_ outdated...).


Preparing the arena

There are a few things necessary for the fix:
[*] the Intel ACPI Source Language compiler from the package https://packages.gentoo.org/packages/sys-power/iasl
[*] the Intel iASL compiler documentation https://acpica.org/sites/acpica/files/aslcompiler_10.pdf
[*] the ACPI specification https://uefi.org/sites/default/files/resources/ACPI_6_2.pdf
[*] the Arch-Wiki entry on the DSDT https://wiki.archlinux.org/index.php/DSDT


Extraction of the DSDT

The first step is to extract the actual DSDT and copy it to a working directory.
Code:
HOME\peter@hydra ~ $ mkdir dsdt
HOME\peter@hydra ~ $ cd dsdt
HOME\peter@hydra ~ $ sudo cat /sys/firmware/acpi/tables/DSDT > dsdt.dat

Next we decompile the DSDT using the Intel iasl:
Code:
HOME\peter@hydra ~/dsdt $ iasl -d dsdt.dat

Intel ACPI Component Architecture
ASL+ Optimizing Compiler/Disassembler version 20180810
Copyright (c) 2000 - 2018 Intel Corporation

Input file dsdt.dat, Length 0xBAFE (47870) bytes
ACPI: DSDT 0x0000000000000000 00BAFE (v02 ALASKA A M I    00000015 INTL 20051117)
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)

Parsing completed

Found 6 external control methods, reparsing with new information
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)

Parsing completed
Disassembly completed
ASL Output:    dsdt.dsl - 435088 bytes

 iASL Warning: There were 6 external control methods found during
 disassembly, but only 0 were resolved (6 unresolved). Additional
 ACPI tables may be required to properly disassemble the code. This
 resulting disassembler output file may not compile because the
 disassembler did not know how many arguments to assign to the
 unresolved methods. Note: SSDTs can be dynamically loaded at
 runtime and may or may not be available via the host OS.

 To specify the tables needed to resolve external control method
 references, the -e option can be used to specify the filenames.
 Example iASL invocations:
     iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml
     iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml
     iasl -e ssdt*.aml -d dsdt.aml

 In addition, the -fe option can be used to specify a file containing
 control method external declarations with the associated method
 argument counts. Each line of the file must be of the form:
     External (<method pathname>, MethodObj, <argument count>)
 Invocation:
     iasl -fe refs.txt -d dsdt.aml


The decompiler generates the file dsdt.dsl, which is the ASL (ACPI Source Language) source of the DSDT.


Fixing the DSDT

Fixing the DSDT means to achieve two things:
[*] the first and foremost issue is to fix the bugs, which are thrown during the recompilation.
[*] second we must remove the offending entries, that prevent the box from a proper shutdown.
So let's start...
Code:
HOME\peter@hydra ~/dsdt $ iasl -tc dsdt.dsl

Intel ACPI Component Architecture
ASL+ Optimizing Compiler/Disassembler version 20180810
Copyright (c) 2000 - 2018 Intel Corporation

dsdt.dsl   2541:                     CreateDWordField (BUF0, \_SB.PCI0._Y0F._LEN, MSLN)  // _LEN: Length
Warning  3128 -                                 ResourceTag larger than Field ^  (Size mismatch, Tag: 64 bits, Field: 32 bits)

dsdt.dsl   2564:                     CreateDWordField (BUF0, \_SB.PCI0._Y0F._LEN, M4LN)  // _LEN: Length
Warning  3128 -                                 ResourceTag larger than Field ^  (Size mismatch, Tag: 64 bits, Field: 32 bits)

dsdt.dsl   2790:                         Return (Zero)
Error    6105 -                                    ^ Invalid object type for reserved name (_CRS: found Integer, Buffer required)
....

That's a lot... we copy it to a file
Code:
HOME\peter@hydra ~/dsdt $ iasl -tc dsdt.dsl &> iasl_errors.txt

After having deleted all the warnings and notifications, we see, what we need to address:
Code:
dsdt.dsl   2790:                         Return (Zero)
Error    6105 -                                    ^ Invalid object type for reserved name (_CRS: found Integer, Buffer required)

dsdt.dsl   4727:                         Name (_HID, "pnp0c14")  // _HID: Hardware ID
Error    6136 -          Non-hex letters must be upper case ^  (pnp0c14)

dsdt.dsl   6242:                             PLD_Revision           = 0x1,
Error    6105 -  Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6279:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6318:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6357:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6396:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6435:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6474:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6513:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl   6552:                                 PLD_Revision           = 0x1,
Error    6105 -      Invalid object type for reserved name ^  (_PLD: found Buffer, Package required)

dsdt.dsl  12779:         Name (_HID, "ABCDEFGH")  // _HID: Hardware ID
Error    6035 -                              ^ _HID suffix must be all hex digits (GH)

Compilation complete. 12 Errors, 6 Warnings, 52 Remarks, 305 Optimizations

So we have three different errors, where one error occurs a multiple times. That's not too bad...
So we fire up vim, set numbers move to the first error location and find:
Code:
 2786                 Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
 2787                 {
 2788                     If (TPMF)
 2789                     {
 2790                         Return (Zero)
 2791                     }
 2792
 2793                     Return (CRS) /* \_SB_.PCI0.TPMX.CRS_ */
 2794                 }


Now it is time, to study the ACPI specification, which defines the ASL in chapter 19. After having a short glance on it, we note chapter 19.3.5.2 Explicit Data Type Conversions - there is a conversion function ToBuffer, which seem to deliver, what the error message complained about. So we modify our dsdt.dsl accordingly:

Code:
 2786                 Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
 2787                 {
 2788                     If (TPMF)
 2789                     {
 2790                         Return (ToBuffer(Zero))
                             //         ^^^^^^^^^^  here!
 2791                     }
 2792
 2793                     Return (CRS) /* \_SB_.PCI0.TPMX.CRS_ */
 2794                 }

The fix on line 4727 (Non-hex letters must be upper case) is trivial ("PNP0c14").
The next error on lines 6242 (_PLD: found Buffer, Package required) again requires that the return argument is declared as a package, rather then returning the plain buffer. We have a look on the package declaration in chapter 19.6.101 of the ACPI specification. The syntax is Package (NumElements) {PackageList}. Have a look on the example provided there.
So we change the lines
Code:
 6241                         Name (_PLD, ToPLD (
 6242                             PLD_Revision           = 0x1,
 6243                             PLD_IgnoreColor        = 0x1,
 ...
 6266                             PLD_Order              = 0x0)

to
Code:
 6241                         Name (_PLD, Package() {ToPLD (
 6242                             PLD_Revision           = 0x1,
 6243                             PLD_IgnoreColor        = 0x1,
 ...
 6266                             PLD_Order              = 0x0)}

We have to do this for nine occurences of the error. The remaining error in line 12779 ("ABCDEF00") is again a trivial one.

Thus we can go over to the second stage, namely to remove that offending routine, which gives those, who want to build a Hackintosh so much grieve. Study the comment #42 of user fseek in https://bbs.archlinux.org/viewtopic.php?id=173648&p=2. So the lesson is, to replace the variable NEXP by One, so that it could never fail... So we have
Code:
 2594                 If (((Arg0 == GUID) && NEXP))
 2595                 {
 2596                     SUPP = CDW2 /* \_SB_.PCI0._OSC.CDW2 */
 2597                     CTRL = CDW3 /* \_SB_.PCI0._OSC.CDW3 */
...
10482         If (NEXP)
10483         {

which we change to
Code:
 2594                 If (((Arg0 == GUID) && One))
 2595                 {
 2596                     SUPP = CDW2 /* \_SB_.PCI0._OSC.CDW2 */
 2597                     CTRL = CDW3 /* \_SB_.PCI0._OSC.CDW3 */
...
10482         If (One)
10483         {

Finally we don't forget to increase the OEM verision from 0x15 to 0x16 according to https://wiki.archlinux.org/index.php/DSDT...
Code:
DefinitionBlock ("", "DSDT", 2, "ALASKA", "A M I", 0x00000016)

and recompile dsdt.dsl a last time...
Code:
HOME\peter@hydra ~/dsdt $ iasl -tc dsdt.dsl
...
ASL Input:     dsdt.dsl - 12868 lines, 435204 bytes, 5260 keywords
AML Output:    dsdt.aml - 48016 bytes, 1420 named objects, 3840 executable opcodes
Hex Dump:      dsdt.hex - 450539 bytes

Compilation complete. 0 Errors, 6 Warnings, 52 Remarks, 315 Optimizations, 1 Constants Folded



Applying the fixed DSDT
I have failed to compile the DSDT directly into the kernel, apparently I had the same issues described here https://forums.gentoo.org/viewtopic-t-1088712-start-0.html - no solution yet given. So I had to follow the cpio approach (where I did not find really good documentation - but maybe I just was a bit overworked, as the whole DSDT hacking was less straightforeward then written down here...).
Code:
hydra /usr/src/dsdt # mkdir -p /usr/src/dsdt/kernel/firmware/acpi
hydra /usr/src/dsdt # cp /home/peter/dsdt/dsdt.aml /usr/src/dsdt/kernel/firmware/acpi
hydra /usr/src/dsdt #find kernel | cpio -H newc --create > /boot/acpi_override
hydra /usr/src/dsdt #grep acpi /etc/default/grub
#GRUB_CMDLINE_LINUX="quiet splash acpi=noirq"
GRUB_EARLY_INITRD_LINUX_CUSTOM="microcode.cpio acpi_override"
hydra /usr/src/dsdt #grub-mkconfig -o /boot/grub/grub.cfg


Anyway, reboot the box - and now the shutdown should work OK with an enabled Wake-on-LAN...

Best regards
Peter

PS: there is still room for improvement - and I would be glad to extent especially the last chapter. If somebody could give me some pointers to both the cpio mechanism and to the direct kernel integration of a patched DSDT.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum