DSDT/SSDT

版权说明:本文章参考tonymacx86的Patching LAPTOP DSDT/SSDTs这篇文章

如果需要转载,请注明原文地址:http://blog.csdn.net/wr132/article/details/54798754

概览

为了让OS X的各个组件在你的笔记本上更好的运行,你通常需要一个经过适当打了补丁的DSDT以及一系列SSDT。本文将为你之后正确地对OEM提供的DSDT/SSDT打补丁打下基础。

高级用户或许希望能够通过Clover实现在不提取DSDT/SSDT的情况下打补丁,参见这篇教程:http://www.tonymacx86.com/threads/guide-using-clover-to-hotpatch-acpi.200137/

如果你尝试使用来自另一台电脑的DSDT,那么你几乎总会以失败告终。你很难验证来自其他电脑的ACPI文件是否有效。如果你使用外来的ACPI文件,有时即使硬件配置上的细微差别(BIOS版本,内存大小,BIOS的设置以及其它硬件差异不如无线网卡)也会导致系统的不稳定和莫名其妙的问题。这些硬件配置差异会导致地址空间的差异,从而导致一台计算机的DSDT并不适合另一台计算机。即使同一型号的电脑,也经常会发生配置了不同的主板这种情况,从而导致ACPI文件的各不相同。

打补丁的过程分为以下几步:

  • 获取原始文件
  • 反编译原始文件
  • 分析和过滤原始文件
  • 打补丁
  • 保存(编译)和安装

获取原始ACPI文件

所有的BIOS都会为操作系统提供一套ACPI文件。所以,不管什么操作系统,你都可以获取这些文件以便后续打补丁。你可以在Linux,OS X,Windows甚至 Clover里取得这些文件。不管什么方式,你获取的这些文件都完全相同,不过因为软件不同,命名可能也不同。

本篇教程将使用三种方法获得ACPI文件:在OS X里使用patchmatic;在Clover里使用F4;使用Linux。

使用patchmatic

如果你已经安装了OS X,并且没有使用任何打过补丁的ACPI文件启动,你可以使用patchmatic来获得DSDT/SSDT原始文件。从此处下载patchmatic可执行文件https://github.com/RehabMan/OS-X-MaciASL-patchmatic(请务必阅读README文件因为下载地址在里面)。如果想要在终端中使用,你需要把可执行文件(在ZIP中)复制到 /usr/bin 中。

安装完patchmatic之后,你可以在终端中这样调用:

cd ~/Desktop
mkdir extract
cd extract
patchmatic -extract

patchmatic会把所有已经加载的ACPI文件释放到当前文件夹,如果你在bootloader中使用了任何选项从而影响了DSDT/SSDT,你将无法获得原始的ACPI文件,所以你需要确保没有使用这样的选项。比如说,如果你使用(Chameleon)DropSSDT=Yes,或者(Clover) DropOem=true,原生的SSDT会被忽略,这样你就没有办法在patchmatic获得它们了。对于Clover DSDT “Fixes”也是相同的道理——这些修复会修改原生的DSDT,所以你需要避免这些修复。有一些选项比如GeneratePStates/GenerateCStates=Yes, 或者是 Clover的 /ACPI/SSDT/Generate/CStates /ACPI/SSDT/Generate/PStates将会注入额外的SSDT,从而导致一些莫名其妙的问题,这些情况都应该被避免。

结合上述这些原因,使用Linux或Clover来获得ACPI文件更加简单。

注意:使用’patchmatic -extract’来确认你获得的DSDT/SSDT是否是你需要的文件是一个有效的方法。

使用Clover F4(推荐)

推荐使用Clover F4这种方法,不仅因为提取的方法很简单,而且还可以很方便地对ACPI的原始文件和打过补丁的文件进行比对(为了分析解决问题)。

在Clover的主页,你可以按F4然后Clover会把原生的ACPI文件放到EFI/Clover/ACPI/origin目录下。当你启动OS X之后你就可以对它们进行反编译或者打补丁操作。注意,有些BIOS需要同时按Fn+F4才能激活F4,所以如果你不确定,把F4盒Fn+F4都按一遍。这个过程并不会有任何反馈,因为要等待文件写入会有一个小小的延迟,如果这些文件被写入USB存储设备,那么这个延迟会更加明显。

有时,Clover F4会写入重复的SSDT。这些副本在反编译的时候会造成一些问题。如果你真的遇到这样的问题,你需要分析哪些文件是副本,最简单的方法就是看文件大小,相同的文件大小往往对应着相同的文件。

你可以通过在终端中输入以下命令来查看SSDT的字节大小。

