ACPI patching troubleshooting guide for RedmiBook

I am an another happy owner of the Xiaomi’s RedmiBook, and this laptop is really amazing for its' price. But nothing is perfect in this world, and one of the issues with RedmiBook is deep sleep support (on Linux).

When I discovered problems with energy consumption while laptop is sleeping, I found this article. I am grateful to author for his work, but unfortunately, copy-pasting commands did not solve my issue - there were some errors during decompilation stage, so recompilation stage failed also.

Problem 1. Disassembling DSDT

As you can see, there are some unresolved external control methods in the DSDT. This is preventing successful disassembly, so future patching and recompilation are impossible.

 $ sudo cat /sys/firmware/acpi/tables/DSDT > dsdt.aml
 $ iasl -d dsdt.aml

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

File appears to be binary: found 7312 non-ASCII characters, disassembling
Binary file appears to be a valid ACPI table, disassembling
Input file dsdt.aml, Length 0x4FA8 (20392) bytes
ACPI: DSDT 0x0000000000000000 004FA8 (v01 XMCC   XMCC1955 00000002      01000013)
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)

Parsing completed

Found 8 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 - 192773 bytes

 iASL Warning: There were 8 external control methods found during
 disassembly, but only 0 were resolved (8 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

Fixing disassembly

But we have some example usage of iasl, mentioning additional SSDTs. And I have a lot of them:

 $ ls /sys/firmware/acpi/tables/SSDT*
/sys/firmware/acpi/tables/SSDT1   /sys/firmware/acpi/tables/SSDT13  /sys/firmware/acpi/tables/SSDT2  /sys/firmware/acpi/tables/SSDT6
/sys/firmware/acpi/tables/SSDT10  /sys/firmware/acpi/tables/SSDT14  /sys/firmware/acpi/tables/SSDT3  /sys/firmware/acpi/tables/SSDT7
/sys/firmware/acpi/tables/SSDT11  /sys/firmware/acpi/tables/SSDT15  /sys/firmware/acpi/tables/SSDT4  /sys/firmware/acpi/tables/SSDT8
/sys/firmware/acpi/tables/SSDT12  /sys/firmware/acpi/tables/SSDT16  /sys/firmware/acpi/tables/SSDT5  /sys/firmware/acpi/tables/SSDT9

Let’s try to disassemble DSDT including all available SSDTs:

 $ sudo iasl -e /sys/firmware/acpi/tables/SSDT* -d dsdt.aml

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

File appears to be binary: found 7312 non-ASCII characters, disassembling
Binary file appears to be a valid ACPI table, disassembling
Input file dsdt.aml, Length 0x4FA8 (20392) bytes
ACPI: DSDT 0x0000000000000000 004FA8 (v01 XMCC   XMCC1955 00000002      01000013)
External object resolution file /sys/firmware/acpi/tables/SSDT9
Input file /sys/firmware/acpi/tables/SSDT9, Length 0xC78 (3192) bytes
ACPI: SSDT 0x0000000000000000 000C78 (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT8
Input file /sys/firmware/acpi/tables/SSDT8, Length 0x1BF4 (7156) bytes
ACPI: SSDT 0x0000000000000000 001BF4 (v01 XMCC   XMCC1955 00000001 AMD  00000001)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT7
Input file /sys/firmware/acpi/tables/SSDT7, Length 0xF8 (248) bytes
ACPI: SSDT 0x0000000000000000 0000F8 (v01 XMCC   XMCC1955 00001000 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT6
Input file /sys/firmware/acpi/tables/SSDT6, Length 0x80 (128) bytes
ACPI: SSDT 0x0000000000000000 000080 (v01 XMCC   XMCC1955 00000002      01000013)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT5
Input file /sys/firmware/acpi/tables/SSDT5, Length 0x47E (1150) bytes
ACPI: SSDT 0x0000000000000000 00047E (v01 XMCC   XMCC1955 00001000 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT4
Input file /sys/firmware/acpi/tables/SSDT4, Length 0x792 (1938) bytes
ACPI: SSDT 0x0000000000000000 000792 (v01 XMCC   XMCC1955 00003000 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT3
Input file /sys/firmware/acpi/tables/SSDT3, Length 0x228 (552) bytes
ACPI: SSDT 0x0000000000000000 000228 (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT2
Input file /sys/firmware/acpi/tables/SSDT2, Length 0x7216 (29206) bytes
ACPI: SSDT 0x0000000000000000 007216 (v02 XMCC   XMCC1955 00000002 MSFT 04000000)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT16
Input file /sys/firmware/acpi/tables/SSDT16, Length 0x517 (1303) bytes
ACPI: SSDT 0x0000000000000000 000517 (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT15
Input file /sys/firmware/acpi/tables/SSDT15, Length 0x7D (125) bytes
ACPI: SSDT 0x0000000000000000 00007D (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT14
Input file /sys/firmware/acpi/tables/SSDT14, Length 0x20A (522) bytes
ACPI: SSDT 0x0000000000000000 00020A (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT13
Input file /sys/firmware/acpi/tables/SSDT13, Length 0x65E (1630) bytes
ACPI: SSDT 0x0000000000000000 00065E (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT12
Input file /sys/firmware/acpi/tables/SSDT12, Length 0x20A (522) bytes
ACPI: SSDT 0x0000000000000000 00020A (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT11
Input file /sys/firmware/acpi/tables/SSDT11, Length 0x30C8 (12488) bytes
ACPI: SSDT 0x0000000000000000 0030C8 (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT10
Input file /sys/firmware/acpi/tables/SSDT10, Length 0x10AC (4268) bytes
ACPI: SSDT 0x0000000000000000 0010AC (v01 XMCC   XMCC1955 00000001 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
External object resolution file /sys/firmware/acpi/tables/SSDT1
Input file /sys/firmware/acpi/tables/SSDT1, Length 0x33BB (13243) bytes
ACPI: SSDT 0x0000000000000000 0033BB (v02 XMCC   XMCC1955 00000000 INTL 20130117)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)

Parsing completed

Found 8 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 - 191166 bytes

Everything seems to be OK, and 8 our control methods were resolved successfully.

Problem 2. DSDT errors

Now we are applying patch from original article (be aware that XMCC version could be different). In my case, proper patch looks like this one:

@@ -18,7 +18,7 @@
  *     Compiler ID      "    "
  *     Compiler Version 0x01000013 (16777235)
  */
-DefinitionBlock ("", "DSDT", 1, "XMCC", "XMCC1955", 0x00000002)
+DefinitionBlock ("", "DSDT", 1, "XMCC", "XMCC1955", 0x00000003)
 {
     External (_SB_.APTS, MethodObj)    // 1 Arguments
     External (_SB_.AWAK, MethodObj)    // 1 Arguments
@@ -733,19 +733,13 @@
         Zero, 
         Zero
     })
-    If ((CNSB == Zero))
+    Name (_S3, Package (0x04)  // _S3_: S3 System State
     {
-        If ((DAS3 == One))
-        {
-            Name (_S3, Package (0x04)  // _S3_: S3 System State
-            {
-                0x03, 
-                0x03, 
-                Zero, 
-                Zero
-            })
-        }
-    }
+        0x03, 
+        0x03, 
+        Zero, 
+        Zero
+    })
 
     Name (_S4, Package (0x04)  // _S4_: S4 System State
     {

Idea is simple - update version to a higher one (in DefinitionBlock) and remove ‘if’ blocks, that are preventing S3 state.

 $ iasl dsdt-sleep.dsl

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

[redacted: many lines with remarks, warnings and errors were deleted]

ASL Input:     dsdt-sleep.dsl -  191027 bytes   2041 keywords   6370 source lines

Compilation failed. 3 Errors, 32 Warnings, 121 Remarks
No AML files were generated due to compiler error(s)

I do not want to do grep for handling multiline errors, so I would simply add -ve flag, which will report only errors:

 $ iasl -ve dsdt-sleep.dsl

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

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

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

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

ASL Input:     dsdt-sleep.dsl -  191027 bytes   2041 keywords   6370 source lines

Compilation failed. 3 Errors, 32 Warnings, 121 Remarks
No AML files were generated due to compiler error(s)

Fixing DSDT compilation

After some small research, I tried to replace Zero with _CRS:

@@ -3564,7 +3564,7 @@
             {
                 Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
                 {
+                    Return (_CRS)
-                    Return (Zero)
                 }
             }
 
@@ -3577,7 +3577,7 @@
             {
                 Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
                 {
+                    Return (_CRS)
-                    Return (Zero)
                 }
             }
 
@@ -3590,7 +3590,7 @@
             {
                 Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
                 {
+                    Return (_CRS)
-                    Return (Zero)
                 }
 
                 Device (WLAN)

Recompiling our patch again:

 $ iasl -ve dsdt-sleep-buffer-fix.dsl 

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

ASL Input:     dsdt-sleep-buffer-fix.dsl -  191027 bytes   2041 keywords   6370 source lines
AML Output:    dsdt-sleep-buffer-fix.aml -   20520 bytes   1137 opcodes     904 named objects

Compilation successful. 0 Errors, 32 Warnings, 124 Remarks, 33 Optimizations

Finally, that worked. Now you can follow further instructions to build cpio archive and add image to initrd.