黑苹果的系统维护

黑苹果的系统维护。

ACPI

DSDT

修改

DTGP方法

许多修复需要调用到该方法,放置于DSDT的前部即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Method (DTGP, 5, NotSerialized)
{
If (LEqual (Arg0, Buffer (0x10)
{
/* 0000 */ 0xC6, 0xB7, 0xB5, 0xA0, 0x18, 0x13, 0x1C, 0x44,
/* 0008 */ 0xB0, 0xC9, 0xFE, 0x69, 0x5E, 0xAF, 0x94, 0x9B
}))
{
If (LEqual (Arg1, One))
{
If (LEqual (Arg2, Zero))
{
Store (Buffer (One)
{
0x03
}, Arg4)
Return (One)
}

If (LEqual (Arg2, One))
{
Return (One)
}
}
}
Store (Buffer (One)
{
0x00
}, Arg4)
Return (Zero)
}

RTC修复

适用于开机时发生错误,然后重新启动的情况。该情况下BIOS会恢复为默认设置。

修改前如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Device (RTC){
Name (_HID, Eisald ("PNP0B00"))
Name (ATT0, ResourceTemplate()
{
IO (Decode16,
0x0070,
0x0070,
0x00,
0x04
)
})
Name (ATT1, ResourceTemplate(){
IO (Decode16,
0x0070,
0x0070,
0x00,
0x04
)
IRQNoFlags ()
{8}
})
Method (_CRS, 0, NotSerialized)
{
If (LGreaterEqual (OSFX, 0x03))
{
If (HPTF){
Return (ATT1)
}
Else
{
Return (ATT0)
}
}
Else
{
Return (ATT0)
}
}
}

修改后如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Device (RTC){
Name (_HID, Eisald ("PNP0B00"))
Name (_CRS, ResourceTemplate() // ATT0修改为_CRS
{
IO (Decode16,
0x0070,
0x0070,
0x00,
0x02 // 0x04修改为0x02以防止BIOS重置
)
})

// 后面的内容非必要,直接删除
}

HPET修复

将HPET设备修改如下即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Device (HPET)
{
Name (_HID, EisaId ("PNP0103"))
Name (_CID, EisaId ("PNP0C01"))
Name (_STA, 0x0F)
Name (_CRS, ResourceTemplate ()
{
IRQNoFlags ()
{0}
IRQNoFlags ()
{8}
Memory32Fixed (ReadOnly,
0xFED00000, // Address Base
0x00000400, // Address Length
)
})
}

PIC/TIMR设备修复

删除它们中的每一条IRQNoFlags () {2}IRQNoFlags () {0}语句即可。

IOATAFamily.kext内核恐慌修复

在SATA和IDE0设备的GPCT方法前添加以下代码。

1
2
3
4
5
6
7
8
9
10
11
Field (IDCS, DWordAcc, NoLock, Preserve)
{
Offset (0x40),
PRIT, 16,
SECT, 16
}
Method (_INI, 0, NotSerialized)
{
Store (0xE307, PRIT)
Store (0xC000, SECT)
}

然后在_WAK方法中的最前面添加以下代码。

1
2
\_SB.PCI0.PATA._INI ()
\_SB.PCI0.SATA._INI ()

原生AHCI支持

在GPCT方法前插入以下代码。此代码依赖DTGP方法,需提前添加DTGP方法到DSDT前部。

1
2
3
4
5
6
7
8
9
10
11
12
13
Method (_DSM, 4, NotSerialized)
{
Store (Package (0x02)
{
"device-id",
Buffer (0x04)
{
0xC5, 0x27, 0x00, 0x00
}
}, Local0)
DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
Return (Local0)
}

Clamshell修复

定位到LID设备的_LID方法并修改如下。

1
2
3
4
5
6
7
8
9
10
11
Name (LIDS, One)
Method (_LID, 0, NotSerialized)
{
Store (^^PCI0.LPC.EC.HPLD, LIDS)
XOr (LIDS, One, Local0)
If (Local0)
{
Notify (SLPB, 0x80)
}
Return (LIDS)
}

修复UUID Error

在DSDT中搜索PCI0设备,查看_UID的值,示例如下。

1
Name (_UID, One)

启动参数添加PciRoot=#即可,其中#为_UID的值,上例为1。

让EHCI USB 2.0识别为内建

此代码依赖DTGP方法,需提前添加DTGP方法到DSDT前部。找到0x001D0007和0x001A0007两个设备,并将原来的设备名称分别更改为EHC1和EHC2。在EHC1设备下添加以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
Method (_DSM, 4, NotSerialized)
{
Store (Package (0x04)
{
"AAPL,clock-id",
Buffer (One)
{
0x01
}
}, Local0)
DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
Return (Local0)
}

在EHC2设备下添加以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
Method (_DSM, 4, NotSerialized)
{
Store (Package (0x04)
{
"AAPL,clock-id",
Buffer (One)
{
0x02
}
}, Local0)
DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
Return (Local0)
}

跳过操作系统检查

在操作系统检查功能的代码下方以及If (LGreaterEqual (_REV, 0x02))上方加入以下代码。

1
2
3
4
Store (One, WNTF)
Store (One, WXPF)
Store (0x02, WSPV)
Store (One, WVIS)

开启亮度滑块

Scope (_SB)块中的_INI方法之后,需要在LNKA设备上方添加以下设备。

1
2
3
4
5
6
7
Device (PNLF)
{
Name (_HID, EisaId ("APP0002"))
Name (_CID, "backlight")
Name (_UID, 0x0A)
Name (_STA, 0x0B)
}

用USB唤醒睡眠

适用于只可通过电源键进行睡眠唤醒的情况。

找到_WAK方法,将Notify附近的代码修改如下。具体为将USB0-USB4修改为UHC1-UHC5,添加EHC1和EHC2,并添加Return方法。

1
2
3
4
5
6
7
8
9
10
11
12
Notify (\_SB.PCI0.UHC1, Zero)
Notify (\_SB.PCI0.UHC2, Zero)
Notify (\_SB.PCI0.UHC3, Zero)
Notify (\_SB.PCI0.UHC4, Zero)
Notify (\_SB.PCI0.UHC5, Zero)
Notify (\_SB.PCI0.EHC1, Zero)
Notify (\_SB.PCI0.EHC2, Zero)
Return (Package (0x02)
{
Zero,
Zero
})

找到Scope (_GPE)物件,将USB0-USB4修改为UHC1-UHC5,USB1-USB2修改为EHC1-EHC2,并删除Notify (\_SB.PCI0.USB3, 0x02),然后在每个修改过的Notify方法后面加Notify (\_SB.PWRB, 0x02)

找到UHC1-UHC5和EHC1-EHC2设备,将其中_PRW中的Package的第二个参数由0x01或One修改为0x03。

添加以下物件后,在引导器配置中修改device-id的参数即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Method (DTGP, 5, NotSerialized)
{
If (LEqual (Arg0, Buffer (0x10)
{
/* 0000 */ 0xC6, 0xB7, 0xB5, 0xA0, 0x18, 0x13, 0x1C, 0x44,
/* 0008 */ 0xB0, 0xC9, 0xFE, 0x69, 0x5E, 0xAF, 0x94, 0x9B
}))
{
If (LEqual (Arg1, One))
{
If (LEqual (Arg2, Zero))
{
Store (Buffer (One)
{
0x03
}, Arg4)
Return (One)
}

If (LEqual (Arg2, One))
{
Return (One)
}
}
}
Store (Buffer (One)
{
0x00
}, Arg4)
Return (Zero)
}

使用VoodooHDA但忘记删除AppleHDA修复

注释HDEF设备即可。

引导加载AC适配器驱动

在AC设备的Name (_UID, Zero)后添加以下代码。

1
2
3
4
5
Name (_PRW, Package (0x02)
{
0x18,
0x03
})

引导加载AppleLPC

DSDT搜索0x001F0000,查看对应的设备,对于技嘉为PX40,可全部修改为LPCB或不修改。然后在该设备添加以下方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
Method (_DSM, 4, NotSerialized)
{
Store (Package (0x02)
{
"device-id",
Buffer (0x04)
{
0x18, 0x3A, 0x00, 0x00
}
}, Local0)
DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
Return (Local0)
}

其中device-id列表如下。

device-id 型号
0x02, 0x3B, 0x00, 0x00 5 Series/3400 Series
0x01, 0x3B, 0x00, 0x00 Mobile 5 Series
0x00, 0x3B, 0x00, 0x00 5 Series
0x18, 0x3A, 0x00, 0x00 ICH10
0x16, 0x29, 0x00, 0x00 ICH9R
0x15, 0x28, 0x00, 0x00 ICH8M
0x11, 0x28, 0x00, 0x00 ICH8M-E
0xBD, 0x27, 0x00, 0x00 ICH7M-DH
0xB9, 0x27, 0x00, 0x00 ICH7M
0x70, 0x26, 0x00, 0x00 ICH6-ESB

引导加载显卡驱动

DSDT搜索PCI0,然后在设备内添加以下内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
Device (PEGP)
{
Name (_ADR, 0x00010000)
Device (GFX0)
{
Name (_ADR, Zero)
Name (_SUN, One)
Method (_DSM, 4, NotSerialized)
{
Store (Package (0x18)
{
// ****可不使用此部分****
"AAPL,slot-name",
Buffer (0x07)
{
"Slot-1"
},
// ********************

"device_type",
Buffer (0x0C)
{
"NVDA,Parent"
},

// 根据显卡名称修改,注意也要修改0x17为字符串长度
"model",
Buffer (0x17)
{
"NVIDIA Geforce 9800 GT"
},

// 在Windows下通过NVFlash取得,具体查看以下解释
"NVCAP",
Buffer (0x14)
{
/* 0000 */ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
/* 0008 */ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
/* 0010 */ 0x00, 0x00, 0x00, 0x00
},

// 根据显卡名称修改,注意也要修改0x06为字符串长度
"rom-revision",
Buffer (0x06)
{
"3173a"
},

// 显卡显存
// 0x10为256MB
// 0x20为512MB
// 0x40为1024MB
"VRAM,totalsize",
Buffer (0x04)
{
0x00, 0x00, 0x00, 0x20
},

"@0,compatible",
Buffer (0x0B)
{
"NVDA,NVMac"
},

"@0,device_type",
Buffer (0x08)
{
"display"
},

"@0,name",
Buffer (0x0F)
{
"NVDA,Display-A"
},

"@1,compatible",
Buffer (0x0B)
{
"NVDA,NVMac"
},

"@1,device_type",
Buffer (0x08)
{
"display"
},

"@1,name",
Buffer (0x0F)
{
"NVDA,Display-B"
}
}, Local0)
DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
Return (Local0)
}
}
}

NVCAP的内容需要先在Windows下打开NVFlash,并输入以下命令以生成ROM。

1
nvflash -b nvidia.rom

然后在Mac下使用NVCAP Maker打开生成的nvidia.rom,得到数字后两两分开即可,示例如下。

1
2
3
4
5
# 处理前
04000000000003000c0000000000000700000000

# 处理后
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00

禁用显卡

在显卡设备的_INI方法添加以下代码即可。

1
_OFF()

若提示未找到对象,添加外部引用即可。

引导加载声卡驱动

DSDT搜索0x001B0000,查看对应的设备,应当为AZAL。将AZAL全部修改为HDEF,然后在该设备添加以下方法即可,注意layout-id需要配合自行制作的驱动参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Method (_DSM, 4, NotSerialized)
{
Store (Package (0x04)
{
"layout-id",
Buffer (0x04)
{
0x78, 0x03, 0x00, 0x00
},

"PinConfigurations",
Buffer (Zero) {}
}, Local0)
DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
Return (Local0)
}

设置调节风扇转速快捷键

以Fn+Home为例,该快捷键在_Q14被定义。也可使用Fn+End,定义于_Q15。根据需求,在快捷键的对应方法添加以下代码。

1
2
3
4
5
6
7
8
9
# 选择其一即可
## 自动模式
Store (0x80, \_SB.PCI0.LPC.EC.HFSP)
## 关闭
Store (0x00, \_SB.PCI0.LPC.EC.HFSP)
## 最慢
Store (0x01, \_SB.PCI0.LPC.EC.HFSP)
## 最快
Store (0x05, \_SB.PCI0.LPC.EC.HFSP)

亮度按键映射

对于使用VoodooPS2Controller,补丁如下。注意LPCB也可能为LPC、SBRG,PS2K也可能为KBD、KBD0。

1
2
3
4
5
6
7
8
9
10
into method label _Q11 replace_content
begin
// Brightness Down\n
Notify(\_SB.PCI0.LPCB.PS2K, 0x0405)\n
end;
into method label _Q12 replace_content
begin
// Brightness Up\n
Notify(\_SB.PCI0.LPCB.PS2K, 0x0406)\n
end

对于使用ApplePS2SmartTouchPad,补丁如下。注意PS2K也可能为KBD、KBD0。

1
2
3
4
5
6
7
8
9
10
11
into method label _Q11 replace_content
begin
// Brightness Down\n
Notify (PS2K, 0x20)\n
end;

into method label _Q12 replace_content
begin
// Brightness Up\n
Notify (PS2K, 0x10)\n
end;

加载AppleLPC

加载AppleLPC可实现原生CPU电源管理。

查看SLE下的AppleLPC.kext/Contents/Info.plist,可查看和AppleLPC匹配的设备ID。打开DSDT,搜索0x001F0000,在该设备下添加以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
Method (_DSM, 4, NotSerialized)
{
Store (Package (0x02)
{
"device-id",
Buffer (0x04)
{
0x18, 0x3A, 0x00, 0x00
}
}, Local0)
DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
Return (Local0)
}