ls -l SSDT*.aml

使用Linux获得文件

在Linux中,原生的ACPI文件直接存在于文件系统之中。你可以在/sys/firmware/acpi/tables 和 /sys/firmware/acpi/tables/dynamic目录中找到它们。你可以在终端中输入命令来获得所有文件。

你没有必要安装Linux,只要从USB启动即可:

http://www.ubuntu.com/download/desktop/create-a-usb-stick-on-windows

在终端中输入

sudo cp -R /sys/firmware/acpi/tables DEST

你需要把这些文件复制到一个FAT32文件系统的USB设备。使用FAT32文件系统可以避免权限问题因为这个文件系统不支持文件权限。DEST的值是你的USB设备的挂载点,它由你的Linux版本和Linux的启动方式决定,你可以 通过在终端中输入mount来查看挂载点,或者在Linux文件管理器中把鼠标放在存储设备的图标上来查看。

反编译所需的工具

为了正确反编译你获得的文件,你需要iasl编译器,它需要在终端运行。

你需要一个较新版的iasl来正确地反编译。可以在这里下载适当的版本:https://bitbucket.org/RehabMan/acpica/downloads。。推荐把iasl的可执行文件复制到/usr/bin,这样就能在终端中方便使用该工具。

举个例子,如果你把它下载到~/Downloads/iasl.zip,你可以在终端中通过以下方法进行解压和复制:

cd ~/Downloads
unzip iasl.zip
sudo cp iasl /usr/bin

从github编译最新版本的iasl

你可以从github编译最新版的iasl,假设你已经安装了Xcode:

1 mkdir ~/Projects && cd ~/Projects
2 git clone https://github.com/RehabMan/Intel-iasl.git iasl.git
3 cd iasl.git

最新的版本总是包含一些实验性的并且没有经过完全测试的代码。比如,新的代码中Intel添加了If/Else代码块因为Switch/Case有Bug。

建议使用修改之前的版本

git checkout b9c6c2b

注意:b9c6c2b这个版本在bitbucket已经提供下载。

然后编译工程:

make

现在你可以使用以下命令安装:

sudo make install

如果你已经安装了MaciASL,你也可以在MaciASL中使用新版的编译器(在/usr/bin这个目录下):

sudo cp /usr/bin/iasl /Applications/MaciASL.app/Contents/MacOS/iasl61

最新版的iasl总会在bitbucket提供下载,但对于那些总是喜欢使用最新版的人,需要自己编译项目。。。

反编译ACPI文件

虽然原生的ACPI文件可以通过MaciASL直接打开,但并不推荐这么做。直接使用MaciASL打开将会导致aml文件被单独反编译,如果aml文件之间有复杂的引用关系,将不能正确地进行反编译,你将会发现一堆难以修复的错误。

因此,最好将所有aml文件一起进行反编译。你需要把所有的DSDT/SSDT放在一个独立的文件夹中,不要把不相关的文件复制进来,并且确保所有文件以.aml结尾。

然后,在终端中输入以下命令进行反编译:

1 cd "to directory where you placed all SSDT/DSDT"
2 iasl -da -dl *.aml

注意:不要尝试使用-da选项反编译其它的ACPI文件,不会有任何效果。

注意:也请阅读下方的部分,考虑使用refs.txt,方法很简单,但可以有效排除许多常见的错误。

完成上述步骤之后,你只需要使用*.dsl文件来做接下来的工作,可以使用MaciALS来编辑它们。当然,要使用它们,你必须把它们保存为“ACPI Machine Language Binary”格式并且以.aml作为文件的后缀,然后将它们放在正确的位置以便被bootloader加载。你可以保留这些打过补丁的..dsl文件以便以后打更多的补丁。

注意:使用ACPI6.1可以更好地处理被iasl编译过的aml文件。ACPI6.1在编译器中添加了一个组件,使用它可以在生成的aml文件中添加外部引用信息。ACPI的解释器会忽略这些信息,但是这些信息对于反编译器正确地反编译一个独立的aml文件很有用。因此,你可能会发现被新的工具重新编译过的aml文件可以直接被MaciASL打开并且不包含任何错误。当然,我们直接提取的aml文件中由于不包含这些信息,所以此时我们仍然需要使用-da选项联合所有的aml文件进行反编译,正如上面所介绍的。

注意:针对Snow Leopard的ACPI文件:很不幸,10.6.8这个版本太老了以至于其阻止aml进行外部引用。如果你需要将ACPI文件应用在Snow Leopard中,你需要在将dsl编译到aml的时候使用-oe选项。这个选项不能在MaciASL中使用,因此你只能在终端中完成编译。

