玩儿黑苹果,免不了和ACPI打交道,也就是大家常说的DSDT和SSDT,在这里我总结一下我在编辑ssdt中的一些经验和技巧
一、系统判断
这个是大家都知道的,就是我们在编写ssdt时都会有这样一段代码
If (_OSI ("Darwin"))
这个代码的作用就是做系统判断,让代码只在黑苹果上生效,不会影响win系统。
一般的,这样判断,都会写在函数里,请看下面代码
DefinitionBlock ("", "SSDT", 2, "OCLT", "MCHC", 0)
{
External (_SB.PCI0, DeviceObj)
Scope (_SB.PCI0)
{
Device (MCHC)
{
Name (_ADR, Zero)
Method (_STA, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}
}
但是呢,我会这样写:请看我的代码
DefinitionBlock ("", "SSDT", 2, "OCLT", "MCHC", 0x00000000){
External (_SB_.PCI0, DeviceObj)
If (_OSI ("Darwin"))
{
Scope (_SB.PCI0)
{
Device (MCHC)
{
Name (_ADR, Zero) // _ADR: Address
Name (_STA, 0x0F) // _STA: Status
}
}
}
}
我用的方法是将系统判断直接放在代码的最外面,
这样能最大程度的减少代码对win的影响,而且能够简化代码,使代码阅读更清晰
这里还有一个技巧,将函数直接定义为变量,
下面的代码
Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake
{
Return (Package (0x02)
{
0x19,
0x04
})
}
可以写成
Name (_PRW, Package (0x02)
{
0x19,
0x04
})
二、用Ioreg来验证ssdt是否生效
编写ssdt,好多时候我们是为了仿冒设备,那你怎么知道你仿冒的设备是否有用?一般在苹果系统中必要的设备都会加载相应的Kext,
IOreg的全称是IORegistryExplorer
他的功能是查看系统 I/O 信息以及驱动和设备的附属关系
如果你仿冒的设备被成功加载,那么该设备名下是有相应的子项存在的,并且在该设备的右面是有你定义的设备属性的
三、利用Hackintool的计算器来给设备改名
有些时候,DSDT中的设备需要改名,改成MacOS系统中常用的设备名
有些时候,我们还需要对系统保留的带_开头的函数进行重新命名使它失效,进而加载我们重新编写的函数,比如_PTS、_PRW、_DSM等
需要注意的是DSDT中设备和函数的命名都是四个字节,比如XHC实际上是XHC_
这里我们利用Hackintool可以很方便的就能计算出相关的设备名或函数名的十六进制代码,可以很方便的通过打ACPI补丁的方式就可以实现对设备或函数的重新命名
三、利用Hex Fiend活用noop来直接修改部分dsdt
在ssdt编写中,noop这个关键字没有任何作用他的作用就是补齐代码
某个设备,有这样一段代码
Device(GTTY)
Name (_STA,0x0F) // _STA: Status
我需要让它返回Zero
但是_STA是多个设备都拥有的函数,每个设备的_STA都不一样,如果贸然使用改名的方法,需要对所有设备的_STA函数重写,牵涉巨大,那么应该怎么做呢?我只需要对这个GTTY设备的_STA函数打补丁,那么我们扩大查找范围把GTTY和_STA都包含进去,那么不就唯一了吗?这样这块补丁不就精确的打到了它应该存在的位置上了吗?
但是还有一个问题
在二进制代码中Zero和0x0F的长度是不一样的为了补齐长度我会把它变成
或
Name (_STA,Zero) // _STA: Status
noop
上面的代码很简单,很好修补是不是?但是下面这段代码
Method (_STA, 0, NotSerialized) // _STA: Status
{
If ((UM00 == 0x03))
{
If ((UP00 == 0x02))
{
UP00 = UAPG (UM00, UP00, UC00)
}
Return (0x0F)
}
Return (0x03)
}
我需要它返回Zero该怎么办呢?
我会把它单独复制出来做成一个aml
DefinitionBlock ("", "SSDT", 2, "WDOC", "DEVICE", 0x00000000)
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If ((UM00 == 0x03))
{
If ((UP00 == 0x02))
{
UP00 = UAPG (UM00, UP00, UC00)
}
Return (0x0F)
}
Return (0x03)
}
}
当然这样编译肯定是不通过啦
所以我要修正这段代码缺失的部分,很显然不通过,是因为存在UM00、UP00、UC00三个变量和UAPG一个函数,
DefinitionBlock ("", "SSDT", 2, "WDOC", "DEVICE", 0x00000000)
{
External (UM00, IntObj)
External (UP00, IntObj)
External (UC00, IntObj)
Method (UAPG, 3, NotSerialized)
{
Return (Zero)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
If ((UM00 == 0x03))
{
If ((UP00 == 0x02))
{
UP00 = UAPG (UM00, UP00, UC00)
}
Return (0x0F)
}
Return (0x03)
}
}
OK,这样不就编译通过了吗?我这样做的目的就是为了获得函数_STA的二进制代码,编译为AML,命名为1.AML
接下来我把这个AML另存为一个副本,这个副本命名为2.AML,打开这个副本修改为
DefinitionBlock ("", "SSDT", 2, "WDOC", "DEVICE", 0x00000000)
{
External (UM00, IntObj)
External (UP00, IntObj)
External (UC00, IntObj)
Method (UAPG, 3, NotSerialized)
{
Return (Zero)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
noop
若干个noop
noop
Return (Zero)
}
}
然后保存后,用Hex find这个软件打开,直到你填充的noop后这个副本和之前的原本长度一致
然后分别在两个AML中查找_STA,从_STA开始到结尾的代码,在1.AML中就是你要查找的代码,而在2.AML中就是你要替换的代码,这样加上这段补丁,就实现了对DSDT的修改 |