修改后需要屏蔽IRQ。查找PNP0000,按以下代码屏蔽IRQ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Device (PIC)
{
...
Name (_CRS, ResourceTemplate()
{
IO (Decode16,
0x0020,
0x0020,
0x01,
0x02,
)
IO (Decode16,
0x00A0,
0x00A0,
0x01,
0x02,
)

/* IRQNoFlags ()
{2} */
})
}

查找PNP0100,按以下代码屏蔽IRQ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Device (TMR){
...
Name (ATT5, ResourceTemplate()
{
IO (Decode16,
0x0040,
0x0040,
0x00,
0x04,
)

/* IRQNoFlags ()
{0} */
})
...
}

调试

可在任意地方插入以下代码,运行时睡眠灯将会闪烁。

1
2
3
\_SB.PCI0.LPC.EC.LED (0x07, 0x80)
Sleep(0x64)
\_SB.PCI0.LPC.EC.LED (0x07, 0x00)

SSDT

应当实现以下SSDT修补。以下修补文件在OpenCore的AcpiSamples文件夹。

列表

平台 CPU EC AWAC/RTC NVRAM USB PCI Backlight I2C触控板 IRQ IMEI
Penryn / SSDT-EC / / / /
Lynnfield and Clarkdale / SSDT-EC / / / /
Clarksfield and Arrandale / SSDT-EC / / SSDT-PNLF IRQ SSDT /
Sandy Bridge CPU-PM(系统安装后使用) SSDT-EC / / / / SSDT-PNLF IRQ SSDT SSDT-IMEI(用于7代主板)
Ivy Bridge CPU-PM(系统安装后使用) SSDT-EC / / / / SSDT-PNLF IRQ SSDT SSDT-IMEI(用于6代主板)
Haswell SSDT-PLUG SSDT-EC / / / / SSDT-PNLF SSDT-GPI0 IRQ SSDT /
Broadwell SSDT-PLUG SSDT-EC / / / / SSDT-PNLF SSDT-GPI0 IRQ SSDT /
Skylake SSDT-PLUG SSDT-EC-USBX / / / / SSDT-PNLF SSDT-GPI0 / /
Kaby Lake SSDT-PLUG SSDT-EC-USBX / / / / SSDT-PNLF SSDT-GPI0 / /
Coffee Lake (8th Gen) and Whiskey Lake SSDT-PLUG SSDT-EC-USBX SSDT-AWAC SSDT-PMC / / SSDT-PNLF-CFL SSDT-GPI0 / /
Coffee Lake (9th Gen) SSDT-PLUG SSDT-EC-USBX SSDT-AWAC SSDT-PMC / / SSDT-PNLF-CFL SSDT-GPI0 /
Comet Lake SSDT-PLUG SSDT-EC-USBX SSDT-AWAC / SSDT-RHUB / SSDT-PNLF-CFL SSDT-GPI0 / /
Ice Lake SSDT-PLUG SSDT-EC-USBX SSDT-AWAC / SSDT-RHUB / SSDT-PNLF-CFL SSDT-GPI0 / /
AMD (15/16h, Bulldozer/Jaguar) / SSDT-EC-USBX / / / /
AMD (17/19h, Zen) SSDT-CPUR for B550 and A520 SSDT-EC-USBX / / / /
Nehalem and Westmere / SSDT-EC / / / /
Sandy Bridge-E / SSDT-EC / / / SSDT-UNC
Ivy Bridge-E / SSDT-EC / / / SSDT-UNC
Haswell-E SSDT-PLUG SSDT-EC-USBX SSDT-RTC0-RANGE / / SSDT-UNC
Broadwell-E SSDT-PLUG SSDT-EC-USBX SSDT-RTC0-RANGE / / SSDT-UNC
Skylake-X SSDT-PLUG SSDT-EC-USBX SSDT-RTC0-RANGE / / /
【旧版】SSDT列表
名称 解释
SSDT-Config SSDT控制入口文件
SSDT-LPC 正确识别LPC总线到系统
SSDT-SMBUS 正确识别SMBus到系统
SSDT-DMAC 将DMA控制器公开给系统
SSDT-MCHC 将内存控制器暴露在系统中
SSDT-IGPU 将属性添加到集成显卡设备,可以实现HDMI音频以及正确显示
SSDT-Disable_DGPU 在启动时关闭独立显卡,因为Mac OS无法使用它
SSDT-ALS0 添加假环境光传感器以在重新启动之间保存背光信息
SSDT-BRT6 将键盘的ACPI管理亮度键映射到VoodooPS2Controller.kext的PS2代码
SSDT-Dell_FN 将键盘的ACPI管理亮度键映射到VoodooPS2Controller.kext的PS2代码 (部分DELL机型)
SSDT-PNLF 显示器亮度控制,为IntelBacklight.kext或AppleBacklight.kext + AppleBacklightInjector.kext添加PNLF设备
SSDT-HDAU 自动注入HDAU属性(适用于Haswell和Broadwell平台)
SSDT-HDEF 自动注入HDEF属性(声卡layoutid注入点)
SSDT-GPRW 通过挂接GPRW或UPRW来解决即时唤醒
SSDT-LANC_PRW 通过挂接GPRW来解决即时唤醒
SSDT-UPRW 通过挂接GPRW或UPRW来解决即时唤醒
SSDT-IMEI 添加IMEI(6系列HD4000,7系HD3000)
SSDT-PTSWAK 在睡眠之前对离散GPU进行驱动,并在唤醒后将其关闭,以确保系统能够跟踪它
SSDT-Debug 用于ACPIDebug,该文件是通过将「添加DSDT调试方法」应用于空SSDT创建的,使用「添加SSDT调试外部声明」从其他方式访问这些方法hotpatch SSDT甚至打补丁的OEM ACPI文件
SSDT-ESEL 关闭ESEL,在DSDT里原生ESEL被重命名为ESEX
SSDT-XWAK 关闭XWAK,在DSDT里原生的XWAK被重命名为ZWAK
SSDT-PluginType1 在_PR.CPU0上插入plugin-type=1,可能是所有支持XCPM的SMBIOS只需要这种插件类型的注入
SSDT-SATA 修复某些不支持的SATA设备
SSDT-XHC 自动注入XHC属性
SSDT-XOSI 操作系统补丁
SSDT-AWAC 修复300系列主板(B360/B365/H310/H370/Z390等)系列主板的RTC设备问题,部分微星的主板/清华同方九代模具需要应用这个补丁,否则会卡住而无法进入系统,建议八代 CoffeeLake以上的用户都添加
SSDT-EC-USBX 添加了一个仿冒的EC设备并完善了USB的供电,若主板的EmbeddedController原生ACPI命名就是EC则不需要该补丁
SSDT-PMC 与NVRAM相关
SSDT-PLUG 启用原生电源管理,Skylake六代以上的机型在Clover中可以直接勾选注入插件类型,自动注入plugin-type=1参数实现同等效果

SSDT示例

SSDT-EC

禁用原有EC设备,并新建一个新的EC设备。

1
2
3
4
5
# Desktop
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-EC-DESKTOP.aml

# Laptop
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-EC-LAPTOP.aml
【进阶】手动编写

在DSDT中搜索PNP0C09,即可定位到EC设备。也可在Windows下的设备管理器下查找Embedded Controller,右键选择属性,在详细页面选择BIOS名称查看设备路径。

根据需求下载以下示例并打开。

1
2
3
4
5
# SSDT-EC-USBX
https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-EC-USBX.dsl

# SSDT-EC
https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-EC.dsl

若为笔记本,则不要修改注释掉的代码,否则取消对代码的注释。这段代码的主要用途为禁用EC设备。

重命名以下地方为获得的EC设备路径。

1
2
External (_SB_.PCI0.LPCB, DeviceObj)
Scope (_SB.PCI0.LPCB)

若出现多个PNP0C09,则检查是否存在_HID_CRS_GPE方法,若均存在,则该设备为所求的EC设备。但若有_STA方法,说明该EC设备是无用设备。

若无PNP0C09,则只需虚拟一个EC。尝试搜索LPCB、LPC0、LPC、SBRG、PX40,若其一存在,则使用其LPC路径取代SSDT中的EC设备路径。

若PNP0C09已被重命名为EC,则无需使用以上SSDT。但若为Skylake及更新版本,则仍需要SSDT-USBX。

SSDT-EC-USBX

用于禁用真正的嵌入式控制器并为Mac创建一个假的控制器。USBX部分用于注入Skylake和更新版本上缺少的USB电源属性。

1
2
3
4
5
# Desktop
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-EC-USBX-DESKTOP.aml

# Laptop
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-EC-USBX-LAPTOP.aml

在Catalina及更新版本中,AppleACPIEC.kext及其插件和USB电源管理依赖于名为EC的ACPI设备。同时,AppleBusPowerController也会查找名为EC的设备,还需要一个USBX设备来为Skylake和更新版本提供USB电源属性,因此SSDT-EC-USBX将SSDT-EC和SSDT-USBX进行了结合。

EC设备在笔记本上主要用于电池管理和热键处理,在台式机上与AppleACPIEC冲突。因此在笔记本上可以通过创建一个假EC设备实现启动,而在台式机中直接禁用该设备。

【备注】SSDT-USBX

SSDT-USBX不可使用于Broadwell及更早版本。

1
https://github.com/dortania/OpenCore-Post-Install/blob/master/extra-files/SSDT-USBX.aml

SSDT-IMEI

在ACPI中不存在IMEI设备时创建IMEI设备。

使用Sandy Bridge CPU的7系列主板(B75、Q75、Z75、H77、Q77、Z77)和Ivy Bridge CPU的6系列主板(H61、B65、Q65、P67、H67、Q67、Z68)需要。

在DSDT中搜索IMEI/HECI/MEI,若出现其一,则不需要SSDT-IMEI。若未出现则需要使用。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-IMEI.aml

SSDT-PLUG

启用Apple的XCPM,从而实现更好的CPU电源管理。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-PLUG-DRTNIA.aml

SSDT-AWAC/SSDT-RTC0-RANGE-HEDT

在Mac中启用旧版RTC时钟,因为不支持较新的AWAC时钟。适用于以下主板。

1
2
3
4
5
6
7
8
9
10
11
12
B360
B365
H310
H370
Z370 (Gigabyte and AsRock boards with newer BIOS versions)
Z390
B460
Z490
400 series (Comet Lake, including Z490)
495 series (Icelake)
X99
X299

SSDT-RTC0-RANGE-HEDT还解决了由于ACPI实施不佳而导致的Big Sur启动的提前停止。

1
2
3
4
5
6
7
# SSDT-AWAC
# 适用于大多数主板
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-AWAC.aml

# SSDT-RTC0-RANGE-HEDT
# 适用于Intel的X99和X299平台
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-RTC0-RANGE-HEDT.aml
【进阶】手动编写

在DSDT中搜索ACPI000E,用于搜索AWAC设备。若无该设备则无需进行以下操作。

继续搜索PNP0B00,用于搜索RTC设备。若有该设备,则证明可以禁用AWAC并启用RTC,使用上面的SSDT-AWAC即可。

若无RTC设备,则需要使用SSDT-RTC0,如下。

1
https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-RTC0.dsl

需要改动的设备路径如下,其中LPCB路径可通过搜索Name (_ADR, 0x001F0000)查看。注意应当保证PCI设备存在,可通过搜索PNP0A08确定。

1
2
External (_SB_.PCI0.LPCB, DeviceObj)
Scope (_SB.PCI0.LPCB)

SSDT-PMC

在300系列主板上启用本机NVRAM,如B360、B365、H310、H370、Z390。Z370、HM370不需要。仅适用于第九代笔记本电脑,第十代不需要。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-PMC.aml
【进阶】手动编写

需要使用的SSDT如下。

1
https://github.com/acidanthera/OpenCorePkg/tree/master/Docs/AcpiSamples/Source/SSDT-PMC.dsl

需要改动的设备路径如下,其中LPCB路径可通过搜索Name (_ADR, 0x001F0000)查看。注意应当保证PCI设备存在,可通过搜索PNP0A08确定。

1
2
External (_SB_.PCI0.LPCB, DeviceObj)
Scope (_SB.PCI0.LPCB)

SSDT-RHUB

重置Asus 400系列主板上的USB控制器。Gigabyte、MSI、AsRock等不需要。主要用于使用Ice Lake的Dell笔记本。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-RHUB.aml
【进阶】手动编写

需要使用的SSDT如下。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/decompiled/SSDT-RHUB.dsl

需要改动的设备路径如下,其中RHUB路径可通过搜索Device (RHUB)查看。也可搜索XHC/XHCI/XHC1。注意应当保证PCI设备存在,可通过搜索PNP0A08确定。

1
2
External (_SB_.PCI0.XHC1.RHUB, DeviceObj)
Scope (_SB.PCI0.XHC1.RHUB)

SSDT-PNLF

控制内部显示器背光。在极少数情况下,可能需要修改GFX0为显卡设备名称。

1
2
3
4
5
# Kaby Lake及更低
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-PNLF.aml

# Coffee Lake及更高
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-PNLF-CFL.aml

SSDT-XOSI

在macOS中启用许多仅限Windows的功能。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-XOSI.aml

SSDT-UNC

确保正确禁用未使用或丢失的非核心桥接器,否则会在Big Sur中出现IOPCIFamily的panic。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-UNC.aml

SSDT-CPUR

用于修复ACPI中的CPU定义,因为Mac不能正确支持B550和更新的主板中使用的ACPI。仅无threadripper的机器以及B550、A520和更新版本需要,X570和更旧版本并不需要。

1
https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-CPUR.aml

