黑苹果电池电量补丁_小白都能看懂的DSDT电量显示补丁教程

[TOC]

简介

知识储备DSDT

正则匹配(不懂就依葫芦画瓢)

背景

由于普通PC的电池设备并不兼容与苹果的SMbus设备,所以,对于黑苹果,只能够通过ACPI来获取电池状态。为了解决电量显示我可是爬了不少帖子、花了不少时间呢。但是从我参考的中外教程来看,我觉得都不太理想,作为一个程序员的我都要看好几遍,普通用户怕是望而却步。再说作为小白用户其实没必要搞清楚里面的弯弯道道,能正常显示电量就是目标,所以萌生了写这篇文章的念头。

参考资料

准备阶段

汇集中外教程资料,准备步骤如下

在DSDT文件中搜索关键词“EmbeddedControl” ,有些机型可能会有多个

1

2# 定义一个0xFF(255)字节的EC域ECF2

OperationRegion (ECF2, EmbeddedControl, Zero, 0xFF)

接着搜关键词“ECF2”(上面EmbeddedControl搜索到多个EC域的都要找),有些机型即使只有一个EC域也在多个块有声明(如例子附件中E430)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19Field (ECF2, ByteAcc, Lock, Preserve)

{

MBVR, 8,

Offset (0x10),

BDN0, 56,

Offset (0x18),

BME0, 8,

Offset (0x1C),

DAY0, 8,

HUR0, 8,

MIN0, 8,

SEC0, 8,

BMN0, 128,

BCT0, 128,

Offset (0x59),

EC59, 1,

DPDS, 1,

……

}

将第二步中所有Field里大于8位的属性定义且在别的地方有访问的都找出来,把这些变量名及调用的代码都一一用文本文件记录下来,后面高级进阶要用。任何属性在任何位置只是声明没有调用的都不用管

计算大于32位属性的偏移量,如上述代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20# 16进制记法:0到15(即0 1 2 3 4 5 6 7 8 9 A B C D E F),满16进位(0x10=16)

Field (ECF2, ByteAcc, Lock, Preserve)

{

MBVR, 8,

Offset (0x10), // 空10位

BDN0, 56, // 0x10

Offset (0x18),

BME0, 8, // 0x18

Offset (0x1C), //

DAY0, 8, // 0x1C

HUR0, 8, // 0x1D=0x1C+1 8位是1字节,所以加1)

MIN0, 8, // 0x1E

SEC0, 8, // 0x1F

BMN0, 128, // 0x20

BCT0, 128, // 0x31=0x20+0x10(16)+1

Offset (0x59),

EC59, 1,

DPDS, 1,

……

}

修改阶段

暴力修改

从Laptop-DSDT-Patch下载了battery_HP-Envy-14(我的是HP Envy 13,当时认为应该是最接近的)参考对照,补丁和源文件都有的留下,补丁有源文件没有的删了,再依葫芦画瓢把源文件有补丁没有的补上,最后编译,除了16位、32位拆字节补丁无效(也就是类似下面的代码),其它的都正常,然后就傻不拉几的手工拆

1

2

3# 我确定自己的设备标识也是H_EC,所以我改成into scope label ^^LPCB

into device label H_EC code_regex BDC0,\s+16 replace_matched begin DC00,8,DC01,8 end;

……

特别注意类型如下代码

1

2

3

4

5

6# 0x10即上面找出来的BDN0偏移量

