黑苹果的系统维护。
ACPI
DSDT
修改
DTGP方法
许多修复需要调用到该方法,放置于DSDT的前部即可。
1 | Method (DTGP, 5, NotSerialized) |
RTC修复
适用于开机时发生错误,然后重新启动的情况。该情况下BIOS会恢复为默认设置。
修改前如下。
1 | Device (RTC){ |
修改后如下。
1 | Device (RTC){ |
HPET修复
将HPET设备修改如下即可。
1 | Device (HPET) |
PIC/TIMR设备修复
删除它们中的每一条IRQNoFlags () {2}
和IRQNoFlags () {0}
语句即可。
IOATAFamily.kext内核恐慌修复
在SATA和IDE0设备的GPCT方法前添加以下代码。
1 | Field (IDCS, DWordAcc, NoLock, Preserve) |
然后在_WAK方法中的最前面添加以下代码。
1 | \_SB.PCI0.PATA._INI () |
原生AHCI支持
在GPCT方法前插入以下代码。此代码依赖DTGP方法,需提前添加DTGP方法到DSDT前部。
1 | Method (_DSM, 4, NotSerialized) |
Clamshell修复
定位到LID设备的_LID
方法并修改如下。
1 | Name (LIDS, One) |
修复UUID Error
在DSDT中搜索PCI0设备,查看_UID
的值,示例如下。
1 | Name (_UID, One) |
启动参数添加PciRoot=#
即可,其中#为_UID的值,上例为1。
让EHCI USB 2.0识别为内建
此代码依赖DTGP方法,需提前添加DTGP方法到DSDT前部。找到0x001D0007和0x001A0007两个设备,并将原来的设备名称分别更改为EHC1和EHC2。在EHC1设备下添加以下代码。
1 | Method (_DSM, 4, NotSerialized) |
在EHC2设备下添加以下代码。
1 | Method (_DSM, 4, NotSerialized) |
跳过操作系统检查
在操作系统检查功能的代码下方以及If (LGreaterEqual (_REV, 0x02))上方加入以下代码。
1 | Store (One, WNTF) |
开启亮度滑块
在Scope (_SB)
块中的_INI方法之后,需要在LNKA设备上方添加以下设备。
1 | Device (PNLF) |
用USB唤醒睡眠
适用于只可通过电源键进行睡眠唤醒的情况。
找到_WAK
方法,将Notify附近的代码修改如下。具体为将USB0-USB4修改为UHC1-UHC5,添加EHC1和EHC2,并添加Return方法。
1 | Notify (\_SB.PCI0.UHC1, Zero) |
找到Scope (_GPE)
物件,将USB0-USB4修改为UHC1-UHC5,USB1-USB2修改为EHC1-EHC2,并删除Notify (\_SB.PCI0.USB3, 0x02)
,然后在每个修改过的Notify方法后面加Notify (\_SB.PWRB, 0x02)
。
找到UHC1-UHC5和EHC1-EHC2设备,将其中_PRW
中的Package的第二个参数由0x01或One修改为0x03。
添加以下物件后,在引导器配置中修改device-id的参数即可。
1 | Method (DTGP, 5, NotSerialized) |
使用VoodooHDA但忘记删除AppleHDA修复
注释HDEF设备即可。
引导加载AC适配器驱动
在AC设备的Name (_UID, Zero)后添加以下代码。
1 | Name (_PRW, Package (0x02) |
引导加载AppleLPC
DSDT搜索0x001F0000,查看对应的设备,对于技嘉为PX40,可全部修改为LPCB或不修改。然后在该设备添加以下方法即可。
1 | Method (_DSM, 4, NotSerialized) |
其中device-id列表如下。
device-id | 型号 |
---|---|
0x02, 0x3B, 0x00, 0x00 | 5 Series/3400 Series |
0x01, 0x3B, 0x00, 0x00 | Mobile 5 Series |
0x00, 0x3B, 0x00, 0x00 | 5 Series |
0x18, 0x3A, 0x00, 0x00 | ICH10 |
0x16, 0x29, 0x00, 0x00 | ICH9R |
0x15, 0x28, 0x00, 0x00 | ICH8M |
0x11, 0x28, 0x00, 0x00 | ICH8M-E |
0xBD, 0x27, 0x00, 0x00 | ICH7M-DH |
0xB9, 0x27, 0x00, 0x00 | ICH7M |
0x70, 0x26, 0x00, 0x00 | ICH6-ESB |
引导加载显卡驱动
DSDT搜索PCI0,然后在设备内添加以下内容。
1 | Device (PEGP) |
NVCAP的内容需要先在Windows下打开NVFlash,并输入以下命令以生成ROM。
1 | nvflash -b nvidia.rom |
然后在Mac下使用NVCAP Maker打开生成的nvidia.rom,得到数字后两两分开即可,示例如下。
1 | # 处理前 |
禁用显卡
在显卡设备的_INI方法添加以下代码即可。
1 | _OFF() |
若提示未找到对象,添加外部引用即可。
引导加载声卡驱动
DSDT搜索0x001B0000,查看对应的设备,应当为AZAL。将AZAL全部修改为HDEF,然后在该设备添加以下方法即可,注意layout-id需要配合自行制作的驱动参数。
1 | Method (_DSM, 4, NotSerialized) |
设置调节风扇转速快捷键
以Fn+Home为例,该快捷键在_Q14
被定义。也可使用Fn+End,定义于_Q15
。根据需求,在快捷键的对应方法添加以下代码。
1 | # 选择其一即可 |
亮度按键映射
对于使用VoodooPS2Controller,补丁如下。注意LPCB也可能为LPC、SBRG,PS2K也可能为KBD、KBD0。
1 | into method label _Q11 replace_content |
对于使用ApplePS2SmartTouchPad,补丁如下。注意PS2K也可能为KBD、KBD0。
1 | into method label _Q11 replace_content |
加载AppleLPC
加载AppleLPC可实现原生CPU电源管理。
查看SLE下的AppleLPC.kext/Contents/Info.plist,可查看和AppleLPC匹配的设备ID。打开DSDT,搜索0x001F0000,在该设备下添加以下代码。
1 | Method (_DSM, 4, NotSerialized) |
修改后需要屏蔽IRQ。查找PNP0000,按以下代码屏蔽IRQ。
1 | Device (PIC) |
查找PNP0100,按以下代码屏蔽IRQ。
1 | Device (TMR){ |
调试
可在任意地方插入以下代码,运行时睡眠灯将会闪烁。
1 | \_SB.PCI0.LPC.EC.LED (0x07, 0x80) |
SSDT
应当实现以下SSDT修补。以下修补文件在OpenCore的AcpiSamples文件夹。
列表
平台 | CPU | EC | AWAC/RTC | NVRAM | USB | PCI | Backlight | I2C触控板 | IRQ | IMEI |
---|---|---|---|---|---|---|---|---|---|---|
Penryn | / | SSDT-EC | / | / | / | / | ||||
Lynnfield and Clarkdale | / | SSDT-EC | / | / | / | / | ||||
Clarksfield and Arrandale | / | SSDT-EC | / | / | SSDT-PNLF | IRQ SSDT | / | |||
Sandy Bridge | CPU-PM(系统安装后使用) | SSDT-EC | / | / | / | / | SSDT-PNLF | IRQ SSDT | SSDT-IMEI(用于7代主板) | |
Ivy Bridge | CPU-PM(系统安装后使用) | SSDT-EC | / | / | / | / | SSDT-PNLF | IRQ SSDT | SSDT-IMEI(用于6代主板) | |
Haswell | SSDT-PLUG | SSDT-EC | / | / | / | / | SSDT-PNLF | SSDT-GPI0 | IRQ SSDT | / |
Broadwell | SSDT-PLUG | SSDT-EC | / | / | / | / | SSDT-PNLF | SSDT-GPI0 | IRQ SSDT | / |
Skylake | SSDT-PLUG | SSDT-EC-USBX | / | / | / | / | SSDT-PNLF | SSDT-GPI0 | / | / |
Kaby Lake | SSDT-PLUG | SSDT-EC-USBX | / | / | / | / | SSDT-PNLF | SSDT-GPI0 | / | / |
Coffee Lake (8th Gen) and Whiskey Lake | SSDT-PLUG | SSDT-EC-USBX | SSDT-AWAC | SSDT-PMC | / | / | SSDT-PNLF-CFL | SSDT-GPI0 | / | / |
Coffee Lake (9th Gen) | SSDT-PLUG | SSDT-EC-USBX | SSDT-AWAC | SSDT-PMC | / | / | SSDT-PNLF-CFL | SSDT-GPI0 | / | |
Comet Lake | SSDT-PLUG | SSDT-EC-USBX | SSDT-AWAC | / | SSDT-RHUB | / | SSDT-PNLF-CFL | SSDT-GPI0 | / | / |
Ice Lake | SSDT-PLUG | SSDT-EC-USBX | SSDT-AWAC | / | SSDT-RHUB | / | SSDT-PNLF-CFL | SSDT-GPI0 | / | / |
AMD (15/16h, Bulldozer/Jaguar) | / | SSDT-EC-USBX | / | / | / | / | ||||
AMD (17/19h, Zen) | SSDT-CPUR for B550 and A520 | SSDT-EC-USBX | / | / | / | / | ||||
Nehalem and Westmere | / | SSDT-EC | / | / | / | / | ||||
Sandy Bridge-E | / | SSDT-EC | / | / | / | SSDT-UNC | ||||
Ivy Bridge-E | / | SSDT-EC | / | / | / | SSDT-UNC | ||||
Haswell-E | SSDT-PLUG | SSDT-EC-USBX | SSDT-RTC0-RANGE | / | / | SSDT-UNC | ||||
Broadwell-E | SSDT-PLUG | SSDT-EC-USBX | SSDT-RTC0-RANGE | / | / | SSDT-UNC | ||||
Skylake-X | SSDT-PLUG | SSDT-EC-USBX | SSDT-RTC0-RANGE | / | / | / |
【旧版】SSDT列表
名称 | 解释 |
---|---|
SSDT-Config | SSDT控制入口文件 |
SSDT-LPC | 正确识别LPC总线到系统 |
SSDT-SMBUS | 正确识别SMBus到系统 |
SSDT-DMAC | 将DMA控制器公开给系统 |
SSDT-MCHC | 将内存控制器暴露在系统中 |
SSDT-IGPU | 将属性添加到集成显卡设备,可以实现HDMI音频以及正确显示 |
SSDT-Disable_DGPU | 在启动时关闭独立显卡,因为Mac OS无法使用它 |
SSDT-ALS0 | 添加假环境光传感器以在重新启动之间保存背光信息 |
SSDT-BRT6 | 将键盘的ACPI管理亮度键映射到VoodooPS2Controller.kext的PS2代码 |
SSDT-Dell_FN | 将键盘的ACPI管理亮度键映射到VoodooPS2Controller.kext的PS2代码 (部分DELL机型) |
SSDT-PNLF | 显示器亮度控制,为IntelBacklight.kext或AppleBacklight.kext + AppleBacklightInjector.kext添加PNLF设备 |
SSDT-HDAU | 自动注入HDAU属性(适用于Haswell和Broadwell平台) |
SSDT-HDEF | 自动注入HDEF属性(声卡layoutid注入点) |
SSDT-GPRW | 通过挂接GPRW或UPRW来解决即时唤醒 |
SSDT-LANC_PRW | 通过挂接GPRW来解决即时唤醒 |
SSDT-UPRW | 通过挂接GPRW或UPRW来解决即时唤醒 |
SSDT-IMEI | 添加IMEI(6系列HD4000,7系HD3000) |
SSDT-PTSWAK | 在睡眠之前对离散GPU进行驱动,并在唤醒后将其关闭,以确保系统能够跟踪它 |
SSDT-Debug | 用于ACPIDebug,该文件是通过将「添加DSDT调试方法」应用于空SSDT创建的,使用「添加SSDT调试外部声明」从其他方式访问这些方法hotpatch SSDT甚至打补丁的OEM ACPI文件 |
SSDT-ESEL | 关闭ESEL,在DSDT里原生ESEL被重命名为ESEX |
SSDT-XWAK | 关闭XWAK,在DSDT里原生的XWAK被重命名为ZWAK |
SSDT-PluginType1 | 在_PR.CPU0上插入plugin-type=1,可能是所有支持XCPM的SMBIOS只需要这种插件类型的注入 |
SSDT-SATA | 修复某些不支持的SATA设备 |
SSDT-XHC | 自动注入XHC属性 |
SSDT-XOSI | 操作系统补丁 |
SSDT-AWAC | 修复300系列主板(B360/B365/H310/H370/Z390等)系列主板的RTC设备问题,部分微星的主板/清华同方九代模具需要应用这个补丁,否则会卡住而无法进入系统,建议八代 CoffeeLake以上的用户都添加 |
SSDT-EC-USBX | 添加了一个仿冒的EC设备并完善了USB的供电,若主板的EmbeddedController原生ACPI命名就是EC则不需要该补丁 |
SSDT-PMC | 与NVRAM相关 |
SSDT-PLUG | 启用原生电源管理,Skylake六代以上的机型在Clover中可以直接勾选注入插件类型,自动注入plugin-type=1 参数实现同等效果 |
SSDT示例
SSDT-EC
禁用原有EC设备,并新建一个新的EC设备。
1 | # Desktop |
【进阶】手动编写
在DSDT中搜索PNP0C09,即可定位到EC设备。也可在Windows下的设备管理器下查找Embedded Controller,右键选择属性,在详细页面选择BIOS名称查看设备路径。
根据需求下载以下示例并打开。
1 | # SSDT-EC-USBX |
若为笔记本,则不要修改注释掉的代码,否则取消对代码的注释。这段代码的主要用途为禁用EC设备。
重命名以下地方为获得的EC设备路径。
1 | External (_SB_.PCI0.LPCB, DeviceObj) |
若出现多个PNP0C09,则检查是否存在_HID
、_CRS
、_GPE
方法,若均存在,则该设备为所求的EC设备。但若有_STA
方法,说明该EC设备是无用设备。
若无PNP0C09,则只需虚拟一个EC。尝试搜索LPCB、LPC0、LPC、SBRG、PX40,若其一存在,则使用其LPC路径取代SSDT中的EC设备路径。
若PNP0C09已被重命名为EC,则无需使用以上SSDT。但若为Skylake及更新版本,则仍需要SSDT-USBX。
SSDT-EC-USBX
用于禁用真正的嵌入式控制器并为Mac创建一个假的控制器。USBX部分用于注入Skylake和更新版本上缺少的USB电源属性。
1 | # Desktop |
在Catalina及更新版本中,AppleACPIEC.kext及其插件和USB电源管理依赖于名为EC的ACPI设备。同时,AppleBusPowerController也会查找名为EC的设备,还需要一个USBX设备来为Skylake和更新版本提供USB电源属性,因此SSDT-EC-USBX将SSDT-EC和SSDT-USBX进行了结合。
EC设备在笔记本上主要用于电池管理和热键处理,在台式机上与AppleACPIEC冲突。因此在笔记本上可以通过创建一个假EC设备实现启动,而在台式机中直接禁用该设备。
【备注】SSDT-USBX
SSDT-USBX不可使用于Broadwell及更早版本。
1 | https://github.com/dortania/OpenCore-Post-Install/blob/master/extra-files/SSDT-USBX.aml |
SSDT-IMEI
在ACPI中不存在IMEI设备时创建IMEI设备。
使用Sandy Bridge CPU的7系列主板(B75、Q75、Z75、H77、Q77、Z77)和Ivy Bridge CPU的6系列主板(H61、B65、Q65、P67、H67、Q67、Z68)需要。
在DSDT中搜索IMEI/HECI/MEI,若出现其一,则不需要SSDT-IMEI。若未出现则需要使用。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-IMEI.aml |
SSDT-PLUG
启用Apple的XCPM,从而实现更好的CPU电源管理。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-PLUG-DRTNIA.aml |
SSDT-AWAC/SSDT-RTC0-RANGE-HEDT
在Mac中启用旧版RTC时钟,因为不支持较新的AWAC时钟。适用于以下主板。
1 | B360 |
SSDT-RTC0-RANGE-HEDT还解决了由于ACPI实施不佳而导致的Big Sur启动的提前停止。
1 | # SSDT-AWAC |
【进阶】手动编写
在DSDT中搜索ACPI000E,用于搜索AWAC设备。若无该设备则无需进行以下操作。
继续搜索PNP0B00,用于搜索RTC设备。若有该设备,则证明可以禁用AWAC并启用RTC,使用上面的SSDT-AWAC即可。
若无RTC设备,则需要使用SSDT-RTC0,如下。
1 | https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-RTC0.dsl |
需要改动的设备路径如下,其中LPCB路径可通过搜索Name (_ADR, 0x001F0000)
查看。注意应当保证PCI设备存在,可通过搜索PNP0A08
确定。
1 | External (_SB_.PCI0.LPCB, DeviceObj) |
SSDT-PMC
在300系列主板上启用本机NVRAM,如B360、B365、H310、H370、Z390。Z370、HM370不需要。仅适用于第九代笔记本电脑,第十代不需要。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-PMC.aml |
【进阶】手动编写
需要使用的SSDT如下。
1 | https://github.com/acidanthera/OpenCorePkg/tree/master/Docs/AcpiSamples/Source/SSDT-PMC.dsl |
需要改动的设备路径如下,其中LPCB路径可通过搜索Name (_ADR, 0x001F0000)
查看。注意应当保证PCI设备存在,可通过搜索PNP0A08
确定。
1 | External (_SB_.PCI0.LPCB, DeviceObj) |
SSDT-RHUB
重置Asus 400系列主板上的USB控制器。Gigabyte、MSI、AsRock等不需要。主要用于使用Ice Lake的Dell笔记本。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-RHUB.aml |
【进阶】手动编写
需要使用的SSDT如下。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/decompiled/SSDT-RHUB.dsl |
需要改动的设备路径如下,其中RHUB路径可通过搜索Device (RHUB)
查看。也可搜索XHC/XHCI/XHC1。注意应当保证PCI设备存在,可通过搜索PNP0A08
确定。
1 | External (_SB_.PCI0.XHC1.RHUB, DeviceObj) |
SSDT-PNLF
控制内部显示器背光。在极少数情况下,可能需要修改GFX0为显卡设备名称。
1 | # Kaby Lake及更低 |
SSDT-XOSI
在macOS中启用许多仅限Windows的功能。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-XOSI.aml |
SSDT-UNC
确保正确禁用未使用或丢失的非核心桥接器,否则会在Big Sur中出现IOPCIFamily的panic。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-UNC.aml |
SSDT-CPUR
用于修复ACPI中的CPU定义,因为Mac不能正确支持B550和更新的主板中使用的ACPI。仅无threadripper的机器以及B550、A520和更新版本需要,X570和更旧版本并不需要。
1 | https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/compiled/SSDT-CPUR.aml |
SSDT-SBUS-MCHC
修复AppleSMBus。非必需,安装时无需此SSDT。
打开Hackintool并点击PCI选项卡,在SubClass下查找SMBus设备,即可找到其ACPI路径。也可在Windows下通过设备管理器,查找SMBus设备并查看其BIOS名称。
获取以下示例。
1 | https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-SBUS-MCHC.dsl |
需要修改的设备路径如下,修改为上面找到的SMBus设备路径即可。
1 | External (_SB_.PCI0, DeviceObj) |
编译并放置后,可在终端输入以下命令以查看是否工作。
1 | kextstat | grep -E "AppleSMBusController|AppleSMBusPCI" |
IRQ SSDT
使用SSDTTime即可。
【进阶】对于HP Compaq DC7900
需要以下SSDT。
1 | https://github.com/khronokernel/trashOS/blob/master/HP-Compaq-DC7900/0.6.1%20HP%20EFI/EFI/OC/ACPI/SSDT-CSR-HPET.aml |
在OpenCore配置文件的ACPI-Patch添加以下内容。
1 | Comment: change CRES to XCRES |
FixShutdown-USB-SSDT
用于替代FixShutdown。
1 | https://github.com/dortania/OpenCore-Post-Install/blob/master/extra-files/FixShutdown-USB-SSDT.dsl |
SSDT生成
可使用SSDTTime生成部分SSDT,具体如下。
1 | IRQ patch |
注意,若进行FixHPET,还需要将oc_patches.plist合并到原来的配置文件中,具体为添加ACPI-Patch部分。
SSDT制作
基础知识
外部引用
由于SSDT仅为DSDT的一部分,在该SSDT中的变量可能并不在这段代码中定义,在编译时则会出现对象不存在
错误。因此需要添加外部引用,声明该变量在DSDT中已被定义过。
外部引用通过以下语句完成,它应当填到DefinitionBlock的下面。
1 | External ([字段名(包含路径)], [字段对象]) |
在DSDT中搜索需要添加的外部字段,一般所得到的第一个结果即为其字段定义,字段定义与字段对象的对应关系如下表。编译不报错时,添加外部引用完成。
添加外部引用的示例可参照电池修补过程。
字段定义 | 字段对象 | 含义 | 示例 |
---|---|---|---|
Name (GZXB, 0) | IntObj | 整数 | External (GZXB, IntObj) |
Field (…){…, OSYS,16, …} | FieldUnitObj | 字段单元 | External (OSYS, FieldUnitObj) |
Mutex (BATM, 0x07) | MutexObj | 互斥体 | External (_SB.PCI0.LPCB.H_EC.BATM, MutexObj) |
Name (BPKH, Package (0x07){……}) | PkgObj | 包 | External (_SB.PCI0.LPCB.H_EC.BAT1.BPKH, PkgObj) |
Device (TPD0) | DeviceObj | 设备 | External (_SB.PCI0.I2C1.TPD0, DeviceObj) |
Method (_STA, 0, NotSerialized) | MethodObj | 函数 | External (_SB.PCI0.I2C1.TPD0._STA, MethodObj) |
OperationRegion (GNVS, SystemMemory, 0x7A4E7000, 0x0866) | OpRegionObj | 操作区 | External (GNVS, OpRegionObj) |
Event (XXXX) | EventObj | 事件 | External (XXXX, EventObj) |
ThermalZone (THRM) | ThermalZoneObj | 温控区 | External (THRM, ThermalZoneObj) |
CreateField (AAAA, Zero, BBBB) | BuffFieldObj | 缓冲区 | External (_SB.PCI0._CRS.BBBB, BuffFieldObj) |
Name (BPKH, Buffer (0x07){……}) | BuffObj | 缓冲 | External (BPKH, BuffObj) |
/ | UnknownObj | 未知 | External (_SB.EROR, UnknownObj) |
Name (MSTR,"ASL") |
StrObj | 字符串 | External (_PR.MSTR, StrObj) |
PowerResource (USBC, 0, 0) | PowerResObj | 电源资源 | External (_SB.PCI0.XDCI, PowerResObj |
Processor (PR00, 0x01, 0x00001810, 0x06) | ProcessorObj | 处理器 | External (_SB.PR00, ProcessorObj) |
/ | DDBHandleObj |
偏移量
以下代码中GNVS可以替换为任意名称,因为0x100, Zero
指向该地址的范围,偏移量地址已经被确定。而OOXX可以用0x1E代替,因为首先要保证的是字段的偏移量正确,故OOXX与OOX1互换,其数据也会跟着变化。
偏移量以字节为单位,一字节等于8位,故OOX1的偏移量为0x1E+1=0x20。
1 | Name (OOXX, Zero) |
预置变量法开关设备
每个设备的_STA方法用于控制设备开关,返回非零为开,返回零为关。因此通过修改_STA的返回值,可以禁用或启用该设备。
预置变量法即在SSDT中对某些变量预先赋值,使某个设备的_STA按照需求返回零或非零。
一般情况
被修正的变量可能存在于多个地方,对它修正后,在达到预期效果的同时,有可能影响到到其它部件。因此应当尽量修正该设备独有的变量。
预置变量法的示例可参照I2C触控板修补过程。
特殊情况
被修正的变量可能来自硬件信息,只能读取不能写入。这种情况下需要二进制更名和SSDT补丁共同完成。示例原文如下。
1 | // IM01为只读 |
为修改IM01,需要将IM01重命名,然后直接通过操作系统而非IM01作为判断条件。假设重命名为XM01,则重命名如下。
1 | Comment: change IM01 to IM01 |
补丁如下。该补丁表示如果操作系统不是Mac,则将IM01恢复为原值。
1 | Name (IM01, 0x02) |
对于仅包含返回设备状态的使能位和根据条件判断返回的使能位的_STA方法,可以直接将该方法引用为IntObj并赋值。示例如下。
1 | // 示例一 |
补丁如下。该方法有效的原因是_STA方法在操作系统OSPM模块对设备状态评估和初始化的优先级高于_INI
、_ADR
、_HID
,且_STA的返回值本身也是整数Integer。
1 | External (_SB_.PCI0.XXXX._STA, IntObj) |
不可使用该方法的示例如下。原因是_STA方法中还有其它操作,直接让_STA返回会使这些操作失效。
1 | // 示例一 |
基本框架
打开MaciASL,新建文件并将本机DSDT中的DefinitionBlock头复制到文件中。然后将里面的DSDT改为SSDT,即可得到适用于本机的SSDT框架。保存时文件名应当以SSDT-
开头。
所有SSDT补丁均需满足该基本框架的需求。以下示例的DefinitionBlock头应当根据本机的具体内容替换。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
电池修补
请基于在修改DSDT后设备能够正常显示电量的前提下制作此热补丁。
电池热补丁的基本原理是,新建一个OperationRegion块,在这个新块里动态注入所有的拆分字节数据,同时对原有的未拆分字节保留空位,从而在保证位移量正确的情况下正确注入并引用新的数据。
确认修改位置
打开IORegistryExplorer,查找BAT
,记录电池设备名称,本机为SB.PCI0.LPCB.EC0.BAT0
。对修补DSDT的补丁进行分析,内容如下。
1 | // 字段拆分 |
可以得出,实际修改的字节数据如下。
1 | B0C3->B1B2(C3HG,C3HF) |
故需要拆解的字节有B0C3、B0SN、B1SN,需要添加的额外方法(Method)为B1B2。比对原DSDT和已修改好的DSDT,查找调用到这些变化过的字段的Method位置,以及需要添加的Method出现位置。本机调用到B0C3、B0SN、B1SN的Method为BIFA和_BIX,需添加的额外方法B1B2在原DSDT中不存在,在修改过的DSDT中位于根目录。至此所有需要修改的地方已完全确定。
数据插入
打开MaciASL,新建一个SSDT框架,如下。
1 | // xxxx用说找到的电池设备名(此处为BAT0)替换 |
打开原DSDT并搜索EmbeddedControl,复制整个OperationRegion到这个热补丁内。注意要把整个OperationRegion复制过来,即从OperationRegion行始,到第一个}
止。
然后把调用到变化字段的Method和所有额外添加的Method复制到OperationRegion后。对于本机而言,需复制OperationRegion段、Method (BIFA)、Method (_BIX)、Method (B1B2),故完成后代码结构应如下所示。注意,在同一个设备下的Method需放到一起。
1 | OperationRegion (ECOR, EmbeddedControl, Zero, 0xFF) |
添加位置代码
在代码块前需添加它们的位置代码,以使BIOS修补时有迹可循。在代码块的前后分别用以下代码框住即可,注意xxxx为位置,需要用绝对路径。
1 | Scope (xxxxx) |
以本机为例,本机的OperationRegion和BIFA方法均在_SB.PCI0.LPCB.EC0
下,而_BIX
方法位于_SB.PCI0.LPCB.EC0
的BAT0设备下。因此将OperationRegion和BIFA用Scope (_SB.PCI0.LPCB.EC0)
框住,而_BIX
方法则用Scope (_SB.PCI0.LPCB.EC0.BAT0)
框住,如下。注意,B1B2和B1B4方法放置于根目录,故无需位置代码。
1 | DefinitionBlock ("", "SSDT", 2, "hack", "BAT0", 0x00000000) |
添加外部引用
完成以上步骤后进行编译,并根据相应错误添加外部引用。
首先添加设备引用。以上面代码为例,设备_SB.PCI0.LPCB.EC0
与_SB.PCI0.LPCB.EC0.BAT0
被引用,故需用以下语句进行声明。
1 | // xxxx是设备地址 |
该部分语句需添加到DefinitionBlock的下面,故代码如下,其中DeviceObj
表示这是一个ACPI设备。再次编译,有关设备的报错均已消失。
1 | DefinitionBlock ("", "SSDT", 2, "hack", "BAT0", 0x00000000) |
然后根据报错,继续在DSDT里搜索其他的报错代码。如对于BIXT,它是BAT0设备下的一个字段,在DSDT查询到的第一个结果是Name (BIXT
,因此用以下代码进行外部引用。
1 | External (_SB.PCI0.LPCB.EC0.BAT0.BIXT, IntObj) |
对于其余变量方法同理,字段定义与字段对象的对应关系见前面所列出的表格。
字节处理
首先需要把OperationRegion和Field里的字段重命名。以本机为例,由ECOR重命名为ECAG,如下。
1 | OperationRegion (ECAG, EmbeddedControl, Zero, 0xFF) |
然后要使字段有正确的偏移量,可把Field里所有不拆分的字节数据段名字去掉,只保留空位,如ACST, 1
,清空变量名后变为, 1,
。示例如下。
1 | Offset (0x93), |
或可采用以下注释的形式。
1 | Offset (0x93), |
或可手动计算偏移量,如下。
1 | Offset (0x93), |
修改完成后,将之前的电量补丁Patch使其生效,然后编译并保存。
添加更名补丁
将热补丁中从原始DSDT复制过来的Method名全部进行修改,如热补丁中有从DSDT复制过来的代码Method (BIFA, 1, NotSerialized)
,则BIFA需要更名。此处以更名为BIGA为例,打开config.plist,添加以下更名规则即可。
1 | Comment: change BIFA(1, N) to BIGA(1, N) |
若所需要更改的方法名位于电池设备(即BAT0)内,则在Tgtbridge栏还应加入该电池设备名的16进制数,如下。
1 | Comment: change _BIX(1, N) to XBIX(1, N) in BAT0 |
但如果添加Tgtbridge后电池补丁反而失效,则将Tgtbridge值删除。
添加_OSI判断
在已经完成的补丁文件中,在每一个Method的开始部分加上_OSI系统判断并在结尾处回调原始方法,示例如下。
1 | Method (_BIF, 0, NotSerialized) |
Else后面的代码为回调原始方法,如果原始方法没有出现Return语句,则可直接以XBIF()的方式回调。如果原始方法的代码中出现了Return语句,则在回调时也需要以Return形式回调原方法,示例如下。
1 | Method (SMTF, 1, NotSerialized) |
完成修补
将上述SSDT保存为aml文件,放到引导器的ACPI部分即可。
特殊处理
惠普笔记本ACEL设备禁止
部分惠普笔记本配备机械硬盘防护传感器。该设备实际为一个加速度传感器,即便没有驱动也能保持运行,持续向EC中读写数据,会导致电池状态刷新异常。
在Windows下确认该设备ACPI名称为ACEL后,可通过ACPI更名其_STA,并在热补丁中要求macOS下禁止该设备即可。
ECRD和ECWT读写控制
部分机器的ACPI对于EC作用域下的寄存器读写有严格控制,有时需要修改其中的代码以解除限制。暂时无相关解决方案。
双电池系统
对于单块物理电池,禁用另一个电池设备即可,一般为BAT1。SSDT示例如下,其中BAT1路径根据实际替换。
在OpenCore中,加载顺序为主补丁-禁用BAT1补丁。
1 | // battery for WTX30,WTX40,X260,X1C2014,X1C2016 |
对于两块物理电池,更改两块电池设备的ACPI _HID名称使其保持运行的情况下不被电池驱动识别,同时新建一个BATC设备用于合并计算两块电池的信息和状态,代替原来两块电池设备的代码为驱动提供信息。
分别使用SSDT-Notify-LPC和SSDT-OCBATC-TP-LPC进行实现,链接如下。注意根据DSDT的相关内容修改补丁,如3代机器的_Q4C的内容和样本内容不同,4/5/6/7代机器无_Q4C,7代+机器有BFCC等。
在OpenCore中,加载顺序为主补丁-BATC设备补丁-Notify补丁。
1 | # SSDT-Notify-LPC |
I2C触控板修补
该SSDT不涉及任何的ACPI更名。
修补准备
按照与修改DSDT时相同的方法,确定设备路径和APIC Pin,并放置VoodooI2C驱动。
禁用原设备
通过预置变量法
本方法在本机上通过Clover引导时可行,通过OpenCore引导时不起作用。
用Macisal打开本机DSDT,查找触控板设备名称,此处为ETPD。观察其_STA方法,该方法用于控制设备的开启与关闭,返回0x0F时为开启,返回Zero时为关闭。示例如下。
1 | Method (_STA, 0, NotSerialized) // _STA: Status |
通过简单的代码知识,可知若TPIF不等于1或DSYN不等于0,则会返回Zero,从而禁用该设备。
在DSDT中搜索TPIF,发现该变量仅在此处被引用。同理搜索DSYN,发现该变量有在其它地方被引用。因此选择改变TPIF而非DSYN的值,以避免对其它设备的影响。此处将TPIF设为0即可。
在DSDT中搜索TPIF,其定义示例如下。
1 | Scope (_SB) |
可见TPIF是一个FieldUnitObj,因此可得如下补丁示例。由于TPIF在Scope (_SB)
内,而_SB即为根目录,因此补丁中可用\
表示。
注意,上述过程仅为示例,用于阐述预置变量法的基本流程。具体的变量类型和数值设置需要根据不同的DSDT做出相应的调整。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
通过_STA修改法
新建一个SSDT框架,如下。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
在其中添加Scope作用域,路径为原触控板设备的路径,此处为ETPD。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
把以下_STA方法复制到Scope作用域中。
1 | Method (_STA, 0, NotSerialized) |
根据添加外部引用的相关办法,添加对ETPD和XSTA的相关引用。其中XSTA为ETPD的原_STA方法,后面会通过更名的方式将其改为XSTA,因此上述注入的新_STA方法意为在系统不为Mac时,调用XSTA即原_STA方法。
完整补丁如下。
1 | DefinitionBlock ("", "SSDT", 2, "DELL", "CBX3", 0x01072009) |
在config.plist中添加以下重命名补丁,示例如下。
1 | Comment:change _STA(0,N) to XSTA(0,N) |
启用GPIO
DSDT搜索Device (GPI0
,观察其_STA方法,示例如下。
1 | Method (_STA, 0, NotSerialized) |
同样使用预置变量法。观察以上代码,可知启用GPI0需要SBRG和GPEN都不等于0。搜索SBRG,发现该变量被多处引用。同理搜索GPEN,发现该变量仅本处被引用。考虑到SBRG可能本来就不为0,因此尝试只设定GPEN。
在DSDT中搜索SBRG和GPEN,其定义示例如下。
1 | // 这里就是根目录,没有Scope() |
可见GPEN是一个FieldUnitObj,因此可得如下补丁示例。
1 | // GPI0 enable |
新建热补丁
新建一个SSDT框架,如下。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
用MaciASL打开系统的DSDT,搜索触控板名称,本机为ETPD,路径为_SB.PCI0.I2C1.ETPD。在新建的SSDT中,首先添加Scope域,注意小括号内为除触控板名称外的路径。然后将触控板名称对应的整个Device复制进去,此处为Device (ETPD)
。完成后形式如下。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
此处也可以写成如下形式。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
将该SSDT中的ETPD进行改名,此处改为TPXX,该名称应当在DSDT中未出现过。然后替换_STA
部分为以下代码。
1 | Method (_STA, 0, NotSerialized) |
在禁用原设备中,若使用的是预置变量法,则在该SSDT中搜索上述用到的变量,此处为TPIF。若有类似If(TPIF...)
的语句,则修改为If(one)
。
在该SSDT中搜索OSYS。若有,则注释以下内容。
1 | If (LLess (OSYS, 0x07DC)) |
移除APIC中断控制器
在该SSDT中搜索_CRS方法。
1 | Method (_CRS, 0, Serialized) |
若代码类似如上,则将Name (SBFI
改为Name (SBFB
,并删除整个Interrupt()函数,修改后变为如下。
1 | Method (_CRS, 0, Serialized) |
在该SSDT中定位到_CRS方法,确保所有返回语句都改成以下内容。
1 | // 若该SSDT中没有I2CM,选择该语句 |
示例如下。
1 | Method (_CRS, 0, Serialized) |
GPIO固定
代码修补
在该SSDT中寻找类似如下的代码。
1 | Name (SBFG, ResourceTemplate () |
若有该代码,则系统会自动注入GPIO Pin,可跳过GPIO Pin的计算与填入。若没有,则需要将该段代码复制到TPXX的根目录,示例如下。
1 | Device (TPXX){ |
计算GPIO Pin
将上面得到的APIC Pin化为十进制,此处为6D,化成十进制为109。带入以下公式计算,计算完成后将答案重新化为十六进制,所得即为GPIO Pin的值。
对于Skylake平台,本机适用,所得为85=0x55。
1 | If APICPIN > 47 And APICPIN <= 79 Then |
对于CoffeeLake-H平台如下。
1 | If APICPIN > 47 And APICPIN <= 71 Then |
对于CoffeeLake-LF/Whiskylake平台如下。
1 | If APICPIN > 47 And APICPIN <= 71 Then |
【进阶】其它方法
打开Hackintool,在PCI选项卡下可以查看触控板类型,包括SunrisePoint、CannonPoint(Lake)[Coffee Lake(-R)]和CannonPoint(Lake)[Whiskylake]。
打开下面相应平台的第一个链接,查找设备的十六进制APIC Pin值,并记录左侧标签值(只需记录GPP_XYY_IRQ中的XYY部分),若有多个标签值,需全部记录。再打开第二个链接,搜索上面所记录的XYY,记下右侧的数值(十进制),此即为触控板的硬件引脚号。
1 | // SunrisePoint[Kaby Lake(-R)] |
对于SunrisePoint,硬件引脚号即为GPIO引脚号。
对于CannonPoint(Lake)[Coffee Lake(-R)]或CannonPoint(Lake)[Whiskylake],前面步骤与上面相同,但得到的硬件引脚号并不是GPIO引脚号,因此还需要进行转换。打开下面转换公式链接,搜索前面记录的GPP_X,得到格式如CHIPSET_GPP(数字, 基数, 终止, GPIO基数)
的内容。用所记下的十进制硬件引脚号减去基数
,再加上GPIO基数
,就是最后的十进制的GPIO引脚号。注意,X_NO_GPIO
表示此引脚号无效。
1 | // CannonPoint(Lake)[Coffee Lake-R] |
得到十进制的GPIO引脚后,需将数字转换为十六进制。
填入GPIO Pin
在某些极端状况下,只能尝试比较常见的GPIO Pin。如SunrisePoint平台可尝试0x17、0x1b、0x34和0x55。
计算完成后把GPIO Pin填入到SBFG的Pin list,示例如下。
1 | Name (SBFG, ResourceTemplate () |
添加外部引用
点击编译并根据报错添加外部引用,过程可参照电池修补部分。
完成修补
至此触控板热补丁已完成,将上述生成的所有SSDT都另存为aml,放到引导器的ACPI部分。重启后打开IORegistryExplorer,查找触控板名称(ETPD),若无此设备则禁用成功。查找新建的触控板设备(TPXX),若有此设备则触控板已处于中断模式。
ACPIDebug
ACPIDebug可用于高级人员排错,也可记录部分按键轨迹。
驱动
ACPIDebug.kext下载链接如下。
1 | https://bitbucket.org/RehabMan/os-x-acpi-debug/downloads/ |
下载后放入SLE中,用Kext Utility修复权限。
然后需要对DSDT进行修改。用MaciASL打开DSDT,点击Patch,在_OS-X-ACPI-Debug
类别下打Add DSDT Debug Methods
和Instrument EC Queries
这两个补丁,退出并保存即可。
也可通过SSDT实现。放置以下SSDT即可。
SSDT-RMDT.aml如下。
1 | // for use with ACPIDebug |
SSDT-TEST.aml,以Dell为例。注意需要重命名。
1 | // In config ACPI, NEVT to XEVT |
使用
重启后在Launchpad找到控制台,在搜索框输入ACPIDebug,然后按下键盘Fn+F5/F6。若控制台中出现信息,则ACPIDebug驱动成功。
系统优化
华硕笔记本键盘修复
按键驱动
利用AsusSMC.kext,可修复华硕笔记本键盘与Fn有关的快捷键不工作的问题。需要Lilu和VirtualSMC,下载链接如下。
1 | https://github.com/hieplpvip/AsusSMC |
将下载好的kext放到Clover的kexts文件夹中,若键盘有睡眠和飞行模式按键则还需运行install_daemon.sh,然后重启。逐个测试按键是否工作,若不工作,可通过SSDT或DSDT进行修补。
按键修复
通过DSDT
用MaciASL打开DSDT。添加以下源,然后点击Patch打相应补丁即可。
1 | http://raw.github.com/hieplpvip/AsusSMC/master |
通过SSDT
选取以下所需代码复制到MaciASL中,创建一个SSDT并保存为SSDT-ASUS.aml,放入引导器的ACPI部分,并按照注释在config.plist中添加更名补丁即可。
1 | DefinitionBlock ("", "SSDT", 2, "hack", "EC", 0x00000000) |
亮度快捷键调整
通过BrightnessKeys.kext即可,链接如下。
1 | https://github.com/acidanthera/BrightnessKeys |
CPU显示未知修复
打开终端并输入以下命令。
1 | cd /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/Resources/zh_CN.lproj/ |
打开AppleSystemInfo.strings,将UnknownCPUKind下的内容修改为需要显示的内容,如下。
1 | <key>UnknownCPUKind</key> |
保存后在终端输入以下命令即可。
1 | sudo cp ~/Desktop/AppleSystemInfo.strings /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/Resources/zh_CN.lproj/ |
系统安装与维护
修改InstallESD.dmg
InstallESD.dmg位于macOS系统的安装包内,修改其内容(如删除部分kexts)可能会使安装过程更加顺利。
打开磁盘工具,点击菜单栏上的映像-转换,选择要转换的镜像,映像格式选择读/写。打开转换好的dmg,修改完成后再次转换,映像格式选择压缩即可。
去除机型检查
可用Flat Package Editor或其它工具编辑OSInstall.mpkg,让Distribution脚本在hwbeModelCheck函数中总是返回true。编辑完成后在终端输入建议以下命令以重建映像。
1 | # Original.dmg为原始镜像 |
恢复盘
FireWolf OS X PE
类似Windows PE,FireWolf OS X PE可视作macPE,可为Mac提供恢复环境。下载链接如下。
1 | https://pe.firewolf.app/manual/downloads/thankyou.html |
安装
在Windows下用Etcher刻录到U盘即可。
引导启动
在启动之前需先确保系统完整性保护(SIP)中已允许加载任意Recovery系统,即启用CSR标志位CSR_ALLOW_ANY_RECOVERY_OS
,修改Clover配置文件中的Rt Variables-CsrActiveConfig为0x3E7即可。
使用引导High Sierra的Clover文件,可以顺利启动该恢复盘。
系统调试与日志
日志内容
previous shutdown cause:5
Mac用于说明先前关机原因的代码。可在终端通过以下命令显示。
1 | log show --predicate 'eventMessage contains "Previous shutdown cause"' --last 24h |
数字具体含义如下。
代码 | 含义 | 备注 |
---|---|---|
5 | 正确关机 | 通过关机菜单或其他关机命令关机 |
7 | CPU线程错误 | 尝试安全模式 |
3 | 硬关机 | 按电源按钮强制关机 |
0 | 电源断开 | 对笔记本而言,若电源仍有电,则代表电池或电池控制器出现问题,可尝试重置SMC |
-3 | 温度传感器超出阈值 | |
-14 | 电流突峰 | 电问题或电池问题 |
-20 | T2芯片导致的关机 | |
-60 | 错误的主目录块(badMDBEr) | 尝试重装系统 |
-61 | 应用程序无响应导致的关机 | |
-62 | 应用程序无响应导致的重启 | |
-71 | SO-DIMM内存温度超出阈值 | 尝试清除风扇灰尘 |
-74 | 电池温度超出阈值 | 尝试重置SMC |
-75 | 充电器通信问题 | |
-78 | 充电器电流不正确 | |
-79 | 电池电流不正确 | |
-86 | 接近温度超出阈值 | |
-95 | CPU温度超出预知阈值 | 尝试重置SMC |
-100 | 电源温度超出阈值 | |
-102 | 过压保护导致的关机 | |
-103 | 电池电压不足 | |
-104 | 可能与电池有关 | |
-108 | 可能与内存有关 | |
-112 | 可能与内存有关 | |
-127 | PMU强制关闭 | |
-128 | 可能与内存有关 |
内核Panic
可在/Library/Logs/DiagnosticReports目录下找到Panic日志。
错误数字含义
向量偏移值 | 描述 | 说明 |
---|---|---|
0 | Devide Error | 当进行除以零的操作时产生 |
1 | Debug Exceptions | 当进行程序单步跟踪调试时,设置了标志寄存器eflags的T标志时产生这个中断 |
2 | NMI Interrupt | 由不可屏蔽产生 |
3 | Breakpoint | 由断点指令INT3产生,与Debug处理相同 |
4 | INTO Detected Overflow | eflags的溢出标志0F引起 |
5 | BOUND Range Exceeded | 寻址到有效地址以外引起 |
6 | Invalid Opcode | CPU执行发现一个无效的指令操作码 |
7 | Coprocessor Not Available | 设备不存在,指协处理器。在两种情况下会产生该中断:CPU遇到一个转意指令并且EM置位;MP和TS都在置位状态,CPU遇到wait或一个转意指令。在这种情况下,处理程序在必要应该更新协处理器的状态 |
8 | Double Exception | 双故障出错 |
9 | Coprocessor Segment Overrun | 协处理器段超出 |
10 | Invalid Task State Segment | CPU切换时发现TSS无效 |
11 | Segment Not Present | 描述符所指的段不存在 |
12 | Stack Fault | 堆栈溢出或者不存在 |
13 | General Protection | 没有符合80386保护机制的(特权机制)操作引起 |
14 | Page Fault | 页溢出或不存在 |
16 | Coprocessor Error | 协处理器检测到非法操作 |
错误分析
在Finder切换到/Library/Logs/DiagnosticReports
,打开后缀名为panic的文档以获取内核错误报告,示例如下。
1 | *** Panic Report *** |
从以上内容可知,该错误由14=page fault
即页面错误引起,RIP寄存器即程序计数器的值为0xffffff7f8c7ba8b1
,CR2寄存器即触发页面错误的内存地址为0xffffff80639b8000
,Kernel slide为0x0000000008600000
。在kext回溯中,可以看到以下两个kext可能触发该页面错误,从而引起恐慌。
1 | kext / com.apple.iokit.IOAcceleratorFamily2 |
下载Hopper,链接如下。
1 | https://www.hopperapp.com/ |
打开Hoppeer并在软件中加载/System/Library/Kernels/kernel,单击Modify-Change File Base Address,在Base Address输入Kernel slide加上0x100000的值,即0xffffff8008700000。
重定位后点击G
,输入Backtrace中的最后一个地址,即0xffffff8008a014f7。汇编代码片段如下。
1 | _call_continuation: |
由堆栈相关知识可知,在调用ffffff8008a014f5处的call时会压入返回地址,此处为0xffffff8008a014f7。同理搜索Backtrace中的倒数第二个地址0xffffff800908f1dc,可得到另一个调用语句的地址。重复以上过程,结果如下。
1 | kernel.call_continuation() |
根据以下内容,可知内核在找到要执行的任务后,首先调用com.apple.iokit.IOAcceleratorFamily2的内核线程,其中调用了restart_channel方法。然后切换到特定的kext即com.apple.kext.AMDRadeonX4150,调用writeDiagnosisReport方法。
在0xffffff7f8c7ba8b1处不是一个call指令,而是mov r8d, dword [r12+rax*4]
。该地址即为RIP寄存器的内容,因此可以确定出现panic的指令位置。
根据内核报告,R12=0xffffff80639b6a70,RAX=0x0000000000000564,计算可得传送的地址为0xffffff80639b8000。该地址为fault CR2寄存器的内容。
因此可以猜测,0xffffff80639b8000指向一个未映射的页面,当com.apple.kext.AMDRadeonX4150中的mov指令尝试从该未映射地址读取时,会发生未处理的页面错误,从而导致panic。
Data Hub日志
Data Hub日志中不包括Kernel和Kext的日志。可在终端通过以下命令获取Data Hub日志。
1 | ioreg -lw0 -p IODeviceTree | grep boot-log | sort | sed 's/.*<\(.*\)>.*/\1/' | xxd -r -p |
UEFI变量日志
可在终端通过以下命令获取UEFI变量日志。
1 | nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:boot-log | awk '{gsub(/%0d%0a%00/,"");gsub(/%0d%0a/,"\n")}1' |
内核调试套件
内核调试工具包(Kernel Debug Kits,KDK)可从内核和核心kext获取日志信息。
安装
在终端输入以下命令以确定需要下载的KDK版本。
1 | sw_vers | grep BuildVersion |
打开以下链接,搜索Kernel Debug Kit并下载相应的版本。
1 | https://developer.apple.com/download/all/ |
下载后运行安装包进行安装。禁用系统SIP后,在终端输入以下命令以挂载根目录为可写。
1 | # Big Sur+ |
然后输入以下命令安装。
1 | # Install KDK to System Volume |
完成安装后,需要添加以下启动参数之一。
1 | # kasan是一个包含AddressSanitizer的日志密集型内核 |
重新启动并在终端输入以下命令以查看当前内核是否已被改变。
1 | sysctl kern.osbuildconfig |
卸载
禁用系统SIP后,在终端输入以下命令以挂载根目录为可写。
1 | # Big Sur+ |
然后输入以下命令删除调试内核和kexts。
1 | # Revert to old snapshot (Big Sur+) |
删除启动参数kcsuffix=
后重新启动,然后在终端输入以下命令以查看当前内核是否已被改变。
1 | sysctl kern.osbuildconfig |
本机文件内容
DSDT
电池
1 | Scope (_SB.PCI0.LPCB.EC0) |
SSDT
电池
更名如下。
1 | Comment: change BIFA to BIGA |
SSDT如下。
1 | // 使用Catalina用户则需将EC0更改为EC |
I2C触控板
SSDT如下。
1 | DefinitionBlock ("", "SSDT", 2, "_ASUS_", "Notebook", 0x01072009) |
附录
工具
SSDTTime
下载
1 | https://github.com/corpnewt/SSDTTime |
常见问题
提示Could not locate or download iasl!
Python版本过时。可更新Python,或下载iasl并放置到SSDTTime的脚本文件夹中。
旧版工具
DSDT editor
1 | https://www.insanelymac.com/forum/topic/223205-dsdt-editor-and-patcher/ |
DSDT库
1 | # Intel NUC5/NUC6/NUC7/NUC8 DSDT patches |
参考教程
Patching LAPTOP DSDT/SSDTs
1 | https://www.tonymacx86.com/threads/guide-patching-laptop-dsdt-ssdts.152573/ |
DSDT与SSDT编译错误解决方案合集汇总
1 | http://imacos.top/2019/08/23/1709/ |
OpenCore引导各平台所需要的SSDT
1 | http://imacos.top/2020/03/29/ssdt/ |
小白也能看懂的入门教程DSDT/SSDT/ROM提取完整步骤编译拆分补丁除错实现笔记本电脑电池显示
1 | http://imacos.top/2019/07/22/1409/ |