SSDT-SBUS-MCHC

修复AppleSMBus。非必需,安装时无需此SSDT。

打开Hackintool并点击PCI选项卡,在SubClass下查找SMBus设备,即可找到其ACPI路径。也可在Windows下通过设备管理器,查找SMBus设备并查看其BIOS名称。

获取以下示例。

1
https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-SBUS-MCHC.dsl

需要修改的设备路径如下,修改为上面找到的SMBus设备路径即可。

1
2
3
4
5
6
7
External (_SB_.PCI0, DeviceObj)
External (_SB_.PCI0.SBUS.BUS0, DeviceObj)
Scope (_SB.PCI0)
{
...
}
Device (_SB.PCI0.SBUS.BUS0

编译并放置后,可在终端输入以下命令以查看是否工作。

1
kextstat | grep -E "AppleSMBusController|AppleSMBusPCI"

IRQ SSDT

使用SSDTTime即可。

【进阶】对于HP Compaq DC7900

需要以下SSDT。

1
https://github.com/khronokernel/trashOS/blob/master/HP-Compaq-DC7900/0.6.1%20HP%20EFI/EFI/OC/ACPI/SSDT-CSR-HPET.aml

在OpenCore配置文件的ACPI-Patch添加以下内容。

1
2
3
Comment: change CRES to XCRES
Find: 48504554085F4849440C41D00103085F5549440A010843524553
Replace: 48504554085F4849440C41D00103085F5549440A010858524553

FixShutdown-USB-SSDT

用于替代FixShutdown。

1
2
3
4
https://github.com/dortania/OpenCore-Post-Install/blob/master/extra-files/FixShutdown-USB-SSDT.dsl

# 搭配以下更名补丁
https://github.com/dortania/OpenCore-Post-Install/blob/master/extra-files/FixShutdown-Patch.plist

SSDT生成

可使用SSDTTime生成部分SSDT,具体如下。

1
2
3
4
5
6
IRQ patch
SSDT-EC(注意没有SSDT-EC-USBX,可手动添加SSDT-USBX)
SSDT-PLUG
SSDT-PMC
SSDT-AWAC/RTC0
SSDT-RHUB

注意,若进行FixHPET,还需要将oc_patches.plist合并到原来的配置文件中,具体为添加ACPI-Patch部分。

SSDT制作

基础知识

外部引用

由于SSDT仅为DSDT的一部分,在该SSDT中的变量可能并不在这段代码中定义,在编译时则会出现对象不存在错误。因此需要添加外部引用,声明该变量在DSDT中已被定义过。

外部引用通过以下语句完成,它应当填到DefinitionBlock的下面。

1
External ([字段名(包含路径)], [字段对象])

在DSDT中搜索需要添加的外部字段,一般所得到的第一个结果即为其字段定义,字段定义与字段对象的对应关系如下表。编译不报错时,添加外部引用完成。

添加外部引用的示例可参照电池修补过程。

字段定义 字段对象 含义 示例
Name (GZXB, 0) IntObj 整数 External (GZXB, IntObj)
Field (…){…, OSYS,16, …} FieldUnitObj 字段单元 External (OSYS, FieldUnitObj)
Mutex (BATM, 0x07) MutexObj 互斥体 External (_SB.PCI0.LPCB.H_EC.BATM, MutexObj)
Name (BPKH, Package (0x07){……}) PkgObj External (_SB.PCI0.LPCB.H_EC.BAT1.BPKH, PkgObj)
Device (TPD0) DeviceObj 设备 External (_SB.PCI0.I2C1.TPD0, DeviceObj)
Method (_STA, 0, NotSerialized) MethodObj 函数 External (_SB.PCI0.I2C1.TPD0._STA, MethodObj)
OperationRegion (GNVS, SystemMemory, 0x7A4E7000, 0x0866) OpRegionObj 操作区 External (GNVS, OpRegionObj)
Event (XXXX) EventObj 事件 External (XXXX, EventObj)
ThermalZone (THRM) ThermalZoneObj 温控区 External (THRM, ThermalZoneObj)
CreateField (AAAA, Zero, BBBB) BuffFieldObj 缓冲区 External (_SB.PCI0._CRS.BBBB, BuffFieldObj)
Name (BPKH, Buffer (0x07){……}) BuffObj 缓冲 External (BPKH, BuffObj)
/ UnknownObj 未知 External (_SB.EROR, UnknownObj)
Name (MSTR,"ASL") StrObj 字符串 External (_PR.MSTR, StrObj)
PowerResource (USBC, 0, 0) PowerResObj 电源资源 External (_SB.PCI0.XDCI, PowerResObj
Processor (PR00, 0x01, 0x00001810, 0x06) ProcessorObj 处理器 External (_SB.PR00, ProcessorObj)
/ DDBHandleObj
偏移量

以下代码中GNVS可以替换为任意名称,因为0x100, Zero指向该地址的范围,偏移量地址已经被确定。而OOXX可以用0x1E代替,因为首先要保证的是字段的偏移量正确,故OOXX与OOX1互换,其数据也会跟着变化。

偏移量以字节为单位,一字节等于8位,故OOX1的偏移量为0x1E+1=0x20。

1
2
3
4
5
6
7
8
9
Name (OOXX, Zero)
OperationRegion (GNVS, SystemMemory, 0x100, Zero)
Field (GNVS,AnyAcc, Lock, Preserve)
{
Offset(0x1E),
OOXX, 16, // 0x1E
OOX1, 8, // 0x20
......
}
预置变量法开关设备

每个设备的_STA方法用于控制设备开关,返回非零为开,返回零为关。因此通过修改_STA的返回值,可以禁用或启用该设备。

预置变量法即在SSDT中对某些变量预先赋值,使某个设备的_STA按照需求返回零或非零。

一般情况

被修正的变量可能存在于多个地方,对它修正后,在达到预期效果的同时,有可能影响到到其它部件。因此应当尽量修正该设备独有的变量。

预置变量法的示例可参照I2C触控板修补过程。

特殊情况

被修正的变量可能来自硬件信息,只能读取不能写入。这种情况下需要二进制更名和SSDT补丁共同完成。示例原文如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// IM01为只读
// 实际情况IM01不等于0x02,If内的代码无法被执行
OperationRegion (PNVA, SystemMemory, PNVB, PNVL)
Field (PNVA, AnyAcc, Lock, Preserve)
{
...
IM01, 8,
...
}
...
If ((IM01 == 0x02))
{
...
}

为修改IM01,需要将IM01重命名,然后直接通过操作系统而非IM01作为判断条件。假设重命名为XM01,则重命名如下。

1
2
3
Comment: change IM01 to IM01
Find: 49 4D 30 31 08
Replace: 58 4D 30 31 08

补丁如下。该补丁表示如果操作系统不是Mac,则将IM01恢复为原值。

1
2
3
4
5
6
7
8
9
Name (IM01, 0x02)
If (_OSI ("Darwin"))
{
...
}
Else
{
IM01 = XM01 /* 同原始ACPI变量的路径 */
}

对于仅包含返回设备状态的使能位和根据条件判断返回的使能位的_STA方法,可以直接将该方法引用为IntObj并赋值。示例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 示例一
Method (_STA, 0, NotSerialized)
{
If ((XXXX == Zero))
{
Return (Zero)
}
Return (0x0F)
}

// 示例二
Method (_STA, 0, NotSerialized)
{
Return (0x0F)
}

// 示例三
Name (_STA, 0x0F)

补丁如下。该方法有效的原因是_STA方法在操作系统OSPM模块对设备状态评估和初始化的优先级高于_INI_ADR_HID,且_STA的返回值本身也是整数Integer。

1
2
3
External (_SB_.PCI0.XXXX._STA, IntObj)

\_SB.PCI0.XXXX._STA = Zero

不可使用该方法的示例如下。原因是_STA方法中还有其它操作,直接让_STA返回会使这些操作失效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 示例一
Method (_STA, 0, NotSerialized)
{
ECTP (Zero)
If (XXXX == One)
{
Return (0x0F)
{

Return (Zero)
}

// 示例二
Method (_STA, 0, NotSerialized)
{
^^^GFX0.CLKF = 0x03
Return (Zero)
}
基本框架

打开MaciASL,新建文件并将本机DSDT中的DefinitionBlock头复制到文件中。然后将里面的DSDT改为SSDT,即可得到适用于本机的SSDT框架。保存时文件名应当以SSDT-开头。

所有SSDT补丁均需满足该基本框架的需求。以下示例的DefinitionBlock头应当根据本机的具体内容替换。

1
2
3
4
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{

}

电池修补

请基于在修改DSDT后设备能够正常显示电量的前提下制作此热补丁。

电池热补丁的基本原理是,新建一个OperationRegion块,在这个新块里动态注入所有的拆分字节数据,同时对原有的未拆分字节保留空位,从而在保证位移量正确的情况下正确注入并引用新的数据。

确认修改位置

打开IORegistryExplorer,查找BAT,记录电池设备名称,本机为SB.PCI0.LPCB.EC0.BAT0。对修补DSDT的补丁进行分析,内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 字段拆分
into device label EC0 code_regex B0C3,\s+16, replace_matched begin C3HG,8,C3HF,8, end;
into device label EC0 code_regex B0SN,\s+16, replace_matched begin BSVN,8,BSVM,8, end;
into device label EC0 code_regex B1SN,\s+16 replace_matched begin SBUY,8,SBUP,8 end;

// 替换调用方法
into method label _BIX code_regex \(B0C3, replaceall_matched begin (B1B2(C3HG,C3HF), end;
into method label BIFA code_regex \(B0SN, replaceall_matched begin (B1B2(BSVN,BSVM), end;
into method label BIFA code_regex \(B1SN, replaceall_matched begin (B1B2(SBUY,SBUP), end;

// 数据处理方法
into method label B1B2 remove_entry;
into definitionblock code_regex . insert
begin
Method (B1B2, 2, NotSerialized)\n
{\n
Return(Or(Arg0, ShiftLeft(Arg1, 8)))\n
}\n
end;

可以得出,实际修改的字节数据如下。

1
2
3
B0C3->B1B2(C3HG,C3HF)
B0SN->B1B2(BSVN,BSVM)
B1SN->B1B2(SBUY,SBUP)

故需要拆解的字节有B0C3、B0SN、B1SN,需要添加的额外方法(Method)为B1B2。比对原DSDT和已修改好的DSDT,查找调用到这些变化过的字段的Method位置,以及需要添加的Method出现位置。本机调用到B0C3、B0SN、B1SN的Method为BIFA和_BIX,需添加的额外方法B1B2在原DSDT中不存在,在修改过的DSDT中位于根目录。至此所有需要修改的地方已完全确定。

数据插入

打开MaciASL,新建一个SSDT框架,如下。

1
2
3
4
5
// xxxx用说找到的电池设备名(此处为BAT0)替换
DefinitionBlock ("", "SSDT", 2, "hack", "xxxx", 0x00000000)
{

}

打开原DSDT并搜索EmbeddedControl,复制整个OperationRegion到这个热补丁内。注意要把整个OperationRegion复制过来,即从OperationRegion行始,到第一个}止。

然后把调用到变化字段的Method和所有额外添加的Method复制到OperationRegion后。对于本机而言,需复制OperationRegion段、Method (BIFA)、Method (_BIX)、Method (B1B2),故完成后代码结构应如下所示。注意,在同一个设备下的Method需放到一起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
OperationRegion (ECOR, EmbeddedControl, Zero, 0xFF)
Field (ECOR, ByteAcc, Lock, Preserve)
{
Offset (0x04),
......
}

Method (BIFA, 0, NotSerialized)
{
......
}

Method (_BIX, 0, NotSerialized)
{
......
}

Method (B1B2, 2, NotSerialized)
{
Return (Or (Arg0, ShiftLeft (Arg1, 0x08)))
}
添加位置代码

在代码块前需添加它们的位置代码,以使BIOS修补时有迹可循。在代码块的前后分别用以下代码框住即可,注意xxxx为位置,需要用绝对路径。

1
2
3
4
Scope (xxxxx)
{

}

以本机为例,本机的OperationRegion和BIFA方法均在_SB.PCI0.LPCB.EC0下,而_BIX方法位于_SB.PCI0.LPCB.EC0的BAT0设备下。因此将OperationRegion和BIFA用Scope (_SB.PCI0.LPCB.EC0)框住,而_BIX方法则用Scope (_SB.PCI0.LPCB.EC0.BAT0)框住,如下。注意,B1B2和B1B4方法放置于根目录,故无需位置代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
DefinitionBlock ("", "SSDT", 2, "hack", "BAT0", 0x00000000)
{

// OperationRegion和BIFA
Scope (_SB.PCI0.LPCB.EC0)
{
OperationRegion (ECOR, EmbeddedControl, Zero, 0xFF)
Field (ECOR, ByteAcc, Lock, Preserve)
{
......
}

Method (BIFA, 0, NotSerialized)
{
......
}
}

// _BIX
Scope (_SB.PCI0.LPCB.EC0.BAT0)
{
Method (_BIX, 0, NotSerialized)
{
......
}
}

// B1B2
Method (B1B2, 2, NotSerialized)
{
Return (Or (Arg0, ShiftLeft (Arg1, 0x08)))
}
}
添加外部引用

完成以上步骤后进行编译,并根据相应错误添加外部引用。

首先添加设备引用。以上面代码为例,设备_SB.PCI0.LPCB.EC0_SB.PCI0.LPCB.EC0.BAT0被引用,故需用以下语句进行声明。

1
2
// xxxx是设备地址
External (xxxx, DeviceObj)

该部分语句需添加到DefinitionBlock的下面,故代码如下,其中DeviceObj表示这是一个ACPI设备。再次编译,有关设备的报错均已消失。

1
2
3
4
5
6
7
DefinitionBlock ("", "SSDT", 2, "hack", "BAT0", 0x00000000)
{
External (_SB.PCI0.LPCB.EC0, DeviceObj)
External (_SB.PCI0.LPCB.EC0.BAT0, DeviceObj) // 可以不写这行
Scope (_SB.PCI0.LPCB.EC0)
{
......

然后根据报错,继续在DSDT里搜索其他的报错代码。如对于BIXT,它是BAT0设备下的一个字段,在DSDT查询到的第一个结果是Name (BIXT,因此用以下代码进行外部引用。

1
External (_SB.PCI0.LPCB.EC0.BAT0.BIXT, IntObj)

对于其余变量方法同理,字段定义与字段对象的对应关系见前面所列出的表格。

字节处理

首先需要把OperationRegion和Field里的字段重命名。以本机为例,由ECOR重命名为ECAG,如下。

1
2
OperationRegion (ECAG, EmbeddedControl, Zero, 0xFF)
Field (ECAG, ByteAcc, Lock, Preserve)

然后要使字段有正确的偏移量,可把Field里所有不拆分的字节数据段名字去掉,只保留空位,如ACST, 1,清空变量名后变为, 1,。示例如下。

1
2
3
4
5
6
7
8
9
10
11
Offset (0x93),
TH00, 8,
TH01, 8,
TH10, 8,
TH11, 8,
Offset (0xBE),
, 16,
, 16,
, 16,
XC30, 8,
XC31, 8,

或可采用以下注释的形式。

1
2
3
4
5
6
7
8
9
10
11
Offset (0x93),
TH00, 8,
TH01, 8,
TH10, 8,
TH11, 8,
Offset (0xBE),
/*B0TM*/, 16,
/*B0C1*/, 16,
/*B0C2*/, 16,
XC30, 8,
XC31, 8,

或可手动计算偏移量,如下。

1
2
3
4
5
6
7
8
Offset (0x93),
TH00, 8,
TH01, 8,
TH10, 8,
TH11, 8,
Offset (0xC4), // 原本为0xBE,加上三个16字节的偏移量后变为0xC4
XC30, 8,
XC31, 8,

修改完成后,将之前的电量补丁Patch使其生效,然后编译并保存。

添加更名补丁

将热补丁中从原始DSDT复制过来的Method名全部进行修改,如热补丁中有从DSDT复制过来的代码Method (BIFA, 1, NotSerialized),则BIFA需要更名。此处以更名为BIGA为例,打开config.plist,添加以下更名规则即可。

1
2
3
Comment: change BIFA(1, N) to BIGA(1, N)
Find: 42494641 01
Replace: 42494741 01

若所需要更改的方法名位于电池设备(即BAT0)内,则在Tgtbridge栏还应加入该电池设备名的16进制数,如下。

1
2
3
4
Comment: change _BIX(1, N) to XBIX(1, N) in BAT0
Find: 5F424958 01
Replace: 58424958 01
Tgtbridge: 42415430

但如果添加Tgtbridge后电池补丁反而失效,则将Tgtbridge值删除。

添加_OSI判断

在已经完成的补丁文件中,在每一个Method的开始部分加上_OSI系统判断并在结尾处回调原始方法,示例如下。

1
2
3
4
5
6
7
8
9
10
11
Method (_BIF, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
// 修改过的方法内容
}
Else
{
Return (XBIF ()) // XBIF为修改后的方法名,即此处为change _BIF to XBIF
}
}

Else后面的代码为回调原始方法,如果原始方法没有出现Return语句,则可直接以XBIF()的方式回调。如果原始方法的代码中出现了Return语句,则在回调时也需要以Return形式回调原方法,示例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Method (SMTF, 1, NotSerialized)
{
If (_OSI ("Darwin"))
{
If ((Arg0 == Zero))
{
Return (B1B2 (B0ET, B1ET))
}

If ((Arg0 == One))
{
Return (Zero)
}

Return (Zero)
}
Else
{
Return (XMTF (Arg0))
}
}
完成修补

将上述SSDT保存为aml文件,放到引导器的ACPI部分即可。

特殊处理
惠普笔记本ACEL设备禁止

部分惠普笔记本配备机械硬盘防护传感器。该设备实际为一个加速度传感器,即便没有驱动也能保持运行,持续向EC中读写数据,会导致电池状态刷新异常。

在Windows下确认该设备ACPI名称为ACEL后,可通过ACPI更名其_STA,并在热补丁中要求macOS下禁止该设备即可。

ECRD和ECWT读写控制

部分机器的ACPI对于EC作用域下的寄存器读写有严格控制,有时需要修改其中的代码以解除限制。暂时无相关解决方案。

双电池系统

对于单块物理电池,禁用另一个电池设备即可,一般为BAT1。SSDT示例如下,其中BAT1路径根据实际替换。

在OpenCore中,加载顺序为主补丁-禁用BAT1补丁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// battery for WTX30,WTX40,X260,X1C2014,X1C2016
//
// In config ACPI, _STA to XSTA
// Count: 1
// Find: 5F 53 54 41
// Replace: 58 53 54 41
// Skip: 12
// TableSignature: 44 53 44 54
//
// battery for WTX50,WTX60,X1C2015
//
// In config ACPI, _STA to XSTA
// Count: 1
// Find: 5F 53 54 41
// Replace: 58 53 54 41
// Skip: 11
// TableSignature: 44 53 44 54
//
DefinitionBlock ("", "SSDT", 2, "OCLT", "BAT1-off", 0)
{
External(_SB.PCI0.LPC.EC.BAT1, DeviceObj)
External(_SB.PCI0.LPC.EC.BAT1.XSTA, MethodObj)

Scope(\_SB.PCI0.LPC.EC.BAT1)
{
Method(_STA)
{
If (_OSI ("Darwin"))
{
Return (0)
}
Else
{
Return (\_SB.PCI0.LPC.EC.BAT1.XSTA ())
}
}
}
}
// EOF

对于两块物理电池,更改两块电池设备的ACPI _HID名称使其保持运行的情况下不被电池驱动识别,同时新建一个BATC设备用于合并计算两块电池的信息和状态,代替原来两块电池设备的代码为驱动提供信息。

分别使用SSDT-Notify-LPC和SSDT-OCBATC-TP-LPC进行实现,链接如下。注意根据DSDT的相关内容修改补丁,如3代机器的_Q4C的内容和样本内容不同,4/5/6/7代机器无_Q4C,7代+机器有BFCC等。

在OpenCore中,加载顺序为主补丁-BATC设备补丁-Notify补丁。

1
2
3
4
5
# SSDT-Notify-LPC
https://github.com/daliansky/OC-little/blob/master/08-%E7%94%B5%E6%B1%A0%E8%A1%A5%E4%B8%81/08-1-Thinkpad/%E5%90%84%E6%9C%BA%E5%9E%8B%E7%94%B5%E6%B1%A0%E8%A1%A5%E4%B8%81/SSDT-Notify-LPC.dsl

# SSDT-OCBATC-TP-LPC
https://github.com/daliansky/OC-little/blob/master/08-%E7%94%B5%E6%B1%A0%E8%A1%A5%E4%B8%81/08-1-Thinkpad/%E5%90%84%E6%9C%BA%E5%9E%8B%E7%94%B5%E6%B1%A0%E8%A1%A5%E4%B8%81/SSDT-OCBATC-TP-LPC.dsl

I2C触控板修补

该SSDT不涉及任何的ACPI更名。

修补准备

按照与修改DSDT时相同的方法,确定设备路径和APIC Pin,并放置VoodooI2C驱动。

禁用原设备
通过预置变量法

本方法在本机上通过Clover引导时可行,通过OpenCore引导时不起作用。

用Macisal打开本机DSDT,查找触控板设备名称,此处为ETPD。观察其_STA方法,该方法用于控制设备的开启与关闭,返回0x0F时为开启,返回Zero时为关闭。示例如下。

1
2
3
4
5
6
7
8
9
Method (_STA, 0, NotSerialized)  // _STA: Status
{
If (((TPIF != One) || (DSYN && One)))
{
Return (Zero)
}

Return (0x0F)
}

通过简单的代码知识,可知若TPIF不等于1或DSYN不等于0,则会返回Zero,从而禁用该设备。

在DSDT中搜索TPIF,发现该变量仅在此处被引用。同理搜索DSYN,发现该变量有在其它地方被引用。因此选择改变TPIF而非DSYN的值,以避免对其它设备的影响。此处将TPIF设为0即可。

在DSDT中搜索TPIF,其定义示例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
Scope (_SB)
{
OperationRegion (ASIO, SystemMemory, ASIB, 0x09)
Field (ASIO, AnyAcc, NoLock, Preserve)
{
ASIS, 32,
TPIF, 8,
TPDI, 8,
TPLP, 8,
TPLI, 8,
TPHI, 8
}
}

可见TPIF是一个FieldUnitObj,因此可得如下补丁示例。由于TPIF在Scope (_SB)内,而_SB即为根目录,因此补丁中可用\表示。

注意,上述过程仅为示例,用于阐述预置变量法的基本流程。具体的变量类型和数值设置需要根据不同的DSDT做出相应的调整。

1
2
3
4
5
6
7
8
9
10
11
12
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{
External (TPIF, FieldUnitObj)

Scope (\)
{
If (_OSI ("Darwin"))
{
TPIF = Zero
}
}
}
通过_STA修改法

新建一个SSDT框架,如下。

1
2
3
4
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{

}

在其中添加Scope作用域,路径为原触控板设备的路径,此处为ETPD。

1
2
3
4
5
6
7
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{
Scope (_SB.PCI0.I2C1.ETPD)
{

}
}

把以下_STA方法复制到Scope作用域中。

1
2
3
4
5
6
7
8
9
10
11
Method (_STA, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
Return (Zero)
}
Else
{
Return (XSTA())
}
}

根据添加外部引用的相关办法,添加对ETPD和XSTA的相关引用。其中XSTA为ETPD的原_STA方法,后面会通过更名的方式将其改为XSTA,因此上述注入的新_STA方法意为在系统不为Mac时,调用XSTA即原_STA方法。

完整补丁如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DefinitionBlock ("", "SSDT", 2, "DELL", "CBX3", 0x01072009)
{
External (_SB.PCI0.I2C0.ETPD,DeviceObj)
External (_SB.PCI0.I2C0.ETPD.XSTA,MethodObj)

Scope (_SB.PCI0.I2C0.TPD0)
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (Zero)
}
Else
{
Return (XSTA())
}
}
}
}

在config.plist中添加以下重命名补丁,示例如下。

1
2
3
Comment:change _STA(0,N) to XSTA(0,N)
Find:5F535441 00A01390 929354
Replace:58535441 00A01390 929354
启用GPIO

DSDT搜索Device (GPI0,观察其_STA方法,示例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Method (_STA, 0, NotSerialized)
{
If ((SBRG == Zero))
{
Return (Zero)
}

If ((GPEN == Zero))
{
Return (Zero)
}

Return (0x0F)
}

同样使用预置变量法。观察以上代码,可知启用GPI0需要SBRG和GPEN都不等于0。搜索SBRG,发现该变量被多处引用。同理搜索GPEN,发现该变量仅本处被引用。考虑到SBRG可能本来就不为0,因此尝试只设定GPEN。

在DSDT中搜索SBRG和GPEN,其定义示例如下。

1
2
3
4
5
6
7
8
9
10
11
// 这里就是根目录,没有Scope()

OperationRegion (PNVA, SystemMemory, PNVB, PNVL)
Field (PNVA, AnyAcc, Lock, Preserve)
{
...
SBRG, 32,
...
GPEN, 8,
...
}

可见GPEN是一个FieldUnitObj,因此可得如下补丁示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// GPI0 enable
DefinitionBlock("", "SSDT", 2, "OCLT", "GPI0", 0)
{
External(GPEN, FieldUnitObj)

Scope (\)
{
If (_OSI ("Darwin"))
{
GPEN = 1
}
}
}
//EOF
新建热补丁

新建一个SSDT框架,如下。

1
2
3
4
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{

}

用MaciASL打开系统的DSDT,搜索触控板名称,本机为ETPD,路径为_SB.PCI0.I2C1.ETPD。在新建的SSDT中,首先添加Scope域,注意小括号内为除触控板名称外的路径。然后将触控板名称对应的整个Device复制进去,此处为Device (ETPD)。完成后形式如下。

1
2
3
4
5
6
7
8
9
10
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{
Scope (_SB.PCI0.I2C1)
{
Device (ETPD)
{
...
}
}
}

此处也可以写成如下形式。

1
2
3
4
5
6
7
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{
Device (_SB.PCI0.I2C1.ETPD)
{
...
}
}

将该SSDT中的ETPD进行改名,此处改为TPXX,该名称应当在DSDT中未出现过。然后替换_STA部分为以下代码。

1
2
3
4
5
6
7
8
9
10
11
Method (_STA, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}

在禁用原设备中,若使用的是预置变量法,则在该SSDT中搜索上述用到的变量,此处为TPIF。若有类似If(TPIF...)的语句,则修改为If(one)

在该SSDT中搜索OSYS。若有,则注释以下内容。

1
2
3
4
If (LLess (OSYS, 0x07DC))
{
SRXO (GPDI, One)
}
移除APIC中断控制器

在该SSDT中搜索_CRS方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Method (_CRS, 0, Serialized)
{
Name (SBFI, ResourceTemplate ()
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.PCI0.I2C1",
0x00, ResourceConsumer, , Exclusive,
)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, )
{
0x0000006D,
}
})
Return (SBFI)
}

若代码类似如上,则将Name (SBFI改为Name (SBFB,并删除整个Interrupt()函数,修改后变为如下。

1
2
3
4
5
6
7
8
9
10
11
Method (_CRS, 0, Serialized)
{
Name (SBFB, ResourceTemplate ()
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.PCI0.I2C1",
0x00, ResourceConsumer, , Exclusive,
)
})
Return (SBFI)
}

在该SSDT中定位到_CRS方法,确保所有返回语句都改成以下内容。

1
2
3
4
5
// 若该SSDT中没有I2CM,选择该语句
Return (ConcatenateResTemplate (SBFB, SBFG))

// 若该SSDT中有I2CM,选择该语句
Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFG))

示例如下。

1
2
3
4
5
6
7
8
9
10
11
Method (_CRS, 0, Serialized)
{
Name (SBFB, ResourceTemplate ()
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.PCI0.I2C1",
0x00, ResourceConsumer, , Exclusive,
)
})
Return (ConcatenateResTemplate (SBFB, SBFG))
}
GPIO固定
代码修补

在该SSDT中寻找类似如下的代码。

1
2
3
4
5
6
7
8
9
Name (SBFG, ResourceTemplate ()
{
GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x0000
}
})