into method label GBTI code_regex \(BDN0, replaceall_matched begin (RECB(0x10,56), end;

# 0x20即上面找出来的BMN0偏移量

into method label GBTI code_regex \(BMN0, replaceall_matched begin (RECB(0x20,128), end;

# 0x31即上面找出来的BCT0偏移量

into method label GBTI code_regex \(BCT0, replaceall_matched begin (RECB(0x31,128), end;

编译成功另存为aml文件替换重启正常显示电量。至此,如果你不想继续看,用我一样的笨方法理论上是能解决问题的。码农天生喜欢折腾,不然也不会玩黑苹果了,于是我把补丁文件研究了一番寻求优雅方式

高级进阶

通过分析补丁文件,我发现了一个特点,就是除了增加方法,其它的都是正则匹配替换(在这里我假设你懂正则),于是我去看了Patching Syntax Grammar,下面我简单说明一下

第一部分into|into_all就是在什么范围(后面跟着的限定),into应该的匹配第一个,into_all有多少匹配多少

第二部分即限定,可以有All|DefinitionBlock|Scope|Method|Device|Processor|ThermalZone这些值

第三部分即名称标识啥的了,支持标签名称、正则匹配、父项名称等

第四部分selector,即选择器(支持正则)

第五部分动作(就是在匹配项里干什么),支持

insert|set_label|replace_matched|replaceall_matched|remove_matched|removeall_matched|remove_entry|replacecontent|store%8|store_%9这些

begin end里面的就是主体

拆字节补丁例子1

2

3

4

5

6

7

8

9

10# 在范围为^LPCB中查找(即)BDC0, 16的内容(s+就是有至少一个空格),替换成DC00,8,DC01,8

# 也就是将BDC0, 16拆成两个字节DC00,8,DC01,8

# 注意这里16后面没有逗号(,),替换第二个8后面也没有,所以即使是}前一个也是通用的

# 这个是GitHub下载补丁里的,我的设备标识是H_EC,但我发现无效,原因未知,于是我改了

into device label H_EC code_regex BDC0,\s+16 replace_matched begin DC00,8,DC01,8 end;

into scope label ^^LPCB code_regex BDC0,\s+16 replace_matched begin DC00,8,DC01,8 end;

# 拆分32位属性

into scope code_regex BTY0,\s+32 replace_matched begin TY00,8,TY01,8,TY02,8,TY03,8 end;

# 所有大于32位的都不用拆

从上面的图片可以看到补丁完美实现拆字节,下面再看看调用例子

访问属性补丁例子1

2

3

4

5

6

7

8

9

10

11

12# 16位属性访问替换补丁

# 注意BFC0在两个方法中有调用,都要写补丁替换

into method label BTIF code_regex \(BFC0, replaceall_matched begin (B1B2(FC00,FC01), end;

into method label _Q09 code_regex \^\^BFC0\) replaceall_matched begin ^^B1B2(FC00,FC01)) end;

# 32位属性访问替换补丁

into method label GBTI code_regex \(BTY0, replaceall_matched begin (B1B4(TY00,TY01,TY02,TY03), end;

# 56位属性替换补丁

into method label GBTI code_regex \(BDN0, replaceall_matched begin (RECB(0x10,56), end;

# 128位属性替换补丁

into method label GBTI code_regex \(BMN0, replaceall_matched begin (RECB(0x20,128), end;

# 从56位和128位属性访问补丁可以看到是通过RECB(偏移量, 位数)这个方法实现的,理论上16位、32位的

# 也可以不拆,访问的时候用这个方法,但是回到准备阶段第4部我们发现算每个属性的偏移量这工作比拆字节还头大

其它举例1

2

3

4# 在做Thinakpad E430电量补丁的时候发现有类型\_SB.PCI0.LPCB.EC.HWAK这样的调用,我用下面的补丁修正

into method label _L43 code_regex \(\\\_SB.PCI0.LPCB.EC.HWAK replaceall_matched begin \(\\_SB.B1B2(\\_SB.PCI0.LPCB.EC.AK00, \\_SB.PCI0.LPCB.EC.AK01) end;

# 理论上不需要上面那个补丁应该都能替换掉所有的,但发现不彻底,原因未知

into ALL code_regex \(\\\_SB.PCI0.LPCB.EC.HWAK replaceall_matched begin \(\\_SB.B1B2(\\_SB.PCI0.LPCB.EC.AK00, \\_SB.PCI0.LPCB.EC.AK01) end;

RehabMan大神提供通用代码1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84# 这部分之间拷贝到你的补丁文件前面

# 特别注意部分行后面的\n,因为补丁里你即使输入了换行也是当一行出来的,所以加入了硬换行代码

# 删除原有B1B2方法(一般都没)

into method label B1B2 remove_entry;

# 新插入B1B2方法

# 这里需要注意一下,一般情况下默认的都没问题

# 有些型号可能会导致打完补丁的少量代码访问不了B1B2方法

# 这时候要么调整补丁绝对路径访问,要么插入的时候改个位置

into definitionblock code_regex . insert

# into Scope label \_SB code_regex . insert // 这是我改的位置

begin

Method (B1B2, 2, NotSerialized) { Return(Or(Arg0, ShiftLeft(Arg1, 8))) }

end;

into method label B1B4 remove_entry;

into definitionblock code_regex . insert

begin

Method (B1B4, 4, NotSerialized)\n

{\n

Store(Arg3, Local0)\n

Or(Arg2, ShiftLeft(Local0, 8), Local0)\n

Or(Arg1, ShiftLeft(Local0, 8), Local0)\n

Or(Arg0, ShiftLeft(Local0, 8), Local0)\n

Return(Local0)\n

}\n

end;

into method label RE1B parent_label EC0 remove_entry;

into method label RECB parent_label EC0 remove_entry;

into device label EC0 insert

begin\n

Method (RE1B, 1, NotSerialized)\n

// Arg0 - offset in bytes from zero-based EC\n

{\n

OperationRegion(ECOR, EmbeddedControl, Arg0, 1)\n

Field(ECOR, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n

Return(BYTE)\n

}\n

Method (RECB, 2, Serialized)\n

// Arg0 - offset in bytes from zero-based EC\n

// Arg1 - size of buffer in bits\n

{\n

ShiftRight(Arg1, 3, Arg1)\n

Name(TEMP, Buffer(Arg1) { })\n

Add(Arg0, Arg1, Arg1)\n

Store(0, Local0)\n

While (LLess(Arg0, Arg1))\n

{\n

Store(RE1B(Arg0), Index(TEMP, Local0))

Increment(Arg0)

Increment(Local0)

}

Return(TEMP)\n

}\n

end;

into method label RE1B parent_label EC remove_entry;

into method label RECB parent_label EC remove_entry;

into device label EC insert

begin

Method (RE1B, 1, NotSerialized)\n

// Arg0 - offset in bytes from zero-based EC\n

{\n

OperationRegion(ECOR, EmbeddedControl, Arg0, 1)\n

Field(ECOR, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n

Return(BYTE)\n

}\n

Method (RECB, 2, Serialized)\n

// Arg0 - offset in bytes from zero-based EC\n

// Arg1 - size of buffer in bits\n

{\n

ShiftRight(Arg1, 3, Arg1)\n

Name(TEMP, Buffer(Arg1) { })\n

Add(Arg0, Arg1, Arg1)\n

Store(0, Local0)\n

While (LLess(Arg0, Arg1))\n

{\n

Store(RE1B(Arg0), Index(TEMP, Local0))\n

Increment(Arg0)\n

Increment(Local0)\n

}\n

Return(TEMP)\n

}\n

end;

补丁例子

提供我做的两个型号(HP-ENVY-13及ThinkaPad E430)的补丁及原始DSL文件参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值