望海之洲


澎湖冰洲的极客地带


电池热补丁制作教程

前言

这个教程,是基于宪武大神的口述,加上博主的亲身实践并精心整理而成的,且发布已经得到宪武大神的授权,任何其他形式的转载请注明出处!!!教程并不一定适用于所有情况,只是给各位提供一个比较基础的思路。如果中间有任何问题,欢迎反馈给我,好让我及时更新教程。

授权

我为什么要修改

修改这个的意义,实际就是热补丁的意义。尽管我已经在我的另一篇教程里面说过了热补丁的好处,我还是乐意在这里再复述一遍。

热补丁的编辑更加高效。使用热补丁,你不需要去修改其他的无关代码,也不需要你去联合反编译DSDT然后除错,更是大大节省了你的工程量。

热补丁更加安全。如果热补丁导致你的启动出现问题,你只需要还原对应的热补丁修改(删除热补丁)即可,既快捷又方便,并且也无需备份什么。而如果是DSDT,在改动前你必须备份原有DSDT,而且出了问题时排除代码是个很让人头疼的问题。

热补丁管理方便。每个功能可以写一个热补丁,无论是配置文件里还是SSDT,都方便管理与添加;并且由于热补丁的动态注入特性,在部分情况下可以实现直接修改DSDT报错而不能完成的修改。

热补丁与平台无关。由于这一点,有些修改的热补丁可以跨平台使用,大大提高了黑果的移植度以及修改工程量。尤其是,当你发现某些机型的DSDT不能通用但是却具有高度相似的修改时,热补丁的优势将尤其明显(比如潮7000 13寸与14寸,以及潮5000关于触摸板的部分)

基于上述这几点,我们也显然可以看到了电池热补丁的优势:跨平台、易修改、易参考、高度可移植

阅读预备

正如我一直跟黑果进阶的同学反复强调的那样,热补丁是DSDT的延伸,因此,基于这一点,以下情况,我不推荐您阅读此教程:

  • 没有良好的DSDT基础

  • 电池尚未用DSDT补丁修改好

在阅读本教程之前,建议先去阅读下这篇帖子:修改dsdt实现电量显示方法(整理修改已有帖子),了解下基础的字节以及补丁工作原理,然后再来阅读下本教程。

原理

电池热补丁的原理,本质就是热补丁的原理以及电池的字节拆分原理,在此我不再赘述,有兴趣的请自己去百度相关教程。不过涉及到一些这二者协调部分的原理,在这里我有必要解释一下:

我们知道,在DSDT的电池补丁里,电池的各种变量,存在一个变量的字节位占用问题,如果将变量字节位搞错,将会导致打补丁后的DSDT无法正常显示电池信息。而热补丁本质就是DSDT的延伸,因此,我们在热补丁中动态修补电池字节数据的时候,也必须保留对原有字节位的占用,而不能随意错位。电池的数据一般存储在一个大的OperationRegion块中。懂热补丁的都知道,显然OperationRegion方法是不允许直接注入的。因此,我们通常想到的就是直接将电池设备改名,重新注入数据。这种方法经过本人测试,存在很大问题,其中之一就是数据无法正确注入修改后的电池数据(OperationRegion)到DSDT中,会报错。另外这样书写的热补丁代码量太大,需要处理的引用与方法交叉十分多。

所幸宪武大神给出了一个折中的方法:新建一个OperationRegion块,在这个新块里动态注入所有的拆分字节数据;同时,对原有的未拆分字节保留空位,从而在保证位移量正确的情况下正确注入并引用新的数据。如此,电池就可以以热补丁的形式注入字节数据并被修改为正确信息。

当然,这种方法也有其弊端在里面:由于二次调用数据,这样的热补丁执行效率会有点低,但是对于现在的机子而言,这个效率的影响微乎其微。

基于这样的一个思路,我们接下来就可以开始制作电池的热补丁。

开始制作

分析补丁