若有该代码,则系统会自动注入GPIO Pin,可跳过GPIO Pin的计算与填入。若没有,则需要将该段代码复制到TPXX的根目录,示例如下。

1
2
3
4
5
6
7
8
9
10
11
Device (TPXX){
Name (SBFG, ResourceTemplate ()
{
GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x0000
}
})
}
计算GPIO Pin

将上面得到的APIC Pin化为十进制,此处为6D,化成十进制为109。带入以下公式计算,计算完成后将答案重新化为十六进制,所得即为GPIO Pin的值。

对于Skylake平台,本机适用,所得为85=0x55。

1
2
3
4
5
6
If APICPIN > 47 And APICPIN <= 79 Then     
GPIOPIN = APICPIN - 24
GPIOPIN2 = APICPIN + 72
ElseIf APICPIN > 79 And APICPIN <= 119 Then
GPIOPIN = APICPIN - 24
End If

对于CoffeeLake-H平台如下。

1
2
3
4
5
6
7
8
9
10
11
12
If APICPIN > 47 And APICPIN <= 71 Then   
GPIOPIN = APICPIN - 16
GPIOPIN2 = APICPIN + 240
If APICPIN > 47 And APICPIN <= 59 Then GPIOPIN3 = APICPIN + 304
ElseIf APICPIN > 71 And APICPIN <= 95 Then
GPIOPIN = APICPIN - 8
GPIOPIN3 = APICPIN + 152
GPIOPIN2 = APICPIN + 120
ElseIf APICPIN > 95 And APICPIN <= 119 Then
GPIOPIN = APICPIN
If APICPIN > 108 And APICPIN <= 115 Then GPIOPIN2 = APICPIN + 20
End If

