【已解决!】10.13寨版华南X79安装AppleACPIPlatform问题分析
本帖最后由 cheneyveron 于 2017-8-31 08:21 编辑配置:主板:华南X79 v2
CPU:E5-2670 V1 C2
显卡:GTX 1050TI
声卡:ALC662
有线网卡:RTL8168/8111/8112
目前10.12.6完美,EFI在这里:https://github.com/cheneyveron/clover-x79-e5-2670-gtx650
鲁大师配置图:
10.13 DP5:
搜了两天谷歌,按照国外大神piker alpha的分析:
https://pikeralpha.wordpress.com/2017/07/02/applesmcrtc-kext-panics
和更具体的alext jam的分析:
https://alextjam.es/debugging-appleacpiplatform
错误定位:
panic的位置在AppleACPIPlatform的_isprint函数中,函数正文反编译如下:
int _isprint(char c)
{
return (_ctype & 0x97) != 0;
}
可以看到_isprint函数用到了_ctype这个表,根据这个表的索引返回一个字符。
看起来_isprint函数重写了acpia 的_isprint函数,acpia的函数在这里:https://github.com/acpica/acpica ... clude/acclib.h#L181
AppleACPIPlatform的_isprint函数被AcpiTbPrintTableHeader调用,这个函数是acpia的函数了,所以也不需要反编译了,代码大概如下:
static void
AcpiTbFixString (
char *String,
ACPI_SIZE Length)
{
while (Length && *String)
{
if (!_isprint ((int) *String))
{
*String = '?';
}
String++;
Length--;
}
}
static void
AcpiTbCleanupTableHeader (
ACPI_TABLE_HEADER *OutHeader,
ACPI_TABLE_HEADER *Header)
{
memcpy (OutHeader, Header, sizeof (ACPI_TABLE_HEADER));
AcpiTbFixString (OutHeader->Signature, ACPI_NAME_SIZE);
AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE);
AcpiTbFixString (OutHeader->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAME_SIZE);
}
void
AcpiTbPrintTableHeader (
ACPI_PHYSICAL_ADDRESS Address,
ACPI_TABLE_HEADER *Header)
{
[...]
else
{
/* Standard ACPI table with full common header */
AcpiTbCleanupTableHeader (&LocalHeader, Header);
ACPI_INFO ((
"%-4.4s 0x%8.8X%8.8X"
" %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)",
LocalHeader.Signature, ACPI_FORMAT_UINT64 (Address),
LocalHeader.Length, LocalHeader.Revision, LocalHeader.OemId,
LocalHeader.OemTableId, LocalHeader.OemRevision,
LocalHeader.AslCompilerId, LocalHeader.AslCompilerRevision));
}
}
真正引起panic的是这句AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAME_SIZE),也就是说,实际上是MATSHeader->AslCompilerId中的某个字符无法解析导致panic。
遂用iasl查看了一下MATS表如下:
Signature : "MATS"
Table Length : 00000034
Revision : 02
Checksum : 67
Oem ID : "ALASKA"
Oem Table ID : "A M I"
Oem Revision : 00000002
Asl Compiler ID : "w x2"
Asl Compiler Revision : 00000000
**** Unknown ACPI table signature
Raw Table Data: Length 52 (0x34)
0000: 4D 41 54 53 34 00 00 00 02 67 41 4C 41 53 4B 41// MATS4....gALASKA
0010: 41 20 4D 20 49 00 00 00 02 00 00 00 77 98 78 32// A M I.......w.x2
0020: 00 00 00 00 B2 00 00 00 01 00 00 00 98 7D 2F CB// .............}/.
0030: EE FF 00 00 // ....
可以看到w x2之间的值是98,而0x98是不能转换成unsigned char的,因为unsigned char的取值范围只能到0x7F,把它改小一些以后就成功的启动了。
综上所述,如果任何一个ACPI表(不止是MATS)的 Signature、OemId、OemTableId 或 AslCompilerId 有字符大于0x7F就会导致AppleACPIPlatform错误。
看到这里,会编辑DSDT或者改BIOS的ACPI表的童鞋可以去解决问题了...
但是我的奇葩的华南X79找不到BIOS的ACPI表的位置...
我在ubuntu下提取了一堆acpi表,但是没办法用MaciASL修改,因为编译不通过...
如果能有景友知道上面两个方法怎么做,求告知。。
附上ROM和原始acpi表、现在用的dsdt
2017.8.31更新:
经过了和坛友们的讨论此问题终于解决啦,见第104楼
几乎没看到远景有X79安装好10.13的先例,所以先来抛砖引个玉。。 厉害了,大神 我想知道主板是怎么改成苹果Mac的? cheneyveron 发表于 2017-8-13 22:24 https://www.pcbeta.com/static/image/common/back.gif
几乎没看到远景有X79安装好10.13的先例,所以先来抛砖引个玉。。
我的HP。X79我晚上试试 q1005291049 发表于 2017-8-14 09:10 https://www.pcbeta.com/static/image/common/back.gif
我想知道主板是怎么改成苹果Mac的?
同问,很好奇 PhysiX 发表于 2017-8-14 09:54 https://www.pcbeta.com/static/image/common/back.gif
同问,很好奇
刷omziss修改 q1005291049 发表于 2017-8-14 09:10 https://www.pcbeta.com/static/image/common/back.gif
我想知道主板是怎么改成苹果Mac的?
我的主板BIOS是AMI的,用AMIBCP修改信息就行啦 cheneyveron 发表于 2017-8-14 13:47 https://www.pcbeta.com/static/image/common/back.gif
我的主板BIOS是AMI的,用AMIBCP修改信息就行啦
谢谢晚上回去试试 修改DMI信息就行了。。。 {:5_280:}佩服楼主钻研能力。 本帖最后由 口袋妖怪heart 于 2017-8-14 17:17 编辑
我觉得更简单的方法,是否可以直接通过对 AppleACPIPlatform 打补丁解决?我记得 10.13 DP1 刚出的时候,Alex James (aka TheRacerMaster) 就 po 了这个文,不过因为我的机器没有这样的问题以及我的 ACPI 也超差,就没再多看了。
借着楼主的问题,刚好看了一下 AppleACPIPlatform 的逆向,如下:
所以,把这个 test 的值改掉就可以了我猜,比如改成 0xFF 。
补丁如下:
Kext: AppleACPIPlatform
Find: F6040797
Repl: F60407FF
楼主试一下?(以上 hex 来自 10.13 DP5)
此外,如需修改 ACPI 表但 iasl 编译不通过,可尝试直接用 hex 编辑器来操作。
我的华南x79是2.47版本的BIOS,能用这个dsdt吗 口袋妖怪heart 发表于 2017-8-14 17:09 https://www.pcbeta.com/static/image/common/back.gif
我觉得更简单的方法,是否可以直接通过对 AppleACPIPlatform 打补丁解决?我记得 10.13 DP1 刚出的时候,Al ...
哇...欢迎口袋妖怪~我今天打算再探究一下,就用手机录了一下错误信息,发现我是isspace出的问题...不是isprint...很尴尬。
刚才反编译了一下,看到__ctype数组有256项,那个isprint的问题不可能是越界访问。
这个问题产生的根本原因其实是C语言中char的一个陷阱。默认的char是signed char包含符号的,我测试了一下,0x0~0x7f时,signed char和unsigned char都是一样的,但是一旦超过了0x7f,signed char其实就是负值了:
不过,只要简单的加一句转换语句就能避免这个问题,如下:
但是因为isprint函数没有转成unsigned char,所以当传进来一个大与0x7f的char时,根据它往__ctype查索引的话就直接溢出了,故而把改test值成FF可能不能解决问题。
要想打补丁的话,可以在isprint函数中先把参数转换成unsigned char在去__ctype查找索引,就像acpia做的那样:
#define isprint(c)(AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU))要转换成unsigned char,只需要 b = b & 0xff 即可:
用汇编语言实现转换unsigned char就是
and rdi, 0xff
二进制就是
48 81 e7 ff
但是不管用Hopper还是Clover都只能修改现成的,没办法添加上面那行代码...
所以归根到底,这要么是苹果程序员的失误,对signed char理解的不够深刻,苹果的acpi表又恰好没有高于0x7f的值,所以他们的测试人员也没发现问题。要么就是故意给广大黑苹果设的坎儿:)
至于isspace,在acpia的源码中isspace相当的简单,就是:
#define isspace(c)(AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_SP))其中_ACPI_SP = 0x20
而apple自己写的这个方法是这样的:
翻译成C语言就是这样:
int _isspace(int arg0) {
rax = (int8_t) __ctype;
rax = (rax & 0x20) >> 5;
return rax;
}
查看一下调用栈,只有一个方法调用了它,就是AcpiUtStrtoul64,看起来就是在做单个字符的循环检测。所以问题应该又是出在_isspace本身没有把参数转换成unsigned char了。
同样的... 本来是在
mov al, byte
前面加上一句
and rdi, 0xff
就行
但是不会加...尝试数次均无果...
huangyuxuan01 发表于 2017-8-14 19:55 https://www.pcbeta.com/static/image/common/back.gif
我的华南x79是2.47版本的BIOS,能用这个dsdt吗
试试就知道啦 lwchangbing 发表于 2017-8-14 09:46 https://www.pcbeta.com/static/image/common/back.gif
我的HP。X79我晚上试试
有木有什么头绪啦? 忽然发现这里已经有Alex James的分析了。。
http://www.insanelymac.com/forum/topic/324194-pre-release-macos-high-sierra/page-38#entry2441580 建议用clover里的 ACPI - FixHeader试试
当时在DP2的时候还加了一个pike的补丁,后来就不用了
cheneyveron 发表于 2017-8-14 22:32 https://www.pcbeta.com/static/image/common/back.gif
哇...欢迎口袋妖怪~我今天打算再探究一下,就用手机录了一下错误信息,发现我是isspace出的问题...不是i ...
Hmm... 如果没记错的话 rdi 是个指针?(我组合语言超差了啦) 然后 rdi 在这里作为一个 arg 来传递。然后这两个 caller 都会传递字符串喔?(如果 XREF 的话) // 我的理解对吗?__text:0000000000001178 0F BE 3B movsx edi, byte ptr ; c
__text:000000000000117B 31 C0 xor eax, eax
__text:000000000000117D E8 4D E4 01 00 call _isspace
__text:000000000000115A 41 0F BE 3F movsx edi, byte ptr ; c
__text:000000000000115E 85 FF test edi, edi
__text:0000000000001160 0F 84 4F 01 00 00 jz loc_12B5
__text:0000000000001166 89 75 D4 mov , esi
__text:0000000000001169 31 C0 xor eax, eax
__text:000000000000116B E8 5F E4 01 00 call _isspace简单搜寻了下调用栈。
ff? no 我觉得应该是需要 & 0x7f 吧,如果问题出在 7-bit ascii 或者 8-bit ascii 上。(不确定虽然)
然后关于patch bin 我觉得是不太可能了... 稍早的时候看了下 kextstat ,发现 AppleACPIPlatform 载入太早了:
13 1 0xffffff7f83539000 0x60000 0x60000 com.apple.driver.AppleACPIPlatform (5.0) 65E05472-6AE7-3308-8CC8-FA6CB0DB2AEE <12 11 7 6 5 4 3 1>
所以用 Lilu 来 func routing 是不大可能... Clover patch的话 bytes 不够......
然后翻了下 Clover 的 log ,发现之前已经有相关的 patch 了。(18F)
所以配合 Clover r4118+ 可以试试 FixHeaders_20000000
口袋妖怪heart 发表于 2017-8-15 00:28 https://www.pcbeta.com/static/image/common/back.gif
Hmm... 如果没记错的话 rdi 是个指针?(我组合语言超差了啦) 然后 rdi 在这里作为一个 arg 来传递。然后这 ...
除了这个以外我又找到另一个方法~
汇编语言在传参数的时候用的是xdi寄存器,而写寄存器依赖三个方法:mov、movsx和movzx。他们三个的区别在这:http://www.cnblogs.com/Reyzal/p/5142302.html
我写了一个很简单的C程序,一个用了char,一个用的unsigned char,然后反编译一下,
发现传char的时候是movsx xdi, 0x98
加上unsigned char类型强转以后用的是 movzx xdi, 0x98传值。
进一步的实验表明,使用movsx即传递的原值,movzx可以起到传递unsigned值的效果。
所以,只需要找到程序中调用_isprint前面的movsx edi, ... 改成 movzx edi, ... 即可从根本上解决unsigned问题。
因为天比较晚了,涉及_isprint的地方较多,所以来不及整理clover patch了。
我用类似的方法patch了_isspace前的代码,现在错误trace里面已经没有_isspace了,而是直接AcpiUtStrtoul64错误...这就很僵硬了。
目前只能等正式版出来,然后等着其他大神有什么巧妙的解决方案啦。。。