[TOC] **** # 【指南】使用Clover来热修补ACPI > 英文原文:[Using Clover to "hotpatch" ACPI](https://www.tonymacx86.com/threads/guide-using-clover-to-hotpatch-acpi.200137/) > 本文出处:http://bbs.pcbeta.com/viewthread-1745275-1-1.html # 前言 hotpatch在RehabMan大神维护得elitebook系列机型方面体现得很完美,我是翻elitebook机型的hotpatch后发现的,所以我决定来翻译这个教程,水平有限(大部分东西看不懂,靠有道翻译对付的,凑合吧),错漏之处请各位指出,谢谢。 先贴上国内的几个帖子,都写得很好,方便大家理解,版权归原作者。 1.华硕 VM510LEFI分享9CC3笔记本主板芯片通用 : https://blog.neroxps.cn/blog/macOS/9CC3-EFI-README.html 2.hotpatch学习笔记: http://bbs.pcbeta.com/forum.php?mod=viewthread&tid=1733965 3.暗影精灵2代Pro安装macOS Sierra 10.12.5全记录(hotpatch): http://bbs.pcbeta.com/viewthread-1742550-1-1.html 目前我认为第三篇帖子和RehabMan的hotpatch方法是比较接近的,不过只是个人主观意见。 最好之前先去看看**SSDT/DSDT**的部分。 # 介绍 在接近MAC配置的非MAC硬件上修补`ACPI`使之启用(接近)MAC的完整功能。 在这里有一份完整的指导:[guide-patching-laptop-dsdt-ssdts](http://www.tonymacx86.com/threads/guide-patching-laptop-dsdt-ssdts.152573/),这里的指导使用所谓的“ **静态修补(static patching)** ”,为了注入ACPI补丁文件,我们提取本机ACPI,将他们拆开,进行修改,然后重新编译放到`\EFI\Clover\ACPI\patch`目录下,这是使用clover注入修补ACPI,而不是修改硬件ACPI。本方法涉及到的技术,可以直接从BIOS读取ACPI的修补文件,跳过提取、拆卸和重编译步骤。 在试图修复ACPI之前,你应该理解ACPI的一些规范、概念,和一些关于二进制补丁和编译的基础。这份指南不会详细讲解这些知识。 # Clover的修补机制 Clover提供了一些方法来完成ACPI hotpatch: - `config.plist/ACPI/DSDT/Fixes`(在config.plist文件ACPI/DSDT/下添加修复) - `config.plist/ACPI/DSDT/Patches`(在config.plist文件ACPI/DSDT/下添加补丁) - `ability to inject additional SSDTs`(在ssdt文件下注入额外的SSDTs) (这一部分体现得最好的是在elitebook机型下面,elitebook机型的hotpatch详见:https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch) DSDT/Fixes提供固定功能的ACPI修补,每个“Fixes”可以做一种特殊的修补,可以用来代替使用MaciASL和静态修补进行的那些典型修补。例如,“IRQ Fix”可以实现与“Fix HPET_0010”“FixIPIC_0040”“FIX_RTC_20000”和“FIX_TMR_40000”;再看另一个实例,”`Fix _WAK Arg0 v2`”可以实现`WAK Arg0 v2`修补。你可以阅读Clover wik了解更多信息。大多数时候,DSDT实现基本功能不需要太多的"Fixes”,DSDT "Fixes" 对于那些很难通过`ACPI/DSDT/Patches` 或者添加到 `SSDTs`实现或修补的补丁是有用的。 Clover允许在`config.plst/DSDT/Patches`下搜索和替换二进制,Clover加载本地ACPI文件时,会应用`config.plst/DSDT/Patches`下的Patches二进制文件进行搜索/替换,然后注入修补ACPI。你需要了解AML的二进制格式和常用的ACPI规范。 ACPI名称空间是在加载时合并DSDT和SSDTs来构建的。通过将额外SSDTs放入到ACPI/patched,我们本质上是将代码添加到这个ACPI集合中。因为许多OS X补丁大多通过`_DSM`方法来添加属性到ioreg,通常是简单的添加一个包含额外的`_DSM`方法的SSDT而不是修补原始的ACPI文件。你比较熟悉的一个完美的例子是由Pike的`ssdtPRgen.sh`生成的`SSDT.aml`实现CPU变频。 在某些情况下,必须使用不止一个机制来实现一个目标。例如,您可能使用二进制补丁来禁用或重命名原始`ACPI`集合中的组件,然后用附加的SSDTs替换它。 # 重命名ACPI对象(Renaming ACPI objects) 因为OS X可以依赖于mac使用的特定的ACPI对象名称,一个常见的补丁是在原始ACPI集合中重命名一个对象。例如,大多数PC笔记本电脑使用`GFX0`来表示集成的Intel GPU对象(Intel HD Graphics)。在OS X中,除非该设备被命名为`IGPU`,否则不会启用英特尔图形的电源管理。使用静态补丁,我们应用“Rename IGPU to GFX0”来重命名这个对象。补丁必须应用到DSDT和所有引用它的SSDTs。 有了hotpatch,我们可以在`ACPI/DSDT/Patches`中使用简单的Clover补丁将`GFX0`重命名为`IGPU`。这些补丁适用于DSDT和所有本地SSDTs(`DSDT/Patches`不适用于通过`ACPI/patched`添加的SSDTs)。重新命名的补丁将是 ~~~ Comment: Rename GFX0 to IGPU Find: <4746 5830> Replace: <4947 5055> ~~~ 查找和替换的十六进制值分别是GFX0和IGPU的ASCII码。 注意: ~~~ u430:~ RehabMan$ echo -n GFX0|xxd 0000000: 4746 5830 GFX0 u430:~ RehabMan$ echo -n IGPU|xxd 0000000: 4947 5055 IGPU ~~~ 有许多常见的renames,而且大多数都在 `config.plist` 是`my Clover/hoptpatch`项目的一部分: https://github.com/RehabMan/OS-X-Clover-Laptop-Config/tree/master/hotpatch 事实上,同一项目的一部分的hotpatch SSDTs依赖于那些被实现的重命名。 常见的重命名: ~~~ GFX0 -> IGPU SAT0 -> SATA EHC1 -> EH01 EHC2 -> EH02 XHCI -> XHC HECI -> IMEI MEI -> IMEI LPC -> LPCB HDAS -> HDEF AZAL -> HDEF ~~~ 注意:所有ACPI标识符都是4个字符。短名称是用下划线填充的。例如,XHC在AML二进制中表示为`XHC_`,EC为`EC__`,EC0 为 `EC_`,MEI 为 `MEI_`,等等。 # 删除方法(Removing methods) 使用Clover二进制补丁来删除ACPI对象(方法、名称、设备等)非常困难。通常,我们必须添加`_DSM`方法来注入属性来描述各种硬件的属性。但是,添加的`_DSM`方法可能会与现有的`_DSM`方法相冲突,这些方法可能已经存在于本地ACPI文件中。使用静态补丁,将使用“`Remove _DSM methods`”。 由于很难删除这些方法,但是我们不希望原始方法与添加的新·`_DSM`方法相冲突,修复方法是将原始方法重命名为其他内容。 所以…同样,我们使用一个简单的重命名补丁: ~~~ Comment: Rename _DSM to XDSM Find: <5f44534d> Replace: <5844534d> ~~~ 有时,您可以重命名一个对象,以有效地禁用它,这样它就不会产生问题。例如,我的Intel DH67GD DSDT定义了一个`APSS`对象。如果这个对象留在DSDT中,它会干扰电源管理(引起恐慌)。我使用`APSS -> APXX`的重命名。因为AppleIntelCPUPowerManagement正在寻找APSS,它改名为`APXX`不会引起问题。 # 重定向和替换(Redirect and Replace) 在某些情况下,我们希望替换代码来改变行为。为此,我们可以重命名对象,并在SSDT中提供一个可替换的实现。 一个常见的解决方法是欺骗DSDT和SSDTs中的ACPI代码,这样它的行为就表现得像特定的windows的ACPI代码。当静态修补时,我们可以使用“OS Check Fix (Windows 8)”。应用时,它会更改代码从: ~~~ If (_OSI("Windows 2012")) ~~~ 变为: ~~~ If (LOr(_OSI("Darwin"),_OSI("Windows 2012")) ~~~ 由于OS X中的`_OSI`实现只响应“Darwin”,所以代码被更改,因此这个特定的`_OSI`检查也可以满足“Darwin”。 hotpatching采取相反的方法,我们不使用`_OSI`更改代码,而是更改代码,因此它调用了一个不同的方法来模拟Windows ACPI主机上的`_OSI`实现。 这项技术依赖于两种技术……一个补丁来改变所有从`_OSI`到`XOSI`的调用…以及`XOSI`的实现,它模仿Windows对一个特定Windows版本的操作。 首先,更改代码来 调用`XOSI` 而不是`_OSI`: ~~~ Comment: Change _OSI to XOSI Find: <5f4f 5349> Replace: <584f 5349> ~~~ 上面的十六进制编码不应该是神秘的(它们分别是`_OSI`和`XOSI`的ASCII码)。以上所述的代码,经过Clover的修补后,将会: ~~~ If (XOSI("Windows 2012")) ~~~ 现在我们需要一个实现`XOSI`的`SSDT`。您将在 rep 中找到这样的实现(`SSDT-XOSI.dsl`)。注意,如果没有实现`XOSI`方法的`SSDT`,对`XOSI`的调用会导致**ACPI中止**(ACPI abort导致ACPI方法的执行立即被错误终止)。如果没有`XOSI`方法,不要使用`_OSI -> XOSI`补丁。 # 重命名和替换(Rename and Replace) 第二种模式,类似于“重定向和替换”是“重命名和替换”。在这种情况下,我们不再更改所有的调用站点,而是更改方法定义,使方法被命名为与原来不同的方法,但是在调用站点上保留原始的方法名称。这允许 被调用的目标方法 可以被替换。 例如,USB设备的“瞬间唤醒”非常常见。作为一种变通方案,在USB上唤醒可以被禁用。大多数笔记本电脑都没有BIOS选项,所以控制这个特性的`_PRW`方法被修补了。 例如,原始的`_SB.PCI0.EHC1._PRW`方法可能被读取: ``` Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake { Return (GPRW (0x6D, 0x03)) } ``` 为了打补丁,在`EHCI#1`上的USB设备不能引起wake,它将被改变: ~~~ Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake { Return (GPRW (0x6D, 0)) } ~~~ 通常,有几个这样的调用站点需要更改`GPRW`(同时,请记住,并不是所有ACPI集都使用特定的名称`GPRW`)。相反,我们可以改为修补`GPRW`的方法定义,而不是像上面那样修补所有的调用站点: 原始代码: ``` Method (GPRW, 2, NotSerialized) { ... } ``` 如果我们改成: ``` Method (XPRW, 2, NotSerialized) { ... } ``` 由于您不希望更改任何调用站点,因此必须构造该补丁,以便它只影响方法本身,而不影响调用站点。根据ACPI规范,方法定义从字节码 14 开始,然后是方法大小、方法名称、参数计数/标志。您可以在`iasl`中使用“`- l`”选项来生成ACPI文件的混合列表。例如,联想u430 `GPRW`混合列表: ``` 4323: Method (GPRW, 2, NotSerialized) 00003F95: 14 45 08 47 50 52 57 02 ".E.GPRW." 4324: { 4325: Store (Arg0, Index (PRWP, Zero)) 00003F9D: 70 68 .................. "ph" 00003F9F: 88 50 52 57 50 00 00 ... ".PRWP.." ``` 我们可以使用方法**头字节**来代替查找: ``` Find: <14 45 08 47 50 52 57 02> Replace: <14 45 08 58 50 52 57 02> ``` 但是如果该方法在不同版本的BIOS或类似的模型之间稍有不同,但不是完全相同,会发生什么情况呢?在这种情况下,由于方法长度的改变,14的字节将会改变。 我的想法是,方法体的开头不太可能与方法的总长度不同,因此,它有助于从方法的主体中添加一些额外的字节到 找到/替换规范: ~~~ Find: <47 50 52 57 02 70 68> Replace: <58 50 52 57 02 70 68> ~~~ 您使用的后续字节数取决于您需要使查找/替换仅影响方法定义的数量。您可以通过十六进制编辑器(例如hex Fiend)(它是一个不错的十六进制编辑器,也是开源的)查看的本地AML二进制文件来验证。 注意:尽管您可以搜索方法名+ `arg count/ flags`,但同样的模式可能会找到一个您不想更改的方法的调用站点。在u430的情况下,不是这样的,所以我只能用`方法名+ flags`来查找/替换。 ``` Find: <47505257 02> Replace: <58505257 02> ``` 在ProBook UPRW的情况下,需要使用方法主体部分的后续字节: ``` Find: <55505257 0a7012> Replace: <58505257 0a7012> ``` 现在,任何调用`GPRW`(或ProBook示例中的UPRW)的代码都不会调用`XPRW`中的实现,因为它的名称不匹配。原始的XPRW现在是不可到达的代码。这意味着`GPRW`的实现可以根据我们的目的而改变: ``` Method(GPRW, 2) { If (0x6d == Arg0) { Return(Package() { 0x6d, 0, }) } External(\XPRW, MethodObj) Return(XPRW(Arg0, Arg1)) } ``` 解释该代码:对于任何调用`GPRW`,将第一个参数设置为`0x6d`(我们正在尝试禁用的`GPE`),而不是返回原来的`GPRW`,我们返回一个带有`0x6d`和`0`的包(禁用尾迹)。对于其他`GPE`值,代码简单地调用现在命名为`XPRW`的`GPRW`原始方法。 另一个简单的例子是 修补 EC查询方法来修复亮度键。对`XQxx`所涉及的`_Qxx`方法进行简单的重命名,并且使用原始名称对方法的新定义是必需的。 例如,在HP Envy Haswell 的repo中: ``` // _Q13 called on brightness/mirror display key Method (_Q13, 0, Serialized) // _Qxx: EC Query { External(\HKNO, FieldUnitObj) Store(HKNO, Local0) If (LEqual(Local0,7)) { // Brightness Down Notify(\_SB.PCI0.LPCB.PS2K, 0x0405) } If (LEqual(Local0,8)) { // Brightness Up Notify(\_SB.PCI0.LPCB.PS2K, 0x0406) } If (LEqual(Local0,4)) { // Mirror toggle Notify(\_SB.PCI0.LPCB.PS2K, 0x046e) } } ``` 和相关的补丁: ``` Comment: change Method(_Q13,0,S) to XQ13 Find: <5f513133 08> Replace: <58513133 08> ``` 同样的“重命名和替换”机制可以在比这更复杂的情况下使用。例如,它通常用于修补电池方法,这需要修补以避免访问多字节的EC字段。 # 对于复杂的重命名和替换的建议 您可能已经知道,修补电池状态(多字节的EC字段)可能非常复杂,并且可能涉及许多代码更改到许多方法。 本节将详细介绍一些用于电池修补的技术和程序,用于给电池打补丁。 最好先给电池打补丁,而不要先用hotpatch。工作完成后,尝试使用hotpatch。另外,未修补得电池代码和已修补电池代码之间的区别也很有帮助。您可以使用“diffmerge”这样的工具来比较它们。如果你的笔记本型号在我的笔记本电脑库里已经有了一个静态电池补丁,这一点尤其正确。 一般流程: ——从本地ACPI开始 ——使用静态修补电池状态(验证效果) ——使用diffmerge来比较未修补的代码与补丁代码 ——对于不同的方法,实现“重命名和替换”模式 ——对于EC字段,创建另一个EC OperationRegion(使用与原始的名称不同的名称)和字段定义作为一种“覆盖”,它只包含您需要修补的EC字段 ——要创建EC层,您可以在修补的DSDT中使用修补的`Field/OperationRegion`,然后删除未修补的字段 ——在SSDT中允许通过替换方法使用外部 访问ACPI集中其他地方定义的字段(通常是DSDT) ——让编译器指出需要使用外部的地方 ——注意不同范围内重复名称的符号 该贴中的2楼中提供了一个示例。 # 代码值修补(Code value patching) 考虑“Fix Mutex with non-zero SyncLevel”的这个补丁例子。这个补丁找到所有的互斥对象(Mutex objects)并替换同步级别(SyncLevel)为0。我们使用这个补丁,因为 OS X 不支持对互斥对象正确的调试,还会终止对任何非零同步级别的互斥对象的捕获。 举个例子,u430的互斥对象是这样的: ``` Mutex (MSMI, 0x07) ``` 要使它与OS X兼容,必须更改: ``` Mutex (MSMI, 0) ``` ACPI规范定义了一个互斥对象如何在AML中编码,但它可以帮助查看一个小ACPI文件的混合反编译: ``` DefinitionBlock ("", "DSDT", 2, "test", "test", 0) { Mutex(ABCD, 7) } ``` iasl编译器可以使用“`- l`”选项创建混合列表文件。 如果我们用`iasl - l`测试来编译上面的文件:`iasl -l test.dsl`,`test.lst` 包含如下: ``` 1: DefinitionBlock ("", "DSDT", 2, "test", "test", 0) 00000000: 44 53 44 54 2B 00 00 00 "DSDT+..." 00000008: 02 36 74 65 73 74 00 00 ".6test.." 00000010: 74 65 73 74 00 00 00 00 "test...." 00000018: 00 00 00 00 49 4E 54 4C "....INTL" 00000020: 10 04 16 20 ............ "... " 2: { 3: Mutex(ABCD, 7) 00000024: 5B 01 41 42 43 44 07 ... "[.ABCD." 4: } ``` 正如你所看到的;这个互斥对象`(ABCD, 7)`,被编码为 `<5B 01 41 42 43 44 07>`。 现在很容易为它构建一个补丁: ``` Comment: Change Mutex(ABCD,7) to Mutex(ABCD,0) Find: <5B 01 41 42 43 44 07> Replace: <5B 01 41 42 43 44 00> ``` # Clover的ACPI 配置(Clover ACPI configuration) 使用静态补丁,使用`DropOem = true`,并将DSDT和SSDTs添加到`ACPI / patched`中。使用hotpatch,使`DropOem = false`,并且只将附加SSDTs放在 `ACPI/patched`下。 需要注意`config.plist/ACPI/patches`只应用于原生的SSDTs,而不是`ACPI/patched`中的SSDTs。这意味着,如果您正在使用`config.plist`进行重命名对象,附加的SSDTs必须引用新的名称,而不是旧的名称。与`ACPI/patched`中的SSDTs不同,`ACPI/patched`中的二进制补丁对可能在`ACPI / patched`中的`DSDT.aml`有应用。如果您使用的是静态和热补丁的组合,你需要考虑到这一点。 另外,打静态补丁,可以使用`SortedOrder`来指定`ACPI/patched`中SSDTs的顺序。有了hotpatch,顺序就不是必要的,因为可以在每个SSDT中构造代码,这样代码就不依赖于顺序。特别是如果你将所有的附加代码放在一个SSDT中,比如关于我的笔记本电脑的git库中的许多例子。除非您的附加SSDTs是顺序相关的,否则您不必按`SortedOrder`方式命名每一个。 对于每个SSDT,也没有必要选择“数字编号的名称”。相反,你可以使用有意义的名字,比如"SSDT-USB.aml", SSDT-XOSI.aml"。使用数字名称会让你迷惑,请不要这样做。 # 解决问题 你可以使用补丁来查看你的完整的ACPI设置,如在修补后的Clover注射。通过运行 '`patchmatic -extract`',patchmatic将写入所有注入的`DSDT.aml`和`SSDT*.aml`按照他们被Clover注射的顺序。你可以用`iasl -da -dl *. aml`把它们拆开。如果`iasl`显示了反编译的错误(例如,重复符号),这就像OS X也在拒绝冲突的SSDTs。 如果您是一个新手,使用这种技术,一次实现一个补丁是一个好主意,并且慢慢地将它构建到一组完整的working patches + SSDTs中。试图一次做所有的事情会使你很难找到你的错误。 # 问题报告 下载 patchmatic: https://bitbucket.org/RehabMan/os-x-maciasl-patchmatic/downloads/RehabMan-patchmatic-2015-0107.zip 解压下载的patchmatic.zip 文件,把它复制到`/usr/bin`,这样二进制文件就是`/usr/bin/patchmatic`这样了。 在终端: ``` if [ -d ~/Downloads/RehabMan ]; then rm -R ~/Downloads/RehabMan; fi mkdir ~/Downloads/RehabMan cd ~/Downloads/RehabMan patchmatic -extract ``` 注意:为了简单,你可以直接复制/粘贴而不是手动输入上面的命令。 附上`Downloads/RehabMan`目录的内容(如ZIP)。 同时,附上`ioreg`:http://www.tonymacx86.com/audio/58368-guide-how-make-copy-ioreg.html 。请使用附件中的IORegistryExplorer v2.1!不要使用`ioregistryexplorer.app`的其他版本然后回复我~。 ``` kextstat|grep -y acpiplat kextstat|grep -y appleintelcpu kextstat|grep -y applelpc ``` 同时,在收集之前,附加上你的`EFI/Clover`文件夹(你可以在主Clover屏幕上按下`F4`提取)。请删除“themes”目录,特别是如果你安装了过多的主题。只提供`EFI/Clover`,而不是整个EFI文件夹。 也可以附上重建缓存日志: ``` sudo touch /System/Library/Extensions && sudo kextcache -u / ``` 翻译到此结束。但是后面是一些示例。 附上RehabMan大神的github: 1.OSX clover laptop config:https://github.com/RehabMan/OS-X-Clover-Laptop-Config 这里面提供了一些常见的补丁和说明,还有笔记本的通用config.plist。 2.elitebook/probook/zbook系列机型:https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch 3.Inter NUC 5/6/7系列:https://github.com/RehabMan/Intel-NUC-DSDT-Patch 4.Lenovo U330/U430/U530系列:https://github.com/RehabMan/Lenovo-U430-Touch-DSDT-Patch 5.HP envy J/K/Q/RHaswell系列:https://github.com/RehabMan/HP-Envy-DSDT-Patch 6.Lenovo Z50-70/Z40-70系列:https://github.com/RehabMan/Lenovo-Z50 7.Lenovo Y50/Y40-70系列:[url]https://github.com/RehabMan/Lenovo-Y50-DSDT-Patch # 参考 [祝贺远景开放,开启完美黑苹果新天地!(抛弃传统DSDT方法,完美黑苹果)](https://weibo.com/p/23041874f0e4330102x1sy) https://blog.daliansky.net/hotpatch-detailed-solution.html # [小小总结](http://bbs.pcbeta.com/viewthread-1766329-1-1.html) 传统 DSDT 方式,是提取机器的 DSDT,反编译后进行改错、编辑、打补丁,然后再次编译,最后把编译好的 DSDT 拿来用。 原理上来说没啥毛病,但是这个反编译和编译却是问题所在,否则为什么要排错啊。 然后,大神就提出这种方法,可以不提取 DSDT,免去了反编译带来的问题。 这种方法是其实可以理解为外挂。基于 Clover的 DSDT 二进制 patch 也就是二进制字符替换,再配合ssdt来实现的。 我们知道,对 DSDT 修改,总结来说就是改名、删除、修改代码,有些 DSDT 简单修改,在 Clover 里可以直接通过勾选相应 Fix 功能实现。 另外对于其他的改名和删除,还可以利用 clover 的 patch 功能,实现一些字符替换,直接实现对dsdt重命名和删除的修改。 但是还有一些是要修改对象和方法里的代码。这个怎么办。没关系,在上面的基础上,然后把要需改的代码放到单独的 SSDT 里,二进制字符替换和 SSDT 配合使用即可实现修改代码的操作。 更改调用时的方法名或者对象名,指向新 SSDT 里用新名字定义的对象或者方法,这叫重定向和替换。 直接把 DSDT 里的对象或方法的名字改掉,然后在SSDT 里重写该对象或方法的定义,这就是重命名和替换。 上面几点对应到Rehabman的教程里,就是hotpatch的四种修改类型: 1. 重命名ACPI对象(Renaming ACPI objects) 2. 删除方法(Removingmethods) 3. 重定向和替换(Redirectand Replace) 4. 重命名和替换Rename andReplace) (具体细节的在上面👆的教程里说的很清楚,我就不展开赘述了。) 这种方式免去了 DSDT 提取、反编译和编译的过程,从而减少了这几个过程出现的错误。 而且从方式上来说,hotpatch这种方式也比较“科学”。 # ======================= # 电池状态的Hotpatch 这第二篇文章致力于用Clover补丁修补电池状态。为了演示这个过程,我们将通过一个示例DSDT来工作。使用的示例文件来自于禁用独立显卡的指南,即“Asus UX303LN”:https://www.tonymacx86.com/threads/guide-disabling-discrete-graphics-in-dual-gpu-laptops.163772/ (我打算翻译) 您应该下载附加到该指南的 `ACPI/origin`文件, 以便您跟着我一起做。 如上面1楼的文章所发布的,一般操作流程如下: ——从原生的ACPI补丁开始。 ——使用静态打补丁方式修补电池状态(验证其效果) ——使用`diffmerge`比较修改代码与修补代码 ——为每个方法都是不同的,实现“Rename and Replace”模式 ——对于EC字段,创建另一个EC OperationRegion(操作区域)(使用与原来不同的名称)和字段定义作为一种“覆盖层”,它只包含您需要修补的EC字段 ——创建EC覆盖层,您可以在修补的DSDT中使用修补的Field/OperationRegion(字段/操作区域),然后删除未修补的字段。 ——使用外部(External)来允许SSDT中的替换方法访问ACPI集合中定义的字段(通常是DSDT)。 ——让编译器指出需要使用外部(External)的地方 ——注意不同范围(scopes)内重复名称的符号 ## 使用diffmerge来发现 打补丁的(patched)和原生的(native) 之间的差异 首先分解源文件:`iasl -da -dl *.aml`(你应该熟悉这个部分,因为它是正常ACPI打补丁的一部分) 接下来,只需要使用`MaciASL`和`dsdt.dsl`就可以应用电池补丁。在这种情况下,我们应用“ASUS N55SL/VivoBook”。没有必要修改任何错误,因为我们只关心应用电池补丁所产生的差异。将补丁文件保存为`dsdt_patch.dsl`。 现在您可以运行`diffmerge`以查看`DSDT.dsl` 和 `DSDT_patched.dsl`之间的区别。我通常是从终端来做这个的: ``` diffmerge DSDT.dsl DSDT_patched.dsl ``` 初始的diffmerge窗口将会是这样的: ![batthot_diffmerge_initial-png](https://box.kancloud.cn/bf4b11a92c8cd288160c1fdbbf77e0e8_1084x849.png) 从这里里,我们可以通过点击左边栏中的标记来检查那些发生变化的部分。 在这些例子中,你会发现: - 第1组: 是否对`EC`字段进行了更改 (多字节 VS 单一字节) - 第2组: 加入`RDBA`,`WRBA`,`RDBB`,`WRBB`方法 - 第3组: 打补丁的 `FBST`, `_BIX`, `B1FA `方法 - 第4组: 打补丁的 `SMBR`, `SMBW`, `ECSB` 方法 - 第5组: 打补丁的 `TACH` 方法 - 最后一组: 额外添加的 `B1B2` 方法 ## 构建初始SSDT 用 MaciASL开始一个空的SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { } ``` 接下来,添加补丁中添加的所有方法。在这个示例中,这包括`RDBA、WRBA、RDBB、WRBB`和`B1B2`方法。您可以直接从`dsdt_patch.dsl`中复制它们。 你要确定每个方法都放在同一个作用域(scope)内。例如,这里是“第2组”的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { Scope (_SB.PCI0.LPCB.EC0) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 并且 `B1B2`被添加: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } // added methods (group 2) Scope (_SB.PCI0.LPCB.EC0) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 不要担心,代码现在没有编译。由于在这个文件中没有定义的`EC`字段(和其他标识符),在这一点上它是不被期望的。它们需要通过外部(最终)被定义或引用。 现在让我们添加补丁方法。就像那些添加了方法的方法一样,补丁方法也只是从`DSDT_patched.dsl`中复制的: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { // patched methods Scope (_SB.PCI0) { Scope (BAT0) { Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) If (^^LPCB.EC0.ACAP ()) { Store (One, Local0) } If (Local0) { If (CHGS (Zero)) { Store (0x02, Local0) } Else { Store (Zero, Local0) } } Else { Store (One, Local0) } If (BLLO) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (And (^^LPCB.EC0.EB0S, 0x08)) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (LGreaterEqual (Local1, 0x8000)) { Subtract (0xFFFF, Local1, Local1) } Store (Arg2, Local2) If (LEqual (PUNT, Zero)) { Multiply (Local1, ^^LPCB.EC0.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 (^^LPCB.EC0.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 (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended { If (LNot (^^LPCB.EC0.BATP (Zero))) { Return (NBIX) } If (LEqual (^^LPCB.EC0.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(^^LPCB.EC0.XC30,^^LPCB.EC0.XC31), Index (BIXT, 0x08)) Store (0x0001869F, Index (BIXT, 0x09)) Return (BIXT) } } } Scope (_SB.PCI0.LPCB.EC0) { Method (BIFA, 0, NotSerialized) { If (ECAV ()) { If (BSLF) { Store (B1B2(B1S0,B1S1), Local0) } Else { Store (B1B2(B0S0,B0S1), Local0) } } Else { Store (Ones, Local0) } Return (Local0) } } Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } // added methods (group 2) Scope (_SB.PCI0.LPCB.EC0) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 注意,如何将`FBST`和`_BIX`添加到 `_SB.PCI0.BAT0`作用范围(scope)中。而`BIFA`被添加到`_SB.PCI0.LPCB.EC0`。把所有的方法都注入到原来的作用范围(scope)是很重要的。 现在,我们添加`SMBR`、`SMBW`、`ECSB`和`TACH`: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { // patched methods Scope (_SB.PCI0) { Scope (BAT0) { Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) If (^^LPCB.EC0.ACAP ()) { Store (One, Local0) } If (Local0) { If (CHGS (Zero)) { Store (0x02, Local0) } Else { Store (Zero, Local0) } } Else { Store (One, Local0) } If (BLLO) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (And (^^LPCB.EC0.EB0S, 0x08)) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (LGreaterEqual (Local1, 0x8000)) { Subtract (0xFFFF, Local1, Local1) } Store (Arg2, Local2) If (LEqual (PUNT, Zero)) { Multiply (Local1, ^^LPCB.EC0.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 (^^LPCB.EC0.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 (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended { If (LNot (^^LPCB.EC0.BATP (Zero))) { Return (NBIX) } If (LEqual (^^LPCB.EC0.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(^^LPCB.EC0.XC30,^^LPCB.EC0.XC31), Index (BIXT, 0x08)) Store (0x0001869F, Index (BIXT, 0x09)) Return (BIXT) } } } Scope (_SB.PCI0.LPCB.EC0) { Method (BIFA, 0, NotSerialized) { If (ECAV ()) { If (BSLF) { Store (B1B2(B1S0,B1S1), Local0) } Else { Store (B1B2(B0S0,B0S1), Local0) } } Else { Store (Ones, Local0) } Return (Local0) } Method (SMBR, 3, Serialized) { Store (Package (0x03) { 0x07, Zero, Zero }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, RDBL)) { If (LNotEqual (Arg0, RDWD)) { If (LNotEqual (Arg0, RDBT)) { If (LNotEqual (Arg0, RCBT)) { If (LNotEqual (Arg0, RDQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { ShiftLeft (Arg1, One, Local3) Or (Local3, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, RDQK)) { If (LNotEqual (Arg0, RCBT)) { Store (Arg2, CMDB) } } WRBA(Zero) Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) If (LEqual (DerefOf (Index (Local0, Zero)), Zero)) { If (LEqual (Arg0, RDBL)) { Store (BCNT, Index (Local0, One)) Store (RDBA(), Index (Local0, 0x02)) } If (LEqual (Arg0, RDWD)) { Store (0x02, Index (Local0, One)) Store (B1B2(T2B0,T2B1), Index (Local0, 0x02)) } If (LEqual (Arg0, RDBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } If (LEqual (Arg0, RCBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } } } Release (MUEC) Return (Local0) } Method (SMBW, 5, Serialized) { Store (Package (0x01) { 0x07 }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, WRBL)) { If (LNotEqual (Arg0, WRWD)) { If (LNotEqual (Arg0, WRBT)) { If (LNotEqual (Arg0, SDBT)) { If (LNotEqual (Arg0, WRQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { WRBA(Zero) ShiftLeft (Arg1, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, WRQK)) { If (LNotEqual (Arg0, SDBT)) { Store (Arg2, CMDB) } } If (LEqual (Arg0, WRBL)) { Store (Arg3, BCNT) WRBA(Arg4) } If (LEqual (Arg0, WRWD)) { Store(Arg4,T2B0) Store(ShiftRight(Arg4,8),T2B1) } If (LEqual (Arg0, WRBT)) { Store (Arg4, DAT0) } If (LEqual (Arg0, SDBT)) { Store (Arg4, DAT0) } Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) } Release (MUEC) Return (Local0) } Method (ECSB, 7, NotSerialized) { Store (Package (0x05) { 0x11, Zero, Zero, Zero, Buffer (0x20){} }, Local1) If (LGreater (Arg0, One)) { Return (Local1) } If (ECAV ()) { Acquire (MUEC, 0xFFFF) If (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } Store (Zero, Local2) While (LNotEqual (Local0, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local1, Zero)) Store (Zero, Local0) } ElseIf (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } } If (LLessEqual (Local2, 0x03E8)) { If (LEqual (Arg0, Zero)) { Store (Arg2, ADDR) Store (Arg3, CMDB) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCNT) WRBA(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DAT0) Store (Arg5, DAT1) } Store (Arg1, PRTC) } Else { Store (Arg2, ADD2) Store (Arg3, CMD2) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCN2) WRBB(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DA20) Store (Arg5, DA21) } Store (Arg1, PRT2) } Store (0x7F, Local0) If (LEqual (Arg0, Zero)) { While (PRTC) { Sleep (One) Decrement (Local0) } } Else { While (PRT2) { Sleep (One) Decrement (Local0) } } If (Local0) { If (LEqual (Arg0, Zero)) { Store (SSTS, Local0) Store (DAT0, Index (Local1, One)) Store (DAT1, Index (Local1, 0x02)) Store (BCNT, Index (Local1, 0x03)) Store (RDBA(), Index (Local1, 0x04)) } Else { Store (SST2, Local0) Store (DA20, Index (Local1, One)) Store (DA21, Index (Local1, 0x02)) Store (BCN2, Index (Local1, 0x03)) Store (RDBB(), Index (Local1, 0x04)) } And (Local0, 0x1F, Local0) If (Local0) { Add (Local0, 0x10, Local0) } Store (Local0, Index (Local1, Zero)) } Else { Store (0x10, Index (Local1, Zero)) } } Release (MUEC) } Return (Local1) } Method (TACH, 1, Serialized) { If (ECAV ()) { Switch (Arg0) { Case (Zero) { Store (B1B2(TH00,TH01), Local0) Break } Case (One) { Store (B1B2(TH10,TH11), Local0) Break } Default { Return (Ones) } } Multiply (Local0, 0x02, Local0) If (LNotEqual (Local0, Zero)) { Divide (0x0041CDB4, Local0, Local1, Local0) Return (Local0) } Else { Return (Ones) } } Else { Return (Ones) } } } Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } // added methods (group 2) Scope (_SB.PCI0.LPCB) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 在MaciASL中扩展了所有的节点,我们的工作如下: ![ssd_with_nodes_expanded-png](https://box.kancloud.cn/3868c8f8fe35292367119dafbdf2eb6e_973x639.png) ## 解决错误(Resolving errors) 现在,我们需要开始使用外部的方法来解决错误,或者根据需要定义修补的EC字段。我们可以使用编译器来提供帮助。单击Compile将显示第一个错误:“`3, 6085, Object not found or not accessible from scope (_SB.PCI0)`“,在这一行: ``` Scope (_SB.PCI0) ``` 编译器表明`_SB.PCI0`没有被声明,所以您不能在作用域操作符(Scope operator)中使用它。 我们需要向外部声明它,因为作用域实际上是在另一个文件(`dsdt.aml`)中定义的:将它添加到文件的顶部 ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) Scope (_SB.PCI0) { ... ``` 现在,下一个错误是“`Scope(BAT0)`”,因此,再一次: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) Scope (_SB.PCI0) { Scope (BAT0) { ... ``` 下一个错误是“`13, 6085, Object not found or not accessible from scope (^^LPCB.EC0.ACAP)`",我们可以从引用ACAP的代码中看出它是一个方法: ``` If (^^LPCB.EC0.ACAP ()) ``` 注意:方法调用由`()`表示(本例中为空参数列表)。因此,我们知道我们可以添加一个外部的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) ... } ``` 注意:路径`^^LPCB.EC0.ACAP`等于`_SB.PCI0.LPCB.EC0.ACAP`,因为引用在`_SB.PCI0.BAT0.FBST`(`FBST`方法的路径)的范围。每个`^`(父)操作符将当前的范围由一个项向上移动,所以`^`表示了`_SB.PCI0.BAT0`。 `^^`表示了`_SB.PCI0`。 在某些情况下,您需要查看DSDT来查找给定标识符的路径和/或类型。例如,下一个错误与`CHGS`有关。同样,我们知道它是一个方法,因为它是方法调用的目标,但是对于路径,我们必须参考`DSDT`: ``` Scope (\) { Method (CHGS, 1, Serialized) { Store (\_SB.PCI0.LPCB.EC0.BCHG (Arg0), Local0) Return (Local0) } ``` 所以,它在根(root)中: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) ... ``` 下一个未定义的符号`BLLO`,是一种方法以外的东西: ``` If (BLLO) { ``` 在DSDT中,我们发现它是用名称定义的(它恰好在根范围(root scope)内): ``` Name (BLLO, Zero) ``` 这使得它成为了一种IntObj: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) ... ``` 修正`FBST`方法中的所有错误: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) ... ``` 现在继续这个过程。 最终,得到: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) ... ``` 将会出现`XC30/XC31`的错误:“153, 6085, Object not found or not accessible from scope (^^LPCB.EC0.XC30)” 这是一个被一分为二的16位字段之一。 这就是创建EC覆盖层(the EC overlay)的必要地方。 为此,我们在EC范围内使用另一个OperationRegion,它的名称与我们在DSDT中发现的名称不同: ``` External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { } } ``` 从`DSDT_patched.dsl`,我们可以得到各种补丁的字段(再次提到`diffmerge`)。这是`DSDT_patched.dsl`中来自`EC`的整个集合: ``` Offset (0x04), CMD1, 8, CDT1, 8, CDT2, 8, CDT3, 8, Offset (0x80), Offset (0x81), Offset (0x82), Offset (0x83), EB0R, 8, EB1R, 8, EPWF, 8, Offset (0x87), Offset (0x88), Offset (0x89), Offset (0x8A), HKEN, 1, Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, TSTP, 8, Offset (0x9C), CDT4, 8, CDT5, 8, Offset (0xA0), Offset (0xA1), Offset (0xA2), Offset (0xA3), EACT, 8, TH1R, 8, TH1L, 8, TH0R, 8, TH0L, 8, Offset (0xB0), B0PN, 16, Offset (0xB4), Offset (0xB6), Offset (0xB8), Offset (0xBA), Offset (0xBC), Offset (0xBE), B0TM, 16, B0C1, 16, B0C2, 16, XC30,8,XC31,8, B0C4, 16, Offset (0xD0), B1PN, 16, Offset (0xD4), Offset (0xD6), Offset (0xD8), Offset (0xDA), Offset (0xDC), Offset (0xDE), B1TM, 16, B1C1, 16, B1C2, 16, YC30,8,YC31,8, B1C4, 16, Offset (0xF0), Offset (0xF2), Offset (0xF4), B0S0,8,B0S1,8, Offset (0xF8), Offset (0xFA), Offset (0xFC), B1S0,8,B1S1,8 ``` 如果我们去掉未修补的标识符,但是保持偏移量(offsets)正确(非常重要!): ``` Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xBE), /*B0TM*/, 16, /*B0C1*/, 16, /*B0C2*/, 16, XC30,8,XC31,8, Offset (0xDE), /*B1TM*/, 16, /*B1C1*/, 16, /*B1C2*/, 16, YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 ``` 同样的事情可以写成如下: ``` Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 ``` 所以,加入到SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 } } ``` 然后在修正更多错误的时候,我们增加了一些外部(External)的: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB.EC0.ECAV, MethodObj) External(BSLF, IntObj) External(_SB.PCI0.LPCB.EC0.RDBL, IntObj) External(_SB.PCI0.LPCB.EC0.RDWD, IntObj) External(_SB.PCI0.LPCB.EC0.RDBT, IntObj) External(_SB.PCI0.LPCB.EC0.RCBT, IntObj) External(_SB.PCI0.LPCB.EC0.RDQK, IntObj) External(_SB.PCI0.LPCB.EC0.MUEC, MutexObj) External(_SB.PCI0.LPCB.EC0.PRTC, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SBBY, IntObj) External(_SB.PCI0.LPCB.EC0.ADDR, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMDB, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SWTC, MethodObj) External(_SB.PCI0.LPCB.EC0.BCNT, FieldUnitObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { ... ``` 然后我们有T2B0和T2B1的错误。这些又被分解为16位的`EC`字段,需要在我们的`EC`覆盖层中定义。事实上,不妨定义我们所需要的剩余部分(来自diffmerge的数据)。 在SMBX中的补丁数据: ``` OperationRegion (SMBX, EmbeddedControl, 0x18, 0x28) ``` 因此,我们创建了一个类似的覆盖层,并有一个唯一的名称: ``` OperationRegion (RMB1, EmbeddedControl, 0x18, 0x28) Field (RMB1, ByteAcc, NoLock, Preserve) { /* Note: disabling these fields (already defined in DSDT, referenced with External if needed, but keeping the correct offset! (very important!) */ /* PRTC, 8, SSTS, 5, , 1, ALFG, 1, CDFG, 1, ADDR, 8, CMDB, 8, */ Offset(4), // the data above is 4 bytes offset from the start of this region! //BDAT, 256, BA00,8,BA01,8,BA02,8,BA03,8, BA04,8,BA05,8,BA06,8,BA07,8, BA08,8,BA09,8,BA0A,8,BA0B,8, BA0C,8,BA0D,8,BA0E,8,BA0F,8, BA10,8,BA11,8,BA12,8,BA13,8, BA14,8,BA15,8,BA16,8,BA17,8, BA18,8,BA19,8,BA1A,8,BA1B,8, BA1C,8,BA1D,8,BA1E,8,BA1F,8 } ``` 与 SMB2有类似的作用域: ``` OperationRegion(RMB2, EmbeddedControl, 0x40, 0x28) Field (RMB2, ByteAcc, NoLock, Preserve) { /* PRT2, 8, SST2, 5, , 1, ALF2, 1, CDF2, 1, ADD2, 8, CMD2, 8, */ Offset(4), //BDA2, 256, BB00,8,BB01,8,BB02,8,BB03,8, BB04,8,BB05,8,BB06,8,BB07,8, BB08,8,BB09,8,BB0A,8,BB0B,8, BB0C,8,BB0D,8,BB0E,8,BB0F,8, BB10,8,BB11,8,BB12,8,BB13,8, BB14,8,BB15,8,BB16,8,BB17,8, BB18,8,BB19,8,BB1A,8,BB1B,8, BB1C,8,BB1D,8,BB1E,8,BB1F,8 } ``` `T2B0`和`T2B1` 存在于 原生的`SMBX`中,但现在`RMB1`是: ``` Field (RMB1, ByteAcc, NoLock, Preserve) { Offset (0x04), T2B0,8,T2B1,8 } ``` 就得到: ``` External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB.EC0.ECAV, MethodObj) External(BSLF, IntObj) External(_SB.PCI0.LPCB.EC0.RDBL, IntObj) External(_SB.PCI0.LPCB.EC0.RDWD, IntObj) External(_SB.PCI0.LPCB.EC0.RDBT, IntObj) External(_SB.PCI0.LPCB.EC0.RCBT, IntObj) External(_SB.PCI0.LPCB.EC0.RDQK, IntObj) External(_SB.PCI0.LPCB.EC0.MUEC, MutexObj) External(_SB.PCI0.LPCB.EC0.PRTC, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SBBY, IntObj) External(_SB.PCI0.LPCB.EC0.ADDR, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMDB, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SWTC, MethodObj) External(_SB.PCI0.LPCB.EC0.BCNT, FieldUnitObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 } OperationRegion (RMB1, EmbeddedControl, 0x18, 0x28) Field (RMB1, ByteAcc, NoLock, Preserve) { /* Note: disabling these fields (already defined in DSDT, referenced with External if needed, but keeping the correct offset! (very important!) */ /* PRTC, 8, SSTS, 5, , 1, ALFG, 1, CDFG, 1, ADDR, 8, CMDB, 8, */ Offset(4), // the data above is 4 bytes offset from the start of this region! //BDAT, 256, BA00,8,BA01,8,BA02,8,BA03,8, BA04,8,BA05,8,BA06,8,BA07,8, BA08,8,BA09,8,BA0A,8,BA0B,8, BA0C,8,BA0D,8,BA0E,8,BA0F,8, BA10,8,BA11,8,BA12,8,BA13,8, BA14,8,BA15,8,BA16,8,BA17,8, BA18,8,BA19,8,BA1A,8,BA1B,8, BA1C,8,BA1D,8,BA1E,8,BA1F,8 } OperationRegion(RMB2, EmbeddedControl, 0x40, 0x28) Field (RMB2, ByteAcc, NoLock, Preserve) { /* PRT2, 8, SST2, 5, , 1, ALF2, 1, CDF2, 1, ADD2, 8, CMD2, 8, */ Offset(4), //BDA2, 256, BB00,8,BB01,8,BB02,8,BB03,8, BB04,8,BB05,8,BB06,8,BB07,8, BB08,8,BB09,8,BB0A,8,BB0B,8, BB0C,8,BB0D,8,BB0E,8,BB0F,8, BB10,8,BB11,8,BB12,8,BB13,8, BB14,8,BB15,8,BB16,8,BB17,8, BB18,8,BB19,8,BB1A,8,BB1B,8, BB1C,8,BB1D,8,BB1E,8,BB1F,8 } Field (RMB1, ByteAcc, NoLock, Preserve) { Offset (0x04), T2B0,8,T2B1,8 } } ``` 然后,通过添加这些外部声明,继续处理更多的外部错误(它最终会结束!): ``` External(_SB.PCI0.LPCB.EC0.DAT0, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.WRBL, IntObj) External(_SB.PCI0.LPCB.EC0.WRWD, IntObj) External(_SB.PCI0.LPCB.EC0.WRBT, IntObj) External(_SB.PCI0.LPCB.EC0.SDBT, IntObj) External(_SB.PCI0.LPCB.EC0.WRQK, IntObj) External(_SB.PCI0.LPCB.EC0.PRT2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DAT1, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.ADD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.BCN2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA20, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA21, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SSTS, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SST2, FieldUnitObj) ``` 注意:使用`DAT0`时,不要在不同的作用域内对“其他”的`DAT0`感到迷惑! 此时,SSDT编译没有任何错误: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB.EC0.ECAV, MethodObj) External(BSLF, IntObj) External(_SB.PCI0.LPCB.EC0.RDBL, IntObj) External(_SB.PCI0.LPCB.EC0.RDWD, IntObj) External(_SB.PCI0.LPCB.EC0.RDBT, IntObj) External(_SB.PCI0.LPCB.EC0.RCBT, IntObj) External(_SB.PCI0.LPCB.EC0.RDQK, IntObj) External(_SB.PCI0.LPCB.EC0.MUEC, MutexObj) External(_SB.PCI0.LPCB.EC0.PRTC, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SBBY, IntObj) External(_SB.PCI0.LPCB.EC0.ADDR, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMDB, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SWTC, MethodObj) External(_SB.PCI0.LPCB.EC0.BCNT, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DAT0, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.WRBL, IntObj) External(_SB.PCI0.LPCB.EC0.WRWD, IntObj) External(_SB.PCI0.LPCB.EC0.WRBT, IntObj) External(_SB.PCI0.LPCB.EC0.SDBT, IntObj) External(_SB.PCI0.LPCB.EC0.WRQK, IntObj) External(_SB.PCI0.LPCB.EC0.PRT2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DAT1, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.ADD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.BCN2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA20, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA21, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SSTS, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SST2, FieldUnitObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 } OperationRegion (RMB1, EmbeddedControl, 0x18, 0x28) Field (RMB1, ByteAcc, NoLock, Preserve) { /* Note: disabling these fields (already defined in DSDT, referenced with External if needed, but keeping the correct offset! (very important!) */ /* PRTC, 8, SSTS, 5, , 1, ALFG, 1, CDFG, 1, ADDR, 8, CMDB, 8, */ Offset(4), // the data above is 4 bytes offset from the start of this region! //BDAT, 256, BA00,8,BA01,8,BA02,8,BA03,8, BA04,8,BA05,8,BA06,8,BA07,8, BA08,8,BA09,8,BA0A,8,BA0B,8, BA0C,8,BA0D,8,BA0E,8,BA0F,8, BA10,8,BA11,8,BA12,8,BA13,8, BA14,8,BA15,8,BA16,8,BA17,8, BA18,8,BA19,8,BA1A,8,BA1B,8, BA1C,8,BA1D,8,BA1E,8,BA1F,8 } OperationRegion(RMB2, EmbeddedControl, 0x40, 0x28) Field (RMB2, ByteAcc, NoLock, Preserve) { /* PRT2, 8, SST2, 5, , 1, ALF2, 1, CDF2, 1, ADD2, 8, CMD2, 8, */ Offset(4), //BDA2, 256, BB00,8,BB01,8,BB02,8,BB03,8, BB04,8,BB05,8,BB06,8,BB07,8, BB08,8,BB09,8,BB0A,8,BB0B,8, BB0C,8,BB0D,8,BB0E,8,BB0F,8, BB10,8,BB11,8,BB12,8,BB13,8, BB14,8,BB15,8,BB16,8,BB17,8, BB18,8,BB19,8,BB1A,8,BB1B,8, BB1C,8,BB1D,8,BB1E,8,BB1F,8 } Field (RMB1, ByteAcc, NoLock, Preserve) { Offset (0x04), T2B0,8,T2B1,8 } } Scope (_SB.PCI0) { Scope (BAT0) { Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) If (^^LPCB.EC0.ACAP ()) { Store (One, Local0) } If (Local0) { If (CHGS (Zero)) { Store (0x02, Local0) } Else { Store (Zero, Local0) } } Else { Store (One, Local0) } If (BLLO) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (And (^^LPCB.EC0.EB0S, 0x08)) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (LGreaterEqual (Local1, 0x8000)) { Subtract (0xFFFF, Local1, Local1) } Store (Arg2, Local2) If (LEqual (PUNT, Zero)) { Multiply (Local1, ^^LPCB.EC0.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 (^^LPCB.EC0.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 (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended { If (LNot (^^LPCB.EC0.BATP (Zero))) { Return (NBIX) } If (LEqual (^^LPCB.EC0.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(^^LPCB.EC0.XC30,^^LPCB.EC0.XC31), Index (BIXT, 0x08)) Store (0x0001869F, Index (BIXT, 0x09)) Return (BIXT) } } } Scope (_SB.PCI0.LPCB.EC0) { Method (BIFA, 0, NotSerialized) { If (ECAV ()) { If (BSLF) { Store (B1B2(B1S0,B1S1), Local0) } Else { Store (B1B2(B0S0,B0S1), Local0) } } Else { Store (Ones, Local0) } Return (Local0) } Method (SMBR, 3, Serialized) { Store (Package (0x03) { 0x07, Zero, Zero }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, RDBL)) { If (LNotEqual (Arg0, RDWD)) { If (LNotEqual (Arg0, RDBT)) { If (LNotEqual (Arg0, RCBT)) { If (LNotEqual (Arg0, RDQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { ShiftLeft (Arg1, One, Local3) Or (Local3, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, RDQK)) { If (LNotEqual (Arg0, RCBT)) { Store (Arg2, CMDB) } } WRBA(Zero) Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) If (LEqual (DerefOf (Index (Local0, Zero)), Zero)) { If (LEqual (Arg0, RDBL)) { Store (BCNT, Index (Local0, One)) Store (RDBA(), Index (Local0, 0x02)) } If (LEqual (Arg0, RDWD)) { Store (0x02, Index (Local0, One)) Store (B1B2(T2B0,T2B1), Index (Local0, 0x02)) } If (LEqual (Arg0, RDBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } If (LEqual (Arg0, RCBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } } } Release (MUEC) Return (Local0) } Method (SMBW, 5, Serialized) { Store (Package (0x01) { 0x07 }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, WRBL)) { If (LNotEqual (Arg0, WRWD)) { If (LNotEqual (Arg0, WRBT)) { If (LNotEqual (Arg0, SDBT)) { If (LNotEqual (Arg0, WRQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { WRBA(Zero) ShiftLeft (Arg1, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, WRQK)) { If (LNotEqual (Arg0, SDBT)) { Store (Arg2, CMDB) } } If (LEqual (Arg0, WRBL)) { Store (Arg3, BCNT) WRBA(Arg4) } If (LEqual (Arg0, WRWD)) { Store(Arg4,T2B0) Store(ShiftRight(Arg4,8),T2B1) } If (LEqual (Arg0, WRBT)) { Store (Arg4, DAT0) } If (LEqual (Arg0, SDBT)) { Store (Arg4, DAT0) } Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) } Release (MUEC) Return (Local0) } Method (ECSB, 7, NotSerialized) { Store (Package (0x05) { 0x11, Zero, Zero, Zero, Buffer (0x20){} }, Local1) If (LGreater (Arg0, One)) { Return (Local1) } If (ECAV ()) { Acquire (MUEC, 0xFFFF) If (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } Store (Zero, Local2) While (LNotEqual (Local0, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local1, Zero)) Store (Zero, Local0) } ElseIf (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } } If (LLessEqual (Local2, 0x03E8)) { If (LEqual (Arg0, Zero)) { Store (Arg2, ADDR) Store (Arg3, CMDB) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCNT) WRBA(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DAT0) Store (Arg5, DAT1) } Store (Arg1, PRTC) } Else { Store (Arg2, ADD2) Store (Arg3, CMD2) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCN2) WRBB(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DA20) Store (Arg5, DA21) } Store (Arg1, PRT2) } Store (0x7F, Local0) If (LEqual (Arg0, Zero)) { While (PRTC) { Sleep (One) Decrement (Local0) } } Else { While (PRT2) { Sleep (One) Decrement (Local0) } } If (Local0) { If (LEqual (Arg0, Zero)) { Store (SSTS, Local0) Store (DAT0, Index (Local1, One)) Store (DAT1, Index (Local1, 0x02)) Store (BCNT, Index (Local1, 0x03)) Store (RDBA(), Index (Local1, 0x04)) } Else { Store (SST2, Local0) Store (DA20, Index (Local1, One)) Store (DA21, Index (Local1, 0x02)) Store (BCN2, Index (Local1, 0x03)) Store (RDBB(), Index (Local1, 0x04)) } And (Local0, 0x1F, Local0) If (Local0) { Add (Local0, 0x10, Local0) } Store (Local0, Index (Local1, Zero)) } Else { Store (0x10, Index (Local1, Zero)) } } Release (MUEC) } Return (Local1) } Method (TACH, 1, Serialized) { If (ECAV ()) { Switch (Arg0) { Case (Zero) { Store (B1B2(TH00,TH01), Local0) Break } Case (One) { Store (B1B2(TH10,TH11), Local0) Break } Default { Return (Ones) } } Multiply (Local0, 0x02, Local0) If (LNotEqual (Local0, Zero)) { Divide (0x0041CDB4, Local0, Local1, Local0) Return (Local0) } Else { Return (Ones) } } Else { Return (Ones) } } } Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } Scope (_SB.PCI0.LPCB) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } //EOF ``` 最后文件可以保存为AML(建议名称:`SSDT-BATT.aml`),并放置在`ACPI/patched`中。 但是你不能期望电池状态与原生的DSDT一起工作。 ## 重新命名现有的方法(Renaming existing methods) 在DSDT和这个`SSDT-BATT.aml`中有重复的方法。对于DSDT中的每个方法,`SSDT-BATT.aml`版本将替换,我们必须将DSDT中的方法重命名为其他的,来允许SSDT版本进行重载(override)。 就像在第一篇文章中一样,这个部分遵循“Rename/Replace”模式。 需要替换的方法有FBST、_BIX、BIFA、SMBR、SMBW、ECSB和TACH。 对于这个步骤,为原生的`dsdt.aml`创建一个混合字节码列表非常有用。 它可以用:“`iasl -l -dl DSDT`”来创建,会在在`dsdt.dsl`中创建一个混合列表。 FBST的方法: ``` Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) FF74: 14 43 12 46 42 53 54 04 7B 69 0B FF FF 61 70 00 // .C.FBST.{i...ap. FF84: 60 ``` 一个可能的重命名补丁 (`FBST->XBST`): ~~~ Find: <46 42 53 54 04> Replace: <58 42 53 54 04> ~~~ 通过在`hex Fiend`这样的hex编辑器中搜索,验证找到的十六进制数据只有一个匹配,这是一个好主意。 因为这个补丁**只**适用于方法定义,而不是其他可能出现在`DSDT`(或原生的`SSDTs`)中的代码。 您选择的目标名称必须在该方法所在的范围内惟一。创建重复的方法会引起内核恐慌(kernel panic)。把第一个字母改成' X '通常是可以的,但不能保证。 其他方法的补丁: ~~~ _BIX->XBIX: Find: <5F 42 49 58 00> Replace: <58 42 49 58 00> BIFA->XIFA: Find: <42 49 46 41 00> Replace: <58 49 46 41 00> SMBR->XMBR: Find: <53 4D 42 52 0B> Replace: <58 4D 42 52 0B> SMBW->XMBW: Find: <53 4D 42 57 0D> Replace: <58 4D 42 57 0D> ECSB->XCSB: Find: <45 43 53 42 07> Replace: <58 43 53 42 07> TACH->XACH: Find: <54 41 43 48 09> Replace: <58 41 43 48 09> ~~~ 将这些补丁添加到`config.plist/ACPI/DSDT/Patches`,原生的DSDT的方法将被Clover重命名。由于重命名,所以会使在`SSDT-BATT.aml`中定义的已经打了补丁的方法被重载(override)。 ## 总结(Conclusion) 电池状态的热修补可能是最复杂的热补丁操作之一。写所有“外部”参考的过程是冗长乏味的。 这需要一些时间(你在这里阅读的文本要花上几个小时)。慢慢看吧~。 # ======================= # 使用Hotpatch 来禁用独显(Disabling discrete)/切换GPU 这第三个帖子专门用于在一个切换的双GPU笔记本中禁用独显,使用的是相同的示例ACPI 文件作为静态补丁指南:https://www.tonymacx86.com/threads/guide-disabling-discrete-graphics-in-dual-gpu-laptops.163772/ 。 您应该下载附加到该指南的 ACPI/origin文件, 以便您跟着我一起做。 与静态补丁指南一样,目的是相对简单:在ACPI初始化过程中,为独立的GPU调用`_OFF`方法(来自`_INI`方法)。 但是由于`_OFF`可以包含`EC`相关的代码,而这些代码需要在`_REG`中执行,而不是`_INI`,所以这些细节使得它更加复杂。 ## 构建替换`_INI/_OFF/_REG`方法(Building the replacement _INI/_OFF/_REG methods) 在这个例子中,目标`_INI`方法在`SSDT-7`中,`_OFF`方法在`SSDT-8`中。这个独显设备的路径是`_SB.PCI0.RP05.PEGP`。在示例文件中,`_OFF`包含的`EC`相关代码必须移动到`_REG`。为了完成这个补丁程序,我们需要替换`_INI`、`_OFF`和`_REG`,因此每个都需要重新命名为`XINI`、`XOFF`和`XREG`。 注意:实际上您需要修补的方法可能是不同的。这完全取决于`_OFF`路径中的代码。例如,在其他ACPI集合中,碰巧地`SGOF`(可能是其他名称)有`EC`相关的代码,而这些代码又必须移动到`_REG`。在这种情况下,您需要为这个`SGOF`使用rename/replace,也许不需要使用`_OFF`方法。仔细分析你现有的代码。 Clover的`config.plist`中补丁将会在后面进行。现在,让我们来看一下替换方法的SSDT: 这SSDT将包括打了补丁的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "D-GPU", 0) { External(_SB.PCI0.RP05.PEGP, DeviceObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.RP05.PEGP.XOFF, MethodObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.LPCB.EC0.SPIN, MethodObj) Scope(_SB.PCI0.RP05.PEGP) { Method(_INI) { XINI() // call original _INI, now renamed XINI _OFF() // call (patched) _OFF } Method(_OFF, 0, Serialized) { If (LEqual (CTXT, Zero)) { /* \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) */ If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } SGOF () } } Scope(_SB.PCI0.LPCB.EC0) { Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) // code that was removed from _OFF } } } } ``` 此时,代码不会编译,因为在`_OFF`中引用的一些符号是不可用的。就像电池打补丁指南一样,我们必须添加适当的外部声明。 使用编译器产生的错误来确定需要查找的符号,然后添加适当的外部声明。在这个示例案例: ``` External(_SB.PCI0.RP05.PEGP.CTXT, IntObj) External(_SB.PCI0.RP05.PEGP.GPRF, IntObj) External(_SB.PCI0.RP05.PEGP.VGAR, FieldUnitObj) External(_SB.PCI0.RP05.PEGP.VGAB, BuffObj) External(_SB.PCI0.RP05.PEGP.SGOF, MethodObj) ``` 然后结果的SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "D-GPU", 0) { External(_SB.PCI0.RP05.PEGP, DeviceObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.RP05.PEGP.XOFF, MethodObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.LPCB.EC0.SPIN, MethodObj) External(_SB.PCI0.RP05.PEGP.CTXT, IntObj) External(_SB.PCI0.RP05.PEGP.GPRF, IntObj) External(_SB.PCI0.RP05.PEGP.VGAR, FieldUnitObj) External(_SB.PCI0.RP05.PEGP.VGAB, BuffObj) External(_SB.PCI0.RP05.PEGP.SGOF, MethodObj) Scope(_SB.PCI0.RP05.PEGP) { Method(_INI) { XINI() // call original _INI, now renamed XINI _OFF() // call (patched) _OFF } Method(_OFF, 0, Serialized) { If (LEqual (CTXT, Zero)) { /* \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) */ If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } SGOF () } } Scope(_SB.PCI0.LPCB.EC0) { Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) // code that was removed from _OFF } } } } ``` 现在编译没有错误,但是有一个警告:"`39, 3079, _REG has no corresponding Operation Region`"。这个警告很重要。除非我们添加一个假冒的EC操作区域(EC OperationRegion),否则不会调用`_REG`。 我们来添加它: ``` ... Scope(_SB.PCI0.LPCB.EC0) { OperationRegion(RME3, EmbeddedControl, 0x00, 0xFF) Method(_REG, 2) { ... ``` 然后完整的SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "D-GPU", 0) { External(_SB.PCI0.RP05.PEGP, DeviceObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.RP05.PEGP.XOFF, MethodObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.LPCB.EC0.SPIN, MethodObj) External(_SB.PCI0.RP05.PEGP.CTXT, IntObj) External(_SB.PCI0.RP05.PEGP.GPRF, IntObj) External(_SB.PCI0.RP05.PEGP.VGAR, FieldUnitObj) External(_SB.PCI0.RP05.PEGP.VGAB, BuffObj) External(_SB.PCI0.RP05.PEGP.SGOF, MethodObj) Scope(_SB.PCI0.RP05.PEGP) { Method(_INI) { XINI() // call original _INI, now renamed XINI _OFF() // call (patched) _OFF } Method(_OFF, 0, Serialized) { If (LEqual (CTXT, Zero)) { /* \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) */ If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } SGOF () } } Scope(_SB.PCI0.LPCB.EC0) { OperationRegion(RME3, EmbeddedControl, 0x00, 0xFF) Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) // code that was removed from _OFF } } } } ``` 此时,您可以保存SSDT(建议:`SSDT-DGPU.aml`)。 准备好放入`ACPI/patched`。 但是我们仍然需要在原生的`ACPI`中重命名原始方法。 ## 重命名方法 如前所述,以下方法需要重新命名: ~~~ _SB.PCI0.RP05.PEGP._INI -> XINI _SB.PCI0.RP05.PEGP._OFF -> XOFF _SB.PCI0.LPCB.EC0._REG -> XREG ~~~ 为了确定所需的二进制补丁,我们需要一个DSDT的混合列表`DSDT.aml`, `SSDT-7.aml`, 和 `SSDT-8.aml`。 用下面的方法创建: ~~~ iasl -dl -l DSDT.aml SSDT-7.aml SSDT-8.aml ~~~ 产生的混合列表在`DSDT.dsl`, `SSDT-7.dsl`, 和 `SSDT-8.dsl`中。 这里是`DSDT.dsl`中的`_REG`的混合清单 ``` Method (_REG, 2, NotSerialized) // _REG: Region Availability { D2B8: 14 12 5F 52 45 47 02 // .._REG. If (LEqual (Arg0, 0x03)) { D2BF: A0 0B 93 68 0A 03 // ...h.. Store (Arg1, ECFL) } } } } D2C5: 70 69 45 43 46 4C ``` 使用的补丁应该只重命名这个`_REG`,而不是ACPI集中的其他`_REG`方法。我们可以通过从代码中获取名称/头(name/header )加上几个字节(bytes)来重命名它。 这个模式可以获取足够的字节来唯一确定: ``` Find: <5F 52 45 47 02 A0 0B 93 68 0A 03 70 69 45 43 46 4C> Replace: <58 52 45 47 02 A0 0B 93 68 0A 03 70 69 45 43 46 4C> ``` `SSDT-7.dsl`的`_INI`方法的混合列表: ``` Method (_INI, 0, NotSerialized) // _INI: Initialize { 03D1: 14 1F 5F 49 4E 49 00 // .._INI. Store (Zero, \_SB.PCI0.RP05.PEGP._ADR) } 03D8: 70 00 5C 2F 05 5F 53 42 5F 50 43 49 30 52 50 30 // p.\/._SB_PCI0RP0 03E8: 35 50 45 47 50 5F 41 44 52 // 5PEGP_ADR ``` 产生的补丁... ~~~ Find: <5F 49 4E 49 00 70 00 5C 2F 05 5F 53 42 5F 50 43 49 30 52 50 30 35 50 45 47 50> Replace: <58 49 4E 49 00 70 00 5C 2F 05 5F 53 42 5F 50 43 49 30 52 50 30 35 50 45 47 50> ~~~ 再来看`SSDT-8.dsl`中的`_OFF`: ``` Method (_OFF, 0, Serialized) // _OFF: Power Off { 032B: 14 45 04 5F 4F 46 46 08 // .E._OFF. If (LEqual (CTXT, Zero)) { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) 0333: A0 39 93 43 54 58 54 00 5C 2F 05 5F 53 42 5F 50 // .9.CTXT.\/._SB_P 0343: 43 49 30 4C 50 43 42 45 43 30 5F 53 50 49 4E 0A // CI0LPCBEC0_SPIN. 0353: 96 00 ``` 产生的补丁... ~~~ Find: <5F 4F 46 46 08 A0 39 93 43 54 58 54> Replace: <58 4F 46 46 08 A0 39 93 43 54 58 54> ~~~ 注意:每个补丁都可能会被减少,但是您需要仔细检查所有原生的DSDT和SSDTs中的**查找**模式,因为您不想和除了目标方法外的其他方法进行匹配。因为`_REG`、`_INI`和`_OFF`是其他作用域中方法的常用名称,所以我们需要小心。 ## 简单例子 由于需要修补 `_OFF`, `_INI`, 和`_REG`,所以上面提到的ASUS文件是相对复杂的。 让我们看一个简单得多的例子。这些是用于`Asus K550VX-DM406T`的文件,并附在这个帖子上。请下载他们,以便你能一起实践。 当我们在`SSDT-14`中查看`_OFF`方法时,没有与`EC`相关的代码。它调用这个`PGOF`,但是这个在`SSDT-3`中定义的`PGOF`方法也没有与`EC`相关的代码: ``` Method (_OFF, 0, Serialized) // _OFF: Power Off { If (LEqual (CTXT, Zero)) { If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } PGOF (Zero) } ``` 这意味着`_OFF`方法可以直接在`_INI`中被调用。 如果你查看在ACPI集合中的所有`_INI`方法,你会发现在`_OFF`的路径(`_SB.PCI0.PEG0.PEGP`)中是没有`_INI`的。 这意味着我们可以简单地在正确的路径上添加一个带有`_INI`的`SSDT`,而`_INI`只需调用`_OFF`。 这是一种简单的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "DGPU", 0) { External(_SB.PCI0.PEG0.PEGP._OFF, MethodObj) Method(_SB.PCI0.PEG0.PEGP._INI) { _OFF() } } ``` 正如在主要的禁用独显指南(静态补丁)中所提到的,有时您需要调用`_PS3`而不是`_OFF`。这是一个尝试和误差处理,以确定哪个是最好的。 和上面相同的代码,但是调用` _PS3`: ``` DefinitionBlock("", "SSDT", 2, "hack", "DGPU", 0) { External(_SB.PCI0.PEG0.PEGP._PS3, MethodObj) Method(_SB.PCI0.PEG0.PEGP._INI) { _PS3() } } ``` 保存为`SSDT-DGPU.aml` 并且 NVIDIA应该被禁用。 ## 简单的例子变得没那么简单了 尽管上面提到的方法通常会在这个场景中使用(即使是在其他出现相同场景的笔记本上:在`_OFF`路径中没有`EC`访问,在该路径中不存在`_INI`),为了关掉专用的Nvidia风扇,这台特定的笔记本电脑需要额外的补丁。 所以需要进行一些调查。通过查看`_OFF`代码可以看到,它调用`PGOF(0)`来完成大部分工作。如果我们搜索通过`Arg0==Zero`参数调用`PGOF`的其他示例,我们会在`SSDT-3.dsl`中找到这段代码: ``` ElseIf (LAnd (LGreater (OSYS, 0x07D9), PEGS ())) { FAOF () PGOF (Zero) ... ``` 注意`FAOF`的调用。这是为了“FAN OFF(风扇关闭)”吗?似乎是可能的。 再看,`SSDT-3`中的`FAOF`和`FAON`: ``` Method (FAON, 0, Serialized) { \_SB.PCI0.LPCB.EC0.WRAM (0x052B, 0x9E) \_SB.PCI0.LPCB.EC0.WRAM (0x0520, 0x8B) Store (\_SB.PCI0.LPCB.EC0.RRAM (0x0521), Local0) And (Local0, 0xCF, Local0) Or (Local0, 0x20, Local0) \_SB.PCI0.LPCB.EC0.WRAM (0x0521, Local0) } Method (FAOF, 0, Serialized) { Store (\_SB.PCI0.LPCB.EC0.RRAM (0x0521), Local0) And (Local0, 0xCF, Local0) \_SB.PCI0.LPCB.EC0.WRAM (0x0521, Local0) \_SB.PCI0.LPCB.EC0.WRAM (0x0520, 0x89) \_SB.PCI0.LPCB.EC0.WRAM (0x03A4, Zero) \_SB.PCI0.LPCB.EC0.WRAM (0x03A5, Zero) } ``` 你可以看到它做了很多EC操作(manipulations)。典型的`EC`控制系统的风扇,所以这似乎证实这些方法是为了“FAN ON(风扇打开)”和“FAN OFF(风扇关闭)”。 由于这些方法操作了`EC`,所以我们不能在没有`EC`的情况下调用`FAOF`。要做到这一点,我们需要修补`_REG`。 因此,将必要的代码添加到我们的`SSDT`中: ``` DefinitionBlock("", "SSDT", 2, "hack", "DGPU", 0) { External(_SB.PCI0.PEG0.PEGP._OFF, MethodObj) Method(_SB.PCI0.PEG0.PEGP._INI) { _OFF() } External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.PEG0.FAOF, MethodObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion(RME3, EmbeddedControl, 0x00, 0xFF) Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.PEG0.FAOF() // turn dedicated Nvidia fan off } } } } ``` 我们需要重命名`_REG to XREG`的补丁(同样,是基于`DSDT.aml`的混合清单): ~~~ Find: <5F 52 45 47 02 A0 0B 93 68 0A 03> Replace: <58 52 45 47 02 A0 0B 93 68 0A 03> ~~~ 通过`config.plist`中的该补丁,`EC0._REG`更名为`XREG`。系统最终调用我们修改的`_REG`,反过来它将调用原始的`_REG`(重命名为`XREG`)并且调用`FAOF`来关闭风扇。 ## 总结 与电池状态相比,通过热修补来禁用独显,代码要简单一些,但涉及到的概念都是类似的。 # ~~4楼为未来预留~~ # ======================= # 如果你还看不懂? [Acer VN7-591G-50LW抛弃传统静态dsdt使用hotpatch方式配置](http://bbs.pcbeta.com/viewthread-1753771-1-1.html) [Hotpatch简易教程(修复声卡、屏蔽独显、驱动核显、快捷键调节亮度)](http://bbs.pcbeta.com/viewthread-1766329-1-1.html) # 常用 hotpatch 1. SSDT-Disable-DGPU.aml 屏蔽独显 2. SSDT-PluginType1.dsl intel 4代及更高平台变频使用,或者你可以使用ssdtPRGen来生成,论坛找,不多说。 3. SSDT-PNLF.dsl 有了这个才能实现快捷键亮度调节 4. SSDT-HDAU.dsl 声卡相关,SSDT-Config.dsl中写入了ID,这里也要写,config.plist中就不需要声卡id了