对于CoffeeLake-LF/Whiskylake平台如下。

1
2
3
4
5
6
7
8
9
10
If APICPIN > 47 And APICPIN <= 71 Then      
GPIOPIN = APICPIN - 16
GPIOPIN2 = APICPIN + 80
ElseIf APICPIN > 71 And APICPIN <= 95 Then
GPIOPIN2 = APICPIN + 184
GPIOPIN = APICPIN + 88
ElseIf APICPIN > 95 And APICPIN <= 119 Then
GPIOPIN = APICPIN
If APICPIN > 108 And APICPIN <= 115 Then GPIOPIN2 = APICPIN - 44
End If
【进阶】其它方法

打开Hackintool,在PCI选项卡下可以查看触控板类型,包括SunrisePoint、CannonPoint(Lake)[Coffee Lake(-R)]和CannonPoint(Lake)[Whiskylake]。

打开下面相应平台的第一个链接,查找设备的十六进制APIC Pin值,并记录左侧标签值(只需记录GPP_XYY_IRQ中的XYY部分),若有多个标签值,需全部记录。再打开第二个链接,搜索上面所记录的XYY,记下右侧的数值(十进制),此即为触控板的硬件引脚号。

1
2
3
4
5
6
7
8
9
10
11
// SunrisePoint[Kaby Lake(-R)]
https://github.com/coreboot/coreboot/blob/master/src/soc/intel/skylake/include/soc/gpio_defs.h#L43
https://github.com/coreboot/coreboot/blob/master/src/soc/intel/skylake/include/soc/gpio_soc_defs.h#L37

// CannonPoint(Lake)[Coffee Lake-R]
https://github.com/coreboot/coreboot/blob/master/src/soc/intel/cannonlake/include/soc/gpio_defs_cnp_h.h#L42
https://github.com/coreboot/coreboot/blob/master/src/soc/intel/cannonlake/include/soc/gpio_soc_defs_cnp_h.h#L40

// CannonPoint(Lake)[Whiskylake]
https://github.com/coreboot/coreboot/blob/master/src/soc/intel/cannonlake/include/soc/gpio_defs.h#L42
https://github.com/coreboot/coreboot/blob/master/src/soc/intel/cannonlake/include/soc/gpio_soc_defs.h#L45

对于SunrisePoint,硬件引脚号即为GPIO引脚号。

对于CannonPoint(Lake)[Coffee Lake(-R)]或CannonPoint(Lake)[Whiskylake],前面步骤与上面相同,但得到的硬件引脚号并不是GPIO引脚号,因此还需要进行转换。打开下面转换公式链接,搜索前面记录的GPP_X,得到格式如CHIPSET_GPP(数字, 基数, 终止, GPIO基数)的内容。用所记下的十进制硬件引脚号减去基数,再加上GPIO基数,就是最后的十进制的GPIO引脚号。注意,X_NO_GPIO表示此引脚号无效。

1
2
3
4
5
// CannonPoint(Lake)[Coffee Lake-R]
https://github.com/coolstar/VoodooGPIO/blob/master/VoodooGPIO/CannonLake-LP/VoodooGPIOCannonLakeLP.hpp#L366

// CannonPoint(Lake)[Whiskylake]
https://github.com/coolstar/VoodooGPIO/blob/master/VoodooGPIO/CannonLake-H/VoodooGPIOCannonLakeH.hpp#L414

得到十进制的GPIO引脚后,需将数字转换为十六进制。

填入GPIO Pin

在某些极端状况下,只能尝试比较常见的GPIO Pin。如SunrisePoint平台可尝试0x17、0x1b、0x34和0x55。

计算完成后把GPIO Pin填入到SBFG的Pin list,示例如下。

1
2
3
4
5
6
7
8
9
Name (SBFG, ResourceTemplate ()
{
GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x55
}
})
添加外部引用

点击编译并根据报错添加外部引用,过程可参照电池修补部分。

完成修补

至此触控板热补丁已完成,将上述生成的所有SSDT都另存为aml,放到引导器的ACPI部分。重启后打开IORegistryExplorer,查找触控板名称(ETPD),若无此设备则禁用成功。查找新建的触控板设备(TPXX),若有此设备则触控板已处于中断模式。

ACPIDebug

ACPIDebug可用于高级人员排错,也可记录部分按键轨迹。

驱动

ACPIDebug.kext下载链接如下。

1
https://bitbucket.org/RehabMan/os-x-acpi-debug/downloads/

下载后放入SLE中,用Kext Utility修复权限。

然后需要对DSDT进行修改。用MaciASL打开DSDT,点击Patch,在_OS-X-ACPI-Debug类别下打Add DSDT Debug MethodsInstrument EC Queries这两个补丁,退出并保存即可。

也可通过SSDT实现。放置以下SSDT即可。

SSDT-RMDT.aml如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// for use with ACPIDebug
// This file was created by applying "Add DSDT Debug Methods" to an empty SSDT
//
// Use "Add SSDT Debug Extern Declarations" to access these methods from other
// hotpatch SSDTs or even patched OEM ACPI files.
//
DefinitionBlock("", "SSDT", 2, "OCLT", "RMDT", 0)
{
If (_OSI ("Darwin"))
{
Device (RMDT)
{
Name (_HID, "RMD0000") // _HID: Hardware ID
Name (RING, Package (0x0100){})
Mutex (RTMX, 0x00)
Name (HEAD, Zero)
Name (TAIL, Zero)
Method (PUSH, 1, NotSerialized)
{
Acquire (RTMX, 0xFFFF)
Local0 = (HEAD + One)
If ((Local0 >= SizeOf (RING)))
{
Local0 = Zero
}

If ((Local0 != TAIL))
{
RING [HEAD] = Arg0
HEAD = Local0
}

Release (RTMX)
Notify (RMDT, 0x80) // Status Change
}

Method (FTCH, 0, NotSerialized)
{
Acquire (RTMX, 0xFFFF)
Local0 = Zero
If ((HEAD != TAIL))
{
Local0 = DerefOf (RING [TAIL])
TAIL++
If ((TAIL >= SizeOf (RING)))
{
TAIL = Zero
}
}

Release (RTMX)
Return (Local0)
}

Method (COUN, 0, NotSerialized)
{
Acquire (RTMX, 0xFFFF)
Local0 = (HEAD - TAIL) /* \RMDT.TAIL */
If ((Local0 < Zero))
{
Local0 += SizeOf (RING)
}

Release (RTMX)
Return (Local0)
}

Method (P1, 1, NotSerialized)
{
PUSH (Arg0)
}

Method (P2, 2, NotSerialized)
{
Local0 = Package (0x02){}
Local0 [Zero] = Arg0
Local0 [One] = Arg1
PUSH (Local0)
}

Method (P3, 3, NotSerialized)
{
Local0 = Package (0x03){}
Local0 [Zero] = Arg0
Local0 [One] = Arg1
Local0 [0x02] = Arg2
PUSH (Local0)
}

Method (P4, 4, NotSerialized)
{
Local0 = Package (0x04){}
Local0 [Zero] = Arg0
Local0 [One] = Arg1
Local0 [0x02] = Arg2
Local0 [0x03] = Arg3
PUSH (Local0)
}

Method (P5, 5, NotSerialized)
{
Local0 = Package (0x05){}
Local0 [Zero] = Arg0
Local0 [One] = Arg1
Local0 [0x02] = Arg2
Local0 [0x03] = Arg3
Local0 [0x04] = Arg4
PUSH (Local0)
}

Method (P6, 6, NotSerialized)
{
Local0 = Package (0x06){}
Local0 [Zero] = Arg0
Local0 [One] = Arg1
Local0 [0x02] = Arg2
Local0 [0x03] = Arg3
Local0 [0x04] = Arg4
Local0 [0x05] = Arg5
PUSH (Local0)
}

Method (P7, 7, NotSerialized)
{
Local0 = Package (0x07){}
Local0 [Zero] = Arg0
Local0 [One] = Arg1
Local0 [0x02] = Arg2
Local0 [0x03] = Arg3
Local0 [0x04] = Arg4
Local0 [0x05] = Arg5
Local0 [0x06] = Arg6
PUSH (Local0)
}
}
}
}
//EOF

SSDT-TEST.aml,以Dell为例。注意需要重命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// In config ACPI, NEVT to XEVT
// Find: 4E 45 56 54 00
// Replace: 58 45 56 54 00
//
DefinitionBlock("", "SSDT", 2, "ACDT", "TEST", 0)
{
External(XEVT, MethodObj)
External(RMDT.P1, MethodObj)

Method (NEVT, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
\RMDT.P1("AAA001")
}
\XEVT()
}
}
//EOF

使用

重启后在Launchpad找到控制台,在搜索框输入ACPIDebug,然后按下键盘Fn+F5/F6。若控制台中出现信息,则ACPIDebug驱动成功。

系统优化

华硕笔记本键盘修复

按键驱动

利用AsusSMC.kext,可修复华硕笔记本键盘与Fn有关的快捷键不工作的问题。需要Lilu和VirtualSMC,下载链接如下。

1
https://github.com/hieplpvip/AsusSMC

将下载好的kext放到Clover的kexts文件夹中,若键盘有睡眠和飞行模式按键则还需运行install_daemon.sh,然后重启。逐个测试按键是否工作,若不工作,可通过SSDT或DSDT进行修补。

按键修复

通过DSDT

用MaciASL打开DSDT。添加以下源,然后点击Patch打相应补丁即可。

1
http://raw.github.com/hieplpvip/AsusSMC/master

通过SSDT

选取以下所需代码复制到MaciASL中,创建一个SSDT并保存为SSDT-ASUS.aml,放入引导器的ACPI部分,并按照注释在config.plist中添加更名补丁即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
DefinitionBlock ("", "SSDT", 2, "hack", "EC", 0x00000000)
{
External (_SB.ATKD.IANE, MethodObj)
External (_SB.ATKP, IntObj)
External (_SB.PCI0.LPCB.EC, DeviceObj)

Scope (_SB.PCI0.LPCB.EC)
{
// F1
// change _Q0A to XQ0A
// Find: 5F513041
// Replace: 58513041
Method (_Q0A, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x5E)
}
}

// F2
// change _Q0B to XQ0B
// Find: 5F513042
// Replace: 58513042
Method (_Q0B, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x7D)
}
}

// F3
// change _Q0C to XQ0C
// Find: 5F513043
// Replace: 58513043
Method (_Q0C, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0xC5)
}
}

// F4
// change _Q0D to XQ0D
// Find: 5F513044
// Replace: 58513044
Method (_Q0D, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0xC4)
}
}

// F5
// change _Q0E to XQ0E
// Find: 5F513045
// Replace: 58513045
Method (_Q0E, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x20)
}
}