使用refs.txt来完成反编译

有时会存在一些未定义的外部符号。isal反编译器会尝试猜测参数的个数,但这种尝试经常出错。你可以通过使用一个记录着外部定义的文本文件来纠正这些错误。常见的未定义符号比如SGPO, ECRD, ECWT, 和 MMTB。下面的refs.txt包括一些常见和非常见的丢失符号(根据论坛上网友的反馈得来)来解决反编译器遇到的问题。

首先在DSDT/SSDT所在的目录下厂家refs.txt文件:

 1 External(MDBG, MethodObj, 1)
 2 External(_GPE.MMTB, MethodObj, 0)
 3 External(_SB.PCI0.LPCB.H_EC.ECWT, MethodObj, 2)
 4 External(_SB.PCI0.LPCB.H_EC.ECRD, MethodObj, 1)
 5 External(_SB.PCI0.LPCB.H_EC.ECMD, MethodObj, 1)
 6 External(_SB.PCI0.PEG0.PEGP.SGPO, MethodObj, 2)
 7 External(_SB.PCI0.GFX0.DD02._BCM, MethodObj, 1)
 8 External(_SB.PCI0.SAT0.SDSM, MethodObj, 4)
 9 External(_GPE.VHOV, MethodObj, 3)
10 External(_SB.PCI0.XHC.RHUB.TPLD, MethodObj, 2)

注意:一个更友好的方式是在终端中使用pbpaste创建文件。你需要首先将上方的文档复制到剪贴板(别告诉我你不会),然后:

pbpaste>refs.txt

上述命令会在当前目录创建refs.txt文件,然后在反编译的过程中使用该文件:

iasl -da -dl -fe refs.txt *.aml

老版本的反编译器会把这些外部声明放在其它声明的前面。这不是一个好方法。大多数时候,你需要把它们移动到其它声明的后面。这种错误非常明显,因此当你看到来自refs.txt中的外部声明的错误时应当能够辨别。在ACPI6.1当中,这个bug已经被修复了。

筛选ACPI文件

对于一些老电脑(Sandy Bridge或者更早的)来说,与CPU相关的SSDT会造成一些问题,如果你遇到这样的问题,那么你不能把这样的SSDT放在ACPI/patched。

如果没有问题,我比较喜欢按照原始的顺序使用那些正确地打过补丁的SSDT。如果又一个SSDT没有经过任何修改,那么你不需要重新编译它,直接使用原始的aml文件即可。

注意:来自Clover或者Linux的动态子目录的SSDT不能被放在ACPI/patched下,因为这些SSDT只有在需要的时候才会被动态加载进来,可能不够完整。

当你成功地反编译所有文件之后,检查每一个SSDT文件从而确定这些SSDT的功能。如果一个SSDT与CPU相关并且你确定其会导致一些问题,那么就将它放在一边,不要把它放在bootloader的相关目录中。大多数时候,如果SSDT中存在包含在Scope _PR.CPUx中的object,那么它很有可能与CPU有关。

下面列出你可能会遇到的典型SSDT

  • 与CPU相关:如上所述,包含一些会导致问题的未知因素。
  • SATA:无所谓是否使用,看你是不是强迫症。
  • PTID:大多数情况这个文件对于OS X来说没什么用,并且包含许多错误。少数情况下,它可能会提供读取风扇转速,温度或者其它系统状态的方法。
  • IAOE:如果这个SSDT存在,它经常作为DSDT中的in _PTS 和 _WAK的入口。如果没有它系统睡眠可能会出现问题。
  • GFX0:通常存在’Device GFX0’的SSDT与集成显卡有关。你需要在这个SSDT上打补丁来实现背光控制。一些老的笔记本经常会把GFX0定义在DSDT中。新的Haswell笔记本通常定义在SSDT中(即使也可以定义在DSDT中)。
  • PEGP:在双显卡的笔记本中PEGP通常与独立显卡有关。这样的SSDT通常不止一个,你需要把它们联合起来,这样打补丁才会有效。最常见的就是禁用独立显卡的补丁。

你最好记下哪些SSDT你打算忽略,哪些需要保留原始文件,哪些需要修改。

修改错误

即使进行联合反编译,反编译出的代码仍然可能包含一些错误。导致这些错误的原因有很多,如果iasl的某些修改,iasl自身的不完善,以及笔记本之间的不同编译环境。比如,一个导致错误的常见原因(我自己的想法)是一些被引用的函数(比如MMTB和MDBG)实际上是存在于Windows系统本身的,而不在ACPI中;还有一种情况是代码中本身存在bug或者是代码被无意地写入(有时很难区分这一点)。