在开始制作之前,我们首先就需要对我们的电池DSDT补丁进行分析,来确定哪些数据是我们接下来需要使用到的。比如以潮7000 13寸的电池热补丁来说,是这样的:

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
1.
2.
3. #BML0, 16,
4. #BAV0, 16,
5. #BAC0, 16,
6. #BRC0, 16,
7. #BTP0, 16,
8. #BCC0, 16,
9. #FCC0, 16,
10.#BDC0, 16,
11.#BDV0, 16,
12.#BMD0, 16,
13.#MANA, 96,
14.#DENA, 64,
15.#CHEM, 32,
16.#ATE0, 16,
17.#ATF0, 16,
18.#FWIN, 64,
19.#BARC, 128,
20.#SMDA, 256,
21.
22.#BAT0 on H_EC
23.#BAT1 on H_EC
24.#BAT2 on H_EC
25.
26. into device label H_EC code_regex BML0,\s+16, replace_matched begin ML00,8,ML01,8, end;
27. into device label H_EC code_regex BAV0,\s+16, replace_matched begin AV00,8,AV01,8, end;
28. into device label H_EC code_regex BAC0,\s+16, replace_matched begin AC00,8,AC01,8, end;
29. into device label H_EC code_regex BRC0,\s+16, replace_matched begin RC00,8,RC01,8, end;
30. into device label H_EC code_regex BTP0,\s+16, replace_matched begin TP00,8,TP01,8, end;
31. into device label H_EC code_regex BCC0,\s+16, replace_matched begin CC00,8,CC01,8, end;
32. into device label H_EC code_regex FCC0,\s+16, replace_matched begin FC00,8,FC01,8, end;
33. into device label H_EC code_regex BDC0,\s+16, replace_matched begin DC00,8,DC01,8, end;
34. into device label H_EC code_regex BDV0,\s+16, replace_matched begin DV00,8,DV01,8, end;
35. into device label H_EC code_regex BMD0,\s+16, replace_matched begin MD00,8,MD01,8, end;
36. into device label H_EC code_regex CHEM,\s+32, replace_matched begin HEM0,8,HEM1,8,HEM2,8,HEM3,8, end;
37. into device label H_EC code_regex ATE0,\s+16, replace_matched begin TE00,8,TE01,8, end;
38. into device label H_EC code_regex ATF0,\s+16, replace_matched begin TF00,8,TF01,8, end;
39.
40. into method label _BIF code_regex \(BML0, replaceall_matched begin (B1B2(ML00,ML01), end;
41.
42. into method label _BST code_regex \(BML0, replaceall_matched begin (B1B2(ML00,ML01), end;
43.
44. into method label _BST code_regex BAV0\), replaceall_matched begin B1B2(AV00,AV01)), end;
45.
46. into method label _BST code_regex \(BAV0, replaceall_matched begin (B1B2(AV00,AV01), end;
47.
48. into method label GSBI code_regex \(BAV0, replaceall_matched begin (B1B2(AV00,AV01), end;
49.
50. into method label _BST code_regex \(BAC0\), replaceall_matched begin (B1B2(AC00,AC01)), end;
51.
52. into method label _BST code_regex \(BAC0, replaceall_matched begin (B1B2(AC00,AC01), end;
53.
54. into method label _BST code_regex \(BRC0, replaceall_matched begin (B1B2(RC00,RC01), end;
55.
56. into method label GSBI code_regex \(BRC0, replaceall_matched begin (B1B2(RC00,RC01), end;
57.
58. into method label GSBI code_regex \(BTP0, replaceall_matched begin (B1B2(TP00,TP01), end;
59.
60. into method label GSBI code_regex \(BCC0, replaceall_matched begin (B1B2(CC00,CC01), end;
61.
62. into method label _BIF code_regex \(FCC0, replaceall_matched begin (B1B2(FC00,FC01), end;
63.
64. into method label _BIF code_regex \(FCC0\) replaceall_matched begin (B1B2(FC00,FC01)) end;
65.
66. into method label GSBI code_regex \(FCC0, replaceall_matched begin (B1B2(FC00,FC01), end;
67.
68. into method label _BIF code_regex \(BDC0, replaceall_matched begin (B1B2(DC00,DC01), end;
69.
70. into method label GSBI code_regex \(BDC0, replaceall_matched begin (B1B2(DC00,DC01), end;
71.
72. into method label _BIF code_regex \(BDV0, replaceall_matched begin (B1B2(DV00,DV01), end;
73.
74. into method label GSBI code_regex \(BDV0, replaceall_matched begin (B1B2(DV00,DV01), end;
75.
76. into method label GSBI code_regex \(BMD0, replaceall_matched begin (B1B2(MD00,MD01), end;
77.
78. into method label GSBI code_regex \(MANA, replaceall_matched begin (\\_SB.PCI0.LPCB.H_EC.RECB(0x30,96), end;
79.
80. into method label GSBI code_regex \(DENA, replaceall_matched begin (\\_SB.PCI0.LPCB.H_EC.RECB(0x8C,64), end;
81.
82. into method label GSBI code_regex \(CHEM, replaceall_matched begin (B1B4(HEM0,HEM1,HEM2,HEM3), end;
83.
84. into method label GSBI code_regex \(ATE0, replaceall_matched begin (B1B2(TE00,TE01), end;
85.
86. into method label SMTF code_regex \(ATF0, replaceall_matched begin (B1B2(TF00,TF01), end;
87.
88. into method label GSBI code_regex \(ATF0, replaceall_matched begin (B1B2(TF00,TF01), end;
89.
90. into method label GSBI code_regex \(FWIN, replaceall_matched begin (\\_SB.PCI0.LPCB.H_EC.RECB(0xA0,64), end;
91.
92. into method label MHIF code_regex \(FWIN, replaceall_matched begin (\\_SB.PCI0.LPCB.H_EC.RECB(0xA0,64), end;
93.
94. into method label GSBI code_regex \(BARC, replaceall_matched begin (\\_SB.PCI0.LPCB.H_EC.RECB(0xA8,128), end;
95.
96. into method label MHPF code_regex Store\s\(FB4,\sSMDA\) replaceall_matched begin \\_SB.PCI0.LPCB.H_EC.WECB(0x04,256,FB4) end;
97.
98. into method label MHPF code_regex \(SMDA, replaceall_matched begin (\\_SB.PCI0.LPCB.H_EC.RECB(0x04,256), end;
99.
100. into device label BAT1 parent_label H_EC remove_entry;
101. into device label BAT2 parent_label H_EC remove_entry;
102.
103. into method label _STA parent_label BAT0 replace_content begin Return (0x1F) end;
104.
105. \#B1B2
106. \#B1B3
107. \#B1B4
108. \#RECB
109. \#WECB
110.
111. into method label B1B2 remove_entry;
112. into definitionblock code_regex . insert
113. begin
114. Method (B1B2, 2, NotSerialized)\n
115. {\n
116. Return(Or(Arg0, ShiftLeft(Arg1, 8)))\n
117. }\n
118. end;
119.
120. \#For 24 bit registers
121. into method label B1B3 remove_entry;
122. into definitionblock code_regex . insert
123. begin
124. Method (B1B3, 3, NotSerialized)\n
125. {\n
126. ​ Store(Arg2, Local0)\n
127. ​ Or(Arg1, ShiftLeft(Local0, 8), Local0)\n
128. ​ Or(Arg0, ShiftLeft(Local0, 8), Local0)\n
129. ​ Return(Local0)\n
130. }\n
131. end;
132.
133. into method label B1B4 remove_entry;
134. into definitionblock code_regex . insert
135. begin
136. Method (B1B4, 4, NotSerialized)\n
137. {\n
138. ​ Store(Arg3, Local0)\n
139. ​ Or(Arg2, ShiftLeft(Local0, 8), Local0)\n
140. ​ Or(Arg1, ShiftLeft(Local0, 8), Local0)\n
141. ​ Or(Arg0, ShiftLeft(Local0, 8), Local0)\n
142. ​ Return(Local0)\n
143. }\n
144. end;
145.
146. \# utility methods to read/write buffers from/to EC
147. into method label RE1B parent_label H_EC remove_entry;
148. into method label RECB parent_label H_EC remove_entry;
149. into device label H_EC insert
150. begin
151. Method (RE1B, 1, NotSerialized)\n
152. {\n
153. ​ OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
154. ​ Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
155. ​ Return(BYTE)\n
156. }\n
157. Method (RECB, 2, Serialized)\n
158. // Arg0 - offset in bytes from zero-based EC\n
159. // Arg1 - size of buffer in bits\n
160. {\n
161. ​ ShiftRight(Arg1, 3, Arg1)\n
162. ​ Name(TEMP, Buffer(Arg1) { })\n
163. ​ Add(Arg0, Arg1, Arg1)\n
164. ​ Store(0, Local0)\n
165. ​ While (LLess(Arg0, Arg1))\n
166. ​ {\n
167. ​ Store(RE1B(Arg0), Index(TEMP, Local0))\n
168. ​ Increment(Arg0)\n
169. ​ Increment(Local0)\n
170. ​ }\n
171. ​ Return(TEMP)\n
172. }\n
173. end;
174.
175. into method label WE1B parent_label H_EC remove_entry;
176. into method label WECB parent_label H_EC remove_entry;
177. into device label H_EC insert
178. begin
179. Method (WE1B, 2, NotSerialized)\n
180. {\n
181. ​ OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
182. ​ Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
183. ​ Store(Arg1, BYTE)\n
184. }\n
185. Method (WECB, 3, Serialized)\n
186. // Arg0 - offset in bytes from zero-based EC\n
187. // Arg1 - size of buffer in bits\n
188. // Arg2 - value to write\n
189. {\n
190. ​ ShiftRight(Arg1, 3, Arg1)\n
191. ​ Name(TEMP, Buffer(Arg1) { })\n
192. ​ Store(Arg2, TEMP)\n
193. ​ Add(Arg0, Arg1, Arg1)\n
194. ​ Store(0, Local0)\n
195. ​ While (LLess(Arg0, Arg1))\n
196. ​ {\n
197. ​ WE1B(Arg0, DerefOf(Index(TEMP, Local0)))\n
198. ​ Increment(Arg0)\n
199. ​ Increment(Local0)\n
200. ​ }\n
201. }\n
202. end;
203.
204. \# utility methods to read/write buffers from/to EC
205. into method label RE1B parent_label EC remove_entry;
206. into method label RECB parent_label EC remove_entry;
207. into device label EC insert
208. begin
209. Method (RE1B, 1, NotSerialized)\n
210. {\n
211. ​ OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
212. ​ Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
213. ​ Return(BYTE)\n
214. }\n
215. Method (RECB, 2, Serialized)\n
216. // Arg0 - offset in bytes from zero-based EC\n
217. // Arg1 - size of buffer in bits\n
218. {\n
219. ​ ShiftRight(Arg1, 3, Arg1)\n
220. ​ Name(TEMP, Buffer(Arg1) { })\n
221. ​ Add(Arg0, Arg1, Arg1)\n
222. ​ Store(0, Local0)\n
223. ​ While (LLess(Arg0, Arg1))\n
224. ​ {\n
225. ​ Store(RE1B(Arg0), Index(TEMP, Local0))\n
226. ​ Increment(Arg0)\n
227. ​ Increment(Local0)\n
228. ​ }\n
229. ​ Return(TEMP)\n
230. }\n
231. end;
232.
233. into method label WE1B parent_label EC remove_entry;
234. into method label WECB parent_label EC remove_entry;
235. into device label EC insert
236. begin
237. Method (WE1B, 2, NotSerialized)\n
238. {\n
239. ​ OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
240. ​ Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
241. ​ Store(Arg1, BYTE)\n
242. }\n
243. Method (WECB, 3, Serialized)\n
244. // Arg0 - offset in bytes from zero-based EC\n
245. // Arg1 - size of buffer in bits\n
246. // Arg2 - value to write\n
247. {\n
248. ​ ShiftRight(Arg1, 3, Arg1)\n
249. ​ Name(TEMP, Buffer(Arg1) { })\n
250. ​ Store(Arg2, TEMP)\n
251. ​ Add(Arg0, Arg1, Arg1)\n
252. ​ Store(0, Local0)\n
253. ​ While (LLess(Arg0, Arg1))\n
254. ​ {\n
255. ​ WE1B(Arg0, DerefOf(Index(TEMP, Local0)))\n
256. ​ Increment(Arg0)\n
257. ​ Increment(Local0)\n
258. ​ }\n
259. }\n
260. end;
261.
262. \# utility methods to read/write buffers from/to EC
263. into method label RE1B parent_label EC0 remove_entry;
264. into method label RECB parent_label EC0 remove_entry;
265. into device label EC0 insert
266. begin
267. Method (RE1B, 1, NotSerialized)\n
268. {\n
269. ​ OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
270. ​ Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
271. ​ Return(BYTE)\n
272. }\n
273. Method (RECB, 2, Serialized)\n
274. // Arg0 - offset in bytes from zero-based EC\n
275. // Arg1 - size of buffer in bits\n
276. {\n
277. ​ ShiftRight(Arg1, 3, Arg1)\n
278. ​ Name(TEMP, Buffer(Arg1) { })\n
279. ​ Add(Arg0, Arg1, Arg1)\n
280. ​ Store(0, Local0)\n
281. ​ While (LLess(Arg0, Arg1))\n
282. ​ {\n
283. ​ Store(RE1B(Arg0), Index(TEMP, Local0))\n
284. ​ Increment(Arg0)\n
285. ​ Increment(Local0)\n
286. ​ }\n
287. ​ Return(TEMP)\n
288. }\n
289. end;
290.
291. into method label WE1B parent_label EC0 remove_entry;
292. into method label WECB parent_label EC0 remove_entry;
293. into device label EC0 insert
294. begin
295. Method (WE1B, 2, NotSerialized)\n
296. {\n
297. ​ OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
298. ​ Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
299. ​ Store(Arg1, BYTE)\n
300. }\n
301. Method (WECB, 3, Serialized)\n
302. // Arg0 - offset in bytes from zero-based EC\n
303. // Arg1 - size of buffer in bits\n
304. // Arg2 - value to write\n
305. {\n
306. ​ ShiftRight(Arg1, 3, Arg1)\n
307. ​ Name(TEMP, Buffer(Arg1) { })\n
308. ​ Store(Arg2, TEMP)\n
309. ​ Add(Arg0, Arg1, Arg1)\n
310. ​ Store(0, Local0)\n
311. ​ While (LLess(Arg0, Arg1))\n
312. ​ {\n
313. ​ WE1B(Arg0, DerefOf(Index(TEMP, Local0)))\n
314. ​ Increment(Arg0)\n
315. ​ Increment(Local0)\n
316. ​ }\n
317. }\n
318. end;
319.
320.#Fix Battery 0% Status
321.#Maintained by: RehabMan for: Laptop Patches
322.#system_Mutex.txt
323.
324.#
325.# Some DSDTs use Mutex objects with non-zero a SyncLevel. Evidently,
326.# OS X has some difficulty with this part of the ACPI spec, either that
327.# or the DSDTs are, in fact, codec incorrectly and Windows is ignoring
328.# it.
329.
330.# The common result of a non-zero SyncLevel is failure of methods at the
331.# point of Acquire on the mutext in question. This can result in strange
332.# behavior, failed battery status, or other issues.
333.#
334. # This patch corrects all Mutex objects declared with a non-zero
335. # SyncLevel to use zero.
336. #
337.
338. # 2x as there is some sort of MaciASL bug...
339. # (code_regex_not seems broken)
340. #into_all all code_regex_not Mutex\s+\([^,]*,\s+0x00\) code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
341. #into_all all code_regex_not Mutex\s+\([^,]*,\s+0x00\) code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
342.
343. # 10x as workaround for MaciASL bug...
344. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
345. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
346. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
347. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
348. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
349. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
350. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
351. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
352. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
353. into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;
354.
355. #Logic bug with charging/discharging status (AC adapter detection)
356. #Some DSDTs suffer from a logic bug where at the point of 100% capacity (fully charged battery), an incorrect #status is returned from _BST. This mostly affects certain ASUS laptops, but also a few others.
357. #Here is a patch to correct this problem:
358. into method label FBST code_regex If\s\(CHGS\s\(Zero\)\)[\s]+\{[\s]+Store\s\(0x02,\sLocal0\)[\s]+\}[\s]+Else[\s]+\{[\s]+Store\s\(One,\sLocal0\)[\s]+\} replaceall_matched begin
359. If (CHGS (Zero))\n
360. {\n
361. ​ Store (0x02, Local0)\n
362. }\n
363. Else\n
364. {\n
365. ​ Store (Zero, Local0)\n
366. }
367. end;
368.
369. #Fix HP OMEN Laptop Baterry to enabled percentage and discharge time
370. into method label SMWR code_regex If\s\(LNot\s\(ECOK\)\)\s+\{\s+Return\s\(0xFF\)\s+\} replaceall_matched begin
371. If (LEqual (ECOK, One))\n
372. {\n
373. ​ Return (0xFF)\n
374. }\n
375. end;
376.
377. #Fix Hasee YOUYA Laptop Baterry to enabled percentage and discharge time
378. into method label SMWR code_regex If\s\(LNot\s\(ECON\)\)\s+\{\s+Return\s\(0xFF\)\s+\} replaceall_matched begin
379. If (LEqual (ECON, One))\n
380. {\n
381. ​ Return (0xFF)\n
382. }\n
383. end;
384.
385. #into definitionblock code_regex . insert
386. #begin
387. #External (_SB.PCI0.BATC, DeviceObj)
388. #end

看起来这个补丁代码确实很复杂,但是仔细分析下,我们修改这个热补丁,无非需要以下这些数据:

  • 电池的设备位置
  • 额外添加的方法
  • 拆分的字节数据
  • 引用修改字节的方法(Method)

通过对于IOReg等的分析,我们得知电池设备为H_EC.BAT0;而对此字节补丁进行分析,我们发现,它实际上修改了这些字节数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
BML0 B1B2 (ML00, ML01)
BAV0 B1B2 (AV00, AV01)
BAC0 B1B2 (AC00, AC01)
BRC0 B1B2 (RC00 ,RC01)
BTP0 B1B2 (TP00, TP01)
BCC0 B1B2 (CC00, CC01)
FCC0B1B2 (FC00, FC01)
BDC0 B1B2 (DC00, DC01)
BDV0 B1B2 (DV00, DV01)
BMD0 B1B2 (MD00, MD01)
MANA → RECB (0x30, 0x60)
DENA → RECB (0x8C, 0x40)
CHEMB1B4 (HEM0, HEM1, HEM2, HEM3)
ATE0B1B2 (TE00, TE01)

这些字节数据全部位于H_EC下的ECF2这个OperationRegion中。随后,对这些拆分的字节添加的语句进行分析,我们也找到了我们需要添加的额外方法:RECB、RE1B、B1B2、B1B4

接下来 ,我们前去阅读潮7000 13修改好电池后的DSDT(样本点击这里下载),通过反复查找对比我们前面找到的额外方法,我们可以发现,这些方法在以下这些DSDT方法中出现(也即引用修改字节的方法):

1
2
3
4
5
6
7
_SB.PCI0.LPCB.H_EC.VPC0下:

MHIF、SMTF、GSBI

_SB.PCI0.LPCB.H_EC.BAT0下:

_BIF、_BST

由此,我们确定了我们需要修改的所有地方,接下来我们就需要把这些修改注入到我们的热补丁中。

数据插入

接下来,我们就需要进行插入操作了。打开Maciasl软件(相关下载可在我博客的资源页面获取),新建一个文件,插入以下这段代码,使其声明为一个热补丁文件;然后保存为DSL文本文件(文件名随意起,只要保证以”SSDT-“开头就好了):

1
2
3
4
DefinitionBlock ("", "SSDT", 2, "hack", "xxxx", 0x00000000)
{

}

这里的XXXX为你前面找到的电池设备名称,比如我的是BAT0,那这里就写为BAT0。

然后,复制DSDT中的电池字节OperationRegion到这个热补丁中,就像这样:

复制ecf2

然后,我们将额外添加的方法引用修改字节的方法(Method)同时插入到这个DSDT里面:

插入方法

注意:在插入的时候,在同一个设备下面的方法一定要放到一块!比如_BIF_BST同为BAT0设备下面的方法,在插入时就要放到一块。这样做的目的,是为了后面修改时方便修改,减少代码的书写以及使代码层次分明。

添加位置代码

到这里,我们并未完全完成代码的插入。我们需要BIOS知道我们插入的这些方法都是动态注入修补到哪些位置的方法,这需要我们添加位置代码。

比如,比如_BIF_BST同为BAT0设备下面的方法,而BAT0位于_SB.PCI0.LPCB.H_EC

。因此,我们需要在 Method (_BIF, 0, NotSerialized)前插入Scope位置代码,在_BST方法结束位置插入结束代码”}”。它看起来的效果应该像这样:

Scope (_SB.PCI0.LPCB.H_EC.BAT0)
{   
     Method (_BIF, 0, NotSerialized) 
     {
             ...
     }

     Method (_BST, 0, NotSerialized) 
     {
             ...
     }
}

同样地,对于ECF2这个OperationRegion,它的位置在_SB.PCI0.LPCB.H_EC,因此,应该像这样在ECF2下插入位置代码:

1
2
3
4
5
6
7
8
Scope (_SB.PCI0.LPCB.H_EC)
{
OperationRegion (ECF2, EmbeddedControl, Zero, 0xFF)
Field (ECF2, ByteAcc, Lock, Preserve)
{
...
}
}

而对于RECB、RE1B、B1B2、B1B4这三个方法,由于其本身就在根设备下,因此不需要再额外添加位置代码,保留原有层级结构即可。

对所有我们刚才插入进来的代码进行位置代码插入,最终修改后,我们可以在左侧的窗格看到类似的层级结构:

层级

在图里我们看到,所有方法,除了OperationRegion外,在层层展开下均能看见,并且位置正确,层级结构不错位;同时进行一下编译,也看不到任何与”}”有关的错误:

无层级错误

添加外部引用

如果以上步骤皆操作正确,那么接下来你所看到的错误,将全部与添加外部引用有关,就像上图你看到的那样。这一部分的步骤主要就是添加外部引用。

首先注意下,我们的位置代码那里,有三个设备被引用,分别是_SB.PCI0.LPCB.H_EC_SB.PCI0.LPCB.H_EC.BAT0_SB.PCI0.LPCB.H_EC.VPC0。由于它们以Scope形式引用,必须要有设备声明,因此,我们需要添加这三个设备的外部引用到第2行下面,就像这样:

1
2
3
4
5
6
7
8
9
DefinitionBlock ("", "SSDT", 2, "hack", "BAT0", 0x00000000)
{
External (_SB_.PCI0.LPCB.H_EC, DeviceObj)
External (_SB_.PCI0.LPCB.H_EC.BAT0, DeviceObj)
External (_SB_.PCI0.LPCB.H_EC.VPC0, DeviceObj)

Scope (_SB.PCI0.LPCB.H_EC)
{
...

其中DeviceObj表示这是一个ACPI设备。

编辑好后,我们再次编译,可以看到相关的报错全都消失了:

编译1

接下来,我们根据报错,继续在DSDT里搜索其他的报错代码,并添加相关引用。

比如对于BASC,我们在DSDT搜索:

basc

可以看到,这是BAT0下的一个Name变量,对应IntObj,添加外部引用如下:

1
2
3
4
5
6
7
8
9
10
DefinitionBlock ("", "SSDT", 2, "hack", "BAT0", 0x00000000)
{
External (_SB_.PCI0.LPCB.H_EC, DeviceObj)
External (_SB_.PCI0.LPCB.H_EC.BAT0, DeviceObj)
External (_SB_.PCI0.LPCB.H_EC.VPC0, DeviceObj)
External (_SB_.PCI0.LPCB.H_EC.BAT0.BASC, IntObj) //这是插入的代码

Scope (_SB.PCI0.LPCB.H_EC)
{
...

再次编译一下,会发现所有与BASC相关的报错全部消失:

编译2

又比如,_SB.PCI0.LPCB.H_EC下的ECMTMutex变量,则对应MutexObj,添加:

1
External (_SB_.PCI0.LPCB.H_EC.ECMT, MutexObj)

B1ST则是:

1
External (_SB_.PCI0.LPCB.H_EC.B1ST, FieldUnitObj)

MAMW则是:

1
External (_SB_.PCI0.LPCB.H_EC.MAMW, MethodObj)

……

通过这一系列外部引用添加,当你最后编译发现不再报错时,外部引用的添加就算结束。

无错

重命名/清空字节

在上面的步骤完成之后,我们实际已经得到了一个基本成型的热补丁,但是这个热补丁到这还尚未修改完成,我们仍然需要两步来完成这个热补丁的修改。

首先,我们要把ECF2这个字节存放区域更名为一个与原来不一样的名字,比如ECFX。利用查找替换功能,我们可以很轻松完成这个步骤。

接下来,我们需要把所有不拆分的字节数据段名字去掉,只保留空位。以我的为例,它就像这样:

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
Scope (_SB.PCI0.LPCB.H_EC)
{
OperationRegion (ECFX, EmbeddedControl, Zero, 0xFF)
Field (ECFX, ByteAcc, Lock, Preserve)
{
Offset (0x0E),
, 8,
, 8,
, 16,
ML00, 8,
ML01, 8,
, 16,
AV00, 8,
AV01, 8,
AC00, 8,
AC01, 8,
, 8,
Offset (0x1C),
RC00, 8,
RC01, 8,
TP00, 8,
TP01, 8,
CC00, 8,
CC01, 8,
, 16,
, 16,
FC00, 8,
FC01, 8,
DC00, 8,
DC01, 8,
DV00, 8,
DV01, 8,
MD00, 8,
MD01, 8,
, 16,
, 96,
, 16,
, 16,
, 8,
Offset (0x42),
, 8,
, 8,
Offset (0x4A),
, 8,
, 8,
Offset (0x4D),
, 8,
Offset (0x50),
, 8,
Offset (0x52),
, 8,
, 8,
Offset (0x64),
, 1,
, 1,
Offset (0x65),
, 4,
, 1,
, 1,
, 1,
, 1,
, 8,
Offset (0x8B),
, 8,
, 64,
HEM0, 8,
HEM1, 8,
HEM2, 8,
HEM3, 8,
, 16,
, 16,
TE00, 8,
TE01, 8,
TF00, 8,
TF01, 8,
, 64,
, 128,
Offset (0xC6)
}
}

这里面的修改有几个要点:

  • 只清空不拆分的字节

对于未拆分的字节数据,就需要清空变量名,后面的数据保持不动。

比如:

1
ACST,   1,

​ 这一行,清空变量名,就是:

1
,   1,

​ 而那些拆分的字节数据,则不要去动,跳过去。

  • 删除无拆分的offset块

如果两个offset块之间,没有任何拆分的字节数据,则这个块可以删除。比如对于我的而言:

1
2
3
4
5
6
7
8
9
10
11
12
...	
TE00, 8,
TE01, 8,
TF00, 8,
TF01, 8,
, 64,
, 128,
Offset (0xC6),
, 8,
...
Offset (0xF1)
}

Offset (0xC6),Offset (0xF1)中间,再也没有任何拆分的字节数据,因此,我们可以抛弃这块的变量,只保留Offset (0xC6),修改为:

                  ...    
                  TE00,   8, 
      TE01,   8, 
      TF00,   8, 
      TF01,   8, 
      ,           64, 
      ,           128, 
      Offset (0xC6)  //此行之后的字节数据删除,并将末尾逗号去掉,表示到此结束
}

这一块修改完成后,进行编译。如无报错,则将文件保存编译为aml文件。至此,我们的电池热补丁制作完成。

添加改名补丁

接下来的过程,就与其他热补丁的改名过程无异了,我们需要生成并在Clover配置文件中添加引用修改字节的方法(需要注入Tgtbridge)。关于如何生成并添加这一补丁,我在我的触摸板教程第二版中有详细描述,不明白的可以点击这里查看参考。对于潮7000 13寸来说,需要添加的是这些改名补丁:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Name: change MHIF to XHIF in VPC0
Find: 4D484946
Replace: 58484946
TgtBridge: 56504330

Name: change SMTF to XMTF in VPC0
Find: 534D5446
Replace: 584D5446
TgtBridge: 56504330

Name: change GSBI to XSBI in BAT0
Find: 47534249
Replace: 58534249
TgtBridge: 42415430

Name: change _BIF to XBIF in BAT0
Find: 5F424946
Replace: 58424946
TgtBridge: 42415430

Name: change _BST to XBST in BAT0
Find: 5F425354
Replace: 58425354
TgtBridge: 42415430

接下来,保存修改后的配置文件,将新配置文件与热补丁放入对应位置,删除DSDT,重启测试。如果修改没有问题,那么电池应该会如在DSDT下一般正常工作了。祝你好运!

本教程所涉及的配置文件、热补丁与电池DSDT打包可以点击这里下载。

-------------本文已结束,感谢您的阅读!!!-------------