// F6
// change _Q0F to XQ0F
// Find: 5F513046
// Replace: 58513046
Method (_Q0F, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x10)
}
}

// F7
// change _Q10 to XQ10
// Find: 5F513130
// Replace: 58513130
Method (_Q10, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x35)
}
}

// F8
// change _Q10 to XQ10
// Find: 5F513131
// Replace: 58513131
Method (_Q11, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x61)
}
}

// F9
// change _Q12 to XQ12
// Find: 5F513132
// Replace: 58513132
Method (_Q12, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x6B)
}
}

// F10
// change _Q13 to XQ13
// Find: 5F513133
// Replace: 58513133
Method (_Q13, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x32)
}
}

// F11
// change _Q14 to XQ14
// Find: 5F513134
// Replace: 58513134
Method (_Q14, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x31)
}
}

// F12
// change _Q15 to XQ15
// Find: 5F513135
// Replace: 58513135
Method (_Q15, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x30)
}
}

// media left arrow key
// change _Q6C to XQ6C
// Find: 5F513643
// Replace: 58513643
Method (_Q6C, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x40)
}
}

// media right arrow key
// change _Q6D to XQ6D
// Find: 5F513644
// Replace: 58513644
Method (_Q6D, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x41)
}
}

// media up arrow key
// change _Q6E to XQ6E
// Find: 5F513645
// Replace: 58513645
Method (_Q6E, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x43)
}
}

// media down arrow key
// change _Q6F to XQ6F
// Find: 5F513646
// Replace: 58513646
Method (_Q6F, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x45)
}
}

// space key
// change _Q71 to XQ71
// Find: 5F513731
// Replace: 58513731
Method (_Q71, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x5C)
}
}

// V key
// change _Q72 to XQ72
// Find: 5F513732
// Replace: 58513732
Method (_Q72, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x8A)
}
}


// C key
// change _Q73 to XQ73
// Find: 5F513733
// Replace: 58513733
Method (_Q73, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x82)
}
}

// ALS toggle A key
// change _Q6F to XQ6F
// Find: 5F513646
// Replace: 58513646
Method (_Q6F, 0, NotSerialized)
{
If (^^^^ATKP)
{
^^^^ATKD.IANE (0x7A)
}
}
}
}

亮度快捷键调整

通过BrightnessKeys.kext即可,链接如下。

1
https://github.com/acidanthera/BrightnessKeys

CPU显示未知修复

打开终端并输入以下命令。

1
2
cd /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/Resources/zh_CN.lproj/
cp AppleSystemInfo.strings ~/Desktop

打开AppleSystemInfo.strings,将UnknownCPUKind下的内容修改为需要显示的内容,如下。

1
2
<key>UnknownCPUKind</key>
<string>Intel Core i7-8700K</string>

保存后在终端输入以下命令即可。

1
sudo cp ~/Desktop/AppleSystemInfo.strings /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/Resources/zh_CN.lproj/

系统安装与维护

修改InstallESD.dmg

InstallESD.dmg位于macOS系统的安装包内,修改其内容(如删除部分kexts)可能会使安装过程更加顺利。

打开磁盘工具,点击菜单栏上的映像-转换,选择要转换的镜像,映像格式选择读/写。打开转换好的dmg,修改完成后再次转换,映像格式选择压缩即可。

去除机型检查

可用Flat Package Editor或其它工具编辑OSInstall.mpkg,让Distribution脚本在hwbeModelCheck函数中总是返回true。编辑完成后在终端输入建议以下命令以重建映像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Original.dmg为原始镜像
# OSInstall.mpkg为修改过的镜像
mkdir RO
hdiutil mount Original.dmg -noverify -noautoopen -noautoopenrw -noautofsck -mountpoint RO cp RO/.DS_Store DS_STORE
hdiutil detach RO -force
rm -rf RO
hdiutil convert Original.dmg -format UDRW -o ReadWrite.dmg
mkdir RW
xattr -c OSInstall.mpkg
hdiutil mount ReadWrite.dmg -noverify -noautoopen -noautoopenrw -noautofsck -mountpoint RW cp OSInstall.mpkg RW/System/Installation/Packages/OSInstall.mpkg
killall Finder fseventsd
rm -rf RW/.fseventsd
cp DS_STORE RW/.DS_Store
hdiutil detach RW -force
rm -rf DS_STORE RW

恢复盘

FireWolf OS X PE

类似Windows PE,FireWolf OS X PE可视作macPE,可为Mac提供恢复环境。下载链接如下。

1
https://pe.firewolf.app/manual/downloads/thankyou.html

安装

在Windows下用Etcher刻录到U盘即可。

引导启动

在启动之前需先确保系统完整性保护(SIP)中已允许加载任意Recovery系统,即启用CSR标志位CSR_ALLOW_ANY_RECOVERY_OS,修改Clover配置文件中的Rt Variables-CsrActiveConfig为0x3E7即可。

使用引导High Sierra的Clover文件,可以顺利启动该恢复盘。

系统调试与日志

日志内容

previous shutdown cause:5

Mac用于说明先前关机原因的代码。可在终端通过以下命令显示。

1
log show --predicate 'eventMessage contains "Previous shutdown cause"' --last 24h

数字具体含义如下。

代码 含义 备注
5 正确关机 通过关机菜单或其他关机命令关机
7 CPU线程错误 尝试安全模式
3 硬关机 按电源按钮强制关机
0 电源断开 对笔记本而言,若电源仍有电,则代表电池或电池控制器出现问题,可尝试重置SMC
-3 温度传感器超出阈值
-14 电流突峰 电问题或电池问题
-20 T2芯片导致的关机
-60 错误的主目录块(badMDBEr) 尝试重装系统
-61 应用程序无响应导致的关机
-62 应用程序无响应导致的重启
-71 SO-DIMM内存温度超出阈值 尝试清除风扇灰尘
-74 电池温度超出阈值 尝试重置SMC
-75 充电器通信问题
-78 充电器电流不正确
-79 电池电流不正确
-86 接近温度超出阈值
-95 CPU温度超出预知阈值 尝试重置SMC
-100 电源温度超出阈值
-102 过压保护导致的关机
-103 电池电压不足
-104 可能与电池有关
-108 可能与内存有关
-112 可能与内存有关
-127 PMU强制关闭
-128 可能与内存有关

内核Panic

可在/Library/Logs/DiagnosticReports目录下找到Panic日志。

错误数字含义

向量偏移值 描述 说明
0 Devide Error 当进行除以零的操作时产生
1 Debug Exceptions 当进行程序单步跟踪调试时,设置了标志寄存器eflags的T标志时产生这个中断
2 NMI Interrupt 由不可屏蔽产生
3 Breakpoint 由断点指令INT3产生,与Debug处理相同
4 INTO Detected Overflow eflags的溢出标志0F引起
5 BOUND Range Exceeded 寻址到有效地址以外引起
6 Invalid Opcode CPU执行发现一个无效的指令操作码
7 Coprocessor Not Available 设备不存在,指协处理器。在两种情况下会产生该中断:CPU遇到一个转意指令并且EM置位;MP和TS都在置位状态,CPU遇到wait或一个转意指令。在这种情况下,处理程序在必要应该更新协处理器的状态
8 Double Exception 双故障出错
9 Coprocessor Segment Overrun 协处理器段超出
10 Invalid Task State Segment CPU切换时发现TSS无效
11 Segment Not Present 描述符所指的段不存在
12 Stack Fault 堆栈溢出或者不存在
13 General Protection 没有符合80386保护机制的(特权机制)操作引起
14 Page Fault 页溢出或不存在
16 Coprocessor Error 协处理器检测到非法操作

错误分析

在Finder切换到/Library/Logs/DiagnosticReports,打开后缀名为panic的文档以获取内核错误报告,示例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
*** Panic Report ***
panic(cpu 6 caller 0xffffff8008b6f2e9): Kernel trap at 0xffffff7f8c7ba8b1, type 14=page fault

registers:
CR0: 0x000000008001003b, CR2: 0xffffff80639b8000, CR3: 0x0000000022202000, CR4: 0x00000000003627e0
RAX: 0x0000000000000564, RBX: 0x0000000000000564, RCX: 0x0000000000000020, RDX: 0x000000000000002a
RSP: 0xffffff92354ebc80, RBP: 0xffffff92354ebce0, RSI: 0x00000000000fbeab, RDI: 0xffffff92487b9154
R8: 0x0000000000000000, R9: 0x0000000000000010, R10: 0x0000000000000010, R11: 0x0000000000000000
R12: 0xffffff80639b6a70, R13: 0xffffff92354ebdc0, R14: 0xffffff92354ebdd4, R15: 0x0000000000000000
RFL: 0x0000000000010297, RIP: 0xffffff7f8c7ba8b1, CS: 0x0000000000000008, SS: 0x0000000000000010
Fault CR2: 0xffffff80639b8000, Error code: 0x0000000000000000, Fault CPU: 0x6, PL: 0, VF: 1

Backtrace (CPU 6), Frame : Return Address
0xffffff92354eb730 : 0xffffff8008a505f6
0xffffff92354eb780 : 0xffffff8008b7d604
0xffffff92354eb7c0 : 0xffffff8008b6f0f9
0xffffff92354eb840 : 0xffffff8008a02120
0xffffff92354eb860 : 0xffffff8008a5002c
0xffffff92354eb990 : 0xffffff8008a4fdac
0xffffff92354eb9f0 : 0xffffff8008b6f2e9
0xffffff92354ebb70 : 0xffffff8008a02120
0xffffff92354ebb90 : 0xffffff7f8c7ba8b1
0xffffff92354ebce0 : 0xffffff7f8c7ba40f
0xffffff92354ebd60 : 0xffffff7f8c7b85e8
0xffffff92354ebda0 : 0xffffff7f8c7b9db2
0xffffff92354ebe00 : 0xffffff7f8b2b3873
0xffffff92354ebe50 : 0xffffff7f8b2bd473
0xffffff92354ebe90 : 0xffffff7f8b2bcc7d
0xffffff92354ebed0 : 0xffffff8009091395
0xffffff92354ebf30 : 0xffffff800908fba2
0xffffff92354ebf70 : 0xffffff800908f1dc
0xffffff92354ebfa0 : 0xffffff8008a014f7

Kernel Extensions in backtrace:
com.apple.iokit.IOAcceleratorFamily2(376.6) @0xffffff7f8b2b0000->0xffffff7f8b345fff
com.apple.kext.AMDRadeonX4150(1.6) @0xffffff7f8c7b4000->0xffffff7f8cf20fff

BSD process name corresponding to current thread: kernel_task

Mac OS version:
17C88

Kernel version:
Darwin Kernel Version 17.3.0: Thu Nov 9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64
Kernel slide: 0x0000000008600000

从以上内容可知,该错误由14=page fault即页面错误引起,RIP寄存器即程序计数器的值为0xffffff7f8c7ba8b1,CR2寄存器即触发页面错误的内存地址为0xffffff80639b8000,Kernel slide为0x0000000008600000。在kext回溯中,可以看到以下两个kext可能触发该页面错误,从而引起恐慌。

1
2
3
4
5
kext / com.apple.iokit.IOAcceleratorFamily2
加载于 / 0xffffff7f8b2b0000

kext / com.apple.kext.AMDRadeonX4150
加载于 / 0xffffff7f8c7b4000

下载Hopper,链接如下。

1
https://www.hopperapp.com/

打开Hoppeer并在软件中加载/System/Library/Kernels/kernel,单击Modify-Change File Base Address,在Base Address输入Kernel slide加上0x100000的值,即0xffffff8008700000。

重定位后点击G,输入Backtrace中的最后一个地址,即0xffffff8008a014f7。汇编代码片段如下。

1
2
3
4
5
6
7
8
                    _call_continuation:
ffffff8008a014e0 mov rcx, rdi
ffffff8008a014e3 mov rdi, rsi
ffffff8008a014e6 mov rsi, rdx
ffffff8008a014e9 mov rsp, qword [gs:0x30]
ffffff8008a014f2 xor rbp, rbp
ffffff8008a014f5 call rcx
ffffff8008a014f7 mov rdi, qword [gs:0x8]

由堆栈相关知识可知,在调用ffffff8008a014f5处的call时会压入返回地址,此处为0xffffff8008a014f7。同理搜索Backtrace中的倒数第二个地址0xffffff800908f1dc,可得到另一个调用语句的地址。重复以上过程,结果如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
kernel.call_continuation()
0xffffff8008a014f5 call rcx

kernel.IOWorkLoop::threadMain()
0xffffff800908f1d6 call qword [rax+0x1a8]

kernel.IOWorkLoop::runEventSources()
0xffffff800908fb9c call qword [rax+0x120]

kernel.IOInterruptEventSource::checkForWork()
0xffffff8009091392 call r11

com.apple.iokit.IOAcceleratorFamily2.IOAccelEventMachine2::hardwareErrorEvent()
0xffffff7f8b2bcc78 call IOAccelEventMachine2::restart_channel()

com.apple.iokit.IOAcceleratorFamily2.IOAccelEventMachine2::restart_channel()
0xffffff7f8b2bd46d call qword [rax+0x160]

com.apple.iokit.IOAcceleratorFamily2.IOAccelFIFOChannel2::restart()
0xffffff7f8b2b386d call qword [rax+0x208]

com.apple.kext.AMDRadeonX4150.AMDRadeonX4150_AMDAccelChannel::getHardwareDiagnosisReport()
0xffffff7f8c7b9dac call qword [rax+0xb00]

com.apple.kext.AMDRadeonX4150.AMDRadeonX4150_AMDGraphicsAccelerator::writeDiagnosisReport()
0xffffff7f8c7b85e2 call qword [rax+0x258]