因此,当你已经知道了你需要哪些ACPI文件,你必须修正它们之中包含的错误。在我的github仓库中有许多修复常见错误的补丁,你可以使用MaciASL完成打补丁的操作。

MaciASL软件: https://github.com/RehabMan/OS-X-MaciASL-patchmatic 
笔记本补丁: https://github.com/RehabMan/Laptop-DSDT-Patch

注意:我没有在DSDT editor上测试我的补丁,因为它包含了太多的bug,而且iasl的版本也太老,因此就不要来问关于它的问题啦。

为了能够顺利完成下载和对MaciASL进行正确的设置,请务必提前阅读README文件。应对syntax/error的补丁的名字以”[syn]”开头,对一些比较老的DSDT来说常见的例子如”Fix _PLD Buffer/Package Error”, “Fix TNOT Error”, 和 “Fix FPED Parse Error”。为了确定你需要哪些补丁,你可以阅读iasl报出的错误信息以及引起错误的代码。你也可以尝试应用一些补丁,同时在MaciASL中观察补丁对文件进行了修改,如果你对某个错误不是很熟悉,可以通过这种方法多尝试几次来修正错误。

对于某些错误,你可以通过简单地删除造成错误的代码。但是这取决于这些代码是否有用。比如说,由’External’引起的错误可以直接删除来解决错误。如果你想,你甚至可以写一个补丁来自动完成这个工作。

如果你对ACPI比较熟悉并且有一点编程基础将会对这些工作很有好处。

目前你的目标是让这些dsl文件在编译的时候没有errors (warnings/remarks/optimizations 一般不会有影响)。一旦你得到一个编译无误的文件,你就可以继续对它进行打补丁来修复你遇到的问题。

常见的补丁

一般来说,只有当你需要修复特定的问题的时候才需要对DSDT打补丁,但是有一些补丁在很多场合下都需要使用并且几乎不大可能会导致问题,这些补丁也在github的仓库中:

“Fix _WAK Arg0 v2” 
“HPET Fix” 
“SMBUS Fix” 
“IRQ Fix” 
“RTC Fix” 
“OS Check Fix” 
“Fix Mutex with non-zero SyncLevel” 
“Fix PNOT/PPNT” (只有当你忽略了与CPU有关的SSDT才需要使用) 
“Add IMEI” (如果你的DSDT或者SSDT已经存在IMEI/HECI/MEI device,不需要使用该补丁)

注意:The OS Check Fix补丁跟你电脑出厂预装的系统或者现在正在使用的系统版本都没有关系。

注意:如果你使用了所有的SSDT不要使用”Fix PNOT/PPNT”这个补丁,只有在你去除了与CPU相关的SSDT情况下才能使用。

USB补丁可以修复“瞬间唤醒”问题,这个问题导致电脑在从睡眠到开始到唤醒的几秒钟内不能再次睡眠。

针对你的硬件适当打上补丁 
“6-series USB” 
“7-series/8-series USB”

USB3 Mutliplex补丁可以让你使用苹果原生的AppleUSBXHCI.kext而不是GenericUSBXCHI.kext。它基于Mieze公布的一些写信。大多数DSDT需要修改才能使用。比如ProBook就需要使用该补丁的一个修改版本。而Lenovo u310/u410可以直接使用: 
“7-series USB3 Multiplex”

如果你正在Yosemite上使用GenericUSBXHCI.kext,确保你使用的是为Yosemite生成的GenericUSBXHCI.kext。要避免瞬间唤醒这种情况你可能还需要内核标识 -gux_defer_usb2。

如果在使用AppleUSBXHCI.kext的时候遇到瞬间唤醒的问题,一个可选的解决方案是使用”USB _PRW 0x6D (instant wake)”。你必须检查DSDT与 _PRW有关的函数的返回值来确定这个补丁是否适合你的DSDT。当然github仓库还提供了”USB _PRW 0x0D (instant wake)”(0x0d和0x6d对于XHC/EHC/HDEF来说都是从_PRW返回的常见值)。

如果你有一个Haswell CPU/8-series 芯片组,,并且AooleLPC.kext没有加载,你需要使用下面的补丁注入一个合适的ID从而允许驱动被加载: 
“Haswell LPC”

如果你有一个Skylake CPU/100-series 芯片组,,并且AooleLPC.kext没有加载,你需要使用下面的补丁注入一个合适的ID从而允许驱动被加载: 
“Skylake LPC”