com.apple.kext.AMDRadeonX4150.AMDRadeonX4150_AMDAccelChannel::writeDiagnosisReport()
0xffffff7f8c7ba40a call AMDRadeonX4150_AMDAccelChannel::writePendingCommandInfo

com.apple.kext.AMDRadeonX4150.AMDRadeonX4150_AMDAccelChannel::writePendingCommandInfoDiagnosisReport()
0xffffff7f8c7ba8b1 mov r8d, dword [r12+rax*4]

kernel.hndl_alltraps()
0xffffff8008a0211b call _kernel_trap

根据以下内容,可知内核在找到要执行的任务后,首先调用com.apple.iokit.IOAcceleratorFamily2的内核线程,其中调用了restart_channel方法。然后切换到特定的kext即com.apple.kext.AMDRadeonX4150,调用writeDiagnosisReport方法。

在0xffffff7f8c7ba8b1处不是一个call指令,而是mov r8d, dword [r12+rax*4]。该地址即为RIP寄存器的内容,因此可以确定出现panic的指令位置。

根据内核报告,R12=0xffffff80639b6a70,RAX=0x0000000000000564,计算可得传送的地址为0xffffff80639b8000。该地址为fault CR2寄存器的内容。

因此可以猜测,0xffffff80639b8000指向一个未映射的页面,当com.apple.kext.AMDRadeonX4150中的mov指令尝试从该未映射地址读取时,会发生未处理的页面错误,从而导致panic。

Data Hub日志

Data Hub日志中不包括Kernel和Kext的日志。可在终端通过以下命令获取Data Hub日志。

1
ioreg -lw0 -p IODeviceTree | grep boot-log | sort | sed 's/.*<\(.*\)>.*/\1/' | xxd -r -p

UEFI变量日志

可在终端通过以下命令获取UEFI变量日志。

1
nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:boot-log | awk '{gsub(/%0d%0a%00/,"");gsub(/%0d%0a/,"\n")}1'

内核调试套件

内核调试工具包(Kernel Debug Kits,KDK)可从内核和核心kext获取日志信息。

安装

在终端输入以下命令以确定需要下载的KDK版本。

1
sw_vers | grep BuildVersion

打开以下链接,搜索Kernel Debug Kit并下载相应的版本。

1
https://developer.apple.com/download/all/

下载后运行安装包进行安装。禁用系统SIP后,在终端输入以下命令以挂载根目录为可写。

1
2
3
4
5
6
7
8
# Big Sur+
mkdir ~/livemount
diskutil list
# 挂载上面看到的系统盘(不包含 - Data 的盘),此处为/dev/disk5s5
sudo mount -o nobrowse -t apfs /dev/disk5s5 ~/livemount

# Catalina
sudo mount -uw /

然后输入以下命令安装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Install KDK to System Volume
# Ensure to replace <KDK Version>
# For 10.15 and older, swap livemount with /Volumes/<Target Volume>
sudo ditto /Library/Developer/KDKs/<KDK Version>/System ~/livemount/System

# Rebuild the kernel cache(Big Sur and newer)
sudo kmutil install --volume-root ~/livemount --update-all

# Rebuild the kernel cache(Catalina and older)
sudo kextcache -invalidate /Volumes/<Target Volume>

# Finally, once done editing the system volume
# we'll want to create a new snapshot (Big Sur and newer)
sudo bless --folder ~/livemount/System/Library/CoreServices --bootefi --create-snapshot

完成安装后,需要添加以下启动参数之一。

1
2
3
4
# kasan是一个包含AddressSanitizer的日志密集型内核
kcsuffix=debug(Big Sur已移除)
kcsuffix=development
kcsuffix=kasan

重新启动并在终端输入以下命令以查看当前内核是否已被改变。

1
sysctl kern.osbuildconfig

卸载

禁用系统SIP后,在终端输入以下命令以挂载根目录为可写。

1
2
3
4
5
6
7
8
# Big Sur+
mkdir ~/livemount
diskutil list
# 挂载上面看到的系统盘(不包含 - Data 的盘),此处为/dev/disk5s5
sudo mount -o nobrowse -t apfs /dev/disk5s5 ~/livemount

# Catalina
sudo mount -uw /

然后输入以下命令删除调试内核和kexts。

1
2
3
4
5
6
7
# Revert to old snapshot (Big Sur+)
sudo bless --mount ~/livemount --bootefi --last-sealed-snapshot

# Reset kernel cache (Catalina and older)
sudo rm /System/Library/Caches/com.apple.kext.caches/Startup/kernelcache.de*
sudo rm /System/Library/PrelinkedKernels/prelinkedkernel.de*
sudo kextcache -invalidate /

删除启动参数kcsuffix=后重新启动,然后在终端输入以下命令以查看当前内核是否已被改变。

1
sysctl kern.osbuildconfig

本机文件内容

DSDT

电池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
Scope (_SB.PCI0.LPCB.EC0)
{
Device (BAT0)
{
Name (_HID, EisaId ("PNP0C0A")) // _HID: Hardware ID
Name (_UID, Zero) // _UID: Unique ID
Name (_PCL, Package (0x01) // _PCL: Power Consumer List
{
PCI0
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (BATP (Zero))
{
Return (0x1F)
}
Else
{
Return (0x0F)
}
}

Name (LOW2, 0x012C)
Name (PUNT, One)
Name (LFCC, 0x1770)
Name (NBIF, Package (0x0D)
{
Zero,
0xFFFFFFFF,
0xFFFFFFFF,
One,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
"",
"",
"",
""
})
Name (PBIF, Package (0x0D)
{
One,
0x1770,
0x1770,
One,
0x39D0,
0x0258,
0x012C,
0x3C,
0x3C,
"M3N",
" ",
"LIon",
"ASUSTeK"
})
Name (PBST, Package (0x04)
{
Zero,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF
})
Name (BIXT, Package (0x14)
{
Zero,
Zero,
0x1770,
0x1770,
One,
0x39D0,
0x0258,
0x012C,
Zero,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0x3C,
0x3C,
"M3N",
" ",
"LIon",
"ASUSTeK"
})
Name (NBIX, Package (0x14)
{
Zero,
Zero,
0xFFFFFFFF,
0xFFFFFFFF,
One,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
Zero,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
"",
"",
"",
""
})
Method (FBIF, 5, NotSerialized)
{
Store (Arg0, PUNT)
Store (Arg1, Local1)
Store (Arg2, Local2)
If (LEqual (PUNT, Zero))
{
Multiply (Local1, 0x0A, Local1)
Multiply (Local2, 0x0A, Local2)
}

Store (Arg0, Index (PBIF, Zero))
Store (Local1, Index (PBIF, One))
Store (Local2, Index (PBIF, 0x02))
Store (Local2, LFCC)
Store (Arg3, Index (PBIF, 0x03))
Store (Arg4, Index (PBIF, 0x04))
Divide (Local1, 0x0A, , Local5)
Store (Local5, Index (PBIF, 0x05))
Divide (Local1, 0x64, , Local6)
Store (Local6, Index (PBIF, 0x06))
Store (Local6, LOW2)
Divide (Local1, 0x64, , Local7)
Store (Local7, Index (PBIF, 0x07))
Store (Local7, Index (PBIF, 0x08))
}

Method (CBIF, 0, NotSerialized)
{
If (PUNT)
{
Store (DerefOf (Index (PBIF, 0x04)), Local0)
Store (Zero, Index (PBIF, Zero))
Multiply (DerefOf (Index (PBIF, One)), Local0, Index (PBIF, One))
Multiply (DerefOf (Index (PBIF, 0x02)), Local0, Index (PBIF, 0x02))
Multiply (DerefOf (Index (PBIF, 0x05)), Local0, Index (PBIF, 0x05))
Multiply (DerefOf (Index (PBIF, 0x06)), Local0, Index (PBIF, 0x06))
Multiply (DerefOf (Index (PBIF, 0x07)), Local0, Index (PBIF, 0x07))
Multiply (DerefOf (Index (PBIF, 0x08)), Local0, Index (PBIF, 0x08))
Divide (DerefOf (Index (PBIF, One)), 0x03E8, , Index (PBIF, One))
Divide (DerefOf (Index (PBIF, 0x02)), 0x03E8, , Index (PBIF, 0x02))
Divide (DerefOf (Index (PBIF, 0x05)), 0x03E8, , Index (PBIF, 0x05))
Divide (DerefOf (Index (PBIF, 0x06)), 0x03E8, , Index (PBIF, 0x06))
Divide (DerefOf (Index (PBIF, 0x07)), 0x03E8, , Index (PBIF, 0x07))
Divide (DerefOf (Index (PBIF, 0x08)), 0x03E8, , Index (PBIF, 0x08))
}
}

Method (_BIF, 0, NotSerialized) // _BIF: Battery Information
{
If (LNot (BATP (Zero)))
{
Return (NBIF)
}

If (LEqual (GBTT (Zero), 0xFF))
{
Return (NBIF)
}

BATO ()
BATS (Zero)
Store (BIF9 (), Index (PBIF, 0x09))
Store (BIF0 (), Local0)
Store (BIF1 (), Local1)
Store (BIF2 (), Local2)
Store (BIF3 (), Local3)
Store (BIF4 (), Local4)
If (LNotEqual (Local0, Ones))
{
If (LNotEqual (Local1, Ones))
{
If (LNotEqual (Local2, Ones))
{
If (LNotEqual (Local3, Ones))
{
If (LNotEqual (Local4, Ones))
{
FBIF (Local0, Local1, Local2, Local3, Local4)
CBIF ()
}
}
}
}
}

If (LEqual (PUNT, Zero))
{
Multiply (Local2, 0x0A, Local2)
}

Store (Local2, LFCC)
BATR ()
Return (PBIF)
}

Method (FBST, 4, NotSerialized)
{
And (Arg1, 0xFFFF, Local1)
Store (Zero, Local0)
If (ACAP ())
{
Store (One, Local0)
}

If (Local0)
{
If (CHGS (Zero))
{
Store (0x02, Local0)
}
Else
{
Store (One, Local0)
}
}
Else
{
Store (One, Local0)
}

If (BLLO)
{
Store (0x04, Local2)
Or (Local0, Local2, Local0)
}

Store (0x09, BRAH)
If (And (EB0S, 0x08))
{
Store (0x04, Local2)
Or (Local0, Local2, Local0)
}

If (LGreaterEqual (Local1, 0x8000))
{
Subtract (0xFFFF, Local1, Local1)
}

Store (Arg2, Local2)
If (LEqual (PUNT, Zero))
{
Store (0x09, BRAH)
Multiply (Local1, B0DV, Local1)
Multiply (Local2, 0x0A, Local2)
}

And (Local0, 0x02, Local3)
If (LNot (Local3))
{
Subtract (LFCC, Local2, Local3)
Divide (LFCC, 0xC8, Local4, Local5)
If (LLess (Local3, Local5))
{
Store (LFCC, Local2)
}
}
Else
{
Divide (LFCC, 0xC8, Local4, Local5)
Subtract (LFCC, Local5, Local4)
If (LGreater (Local2, Local4))
{
Store (Local4, Local2)
}
}

If (LNot (ACAP ()))
{
Divide (Local2, MBLF, Local3, Local4)
If (LLess (Local1, Local4))
{
Store (Local4, Local1)
}
}

Store (Local0, Index (PBST, Zero))
Store (Local1, Index (PBST, One))
Store (Local2, Index (PBST, 0x02))
Store (Arg3, Index (PBST, 0x03))
}

Method (CBST, 0, NotSerialized)
{
If (PUNT)
{
Store (0x09, BRAH)
Store (B0DV, Index (PBST, 0x03))
Store (DerefOf (Index (PBST, 0x03)), Local0)
Multiply (DerefOf (Index (PBST, One)), Local0, Index (PBST, One))
Divide (DerefOf (Index (PBST, One)), 0x03E8, , Index (PBST, One))
Multiply (DerefOf (Index (PBST, 0x02)), Local0, Index (PBST, 0x02))
Divide (DerefOf (Index (PBST, 0x02)), 0x03E8, , Index (PBST, 0x02))
}
}

Method (_BST, 0, NotSerialized) // _BST: Battery Status
{
Store (Zero, Index (PBST, Zero))
Store (Ones, Index (PBST, One))
Store (Ones, Index (PBST, 0x02))
Store (Ones, Index (PBST, 0x03))
If (LNot (BATP (Zero)))
{
Store (One, Index (PBST, Zero))
Return (PBST)
}

If (LEqual (GBTT (Zero), 0xFF))
{
Return (PBST)
}

BATO ()
BATS (Zero)
Store (BSTS (), Local0)
Store (BCRT (), Local1)
Store (BRCP (), Local2)
Store (BVOT (), Local3)
If (LNotEqual (Local0, Ones))
{
If (LNotEqual (Local1, Ones))
{
If (LNotEqual (Local2, Ones))
{
If (LNotEqual (Local3, Ones))
{
FBST (Local0, Local1, Local2, Local3)
CBST ()
}
}
}
}

BATR ()
Return (PBST)
}

Method (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended
{
If (LNot (BATP (Zero)))
{
Return (NBIX)
}

If (LEqual (GBTT (Zero), 0xFF))
{
Return (NBIX)
}

_BIF ()
Store (DerefOf (Index (PBIF, Zero)), Index (BIXT, One))
Store (DerefOf (Index (PBIF, One)), Index (BIXT, 0x02))
Store (DerefOf (Index (PBIF, 0x02)), Index (BIXT, 0x03))
Store (DerefOf (Index (PBIF, 0x03)), Index (BIXT, 0x04))
Store (DerefOf (Index (PBIF, 0x04)), Index (BIXT, 0x05))
Store (DerefOf (Index (PBIF, 0x05)), Index (BIXT, 0x06))
Store (DerefOf (Index (PBIF, 0x06)), Index (BIXT, 0x07))
Store (DerefOf (Index (PBIF, 0x07)), Index (BIXT, 0x0E))
Store (DerefOf (Index (PBIF, 0x08)), Index (BIXT, 0x0F))
Store (DerefOf (Index (PBIF, 0x09)), Index (BIXT, 0x10))
Store (DerefOf (Index (PBIF, 0x0A)), Index (BIXT, 0x11))
Store (DerefOf (Index (PBIF, 0x0B)), Index (BIXT, 0x12))
Store (DerefOf (Index (PBIF, 0x0C)), Index (BIXT, 0x13))
If (LEqual (DerefOf (Index (BIXT, One)), One))
{
Store (Zero, Index (BIXT, One))
Store (DerefOf (Index (BIXT, 0x05)), Local0)
Multiply (DerefOf (Index (BIXT, 0x02)), Local0, Index (BIXT, 0x02))
Multiply (DerefOf (Index (BIXT, 0x03)), Local0, Index (BIXT, 0x03))
Multiply (DerefOf (Index (BIXT, 0x06)), Local0, Index (BIXT, 0x06))
Multiply (DerefOf (Index (BIXT, 0x07)), Local0, Index (BIXT, 0x07))
Multiply (DerefOf (Index (BIXT, 0x0E)), Local0, Index (BIXT, 0x0E))
Multiply (DerefOf (Index (BIXT, 0x0F)), Local0, Index (BIXT, 0x0F))
Divide (DerefOf (Index (BIXT, 0x02)), 0x03E8, Local0, Index (BIXT, 0x02))
Divide (DerefOf (Index (BIXT, 0x03)), 0x03E8, Local0, Index (BIXT, 0x03))
Divide (DerefOf (Index (BIXT, 0x06)), 0x03E8, Local0, Index (BIXT, 0x06))
Divide (DerefOf (Index (BIXT, 0x07)), 0x03E8, Local0, Index (BIXT, 0x07))
Divide (DerefOf (Index (BIXT, 0x0E)), 0x03E8, Local0, Index (BIXT, 0x0E))
Divide (DerefOf (Index (BIXT, 0x0F)), 0x03E8, Local0, Index (BIXT, 0x0F))
}

Store (B0C3, Index (BIXT, 0x08))
Store (0x0001869F, Index (BIXT, 0x09))
Return (BIXT)
}

Method (_BTP, 1, NotSerialized) // _BTP: Battery Trip Point
{
ST8E (0x29, 0xFF)
ST8E (0x2A, 0xFF)
ST8E (0x28, 0x0F)
If (LNotEqual (Arg0, Zero))
{
Store (DerefOf (Index (PBIF, 0x04)), Local0)
Multiply (Arg0, 0x03E8, Local1)
Divide (Local1, Local0, Local2, Local3)
If (CHGS (Zero))
{
If (LNotEqual (Local2, Zero))
{
Add (Local3, One, Local3)
}
}

ST9E (0x29, 0xFF, And (Local3, 0xFF))
ShiftRight (Local3, 0x08, Local2)
And (Local2, 0xFF, Local2)
ST9E (0x2A, 0xFF, Local2)
}
}
}
}

SSDT

电池

更名如下。

1
2
3
4
5
6
7
Comment: change BIFA to BIGA
Find: 42494641
Replace: 42494741

Comment: change _BIX to XBIX
Find: 5F424958
Replace: 58424958

SSDT如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// 使用Catalina用户则需将EC0更改为EC
DefinitionBlock ("", "SSDT", 2, "hack", "BAT0", 0x00000000)
{
External (_SB.PCI0.LPCB.EC0, DeviceObj)
External (_SB.PCI0.LPCB.EC0.BAT0, DeviceObj)
External (_SB.PCI0.LPCB.EC0.BAT0._BIF, MethodObj)
External (_SB.PCI0.LPCB.EC0.BAT0.BIXT, IntObj)
External (_SB.PCI0.LPCB.EC0.BAT0.NBIX, IntObj)
External (_SB.PCI0.LPCB.EC0.BAT0.PBIF, IntObj)
External (_SB.PCI0.LPCB.EC0.BATP, MethodObj)
External (_SB.PCI0.LPCB.EC0.BSLF, IntObj)
External (_SB.PCI0.LPCB.EC0.ECAV, MethodObj)
External (_SB.PCI0.LPCB.EC0.GBTT, MethodObj)

Scope (_SB.PCI0.LPCB.EC0)
{
OperationRegion (ECAG, EmbeddedControl, Zero, 0xFF)
Field (ECAG, ByteAcc, Lock, Preserve)
{
Offset (0x04),
Offset (0x05),
Offset (0x06),
Offset (0x07),
Offset (0x08),
Offset (0x80),
Offset (0x81),
Offset (0x82),
Offset (0x83),
Offset (0x84),
Offset (0x85),
Offset (0x86),
Offset (0x87),
Offset (0x88),
Offset (0x89),
Offset (0x93),
Offset (0x95),
Offset (0x97),
Offset (0x98),
Offset (0x9C),
Offset (0x9D),
Offset (0x9E),
Offset (0xA0),
Offset (0xA1),
Offset (0xA2),
Offset (0xA3),
Offset (0xA4),
Offset (0xA5),
Offset (0xA6),
Offset (0xA7),
Offset (0xA8),
Offset (0xB0),
Offset (0xB2),
Offset (0xB4),
Offset (0xB6),
Offset (0xB8),
Offset (0xBA),
Offset (0xBC),
Offset (0xBE),
Offset (0xC0),
Offset (0xC2),
Offset (0xC4),
C3HG, 8,
C3HF, 8,
Offset (0xC8),
Offset (0xD0),
Offset (0xD2),
Offset (0xD4),
Offset (0xD6),
Offset (0xD8),
Offset (0xDA),
Offset (0xDC),
Offset (0xDE),
Offset (0xE0),
Offset (0xE2),
Offset (0xE4),
Offset (0xE6),
Offset (0xE8),
Offset (0xF0),
Offset (0xF2),
Offset (0xF4),
BSVN, 8,
BSVM, 8,
Offset (0xF8),
Offset (0xFA),
Offset (0xFC),
SBUY, 8,
SBUP, 8
}

Method (BIFA, 0, NotSerialized)
{
If (ECAV ())
{
If (BSLF)
{
Store (B1B2 (SBUY, SBUP), Local0)
}
Else
{
Store (B1B2 (BSVN, BSVM), Local0)
}
}
Else
{
Store (Ones, Local0)
}

Return (Local0)
}
}

Scope (_SB.PCI0.LPCB.EC0.BAT0)
{
Method (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended
{
If (LNot (BATP (Zero)))
{
Return (NBIX)
}

If (LEqual (GBTT (Zero), 0xFF))
{
Return (NBIX)
}

_BIF ()
Store (DerefOf (Index (PBIF, Zero)), Index (BIXT, One))
Store (DerefOf (Index (PBIF, One)), Index (BIXT, 0x02))
Store (DerefOf (Index (PBIF, 0x02)), Index (BIXT, 0x03))
Store (DerefOf (Index (PBIF, 0x03)), Index (BIXT, 0x04))
Store (DerefOf (Index (PBIF, 0x04)), Index (BIXT, 0x05))
Store (DerefOf (Index (PBIF, 0x05)), Index (BIXT, 0x06))
Store (DerefOf (Index (PBIF, 0x06)), Index (BIXT, 0x07))
Store (DerefOf (Index (PBIF, 0x07)), Index (BIXT, 0x0E))
Store (DerefOf (Index (PBIF, 0x08)), Index (BIXT, 0x0F))
Store (DerefOf (Index (PBIF, 0x09)), Index (BIXT, 0x10))
Store (DerefOf (Index (PBIF, 0x0A)), Index (BIXT, 0x11))
Store (DerefOf (Index (PBIF, 0x0B)), Index (BIXT, 0x12))
Store (DerefOf (Index (PBIF, 0x0C)), Index (BIXT, 0x13))
If (LEqual (DerefOf (Index (BIXT, One)), One))
{
Store (Zero, Index (BIXT, One))
Store (DerefOf (Index (BIXT, 0x05)), Local0)
Multiply (DerefOf (Index (BIXT, 0x02)), Local0, Index (BIXT, 0x02))
Multiply (DerefOf (Index (BIXT, 0x03)), Local0, Index (BIXT, 0x03))
Multiply (DerefOf (Index (BIXT, 0x06)), Local0, Index (BIXT, 0x06))
Multiply (DerefOf (Index (BIXT, 0x07)), Local0, Index (BIXT, 0x07))
Multiply (DerefOf (Index (BIXT, 0x0E)), Local0, Index (BIXT, 0x0E))
Multiply (DerefOf (Index (BIXT, 0x0F)), Local0, Index (BIXT, 0x0F))
Divide (DerefOf (Index (BIXT, 0x02)), 0x03E8, Local0, Index (BIXT, 0x02))
Divide (DerefOf (Index (BIXT, 0x03)), 0x03E8, Local0, Index (BIXT, 0x03))
Divide (DerefOf (Index (BIXT, 0x06)), 0x03E8, Local0, Index (BIXT, 0x06))
Divide (DerefOf (Index (BIXT, 0x07)), 0x03E8, Local0, Index (BIXT, 0x07))
Divide (DerefOf (Index (BIXT, 0x0E)), 0x03E8, Local0, Index (BIXT, 0x0E))
Divide (DerefOf (Index (BIXT, 0x0F)), 0x03E8, Local0, Index (BIXT, 0x0F))
}

Store (B1B2 (C3HG, C3HF), Index (BIXT, 0x08))
Store (0x0001869F, Index (BIXT, 0x09))
Return (BIXT)
}
}

Method (B1B2, 2, NotSerialized)
{
Return (Or (Arg0, ShiftLeft (Arg1, 0x08)))
}
}

I2C触控板

SSDT如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009)
{
External(TPDI, FieldUnitObj)
External(TPHI, FieldUnitObj)
External (_SB.PCI0.I2C1,DeviceObj)


Scope (_SB.PCI0.I2C1)
{
Device (TPXX)
{
Name (SBFG, ResourceTemplate ()
{
GpioInt (Level, ActiveLow, Exclusive, PullUp, 0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x55
}
})

Name (_ADR, One) // _ADR: Address
Name (ETPH, Package (0x16)
{
"ELAN1200",
"ELAN1201",
"ELAN1203",
"ELAN1200",
"ELAN1201",
"ELAN1300",
"ELAN1301",
"ELAN1300",
"ELAN1301",
"ELAN1000",
"ELAN1200",
"ELAN1200",
"ELAN1200",
"ELAN1200",
"ELAN1200",
"ELAN1203",
"ELAN1203",
"ELAN1201",
"ELAN1300",
"ELAN1300",
"ELAN1200",
"ELAN1300"
})
Name (FTPH, Package (0x05)
{
"FTE1001",
"FTE1200",
"FTE1200",
"FTE1300",
"FTE1300"
})
Method (_HID, 0, NotSerialized) // _HID: Hardware ID
{
If ((TPDI & 0x04))
{
Return (DerefOf (ETPH [TPHI]))
}

If ((TPDI & 0x10))
{
Return (DerefOf (FTPH [TPHI]))
}

Return ("ELAN1010")
}

Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */) // _CID: Compatible ID
Name (_UID, One) // _UID: Unique ID
Name (_S0W, 0x03) // _S0W: S0 Device Wake State
Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method
{
If ((Arg0 == ToUUID ("3cdff6f7-4267-4555-ad05-b30a3d8938de") /* HID I2C Device */))
{
If ((Arg2 == Zero))
{
If ((Arg1 == One))
{
Return (Buffer (One)
{
0x03 // .
})
}
Else
{
Return (Buffer (One)
{
0x00 // .
})
}
}

If ((Arg2 == One))
{
Return (One)
}
}
Else
{
Return (Buffer (One)
{
0x00 // .
})
}
}

Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}

Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings
{
Name (SBFB, ResourceTemplate ()
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.PCI0.I2C1",
0x00, ResourceConsumer, , Exclusive,
)
})
Return (ConcatenateResTemplate (SBFB, SBFG))
}
}
}
}

附录

工具

SSDTTime

下载

1
https://github.com/corpnewt/SSDTTime

常见问题

提示Could not locate or download iasl!

Python版本过时。可更新Python,或下载iasl并放置到SSDTTime的脚本文件夹中。

旧版工具

DSDT editor

1
2
https://www.insanelymac.com/forum/topic/223205-dsdt-editor-and-patcher/
http://www.macbreaker.com/2012/03/make-dsdt-with-dsdt-editor.html

DSDT库

1
2
3
4
5
# Intel NUC5/NUC6/NUC7/NUC8 DSDT patches
https://github.com/RehabMan/Intel-NUC-DSDT-Patch

# DSDT Database
https://www.tonymacx86.com/dsdt-database

参考教程

Patching LAPTOP DSDT/SSDTs

1
https://www.tonymacx86.com/threads/guide-patching-laptop-dsdt-ssdts.152573/

DSDT与SSDT编译错误解决方案合集汇总

1
http://imacos.top/2019/08/23/1709/

OpenCore引导各平台所需要的SSDT

1
http://imacos.top/2020/03/29/ssdt/

小白也能看懂的入门教程DSDT/SSDT/ROM提取完整步骤编译拆分补丁除错实现笔记本电脑电池显示

1
http://imacos.top/2019/07/22/1409/