注意:重命名一定要彻底。通常,重命名可以更好地适配OS X系统。比如把GFX0重命名为IGPU可以让IGPU power management正确工作。在这种情况下,所有与其有关的SSDT/DSDT都需要参与重命名。

注意:一定要避免重名现象发生。一种很常见的情况是往SSDT中添加一个_DSM函数,但同时OEM也在同一个路径中定义了一个_DSM函数。要避免这种情况,你可以使用”Remove _DSM methods”补丁作为你使用的第一个补丁,当然也可以选择”Rename _DSM methods to XDSM” 这个补丁,因为有时”Remove _DSM methods”会暴露出MaciASL的一个bug。

针对特定问题的补丁

电池状态:http://www.tonymacx86.com/yosemite-laptop-support/116102-guide-how-patch-dsdt-working-battery-status.html

背光控制:http://www.tonymacx86.com/yosemite-laptop-support/152659-patching-dsdt-ssdt-laptop-backlight-control.html

禁用独立显卡:http://www.tonymacx86.com/yosemite-laptop-support/163772-guide-disabling-discrete-graphics-dual-gpu-laptops.html

当你在阅读一些针对特定笔记本的教程的时候,这些文章可能会直接将补丁的内容贴出来,你只需要把这些补丁的内容直接粘贴到MaciASL的窗口中,然后点击Apply即可。

如果你对编写补丁文件很感兴趣,请阅读MaciASL的补丁语法: 
http://sourceforge.net/p/maciasl/wiki/Patching Syntax Grammar/

注意:在许情况下,对DSDT补丁需要与一些附加的kext结合从而使kext被系统正确加载。

保存与加载

为了使用打过补丁的DSDT/SSDT,你需要把它们保存在正确的位置从而可以让bootloader加载它们。对于不同的bootloader,保存的路径不同,命名要求也不同。首先你必须保存为”ACPI Machine Language Binary”格式。如果保存为AML extension可能会导致系统出现一些非常奇怪的问题。

Clover:文件首先应该被放置在Clover所在的分区(一般都是EFI分区),所以路径就是EFI/Clover/ACPI/patched。如果DSDT.aml文件存在,会自动替换OEM的DSDT。对于版本号低于3062的Clover,ACPI文件必须被命名为SSDT-x,x表示一个数字,最高到19.Clover允许数字不连续。版本号大于等于3062的Clover,会加载所有后缀为aml的文件,对于命名没有要求。记住SSDT的加载顺序很重要,因此按照原始的顺序命名SSDT很重要。

注意,针对Clover 3062+,由于SSDT加载方式的改变导致加载顺序变得随机,因此需要规定通过修改config.plist/ACPI/SortedOrder来指定加载顺序,下面的文件提供了一个很好的加载顺序模板: 
http://www.tonymacx86.com/yosemite-laptop-support/148093-guide-booting-os-x-installer-laptops-clover.html

Chameleon(或者 Chimera):文件需要放置在 系统盘的/Extra目录下。如果DSDT.aml文件存在,会自动替换OEM的DSDT。Chameleon不允许不连续的编号,所以需要命名为SSDT.aml, SSDT-1.aml, SSDT-2.aml, SSDT-3.aml等等。如果你命名为SSDT.aml, SSDT-1.aml, SSDT-4.aml, SSDT-5.aml,那么只有SSDT.aml, SSDT-1.aml会被加载因为后面的不再连续,所以被忽略。

最后,记住你不能只是把ACPI文件放在目录里而不忽略OEM的SSDT。最简单的办法就是使用DropSSDT=Yes (Chameleon) 或者 ACPI/SSDT/DropOem=true (Clover)来忽略所有的原生SSDT从而加载你修改过的SSDT。

资源

MaciASL (RehabMan fork): https://github.com/RehabMan/OS-X-MaciASL-patchmatic 
patchmatic: https://github.com/RehabMan/OS-X-MaciASL-patchmatic 
iasl (RehabMan fork): https://bitbucket.org/RehabMan/acpica/downloads 
ACPI spec: http://acpi.info/spec.htm

RehabMan github: https://github.com/RehabMan?tab=repositories

Clover laptop guide: http://www.tonymacx86.com/yosemite-…oting-os-x-installer-laptops-clover-uefi.html 
Clover config.plist files for laptops: https://github.com/RehabMan/OS-X-Clover-Laptop-Config

Clover thread: http://www.insanelymac.com/forum/topic/284656-clover-general-discussion/ 
Clover changes: http://www.insanelymac.com/forum/topic/304530-clover-change-explanations/

原文地址:https://www.cnblogs.com/linxmouse/p/9155275.html