dd

最后更新于:2022-04-02 05:46:32

22sds
';

刷BIOS大法

最后更新于:2022-04-02 05:46:30

[TOC] # BIOS(\['baiɔs\]) > T57 D6 AMI Aptio V 主板修改工具 AMIBCP 5.01 -- 蓝天 > 神舟 战神 Z6-SL7D1 如果你的BIOS(一般是指笔记本)不能如下开启隐藏的 BIOS 菜单; 那么可以考虑通过刷 BIOS 或者指令设置某些选项。 > ❗ 论坛上有机器是可以:[**打开隐藏 BIOS 菜单**可以快速的搞定](http://bbs.pcbeta.com/viewthread-1840381-1-1.html) > 开机进入 BIOS 后,**按住 R-ctrl、R-shift、L-alt 不放,再按 F2**,在高级菜单(advance)里就会出现之前被隐藏的设置。已在**微星 GS63RE**、**微星 GS65RF**上测试。 > ❗注意📛,一定要记得备份本机得 BIOS,如果官网得不好使,你说你后悔不后悔? 本人笔记本 BIOS 下载查找:[https://repo.palkeo.com/clevo-mirror/N1xxRD/](https://repo.palkeo.com/clevo-mirror/N1xxRD/) # BIOS 中的设置 ## BIOS Lock BIOS 中的一个隐藏选项,主要是为了防止刷入未经签名**BIOS**文件,但作为折腾黑苹果屌丝的我怎能没有刷**BIOS**勇气。所以直接解锁它,以便以后可以随时更改**BIOS**选项或重置**BIOS**。 ## cfg/mrs Lock 检查你的 BIOS 里面有没有 “CFG LOCK” 这个选项,如果有的话,把它关掉。这个选项就是用来 设置 0xE2 寄存器的,只要关掉它,就和技嘉板一样了,可以**直接用原生电源管理**。 1. 使用 hackintool 检测 CFG Lock 状态 [查看主板CFG Lock状态]([https://www.zdynb.cn/2020/cha-kan-zhu-ban-cfg-lock-zhuang-tai.html) 2. 去除 OpenCore 勾选的该相关值 [OpenCore 引导 Mac 下解除 CFG LOCK 锁定的方法(2020-02-15 更新)](https://blog.csdn.net/shuiyunxc/article/details/104295837) ## DVMT-Pre-Allocted [Intel HD Graphics 修正 DVMT 完美免驱](http://bbs.pcbeta.com/viewthread-1791543-1-1.html) ## Boot Logo [修改 AMI BIOS 启动图片](http://bbs.pcbeta.com/viewthread-1787950-1-1.html) ## Intel(R) Speed Shift Technology 这是一种新的电源管理技术。Intel 早就提出了一种动态电压频率切换技术 SpeedStep,配合操作系统,能为不同的工作负载分配不同的性能和电源状态,但缺点是状态切换速度慢,最快也得 30 毫秒,系统能控制的状态也有限。Speed Shift 则绕过了操作系统,由处理器直接与电源控制单元沟通,并将所有电源状态都开放给操作系统,配合之下可在最快 1 毫秒的时间内完成状态切换。黑苹果中是否启用这项看个人,在启用后似乎性能更平稳了 ## 其他 启用 UEFI 引导 (建议选择混合或者开启 CSM 模式) 启用虚拟化技术 (VTx) 和直接 I/O 虚拟化技术 (VTd)(开启虚拟机支持) SpeedShift 可以开启; 如果电脑有时操作会卡可以关闭:CPU C states。 启用 EHCI/XHCI Hand-off 接手 EHCI/XHCI 控制 启用 OS type: other types 操作系统类型:其他 # 刷 BIOS > 本机 F2 进入 BIOS,重启按 F12/F7 快捷键,在启动菜单中选择 USB 启动 **BIOS**中隐藏选项位置为: 1. CFG Lock Setup->Advanced->CPU Configuration-> CFG Lock CFG lock 设置为 disabled 3. DVMT-Pre-Allocted Setup->Chipset -> System Agent(SA) Configuration-> Graphics Configuration DVMT Pre-Allocated 设置为 96m 其他比如**BIOS**Lock、DVMT、CFG Lock、CPU C states、SpeedShift 等,本人笔记本已经默认都是符合要求的😁。 ## 蓝天 BIOS 修改 logo default 这项是 uefi 开机启动的图片。 myoemlogo1 这项是普通 bios 开机启动的图片。 > [自制解锁 bios,加 slic,改 logo 和添加序列号](https://tieba.baidu.com/p/4936939406) > [AptioV BIOS 解锁 Chipset 菜单的方法,适用于 D2 等新版](https://tieba.baidu.com/p/5140565869) > [AMI BIOS 固件修改开机 logo 和解锁 CSM 等高级选项](http://blog.chinaunix.net/uid-29764914-id-5784902.html) > [求大神找出 bios 芯片位置,急!!](https://tieba.baidu.com/p/5293992416?pid=111232396864&cid=0&red_tag=1888335742) ## AFUDOS 强刷 > 官方推荐的方式不能刷如修改后的BIOS,校验不通过 [AMIBIOS 刷新工具 AFUDOS 刷新备份](http://www.biosrepair.com/bios/afudos.htm) 再介绍一个上面没有的参数:`/santa`,这个参数可以用在常规刷新不能刷的时候,如在写入修改后的文件或降低 BIOS 版本时。   提示:`-Error:Activation Key Checksum error`(作用的一个关键的校验和错误) 这时可以用 /santa 参数。 加了 `/santa` 参数,出现警告,并提示: ```     “F” 强制刷 BIOS     “E” 退出     “A” 激活所有 flash 命令并更新所有模块。 ``` 选择 “A”,开始更新,最后完成。 # 解锁之后配置 刷完固件记得要重新设置 BIOS [使用 UEFIPatch 解锁 MSR 0XE2 CFG LOCK (支持新版 x299 C422 C621 bios 修改)](http://bbs.pcbeta.com/viewthread-1849940-1-1.html) # 失败拯救 ## 盲(黑)刷拯救法 我按这里操作:[解锁 MSR 0xE2、BIOS Lock 等隐藏选项新姿势,还黑果原生体验(附刷 AMI BIOS 教程)](http://bbs.pcbeta.com/forum.php?mod=viewthread&tid=1834965&extra=&highlight=AMI%2BBIOS&page=12) 结果黑了,可能是我没在原来的 BIOS 基础上修改!但是我下的是官方提供的 BIOS 啊哎! > 目测你没有加 - bios 参数,导致 ME 区域被覆盖 如果 开机硬盘灯 ,还是否有指示。那么还是可以盲刷回来的。 一般来说,借助 Phoenixtool273CN 工具 找到恢复的文件名就行了。如果 没有提示恢复文件名! 那么还可以借助 Phoenix 的 WinCRIS 来制作盲刷盘了! 1. 准备步骤: 1. 更改需要使用的 bios 文件名 为 BIOS.WPH 拷贝到 WINCRIS 目录下。 1. 准备个 2G 以下(含 2G)的 U 盘,直接格式化成 FAT 32的(**网友说**:不需要要制作启动引导盘| 也不需要重新格式化,可保留原有文档只要能存放下 BIOS 文件即可)。 2. 运行 wincris.exe,(用 xp 兼容模式,管理员身份运行)选择 U 盘盘符,点 start。 弹出对话框问你盘会格式化掉是否继续,选是。然后拔出 U 盘,再插进去。 3. 查看制作成功的 U 盘里面是否有 MINIDOS.SYS、PHLASH16.EXE、BIOS.WPH 这三个文件,其中前两者可以从 WINCRIS 目录 COPY。。。。BIOS.WPH 是要刷的 BIOS 文件。 2. 盲刷 BIOS 1. 拔掉本本的电源 和电池 再插 U 盘 2. 按住键 `Fn+b` 不放(不同的品牌的盲刷 BIOS 的启动键不同,以 Phoenix BIOS 芯片的都为 `Fn+B`,其他还可能 `Win+B / Fn+Esc /Win+Esc/ Ctrl+Home`),然后**插上电源开机** 3. 等电源指示灯或者 **U盘指示灯 闪烁**后,过一会(30 秒至 1 分钟)放开按键 4. 电脑自动读取 U 盘中的 BIOS 文件,U 盘指示灯会亮起来,(可能会出现:屏幕仍为黑屏,大概需要 45 秒,刷新成功后电脑会自动关机),并开始刷 BIOS,期间会有报警声(不用理),当 BIOS 刷完后会自动重启,不出意外,电脑的 BIOS 就修复完毕了!!! 5. 15 分钟不动电脑。如果电脑没有自己重启,强制关机。 6. 插上电池,开机。(可以不插上试试。后面不必重复插拔电池。即后面一直不插电池尝试。但是外接电源每次尝试前都要拔掉)。 7. 若不成功,更换 bios.wph 为另一个版本再尝试以上步骤。 [刷坏 BIOS 黑屏,解救方法!!](http://www.ziibm.com/read.php?tid=3695) [BIOS 刷新纯 DOS 启动盘制作](http://www.biosrepair.com/pic/pic106.htm) [刷坏 BIOS 不要急,盲刷方法实测有效(T400,X200)但是有局限性](http://bbs.zol.com.cn/diybbs/d34121_265.html) # 血崩咋办嘛 种种方法都不行?那么终极大法和送修~: 建议买个编程器和烧录夹,不用拆下芯片就能刷 bios,很简单,淘宝几十块钱就能买到。 贴吧有教程:http://tieba.baidu.com/p/3954385586 淘宝编程器 自己刷 http://bbs.pcbeta.com/viewthread-1641254-1-1.html ## 上编程器 ![本人 VBIOS芯片](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/52/aa/52aaa606e9655fabe231edba8b970252_326x266.png) 本人笔记本 显卡BIOS 芯片 好像是 GIGADEV 25Q21BT 容量是 2Mb=256KB 那么 主板 BIOS 芯片呢? ![主BIOS](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/33/3e/333eb9799f3eda88f4e9426c8f5e093f_514x595.png) 1. 点击 检测,是否连接好 2. 点击 读取,备份原来的文件,以防万一 3. 点击查空,不为空的话,再点击 擦除,再点击查空 4. 打开 要写入的 BIOS 文件(后缀名改为:bin),点击 编程,结束(100%为完成)后点击 校验。提示已刷入校验证完成,表示已经刷好 BIOS 5. 装回原电脑,重启开机! 友情提示:如果你试了多个BIOS 都不行,那么可以去万能的淘宝上搜搜~ > [编程器使用教程,烧录器,必会的教学,ch341a 怎么刷 bios](https://tieba.baidu.com/p/6103207732?pn=1) > [# 求助帖 求定位哪个是 bios 芯片](https://tieba.baidu.com/p/5846365354) # 免刷 BIOS 修改位置: ``` 0x1E0AA Setting: CFG lock, Variable: 0xE7 {05 91 1B 01 1C 01 48 01 01 00 E7 00 10 10 00 01 00} 0x1E0BB Option: Disabled, Value: 0x0 {09 07 27 02 00 00 00} 0x1E0C2 Option: Enabled, Value: 0x1 {09 07 26 02 30 00 01} 0x1E0C9 End of Options {29 02} ``` 可以看到我的笔记本要修改的`Variable: 0xE7`! ~~~ setup_var_3 0xe7 0x00 ~~~ 该命令是修改 0xe7 这个地址的数值为 0x00,也就是把 CFG-Lock 这个选项设置为 Disabled。 [无需刷 BIOS!使用 setup\_var 命令解锁 MSR 0xE2 锁定](https://www.bilibili.com/read/CV4646116) [无需刷 BIOS!使用 `setup_var` 命令解锁 MSR 0xE2 锁定,修改 dvmt 值,开启 AHCI](http://bbs.pcbeta.com/viewthread-1845591-1-1.html) [https://www.misonsky.cn/115.html](https://www.misonsky.cn/115.html) https://www.zdynb.cn/2020/cha-kan-zhu-ban-cfg-lock-zhuang-tai.html # 解锁有校验的 BIOS # 更新 BIOS > 这里提一下官方方式更新 BIOS (翻译) 1. 插入电源,防止更新过程断电 2. 进入 bios,设置 "UEFI" 选项为 disabled. 3. 进入纯 dos 环境,运行 Meset.exe 系统会自动重启,请再次手动进入纯 DOS 环境。 4. 运行 `flashme.bat` 系统会自动关机 5. 拔掉电源(AC adaptor) 10 秒后,插上电源 (!!!重要!!!否则会导致黑屏死机问题) 6. 开机,进入bios 检查 BIOS 版本 7. 设置自己的bios版本,按 F4 保存并重新启动 # 参考 刷 bios 工具連結: https://pan.baidu.com/s/1b33AeSWjta33bOZMKtGmcw 密碼: 7ite 有標註 i7 的支持 i7,沒標註的支持 i5 8 代 各機型 bios 連結: https://pan.baidu.com/s/14wrHm0zul-DGsdp9ktAEaA 密碼: r1v4 [升级 BIOS / 更换开机 logo 教程](https://www.bilibili.com/read/cv2802267/) [这么多年 DIY 瞎忙活了 高手才会的 BIOS 进阶教程](http://www.360doc.com/content/16/0329/12/17064127_546226399.shtml#) [有大神解释下 Intel ME 管理引擎到底是什么](http://bbs.pcbeta.com/viewthread-1772088-1-1.html) [BIOS-工具-7p99](https://pan.baidu.com/s/1bpL8TVD)
';

黑苹果装机

最后更新于:2022-04-02 05:46:28

# 黑苹果电脑配置 ## mini-itx | 配件 | 品牌型号 | 价格 | | :-: | :-: | :-: | | CPU | [intel 酷睿i5](https://detail.tmall.com/item.htm?spm=a220m.1000858.1000725.6.33ad3272WeAQN6&id=627337403965&skuId=4503637853935&areaId=320100&user_id=1713504106&cat_id=2&is_b=1&rn=406fc3c9778ec7c32321c1daf27ce294)| ¥1200 | | 散热器 | [ID COOLING IS 30 40 50 60 X静音intel AMD 4 ITX超薄CPU散热](https://detail.tmall.com/item.htm?spm=a230r.1.14.186.567e3c67Ud9Q0N&id=587268337278&ns=1&abbucket=1&skuId=4213804512927) | ¥100 | | 主板 | 华硕 STRIX Z490-I GAMING | ¥2099 | | 内存 | ~~XXXXXXXX~~ | ~~¥560~~ | | 显卡 | [AMD磐镭RX5500XT 8G显卡](https://item.jd.com/100012690094.html) | ¥1799 | | 存储 | ~~三星970 EVO 500G nvme M.2(还是网上搜一个靠谱的NVME)~~ | ~~¥1300~~ | | 机箱 | [M34](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-21045481591.6.75082e5dpSSOkM&id=591485140674)| ¥240| | 电源 | [### 全新益衡7660B额定600w白金FLEX电源小1U电源](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-21045481589.20.75082e5dpSSOkM&id=606165680512) | ¥868 | | 键鼠装 | 自选 | --- | | 显示器 | 自选 | --- | | 报价: | --- | 6200 元 | ## itx | 配件 | 品牌型号 | 价格 | | :-: | :-: | :-: | | CPU | [intel 酷睿i5](https://detail.tmall.com/item.htm?spm=a220m.1000858.1000725.6.33ad3272WeAQN6&id=627337403965&skuId=4503637853935&areaId=320100&user_id=1713504106&cat_id=2&is_b=1&rn=406fc3c9778ec7c32321c1daf27ce294)| ¥1200 | | 散热器 | [ID COOLING IS 30 40 50 60 X静音intel AMD 4 ITX超薄CPU散热](https://detail.tmall.com/item.htm?spm=a230r.1.14.186.567e3c67Ud9Q0N&id=587268337278&ns=1&abbucket=1&skuId=4213804512927) | ¥100 | | 主板 | 华硕 STRIX Z490-I GAMING | ¥2099 | | 内存 | ~~XXXXXXXX~~ | ~~¥560~~ | | 显卡 | [AMD磐镭RX5500XT 8G显卡](https://https://detail.tmall.com/item.htm?spm=a230r.1.14.43.56ca784cY4kmdN&id=627739941873&ns=1&abbucket=1 )| 1600 | | 存储 | ~~三星970 EVO 500G nvme M.2(还是网上搜一个靠谱的NVME)~~ | ~~¥1300~~ | | 机箱 | [机械大师 C24 小方糖](https://detail.tmall.com/item.htm?spm=a220o.1000855.1998025129.1.630d276b48ILks&pvid=dcb752e1-6ca8-4971-b596-15ebeda1909d&pos=1&acm=03054.1003.1.2768562&id=603846504023&scm=1007.16862.95220.23864_0_0&utparam=%7B%22x_hestia_source%22:%2223864%22,%22x_object_type%22:%22item%22,%22x_hestia_subsource%22:%22default%22,%22x_mt%22:0,%22x_src%22:%2223864%22,%22x_pos%22:1,%22wh_pid%22:-1,%22x_pvid%22:%22dcb752e1-6ca8-4971-b596-15ebeda1909d%22,%22scm%22:%221007.12144.95220.23864_0_0%22,%22x_object_id%22:603846504023%7D&skuId=4306915772929)| ¥600| | 电源 | [全汗/海盗船SF600 SFX全模组电源](https://detail.tmall.com/item.htm?spm=a220o.1000855.0.da321h.72424cafAiRkqf&id=574968270386&skuId=4545047721728) | ¥650 | | 键鼠装 | 自选 | --- | | 显示器 | 自选 | --- | | 报价: | --- | 6200 元 | # 可选 https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-21045481589.20.75082e5dpSSOkM&id=606165680512 ## 散热器 https://item.taobao.com/item.htm?spm=2013.1.20141001.2.205712a2YToiWr&id=588415983133&scm=1007.12144.95220.42296_0_0&pvid=227f1c2a-84e3-4e56-9ffb-82cb17526a32&utparam=%7B%22x_hestia_source%22%3A%2242296%22%2C%22x_object_type%22%3A%22item%22%2C%22x_hestia_subsource%22%3A%22default%22%2C%22x_mt%22%3A0%2C%22x_src%22%3A%2242296%22%2C%22x_pos%22%3A2%2C%22wh_pid%22%3A-1%2C%22x_pvid%22%3A%22227f1c2a-84e3-4e56-9ffb-82cb17526a32%22%2C%22scm%22%3A%221007.12144.95220.42296_0_0%22%2C%22x_object_id%22%3A588415983133%7D https://detail.tmall.com/item.htm?spm=a230r.1.14.186.567e3c67Ud9Q0N&id=587268337278&ns=1&abbucket=1&skuId=4213804512927 https://detail.tmall.com/item.htm?spm=a230r.1.14.16.45e745a1DUwUQg&id=624326547367&ns=1&abbucket=1 https://item.taobao.com/item.htm?spm=a230r.1.14.324.567e3c67Ud9Q0N&id=614015721882&ns=1&abbucket=1#detail ## CPU i5 10600k 6/12 i7 10700 6/12 https://detail.tmall.com/item.htm?spm=a220m.1000858.1000725.6.33ad3272WeAQN6&id=627337403965&skuId=4503637853935&areaId=320100&user_id=1713504106&cat_id=2&is_b=1&rn=406fc3c9778ec7c32321c1daf27ce294 ## 主板 itx 主板 ## 内存 海盗船复仇者32G 3000 DDR4 RGB 双通道 ## 电源 https://item.taobao.com/item.htm?spm=2013.1.0.0.57a1469bIX21be&id=621610040503&scm=1007.12144.95220.42296_0_0&pvid=4dddd44c-d6bd-4c89-8376-56864e1b011d&utparam=%7B%22x_hestia_source%22%3A%2242296%22%2C%22x_object_type%22%3A%22item%22%2C%22x_hestia_subsource%22%3A%22default%22%2C%22x_mt%22%3A0%2C%22x_src%22%3A%2242296%22%2C%22x_pos%22%3A1%2C%22wh_pid%22%3A-1%2C%22x_pvid%22%3A%224dddd44c-d6bd-4c89-8376-56864e1b011d%22%2C%22scm%22%3A%221007.12144.95220.42296_0_0%22%2C%22x_object_id%22%3A621610040503%7D 1u? 550w? ## 硬盘 西数(western Digital) SN550 1T m.2 NVME 蓝盘 ## 显卡 [小卡](https://item.jd.com/100012690094.html#) 撼迅 PowerColor RX5500XT 8G Radeon RX5500XT 8G https://detail.tmall.com/item.htm?spm=a230r.1.14.167.56ca784cY4kmdN&id=610293407109&ns=1&abbucket=1&skuId=4288794541921 ## 机箱 [机械大师 C24 小方糖](https://item.taobao.com/item.htm?spm=a230r.1.14.19.2fc8377bo8h1Xv&id=623925268182&ns=1&abbucket=1#detail) [装机步骤](https://item.taobao.com/item.htm?spm=a1z0d.6639537.1997196601.65.67277484PD4z6l&id=632397908422) # 参考 [NFC 迷你机箱S4 MINI 强烈推荐](https://sff.design/368.html) > https://item.taobao.com/item.htm?spm=a230r.1.14.38.2fc8377bo8h1Xv&id=613883205262&ns=1&abbucket=1#detail > [全汉MS600 + 定制模组线](https://item.taobao.com/item.htm?spm=a230r.1.14.19.2fc8377bo8h1Xv&id=623925268182&ns=1&abbucket=1#detail) > https://item.taobao.com/item.htm?spm=a230r.1.14.38.2fc8377bo8h1Xv&id=613883205262&ns=1&abbucket=1#detail [ITX机箱装机萌新需要了解的入门知识](https://www.dgtle.com/thread-1507069-1-1.html) # 参考 [小明和他的女朋友](https://space.bilibili.com/591453294/) [linjimmy](https://space.bilibili.com/94213468/) [大海测评](https://space.bilibili.com/66068315/)
';

hotpatch

最后更新于:2022-04-02 05:46:25

[TOC] # 授人以渔 要参照对比学习! # 提取 DSDT 1. 在Mac 下,用MaciASL就可以直接获取DSDT信息(New from ACPI)。 2. 启动到 Clover 界面,按键盘 F4(部分笔记本可能是`F4+Fn`)会自动提取 DSDT 文件到 U 盘`EFI/ClOVER/ACPI/origin` 文件夹下 # FN 小太阳 用 MaciASL 打开 `DSDT.aml`,然后搜索 0x86 和 0x87 (不要问为什么是这两个值,不多谈,经验所得,知道这两个值是跟亮度调节有关的! 本机 是在 `_Q11` 和 `_Q12` 两个方法中! # 原生电源管理 1. MaciASL.app 打开 DSDT.aml 2. 然后搜索你 CPU 的名字。一般情况下,CPU 的名字可能是:`PR.CPU0`,`PR.P000`,`PR.PR00`,`SB.CPU0`,`SB.P000`,`SB.PR00`, `SCK0.C000`, `SCK0.CPU0`。请依次搜索直到找到自己的CPU名字,比如我的 PC 就是`PR.CPU0` 3. 仓库地址在这里:https://github.com/daliansky/OC-little ,找到“电源 -> 注入X86文件夹”,寻找包含有自己 CPU 名字的 dsl 文件。 4. 另存为,文件名字随便写吧,就叫`PLUG-XCPM.aml`,记住后缀为`.aml`。 5. 将 `PLUG-XCPM.aml`放入 OC 引导文件夹`EFI/OC/ACPI`下,并在 config.plist 中添加加载此`.aml`文件。 6. 重启系统(不行的话,可以尝试清理一次 nvram),我们看到“偏好设置–节能中,原生电源管理已经被加载了。 7. 一般有4项节能出现,而第五项“断电后重启”这项还需要加载 PPMC 以及 LPCB 下的 PMCR 才能出现。虽然说这项功能没啥鸟用,使用通用的`SSDT-PM.aml`载入即可。 提醒一下,并非所有的机型都可以开启“节能四项”或“节能五项”,如 Mac mini 仅提供三项,具体情况可以参考苹果官方帮助文档:https://support.apple.com/zh-cn/HT202824 。 > [手把手教你 黑苹果加载原生电源管理,开启节能五项!](https://macx.top/8842.html) ## 加载 AppleLPC 驱动原生电源管理 结合以下两个 方法,使用 Hackintool 工具 “> PCIe -> Device Name” 下 查找 LPC 关键字,来修改 VirtualSMC.kext 中的`info.plist`文件,注意字母小写! > [黑苹果最简单加载applelpc的方法利用 fakesmc](https://www.bilibili.com/video/av51049909/) # 电量显示(笔记本) 先搜索电池相关设备所在位置:是 `EC` 还是 `H_EC` 还是 `EC0`;本机 `EC` 位置: ``` Scope (_SB.PCI0.LPCB) { Device (EC) { Name (_HID, EisaId ("PNP0C09")) // _HID: Hardware ID ``` 可以看出 EC 的 ACPI 路径为 `_SB.PCI0.LPCB.EC`,我们需要寻找位于该范围下 `OperationRegion` 和 `Field` ## 筛选 过 8位 ``` OperationRegion (RAM, SystemMemory, 0xFF700100, 0x0100) Field (RAM, ByteAcc, Lock, Preserve) { ... } ... OperationRegion (EC81, EmbeddedControl, Zero, 0xFF) Field (EC81, ByteAcc, Lock, Preserve) { ... } ``` 清理找出 存在被调用的情况)整理出: 16 位: OEM3 拆分: OEM3:OE0M OE1M 32 位: BDC0 BFC0 BDV0 BST0 BPR0 BRC0 BPV0 BCW0 BCL0 拆分: BD0C BF0C BD0V BS0T BP0R BR0C ... 需要修改的 Method: ``` _SB.PCI0.LPCB.EC._Q35 _SB.PCI0.LPCB.EC._Q37 _SB.WMI.GCMD _SB.BAT0.UPBI _SB.BAT0.UPBS ``` ## 需要 16 位和32 位拆分函数 添加 16 位拆分读取 `B1B2` 函数 添加 32 位拆分读取 `B1B4` 函数 写入注意!: ``` Store (RECB (0x64, 0x0100), FB4) WECB (0x64, 0x0100, FB4) ``` ## 计算 offset 要点:8 bit 进 1 ``` OperationRegion (XRAM, SystemMemory, 0xFF700100, 0x0100) // 保持原来的起始偏移量,其他位置可能要加上原起始偏移量 Field (XRAM, ByteAcc, Lock, Preserve) { Offset (0x16), // 根据原 DSDT.dsl 位置的 BDC0 前一个值的位置(保持 8进1 ,十六进制) BD0C, 8, BD1C, 8, BD2C, 8, BD3C, 8, BF0C, 8, ``` ## EC 域外的引用修改 代码段: `If (LNot (^^LPCB.EC0.BATP (Zero)))` `^^LPCB.EC0.BATP` 这个方法写法中存在 `^^` 这两个字符,意思上级的上级域里面的,类似于相对路径,`LPCB.EC.BATP` 方法,完整路径就是 `\\\_SB.PCI0.LPCB.EC0.BATP`, 因为这个方法不在我们的 SSDT 里面,故此我们需要外部引入他。在 `External` 的部分加入 `External (\\\_SB.PCI0.LPCB.EC0.BATP, MethodObj)` 但是上面的 `^^LPCB.EC0.BATP` 这样的调用方法猜测应该是同一 SSDT 或是在 DSDT 中存在才能这样写,如果是外部引入后,我们需要将其改成绝对路径. 将 `^^LPCB.EC0.BATP` 替换成 `\\\_SB.PCI0.LPCB.EC0.BATP`. ``` * 140, 6084, Object does not exist (NBIX) ``` 或者: ``` B1B2 (^^PCI0.LPCB.EC.OE0M, ^^PCI0.LPCB.EC.OE1M) 改为 If ((B1B2 (^^PCI0.LPCB.EC0.ADC0, ^^PCI0.LPCB.EC0.ADC1) < 0x0C80)) ``` ## 注意 改名函数参数个数! 注意返回值!不是所有函数都定义了返回值! ``` ... Else { IVBI () // 没有返回 } } Else { Return (\_SB.PCI0.LPCB.EC0.XTST(Arg0, Arg1)) // 这里其实不需要 Return ,并且加了参数 } ``` ## 改名! 最后好需要 配合在 `OC/ACPI/patch` 中改名! ## 结果: ```swift // battery // In config ACPI, _Q35 renamed XQ35 // Find: 5F513335 00 // Replace: 58513335 00 // // In config ACPI, _Q37 renamed XQ37 // Find: 5F513337 00 // Replace: 58513337 00 // // In config ACPI, GCMD renamed XCMD // Find: 47434D44 0B // Replace: 58434D44 0B // // In config ACPI, UPBI renamed XPBI // Find: 55504249 00 // Replace: 58504249 00 // // In config ACPI, UPBS renamed XPBS // Find: 55504253 00 // Replace: 58504253 00 // DefinitionBlock ("", "SSDT", 2, "ACDT", "BATT", 0x00000000) { External (_SB.PCI0.LPCB.EC, DeviceObj) External (_SB.PCI0.PEG0.PEGP, DeviceObj) External (_SB.BAT0, DeviceObj) // 0 Arguments External (_SB.WMI, DeviceObj) // 0 Arguments External (_SB.WMI.GCMD, MethodObj) // 0 Arguments External (_SB.BAT0.IVBI, MethodObj) // 0 Arguments External (_SB.BAT0.IVBS, MethodObj) // 0 Arguments External (_SB.BAT0.PBST, PkgObj) External (_SB.BAT0.PBIF, PkgObj) External (GNVS, FieldUnitObj) External (NVBB, FieldUnitObj) External (BSCP, FieldUnitObj) External (PSF2, FieldUnitObj) External (BAEE, FieldUnitObj) External (BTCP, FieldUnitObj) External (PSF0, FieldUnitObj) External (P80H, FieldUnitObj) External (PSF1, FieldUnitObj) External (PSST, FieldUnitObj) External (VGAS, FieldUnitObj) External (_SB.PCI0.LPCB.EC.FCMD, FieldUnitObj) External (_SB.PCI0.LPCB.EC.FDAT, FieldUnitObj) External (_SB.PCI0.LPCB.EC.BBST, FieldUnitObj) External (_SB.PCI0.LPCB.EC.BAT0, FieldUnitObj) External (_SB.PCI0.LPCB.EC.FBUF, FieldUnitObj) External (_SB.PCI0.LPCB.EC.FBF1, FieldUnitObj) External (_SB.PCI0.LPCB.EC.FBF2, FieldUnitObj) External (_SB.PCI0.LPCB.EC.B15C, IntObj) External (_SB.PCI0.LPCB.EC.SLFG, IntObj) External (_SB.PCI0.LPCB.EC.ECOK, IntObj) External (_SB.AC.ACFG, IntObj) External (_SB.WMI.INDX, IntObj) External (_SB.WMI.EVNT, IntObj) External (_SB.WMI.HKDR, IntObj) External (_SB.BAT0.BFCC, IntObj) External (_TZ.TZ0.PPFG, IntObj) External (_SB.AC.ADJP, MethodObj) External (_SB.PCI0.GFX0.PDDS, MethodObj) External (_SB.WMI.XCMD, MethodObj) // 3 Arguments External (_SB.PCI0.LPCB.EC.XQ35, MethodObj) // 0 Arguments External (_SB.PCI0.LPCB.EC.XQ37, MethodObj) // 0 Arguments External (_SB.BAT0.XPBI, MethodObj) // 0 Arguments External (_SB.BAT0.XPBS, MethodObj) // 0 Arguments // 16 bits chaifeng Method (B1B2, 2, NotSerialized) { Return ((Arg0 | (Arg1 << 0x08))) } // 32 bits chaifeng Method (B1B4, 4, NotSerialized) { Local0 = (Arg2 | (Arg3 << 0x08)) Local0 = (Arg1 | (Local0 << 0x08)) Local0 = (Arg0 | (Local0 << 0x08)) Return (Local0) } Scope (_SB.BAT0) { Method (UPBI, 0, NotSerialized) { If (_OSI ("Darwin")) { If (\_SB.PCI0.LPCB.EC.BAT0) { And (B1B4 (^^PCI0.LPCB.EC.BD0C, ^^PCI0.LPCB.EC.BD1C, ^^PCI0.LPCB.EC.BD2C, ^^PCI0.LPCB.EC.BD3C), 0xFFFF, Local0) Store (Local0, Index (PBIF, One)) And (B1B4 (^^PCI0.LPCB.EC.BF0C, ^^PCI0.LPCB.EC.BF1C, ^^PCI0.LPCB.EC.BF2C, ^^PCI0.LPCB.EC.BF3C), 0xFFFF, Local0) Store (Local0, Index (PBIF, 0x02)) Store (Local0, BFCC) And (B1B4 (^^PCI0.LPCB.EC.BD0V, ^^PCI0.LPCB.EC.BD1V, ^^PCI0.LPCB.EC.BD2V, ^^PCI0.LPCB.EC.BD3V), 0xFFFF, Local0) Store (Local0, Index (PBIF, 0x04)) And (B1B4 (^^PCI0.LPCB.EC.BC0W, ^^PCI0.LPCB.EC.BC1W, ^^PCI0.LPCB.EC.BC2W, ^^PCI0.LPCB.EC.BC3W), 0xFFFF, Local0) Store (Local0, Index (PBIF, 0x05)) And (B1B4 (^^PCI0.LPCB.EC.BC0L, ^^PCI0.LPCB.EC.BC1L, ^^PCI0.LPCB.EC.BC2L, ^^PCI0.LPCB.EC.BC3L), 0xFFFF, Local0) Store (Local0, Index (PBIF, 0x06)) Store ("BAT", Index (PBIF, 0x09)) Store ("0001", Index (PBIF, 0x0A)) Store ("LION", Index (PBIF, 0x0B)) Store ("Notebook", Index (PBIF, 0x0C)) } Else { IVBI () } } Else { \_SB.BAT0.XPBI () } } Method (UPBS, 0, NotSerialized) { If (_OSI ("Darwin")) { If (\_SB.PCI0.LPCB.EC.BAT0) { Store (Zero, Local0) Store (Zero, Local1) If (^^AC.ACFG) { If (LEqual (And (B1B4 (^^PCI0.LPCB.EC.BS0T, ^^PCI0.LPCB.EC.BS1T, ^^PCI0.LPCB.EC.BS2T, ^^PCI0.LPCB.EC.BS3T), 0x02), 0x02)) { Or (Local0, 0x02, Local0) And (B1B4 (^^PCI0.LPCB.EC.BP0R, ^^PCI0.LPCB.EC.BP1R, ^^PCI0.LPCB.EC.BP2R, ^^PCI0.LPCB.EC.BP3R), 0xFFFF, Local1) } } Else { Or (Local0, One, Local0) And (B1B4 (^^PCI0.LPCB.EC.BP0R, ^^PCI0.LPCB.EC.BP1R, ^^PCI0.LPCB.EC.BP2R, ^^PCI0.LPCB.EC.BP3R), 0xFFFF, Local1) } And (Local1, 0x8000, Local7) If (LEqual (Local7, 0x8000)) { XOr (Local1, 0xFFFF, Local1) } And (B1B4 (^^PCI0.LPCB.EC.BR0C, ^^PCI0.LPCB.EC.BR1C, ^^PCI0.LPCB.EC.BR2C, ^^PCI0.LPCB.EC.BR3C), 0xFFFF, Local2) And (B1B4 (^^PCI0.LPCB.EC.BP0V, ^^PCI0.LPCB.EC.BP1V, ^^PCI0.LPCB.EC.BP2V, ^^PCI0.LPCB.EC.BP3V), 0xFFFF, Local3) Store (Local0, Index (PBST, Zero)) Store (Local1, Index (PBST, One)) Store (Local2, Index (PBST, 0x02)) Store (Local3, Index (PBST, 0x03)) If (LNotEqual (BFCC, B1B4 (^^PCI0.LPCB.EC.BF0C, ^^PCI0.LPCB.EC.BF1C, ^^PCI0.LPCB.EC.BF2C, ^^PCI0.LPCB.EC.BF3C))) { Notify (BAT0, 0x81) } } Else { IVBS () } } Else { \_SB.BAT0.XPBS () } } } Scope (_SB.WMI) { Method (GCMD, 3, Serialized) { If (_OSI ("Darwin")) { Name (ARGS, Zero) If (SizeOf (Arg2)) { Store (Arg2, ARGS) } Store (Zero, Local0) If (LEqual (ToInteger (Arg1), One)) { If (\_SB.WMI.HKDR) { Store (\_SB.WMI.EVNT, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x05)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0xA1, ^^PCI0.LPCB.EC.FDAT) Store (0xB8, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) If (And (B1B2 (^^PCI0.LPCB.EC.OE0M, ^^PCI0.LPCB.EC.OE1M), 0x08)) { If (And (Local1, 0x02)) { Store (One, Local0) } Else { Store (Zero, Local0) } } Else { Store (0x02, Local0) } Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x06)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0xA1, ^^PCI0.LPCB.EC.FDAT) Store (0xB8, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) If (And (B1B2 (^^PCI0.LPCB.EC.OE0M, ^^PCI0.LPCB.EC.OE1M), 0x04)) { If (And (Local1, One)) { Store (One, Local0) } Else { Store (Zero, Local0) } } Else { Store (0x02, Local0) } Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x07)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0xA1, ^^PCI0.LPCB.EC.FDAT) Store (0xB8, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) If (And (B1B2 (^^PCI0.LPCB.EC.OE0M, ^^PCI0.LPCB.EC.OE1M), 0x10)) { If (And (Local1, 0x04)) { Store (One, Local0) } Else { Store (Zero, Local0) } } Else { Store (0x02, Local0) } Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x09)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0xA1, ^^PCI0.LPCB.EC.FDAT) Store (0xB8, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) If (And (Local1, 0x10)) { Store (One, Local0) } Else { Store (Zero, Local0) } Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x0A)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0xA1, ^^PCI0.LPCB.EC.FDAT) Store (0xB8, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) If (And (B1B2 (^^PCI0.LPCB.EC.OE0M, ^^PCI0.LPCB.EC.OE1M), 0x20)) { If (And (Local1, 0x08)) { Store (One, Local0) } Else { Store (Zero, Local0) } } Else { Store (0x02, Local0) } Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x10)) { If (^^PCI0.LPCB.EC.SLFG) { Or (Local0, One, Local0) } If (\_TZ.TZ0.PPFG) { Or (Local0, 0x02, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x11)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0xA1, ^^PCI0.LPCB.EC.FDAT) Store (0xB8, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) If (And (Local1, 0x40)) { Store (One, Local0) } Else { Store (Zero, Local0) } Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x12)) { If (^^PCI0.LPCB.EC.ECOK) { If (And (B1B2 (^^PCI0.LPCB.EC.OE0M, ^^PCI0.LPCB.EC.OE1M), 0x0800)) { Store (One, Local0) } Else { Store (Zero, Local0) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x32)) { If (^^PCI0.LPCB.EC.ECOK) { Store (B1B4 (^^PCI0.LPCB.EC.BD0C, ^^PCI0.LPCB.EC.BD1C, ^^PCI0.LPCB.EC.BD2C, ^^PCI0.LPCB.EC.BD3C), Local0) } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x33)) { If (^^PCI0.LPCB.EC.ECOK){} Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x34)) { If (^^PCI0.LPCB.EC.ECOK){} Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x38)) { Store (One, Local0) Return (Local0) } If (LEqual (ToInteger (Arg1), 0x39)) { Return (Zero) } If (LEqual (ToInteger (Arg1), 0x3B)) { Noop Return (Local0) } If (LEqual (ToInteger (Arg1), 0x3C)) { If (LEqual (And (PSF0, 0x10), Zero)) { If (^^PCI0.GFX0.PDDS (0x0300)) { Store (One, Local0) } Else { Store (Zero, Local0) } } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x3D)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0x61, P80H) Store (One, ^^PCI0.LPCB.EC.FDAT) Store (0xCA, ^^PCI0.LPCB.EC.FCMD) Store (^^PCI0.LPCB.EC.FBUF, Local0) } Else { Store (Zero, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x3F)) { Store (Zero, Local0) Return (Local0) } If (LEqual (ToInteger (Arg1), 0x43)) { If (^^PCI0.LPCB.EC.ECOK){} Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x44)) { Store (0x03, ^^PCI0.LPCB.EC.FDAT) Store (0xCD, ^^PCI0.LPCB.EC.FCMD) Store (^^PCI0.LPCB.EC.FBUF, Local0) Return (Local0) } If (LEqual (ToInteger (Arg1), 0x45)) { Return (Local0) } If (LEqual (ToInteger (Arg1), 0x51)) { Noop Return (Local0) } If (LEqual (ToInteger (Arg1), 0x52)) { Or (Local0, 0x40000000, PSF1) Or (PSF1, 0x00200000, PSF1) Return (PSF1) } If (LEqual (ToInteger (Arg1), 0x54)) { Return (VGAS) } If (LEqual (ToInteger (Arg1), 0x62)) { Return (Zero) } If (LEqual (ToInteger (Arg1), 0x63)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0x02, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) Store (^^PCI0.LPCB.EC.FDAT, Local1) Store (^^PCI0.LPCB.EC.FBF2, Local2) Store (0x03, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) Store (^^PCI0.LPCB.EC.FDAT, Local1) Store (^^PCI0.LPCB.EC.FBF2, Local0) Or (ShiftLeft (Local0, 0x08), Local2, Local0) Or (ShiftLeft (Local0, 0x08), Local1, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x64)) { If (^^PCI0.LPCB.EC.ECOK) { Store (Zero, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local0) Store (^^PCI0.LPCB.EC.FBUF, Local2) Store (^^PCI0.LPCB.EC.FBF1, Local3) Or (ShiftLeft (Local0, 0x08), Local2, Local0) Or (ShiftLeft (Local0, 0x08), Local3, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x6E)) { If (^^PCI0.LPCB.EC.ECOK) { Store (One, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local0) Store (^^PCI0.LPCB.EC.FBUF, Local2) Store (^^PCI0.LPCB.EC.FBF1, Local3) Or (ShiftLeft (Local0, 0x08), Local2, Local0) Or (ShiftLeft (Local0, 0x08), Local3, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x6F)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0x02, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) Store (^^PCI0.LPCB.EC.FBF2, Local0) Or (ShiftLeft (Local0, 0x08), Local0, Local0) Or (ShiftLeft (Local0, 0x08), Local1, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x70)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0x03, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FBUF, Local1) Store (^^PCI0.LPCB.EC.FBF1, Local0) Or (ShiftLeft (Local1, 0x08), Local0, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } Store (0x04, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local2) Store (^^PCI0.LPCB.EC.FBUF, Local1) Or (ShiftLeft (Local2, 0x08), Local1, Local1) Or (ShiftLeft (Local1, 0x10), Local0, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x71)) { If (^^PCI0.LPCB.EC.ECOK) { Store (0x05, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FDAT, Local1) Store (^^PCI0.LPCB.EC.FBUF, Local0) Or (ShiftLeft (Local1, 0x08), Local0, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } Store (0x02, ^^PCI0.LPCB.EC.FDAT) Store (0xC0, ^^PCI0.LPCB.EC.FCMD) If (One) { Store (^^PCI0.LPCB.EC.FBUF, Local2) Store (^^PCI0.LPCB.EC.FBF1, Local1) Or (ShiftLeft (Local2, 0x08), Local1, Local1) Or (ShiftLeft (Local1, 0x10), Local0, Local0) Store (Zero, ^^PCI0.LPCB.EC.FCMD) } } Else { Store (Ones, Local0) } Return (Local0) } If (LEqual (ToInteger (Arg1), 0x73)) { And (INDX, 0xFFFF, Local1) And (ShiftRight (INDX, 0x10), 0xFFFF, Local2) If (LGreater (Local2, 0x02)) { Store (Zero, Local2) } If (LGreater (Local1, 0xFF)) { Return (Zero) } ShiftLeft (One, Local2, Local2) Store (Local2, Local3) Decrement (Local3) If (LGreater (Add (Local1, Local3), 0xFF)) { Return (Zero) } Add (Local1, 0xFF700100, Local0) Name (RBUF, Buffer (0x04) { 0x00, 0x00, 0x00, 0x00 }) If (^^PCI0.LPCB.EC.ECOK) { OperationRegion (RH2M, SystemMemory, Local0, Local2) Switch (ToInteger (Local2)) { Case (One) { Field (RH2M, ByteAcc, Lock, Preserve) { RHMB, 8 } Store (RHMB, RBUF) } Case (0x02) { Field (RH2M, ByteAcc, Lock, Preserve) { RHMW, 16 } Store (RHMW, RBUF) } Case (0x04) { Field (RH2M, ByteAcc, Lock, Preserve) { RHMD, 32 } Store (RHMD, RBUF) } } } Return (RBUF) } If (LEqual (ToInteger (Arg1), 0x77)) { Store (ShiftRight (BAEE, One), Local0) Or (Local0, ShiftLeft (BSCP, 0x08), Local0) Or (Local0, ShiftLeft (BTCP, 0x10), Local0) Return (Local0) } If (LEqual (ToInteger (Arg1), 0x7A)) { Store (And (PSF2, 0xFFFFFFFFFFFFFBFF), Local0) If (PSST) { Or (Local0, 0x0400, Local0) } If (PSST) { Or (Local0, 0x0400, Local0) } Or (Local0, 0x02, Local0) Or (Local0, 0x04, Local0) Or (Local0, 0x10, Local0) Or (Local0, 0x40, Local0) Or (Local0, 0x4000, Local0) Or (Local0, 0x00020000, Local0) Or (Local0, 0x00080000, Local0) Or (Local0, 0x00100000, Local0) Return (Local0) } Return (Ones) } Else { Return (\_SB.WMI.XCMD (Arg0, Arg1, Arg2)) } } } Scope (\_SB.PCI0.LPCB.EC) { OperationRegion (XRAM, SystemMemory, 0xFF700100, 0x0100) // 保持原来的起始偏移量 Field (XRAM, ByteAcc, Lock, Preserve) { Offset (0x16), // 根据原 DSDT.dsl 位置的 BDC0 前一个值的位置(保持 8进1 ,十六进制) BD0C, 8, BD1C, 8, BD2C, 8, BD3C, 8, BF0C, 8, BF1C, 8, BF2C, 8, BF3C, 8, Offset (0x22), BD0V, 8, BD1V, 8, BD2V, 8, BD3V, 8, BS0T, 8, BS1T, 8, BS2T, 8, BS3T, 8, BP0R, 8, BP1R, 8, BP2R, 8, BP3R, 8, BR0C, 8, BR1C, 8, BR2C, 8, BR3C, 8, BP0V, 8, BP1V, 8, BP2V, 8, BP3V, 8, Offset (0x3A), BC0W, 8, BC1W, 8, BC2W, 8, BC3W, 8, BC0L, 8, BC1L, 8, BC2L, 8, BC3L, 8, Offset (0xCA), OE0M, 8, OE1M, 8 } Method (_Q35, 0, NotSerialized) // _Qxx: EC Query { If (_OSI ("Darwin")) { Store (0x35, P80H) If (^^^^WMI.HKDR) { If (And (B1B2 (OE0M, OE1M), 0x8000)) { Store (One, SLFG) Store (0xDE, ^^^^WMI.EVNT) } Else { Store (Zero, SLFG) Store (0xDF, ^^^^WMI.EVNT) } } Notify (WMI, 0xD0) ^^^^AC.ADJP (Zero) } Else { \_SB.PCI0.LPCB.EC.XQ35 () } } Method (_Q37, 0, NotSerialized) // _Qxx: EC Query { If (_OSI ("Darwin")) { Store (0x37, P80H) Store (B1B2 (OE0M, OE1M), Local0) If (And (Local0, 0x2000)) { Store (One, B15C) } Else { Store (Zero, B15C) } If (And (NVBB, 0xFFFF)) { If (LNotEqual (And (PSF1, 0x30), 0x20)) { Store (Zero, BBST) Store (And (NVBB, 0x0F), Local1) } Else { If (And (Local0, 0x2000)) { Add (And (ShiftRight (NVBB, 0x08), 0xFF), And (NVBB, 0xFF), Local1) Decrement (Local1) } Else { Store (And (NVBB, 0x0F), Local1) } Store (Or (And (ShiftRight (NVBB, 0x04), 0xF0), Local1), BBST) } Notify (^^^PEG0.PEGP, Or (Local1, 0xD0)) } ^^^^AC.ADJP (Zero) } Else { \_SB.PCI0.LPCB.EC.XQ37 () } } } } ``` 将驱动 [ACPIBatteryManager.kext](https://github.com/fishrong/ASUS-FL5500L-EFI/tree/master/EFI/CLOVER/kexts/Other/ACPIBatteryManager.kext/Contents) 放到 clover 的 kexts 目录下,再向 **DSDT** 中打相应补丁,在 [Rehabman 电池补丁](https://github.com/RehabMan/Laptop-DSDT-Patch/tree/master/battery)找自己电脑相应型号的补丁。将生成的 **DSDT.aml** 放到 **EFI/CLOVER/patched/。** 如果重启没有效果,可尝试拔下电源适配器(笔记本)再重启。 # 屏蔽独显 我的笔记本好像直接可以在bios里面关闭独显, 但是集显还是要驱动的! ## 参考 [【Hotpatch】安装 10.13 时屏蔽独显的方法分享(EC 相关\_OFF 方法)](http://bbs.pcbeta.com/viewthread-1778010-1-1.html) # acpi 打补丁 – OpenCore 为了让黑果更加接近白果,在很多方面我们都需要打补丁,如 USB,原生电源管理,开关机,显卡等等很多方面完善都需要用到打补丁。 我们举个例子说明如何打补丁 。 比如我们想把xhc 下的 `_PRW` 进行改名为 `XPRW`。 ~~~ Comment String XHC:_PRW to XPRW Count Number //需要重点解释 Enabled Boolean True //表示应用此补丁,不应用选False Find Data 5F505257 //hex转text的含义即是:_PRW Limit Number 0 //这个按默认即可 不去管他 Mask Data <> //这个按默认即可 不去管他 OemTableId Data <> //这个按默认即可 不去管他 Replace Data 58505257 //hex转text的含义即是:XPRW ReplaceMask Data <> //这个按默认即可 不去管他 Skip Number //需要重点解释 TableLength Number 0 //这个按默认即可 不去管他 TableSignature Data 44534454 //hex转text的含义即是:DSDT,这里按默认即可,代表对dsdt进行修改 ~~~ oc 的 tgtbridge 是通过一个数过去来定位具体哪一个位置的。 比如 xhc 的 prw 是整张 dsdt 里面的第 55 个,那 skip 填 54,意味着跳过前 54 个,从第 55 个开始执行。那执行多少次呢?执行一次 count 就填 1;比如你要同时改第 55 个和 56 个,那 count 就填 2。 ``` grep -nr "GPRW" *.dsl // 查找具体位置 grep -cnr "GPRW" *.dsl // 查找具体个数 ``` 然后以 -v 重启,看看能不能正常开机。如果可以正常开机,登录以后打开终端执行以下命令,查看日志中是否包括 ACPI Error: ``` $ log show --last boot | grep -Ei "ACPI" ``` > [3.10.2 方法二:沿用 Clover 版本的 0D/06 补丁 & 展示 TgtBridge 在 OC 下的用法](https://www.jianshu.com/p/275789cc105f) # 睡眠问题 ## 解决睡眠即醒的问题。 [https://www.jianshu.com/p/275789cc105f](https://www.jianshu.com/p/275789cc105f) # 未完成 voodoops2controller 换成 其他作者的 ## 相同 DSDT 机型整理 [http://bbs.pcbeta.com/forum.php?mod=viewthread&tid=1827111](http://bbs.pcbeta.com/forum.php?mod=viewthread&tid=1827111) # 参考 [ACPI 官方指导网址](https://dortania.github.io/Getting-Started-With-ACPI/) [Getting-Started-With-ACPI](https://khronokernel.github.io/Getting-Started-With-ACPI/) [OC-little hotpatch](https://github.com/daliansky/OC-little) [【分享】我的 Hotpatch 学习笔记](http://bbs.pcbeta.com/viewthread-1733965-1-1.html) https://xstar-dev.github.io/hackintosh_advanced/Guide_For_Battery_Hotpatch.html [[Guide] Using Clover to "hotpatch" ACPI](https://www.tonymacx86.com/threads/guide-using-clover-to-hotpatch-acpi.200137/) [DSDT 基础知识收集](https://www.jianshu.com/p/8bbb1cef40e2)
';

多系统引导

最后更新于:2022-04-02 05:46:23

[TOC] # 黑苹果的四大引导 http://hiosx.cn/?p=269 首先,我公布黑苹果的四大引导是哪四大引导? 他们分别是:bootthink、变色龙(chameleon)及其分支、四叶草(clover)、ozmosis # 多系统引导 uefi引导可以使用EasyUEFI工具进行修改或者在BIOS里进行修改。 --- 本人双硬盘,对应双系统(Mac,Win)引导,只需要进行Clover设置即可,如果不玩游戏(Dota2),可能会装Manjaro Linux操作系统。 # 黑苹果 与 windows时间同步 由于Mac使用的是UTC时间,而windows是使用local时间,造成两个系统相差了8小时。 一般采用Windows下,以管理员身份,修改注册表方法解决(推荐):把下面的内容复制记事本中,另存为ChangeToUTC.reg,然后双击导入注册表。 ~~~ Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation] “RealTimeIsUniversal”=dword:00000001 ~~~ 或者 打开命令行,输入下面的命令回车即可 ~~~ Reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation /v RealTimeIsUniversal /t REG_DWORD /d 1 ~~~ 也可以搜索时间同步补丁,有**mac版的LocalTimeToggle.pkg** **如何卸载LocalTimeToggle.pkg这个补丁** 删了 `/sbin/localtime-toggle` 以及 `/System/Library/LaunchDaemons/org.osx86.localtime-toggle.plist`
';

OpenCore

最后更新于:2022-04-02 05:46:21

[TOC] # OpenCore [OpenCore 简体中文参考手册](https://oc.skk.moe/) [OpenCore健全性检查器](https://opencore.slowgeek.com/) [OpenCore 配置文件在线编辑器](https://galada.gitee.io/opencoreconfiguratoronline) [从 Clover 到 OpenCore](https://blog.skk.moe/post/from-clover-to-opencore/) ## OC auxiliary tools(OCAT) 源跨平台的OpenCore配置文件编辑器 GitHub地址:[OC auxiliary tools(OCAT)](https://github.com/ic005k/QtOpenCoreConfig/blob/master/READMe-cn.md) **If you like to use Plist editor to complete the editing of configuration files, you can give it a try:**[PlistEDPlus](https://hub.fastgit.org/ic005k/PlistEDPlus/blob/main/README-en.md) OpenCore逐渐流行起来,一直想做一款开源的跨平台的oc配置文件编辑器,目前终于达成。这样在mac之外的平台下配置oc显得格外轻松,特别是win平台。 该软件是根据oc最新的开发版提供的Sample.plist为蓝本,使用该软件前,建议将oc升级到最新版或最新的开发版。 APP将进行重新定位,因此名称更改为:OC Auxiliary Tools(简称OCAT或者ocat) OC辅助工具(简称OCAT或ocat) = Config.plist编辑器 + Config.plist数据库 等等 ## OC 定制工具 [OC Gen X](https://github.com/Pavo-IM/OC-Gen-X) 算是黑苹果最小白的OC定制工具,搭配OCC软件使用绝佳。 唯一的缺点可能是目前仅支持MacOS平台 OC Gen X 自动化生成的EFI引导文件,还缺少一些信息,还需要完善一下 * ACPI补丁 * 核显ID及缓冲帧 * 没有OC主题 ## OpenCore 原生苹果快捷键支持 在 BIOS 中开启 Optional Key Display,这样在开机时可以看到「Press Enter to interupt the start」,此时按下 `F1` 可以进 ThinkPad 自检、`F2` 进 BIOS、`F12` 进启动菜单。当这行字消失的时候就是 OpenCore 开始被引导了,这个时候就可以开始按下苹果快捷键了: * `Esc` 进入引导菜单(EFI 中已内置 OpenCore 原生` OpenCanopy` GUI 菜单支持) * `Command + V` 进入 verbose 模式 * 等等等等。 ## 注意⚠️ 1. OpenCore 配置 是注重 文件排列顺序的,比如:`Kernel / add `中的 kext 文件顺序!比如核心驱动 `Lilu.kext` 必须放在第一个(因为它需要被其他驱动引用)! # 设置默认启动项 这是在 opencore0.54 中加入的新功能,只要把 `MISC/Security/AllowSetDefault`的值设置为`true`,然后在 opencore 启动项选择界面,光标移到要设置默认启动项处,按 `crtl+enter` 或者 `ctrl+index` 即可。 # NVRAM 确认电脑是否支持原生NVRAM (本笔记本支持!) > 打开终端输入:`sudo nvram TestVar=HelloWorld`然后输入密码 > 重启系统后输入:`sudo nvram -p | grep 'TestVar'` > 如果显示:`TestVar HelloWorld` > 说明原生支持 NVRAM ## 如何清除NVRAM 修改你的OC配置文件config: > 1.找到Misc — Boot–Show Picker 并勾选; > 2.找到Misc — Boot–HideAuxiliary 确保取消勾选 保存重启,然后再OC引导界面选Reset NVRAM 按回车键即可清除NVRAM ## 相关参考资料 * [aliyoge/Hackintosh-ThinkPad-E480](https://github.com/aliyoge/Hackintosh-ThinkPad-E480) - aliyoge 维护的 ThinkPad E480 i5-8250U 机型的黑苹果 EFI 他的 EFI 电池补丁不完美(有 ACPI Error)、不支持小红点、没有修复关机变重启。 * https://oc.skk.moe - OpenCore 简体中文文档翻译,由我和黑苹果爱好者们维护(GitHub) [ThinkPad E480 黑苹果踩坑和黑苹果常用操作备忘](https://blog.skk.moe/post/thinkpad-e480-hackintosh/) - 由我之前编写的 ThinkPad E480 黑苹果指南 ## 参考 [OpenCore 引导迁移折腾记录](https://kirainmoe.com/blog/post/opencore-migration-experience/) [Converting common properties from Clover to Opencore](https://github.com/khronokernel/Opencore-Vanilla-Desktop-Guide/blob/master/clover-conversion/Clover-config.md) [OpenCore 黑苹果引导配置说明 (转)](https://www.chenweikang.top/?p=952) https://www.jianshu.com/p/da68e410612f 黑苹果引导工具 OpenCore 配置文件在线编辑器 [https://www.jianshu.com/p/ce58b950e034](https://www.jianshu.com/p/ce58b950e034) [使用 OpenCore 安装黑苹果](https://github.com/cattyhouse/oc-guide) [OpenCore 指南](https://oc.zuiyu1818.cn/) # ACPI 入门 我所知道的 ACPI (3) -- ASL 入门简介 # clover 配置文件 http://www.cnblogs.com/oaks/p/3936587.html https://blog.daliansky.net/clover-user-manual.html ## SSDT: DropOemSSDT:使用提取的ssdt。ssdt放在EFI/CLOVER/acpi/patched下。可直接用clover引导界面按F4获取;自动保存在EFI/clover/ACPI/origin文件夹.i系列的还有懒人包~反正我没用过。 GenerateCState:生成 CPU 闲置休眠状态的功能 (C-States),管理 CPU 电源状态,可以让 CPU 在闲置状态下处于不同低功耗状态 GeneratePStates:生成 CPU 功耗表现状态的功能 (P-States),管理 CPU 性能状态,可以让 CPU 在不同负载量下改变功耗。 ## 启动项 下面教一下大家如何在Clover主题中、为特定系统指定特定的图标、以及自定义显示名称、(即自定义GUI) http://bbs.pcbeta.com/viewthread-1612942-1-1.html ## 默认启动项 两种办法: * 把`Default Boot Volume`参数设置为你的启动分区的名称。 * 这个设置只能启动windows系统:设置gpt 上win8或者win7 默认启动 在 `default boot volume` 里填上 `EFI defaul loader` 上`bootmgfw.efi` ## 隐藏其他启动项 http://bbs.pcbeta.com/viewthread-1635970-1-4.html 另外如果是装了原版的话,就再Clover Configurator里面点击打开gui右上角hide volume 添加Recovery HD 就可以屏蔽掉备份这咯。反正我就基本全部屏蔽掉咯,只剩下win10+Mac两个而已。 ## Clover 引导界面调整 Clover Configurator - Gui 一项中-隐藏磁盘-输入卷标名即可。。。。 (卷名可以去看Mount EFI项中的各个分区的UUID,或者启动日志(Boot log 项)。) [10.13 全新安装启动菜单多了个 FileVault Prebooter from preboot](http://bbs.pcbeta.com/viewthread-1759964-1-1.html) 还有来自 insanelymac的一片详细文章:[Create Custom Entries to Hide Preboot and Recovery APFS Volumes with Clover Configurator](http://www.insanelymac.com/forum/topic/326527-create-custom-entries-to-hide-preboot-and-recovery-apfs-volumes-with-clover-configurator/) ## 合并Windows系统的EFI分区 这里有一点需要注意:如果之前安装过Windows系统的话,会存在EFI的目录,只是EFI的目录下面只有BOOT和Microsoft这两个目录,如果希望添加macOS的Clover引导的话,可以将USB的**EFI分区里面的EFI目录下面的CLOVER目录**复制到磁盘里的EFI目录下,也就是执行的是**合并**的操作,让EFI同时支持WINDOWS和macOS的引导.千万不要全部复制,否则有可能造成EFI无法启动Windows. ## SMBIOS是干什么用的 SMBIOS(System Management BIOS)是主板或系统制造者以标准格式显示产品管理信息所需遵循的统一规范。对于符合 SMBIOS 规范的计算机,可以通过访问 SMBIOS 的结构获得系统信息。 诸如:CPU型号、内存规格、序号、Boot ROM版本……等等。 设置合适机型有时候可以顺利启动你的黑苹果,或者实现变频、驱动显卡、解决USB接口问题,有时可以解决无法登入facetime、icloud的问题(因为有正确的系列号),等等。
';

[指南]

最后更新于:2022-04-02 05:46:18

[TOC] # 【指南】笔记本的原生电池管理 英文原文:https://www.tonymacx86.com/threads/guide-native-power-management-for-laptops.175801/ # 概述 Power Management should be one of the first things implemented when trying to install OS X on a laptop. Because of heat/noise and battery life issues, using NullCPUPowerManagement is not a realistic option on a laptop. Fortunately, with Clover, NullCPUPowerManagement is never needed. This guide will assume you started by following my Clover guide for laptops: http://www.tonymacx86.com/el-capita...de-booting-os-x-installer-laptops-clover.html # 使用 `ssdtPRGen.sh` 自定义 `SSDT.aml` Use the ssdtPRGen.sh script by Pike R. Alpha: https://github.com/Piker-Alpha/ssdtPRGen.sh Instructions for using it are provided in the README. The generated SSDT.aml should be placed on the EFI partition at /EFI/Clover/ACPI/patched/SSDT.aml. Based on the current instructions at the README, what follows is a synopsis... To prepare, you only need to do the first two commands: ``` cd ~ curl -o ./ssdtPRGen.sh https://raw.githubusercontent.com/Piker-Alpha/ssdtPRGen.sh/master/ssdtPRGen.sh chmod +x ./ssdtPRGen.sh ```
';

[指南]在双GPU笔记本电脑中禁用独立显卡.md

最后更新于:2022-04-02 05:46:16

[TOC] # 在双GPU笔记本电脑中禁用独立显卡 [在双GPU笔记本电脑中禁用独立显卡](https://www.tonymacx86.com/threads/guide-disabling-discrete-graphics-in-dual-gpu-laptops.163772/) # 总览 本指南的目的是向您展示如何在“切换式”双GPU笔记本电脑(例如Intel+Nvidia\[Optimus\] 和 Intel+Radeon)中通过 DSDT/SSDT 编辑禁用独显。 由于这些笔记本电脑只能使用Intel设备,因此分立设备通常处于活动状态并使用电源,从而导致发热量,噪声和电池消耗。 尽管通常可以在BIOS中禁用设备,但最好使用自定义ACPI设置禁用它,以便在引导Windows时仍可以使用该设备。 尽管它是一个相对简单的补丁程序(有时只有一行更改),但是由于该补丁程序是针对一个或多个SSDT进行的,因此存在很多陷阱。 同样,某些机器/ ACPI配置 需要不同的方法,从而导致更高的复杂性。 本指南使用的示例DSDT/SSDT 设置是较复杂的设置之一,因此它涵盖了您可能会遇到的大多数问题。 在修补自己的示例之前,您应该按照本演练的示例进行操作。 用于本指南/示例的笔记本电脑是带有Intel HD4400 + Nvidia 的“ Asus UX303LN”。 此文章的附件中提供了 Clover F4 提取的表( `ACPI/origin` 目录)。 注意:这里也有完整的hotpatch 修补程序指南(适用于同一台计算机):https://www.tonymacx86.com/threads/guide-using-clover-to-hotpatch-acpi.200137/ # 修补要求 目标很简单。这些机器提供了一种关闭方法,通常在SSDT中,可以调用该方法来关闭离散设备。最简单的修复方法是从相应的INI方法中取消。注意 `_OFF` 方法可能在DSDT中,也可能有不同的名称(GPOF、OPOF、PS3等)。 某些OFF实现不能从INI中调用,因为它们访问EC(嵌入式控制器)空间。对于这些机器,关闭(或部分关闭)必须延迟到REG(当Arg0==3和Arg1==1时,有关REG的更多信息,请参阅ACPI规范)。在某些情况下,从REG调用太迟了,要么没有效果,要么导致崩溃。在这种情况下,需要编辑OFF来删除EC依赖项,这样就可以从INI中调用它。然后将从 `_OFF`中删除的代码插入`_REG`中,因此尽管EC工作稍后进行,但效果相同。 本指南中的示例ACPI设置就是这种情况。
';

[指南] 怎么给DSDT打补丁来显示电池状态

最后更新于:2022-04-02 05:46:14

[TOC] # 如何给 DSDT 打补丁显示电池状态 英文原文:[[Guide] How to patch DSDT for working battery status](https://www.tonymacx86.com/threads/guide-how-to-patch-dsdt-for-working-battery-status.116102/) # 背景 由于PC中的电池硬件与 Apple SMbus 硬件不兼容,因此在笔记本电脑上运行OS X 时,我们使用 ACPI 访问电池状态。 通常,我建议您使用ACPIBatteryManager.kext,可在此处找到:https://github.com/RehabMan/OS-X-ACPI-Battery-Driver AppleACPIPlatform 的更高版本无法正确访问EC(嵌入式控制器)中的字段。 由于各种ACPI电池故障方法(`_BIF`,`_STA`,`_BST`等),这会导致ACPIBatteryManager 出现问题。 尽管可以使用较旧版本的AppleACPIPlatform(来自Snow Leopard),但还是希望使用最新版本的AppleACPIPlatform,因为对于具有Ivy Bridge CPU的计算机,它可以为这些计算机启用本机电源管理。 要使用最新版本,必须更改 DSDT 以符合 Apple的AppleACPIPlatform 的限制。 特别是,EC 中大于8位的任何字段都必须更改为一次访问8位。 这包括16、32、64和更大的字段。 您应该熟悉DSDT / SSDT修补程序的基本知识:http://www.tonymacx86.com/yosemite-laptop-support/152573-guide-patching-laptop-dsdt-ssdts.html # 现有补丁 首先,可能是笔记本电脑已经有可用的补丁程序。 在以下位置查看我的补丁程序:https://github.com/RehabMan/Laptop-DSDT-Patch 为了将您的 DSDT与补丁匹配,通常需要首先了解补丁是如何生成的,这样您就知道在 DSDT 中寻找什么,并能够将您看到的与已经可用的补丁匹配。补丁集与补丁的更改比例很高,不会产生错误,并且似乎对所有需要修补的字段都进行了修补。 此处提供更多信息:https://www.tonymacx86.com/threads/guide-how-to-patch-dsdt-for-working-battery-status.116102/page-333#post-1360697 **注意**:不要使用DSDT编辑器或MaciASL以外的任何程序。我只用 MaciASL 测试。 # 其他相关的DSDT补丁 除了多字节EC字段外,还有一些其他的 DSDT 问题会影响电池状态。这些特殊的问题并不特定于电池状态,但它们通常是在尝试实现电池状态时第一次被注意到。电池代码可能依赖于有一个可识别的Windows版本作为主机操作系统。要进行修复,请从 laptop DSDT 补丁库应用 “OS Check fix”。这将导致 DSDT 采取与运行 “Windows 2006” 时相同的操作,您可以更改补丁以影响不同的选择(例如。“Windows 另一个常见的问题是,OS X 的 ACPI 实现很难使用非零 SyncLevel 声明的 Mutex 对象(有关更多信息,请阅读ACPI规范)。要进行修复,请应用笔记本 DSDT 补丁库中的 “Fix Mutex with non-zero SyncLevel”。 # 所需技能 DSDT是一个“程序”。 因此,在进行修改时具有一些编程/计算机技能会很有帮助。 同样,DSDT 补丁本身也具有自己的语言(在 MaciASL Wiki 中进行了简要说明,可在此处找到:http://sourceforge.net/projects/maciasl/ )。 最后,补丁本身基本上是正则表达式搜索/替换的作用域,因此有助于理解正则表达式(regex)。 熟悉编译器,编译器错误以及确定编译器告诉您有关代码错误的内容的功能也很有用。 另外,熟悉 ACPI 是一个好主意。 您可以在此处下载规范:https://www.acpica.org/ 本指南的目的不是教您基本的编程技巧,正则表达式或 ACPI 语言。 # 修补过程 我使用了一种相当 “机械” 的过程来修补 DSDT 的电池状态。 我只是寻找OS X觉得讨厌的部分并机械地转换它。我不太努力去确定代码的哪些部分将实际执行,我只是转换我看到的一切。 要继续学习,请从本文下载示例DSDT并继续学习。这个特殊的例子DSDT是 HP Envy 14 的。最终的,完整的补丁,可以从我的补丁库 HP Envy 14 中获得。 首先确定 DSDT 中可能需要更改的区域。将 DSDT加载到 MaciASL 中并搜索“EmbeddedControl”。在单个DSDT中可以有多个“EmbeddedControl”部分,每个部分都附加了字段声明。 因此,为了找到这个声明,我总是从寻找embeddedcontrol开始。在示例DSDT中,您将找到这个单独的EC区域
';

[指南] Intel IGPU HDMI/DP audio (Sandy/Ivy/Haswell/Broadwell/Skylake)

最后更新于:2022-04-02 05:46:12

[TOC] # 【指南】Intel IGPU HDMI/DP audio (Sandy/Ivy/Haswell/Broadwell/Skylake) 英文原文:https://www.tonymacx86.com/threads/guide-intel-igpu-hdmi-dp-audio-sandy-ivy-haswell-broadwell-skylake.189495/
';

[指南] 为USBInjectAll.kext创建一个自定义的SSDT

最后更新于:2022-04-02 05:46:09

[TOC] *** # 【指南】 为`USBInjectAll.kext`创建一个自定义的SSDT 英文原文:[[Guide] Creating a Custom SSDT for USBInjectAll.kext](https://www.tonymacx86.com/threads/guide-creating-a-custom-ssdt-for-usbinjectall-kext.211311/) # 概述 (Overview) One of the serious issues most users will face with 10.11.x (and later, including 10.12.x) is the new USB stack in OS X/macOS. It has a much heavier reliance on ACPI, and as a result is much more likely to expose bugs in your ACPI implementation of _PLD, and _UPC. It is covered in detail in my guide: https://www.tonymacx86.com/threads/guide-10-11-usb-changes-and-solutions.173616/ You should be familiar with the writeup above before attempting a custom SSDT. Many tend to over-simplify the problem, and, for example, believe they can simply apply the port-limit patch and install USBInjectAll.kext and be done with it. In fact, the port limit patch is known to cause problems (it causes access outside a fixed array bounds). Somewhat alarming is the fact that Multibeast includes the port limit patch without mention of its problems. The fact: Using the port limit patch is not a long term solution. For reliable USB (assuming your ACPI implementation of _PLD and _UPC is broken... and you don't want to fix it), you must implement a custom SSDT for USBInjectAll.kext that configures your ports on XHC such that the port limit patch is not needed, and each UsbConnnector value is correct for each port. Not only does a custom SSDT allow you to avoid the port limit patch, disabling USB ports that are not used, can have some power saving properties, and can avoid bugs with sleep, restart, or shutdown. This guide will show how this is done. The process consists of the following steps: - preparation for port discovery - port discovery - creating custom SSDT for USBInjectAll.kext - testing/verification The MaciASL used by this guide is available here: https://bitbucket.org/RehabMan/os-x-maciasl-patchmatic/downloads/ Make sure you have ACPI 6.1 selected in MaciASL->Preferences->iASL. # 为发现端口做准备(Preparation for port discovery) In order to create a custom SSDT that contains the correct data for a given computer's USB arrangement, we must first discover all the ports that need to be enabled. Once we know which ports are used, we can eliminate the unused ports. In order to discover the ports, we need to be certain all ports are enabled. Requirements: - EHC1->EH01 and EHC2->EH02 rename (in config.plist), if applicable (your chipset may not have EHCI, or it may be disabled) - XHCI controller must be named XHC (for most PCs it is default) - port limit patch (in config.plist) - install USBInjectAll.kext (install to the system volume) - if you plan to use it, install FakePCIID.kext + FakePCIID_XHCIMux.kext - if you have an existing SSDT for USBInjectAll, use -uia_ignore_rmcf - XHCI injector kext, if required (200-series need XHCI-200-series-injector.kext) The EHCx renames and port limit patches are available in config_patches.plist (https://github.com/RehabMan/OS-X-USB-Inject-All/raw/master/config_patches.plist) in the USBInjectAll.kext repository. Use copy/paste from a plist editor to get them into your own config.plist. The EHCx renames look like this in Xcode: ![EHCx-renames](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/1dcce1a30d08c2f84e0475915c7ff5b3_499x303.png)
';

[指南] 10.11+ USB的变化和解决方案

最后更新于:2022-04-02 05:46:07

[TOC] ***** # 【指南】10.11+之后 USB的变化和解决方案 英文原文:[[Guide] 10.11+ USB changes and solutions](https://www.tonymacx86.com/threads/guide-10-11-usb-changes-and-solutions.173616/) # 概述 (Overview) 在10.11版本,苹果完全重写了USB驱动程序。新的驱动程序似乎在很大程度上使用了ACPI,比以前的驱动程序更大。这给ACPI(DSDT)的正确性带来了更多的压力。如果不正确,存在的端口可能不会被新的驱动程序启用 事实上,即使是苹果自己的产品也被发现是不正确的,因此苹果公司发明了一种方法来用一个端口注入器来覆盖DSDT。在事件属性被注入来定义可用端口时,这些属性将被使用而不是ACPI。 内置的端口注入器也可以干扰USB接口,因为一个给定型号的Mac的USB拓扑不太可能与你的PC相同。 要解决这些问题,可能需要采取一些步骤。 注意本指南适用于英特尔USB3。第三方USB3,如Asmedia, NEC/Renasas还是有问题的。这些控制器没有解决方案。所以请不要在这个帖子里问这个问题。 更新:对于不支持的USB3控制器(例如,不是英特尔生产的,不是睿思科技生产的 | not Intel, not Fresco Logic )你可以试试最新的[GenericUSBXHCI.kext](https://github.com/RehabMan/OS-X-Generic-USB3)。 # 工具/解决方案的概述 有一些方法(methods)/驱动(kexts)/技术 (techniques)来解决这些。 * 选择正确的BIOS选项 * 在`DSDT`中使用`EHCx->EH0x`重命名 * 通过`XHC to EHCI`上,使用`FakePCIID_XHCIMux`路由(route)`USB2`设备 * 用一个自定义的端口注入器或自定义`SSDT`为`USBInjectAll.kext`注入端口 * 使用`USBInjectAll.kext`来注入端口 * 在运行OS X时,给DSDT打补丁来模拟Windows的一个版本 `USBInjectAll.kext` 和一些其他的好东西: https://github.com/RehabMan/OS-X-USB-Inject-All 。如果您需要开源库中的各种文件,请下载这个ZIP: https://github.com/RehabMan/OS-X-USB-Inject-All/archive/master.zip 。已经构建发布的`USBInjectAll.kext`版本在README中提供链接,请仔细读。 注意:阅读`USBInjectAll`的README是一个好主意,但在阅读这篇文章之前,你可能不会读懂,这样你就能更清楚地理解这些问题。 除非您的ACPI实现是完美的,否则您应该创建一个为了`USBInjectAll.kext`的自定义SSDT。它被包括在我的相关指南里:https://www.tonymacx86.com/threads/guide-creating-a-custom-ssdt-for-usbinjectall-kext.211311/ # BIOS选项 USB控制器的配置通常依赖于BIOS设置。 对于大多数个人电脑,你应该设置 `XHCI` “auto” 或 “smart auto”。 这些设置通常会影响与XHCI控制器初始化、USB2路由、USB3端口启用 有关的DSDT中的代码。一些DSDTs非常准确,并对所选的选项(例如,BRIX)做出适当的响应,而有些则不是。 # 禁用默认的注射器(Disabling the default injectors) 第一步是确保默认的注入器没有效果。有这两类注入器: * 控制器(Controller)注入器: 这些 匹配Mac型号(SMBIOS)和ACPI中的控制器名称(EHC1/EHC2/XHC1)。 * 集线器(Hub)端口注入器: 这些 匹配Mac型号和`locationID`(基于控制器和端口的地址). 第一类端口注入器很容易通过`DSDT`补丁来禁用。对于大多数个人电脑(PCs),`XHCI`控制器(`USB3`)被命名为“XHC”,因此它不会与使用“`XHC1`”的内置注入器匹配。 `EHC1`和`EHC2`通常被mac电脑和个人电脑( PCs)用来识别这两个`EHCI`控制器(USB2)。通过将`EHC1`重命名为`EH01`和将`EHC2`重命名为`EH02`,您可以有效地禁用与您所使用的SMBIOS相匹配的内置端口注入器。 重命名可以用通过你打了补丁的DSDT中的`find/replace`来完成,或者通过 Clover 的`config.plist/ACPI/DSDT/Patches`。 例如,我的 Lenovo u430,我使用了下面的补丁来完成`EHCx->EH0x`的重命名: ``` # rename EHC1 to EH01 into device label EHC1 set_label begin EH01 end; into_all all code_regex EHC1\. replaceall_matched begin EH01. end; into_all all code_regex \.EHC1, replaceall_matched begin .EH01, end; # rename EHC2 to EH02 into device label EHC2 set_label begin EH02 end; into_all all code_regex EHC2\. replaceall_matched begin EH02. end; into_all all code_regex \.EHC2, replaceall_matched begin .EH02, end; ``` 注意:很有可能,上面的补丁可能无法捕捉到你的`DSDT`中所有的 `EHC1/EHC2` 实例,所以您可能需要手动更改一些引用。一个全局的搜索和替换也是一个合理的策略方法。 对于 技嘉 BRIX,我不需要给DSDT打补丁,所以我使用了通过`config.plist/ACPI/DSDT/Patches`中的Clover配置来补丁: 第1个: ``` Comment: change EHC1 to EH01 Find: <45484331> Replace: <45483031> ``` 第2个: ``` Comment: change EHC2 to EH02 Find: <45484332> Replace: <45483032> ``` 在Xcode中,它看起来如下: ![ehc_rename](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/78eb56e050975e00aa6b92ffc2a4184f_400x191.png) 你可以从 USBInjectAll 项目(上面有该项目的链接)提供 ` config_patches.plist`中 复制/黏贴这些补丁到你的 DSDT。使用`config.plist`实现这些补丁是最简单也是最直接的方法。 注意:您还可以看到“第0个”,这是模拟Windows的一部分。现在不用考虑,后面会讨论。 您还应该验证`XHCI`被命名为`XHC`,而不是`XHC1`。之前的OS X版本的一个常见解决方案是应用“`USB3 Multiplex`”补丁。该补丁应该在10.11中避免,因为它将`XHC`重新命名为`XHC1`,它引入了与内置端口注入器相匹配(matching against)的可能性。在 `FakePCIID.kext` 和 `FakePCIID_XHCIMux.kext` (稍后讨论)中实现USB2路由还有一种更简单的方法。 对于一个集散器(hub)来说,没有一种简单的方法可以让一个中心的内置端口注入器失效。您的SMBIOS选择 有一个内置的注入器,并且由于端口注入器,在内部集线器(hub)有设备问题,您需要创建自己的集线器端口注入器来重写(overrides)默认值。可以通过设置高`IOProbeScore`来重写默认值,这与 ProBook 4540s 的 MacBookPro9,1-EH02-hub 注射器非常相似。 注意:`USBInjectAll.kext` 也有两个用于 `EH01` 和 `EH02`(`port #1 only`)的集线器端口注入器。 # 端口注入器的一些需求 在通过重命名来禁用内置的端口注入器后,驱动程序将使用来自`ACPI`(`_UPC` 对象)的数据来确定哪些端口可用。你需要多阅读一些ACPI规范中关于`_UPC`对象的内容。 你可以看见`ioreg`中哪些端口是处于活动状态。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/96a2ef07c5d1f916874b5f2e1edfb9cf_356x216.png) 注意:这是我的端口注入器`kext`处于活动。没有它,情况就大不一样了。有许多端口会不见。 如果你需要的端口不处于活动状态,很可能你的 DSDT 是不正确的并且有一些端口实际上是连接的但是被标记“`不可连接`”(` _UPC` 0的第一个字段 | first field of `_UPC` zero) 尽管您可以修补 DSDT 来更改 `_UPC` 返回的数据,但是构建一个能够支持消失的端口(the missing ports)的注入器更容易。由于控制器对象被重命名,所以不可能与内置的端口注入器发生冲突。 在我的各种repos中有几个端口注入器的例子: https://github.com/RehabMan/Lenovo-U430-Touch-DSDT-Patch https://github.com/RehabMan/Lenovo-Y50-DSDT-Patch https://github.com/RehabMan/HP-Envy-DSDT-Patch https://github.com/RehabMan/HP-Envy-K-DSDT-Patch https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch 在当前的项目中,注入器实际上并没有被使用。这些项目还包含自定义的 `USBInjectAll` 配置(通过 `SSDT-HACK` 中的`UIAC/RMCF`)。您可以在`USBInjectAll` 的 README上阅读更多关于 `USBInjectAll` 配置的信息 `IOACPIPlane` 中的数据在确定可能需要启用的端口时是有价值的。 这是我的 u430 在 `IOACPIPlane` 的`XHC`的图像: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/7bfa5d8053096f0730f0dd13f2e452f9_255x260.png) 事实上,端口地址完全依赖于 `XHCI` 设备id。USBInjectAll使用此方法向每个端口注入适当的地址。 记住那15个端口的限制。您可能需要测试您的端口注入器的不同版本,因为潜在端口的数量可能不在15个端口限制之内。例如,您可能有`HS01-HS15`,以及`SSP1-SSP6`。这将是21个总端口(15+6)。仅供参考……目前的芯片组不可能有21个端口(8/9系列芯片组最多支持14个端口,6个端口可以配置为USB3,会一共有20个端口... 不知道为什么会有额外的端口。 要测试每个端口,您需要一个端口注入器,它覆盖了`HS01-HS09`和`SSP1-SSP6`(总共15个),第二个用于 `HS10-15` 和 `SSP1-SSP6`。或者您可以取消USB3端口,并独立地测试`SSPx`和`HSxx`。你懂的。一旦确定了活动的实际端口,就可以自定义端口注入器。 `USBInjectAll` 有一些特殊的标志,用于在组中禁用端口。因此,除了创建两个自定义的注入器,您还可以使用`USBInjectAll.kext`。内核标记 `-uia_exclude_hs` 将会排除所有`HSxx`端口被注入到`XHC`上。内核标记 `-uia_exclude_ssp` 或者`-uia_exclude_ss` 将会排除`SSPx` 或 `SSxx`。使用这些标志,您可以在不使用端口限制补丁的情况下测试所有端口。请记住,如果所有USB端口都在`XHC`上,那么使用 `-uia_exclude_hs` 可能会使你的USB鼠标/键盘无法正常工作(USB3键盘/鼠标不常见)。这在笔记本电脑上并不是问题,因为内置的PS2触控板和键盘都是可用的。为了在没有键盘和鼠标的情况下收集信息,您可以通过局域网(LAN)上另一台计算机进行远程桌面控制。 您可以使用 `USBInjectAll.kext` 为您的USB控制器注入所有端口。通过注入所有端口,您可以确定哪些端口已经被使用了。还有一个可用的补丁可以增加端口的限制。只使用短期来确定哪些端口需要进入您的端口注入器。请确保您阅读了 `USBInjectAll.kext` 的README。 **重要提示!** 端口限制补丁不应该作为一个永久的解决方案使用。现在有明确的证据表明,使用它会导致其他数据超出明显的固定大小的数组被破坏。当端口限制超过时,USB驱动程序就会产生奇怪的行为。 集线器端口注入器(Hub port injectors)只匹配 `locationID` 和 SMBIOS 。由于`locationID`来自于控制器的端口号和地址(在 Macs和 PCs上是相同的),所以不可能通过重命名来禁用匹配的内置端口注入器。相反,必须在端口注入器驱动程序(kext)中使用更高的 `IOProbeScore` 来重写 现有的端口注入器。`u430` 开源库(repo)有一个集线器(hub)端口注入器的例子,这是在使用 `FakePCIID_XHCIMux.kext` 时所需要的。ProBook 开源库有一个集线器(hub)端口注入器的例子它使用一个更高的 `IOProbeScore` 重写了一个内置的集线器端口注入器。 注意,每个控制器/集线器(controller/hub)都有15个端口限制。也就是说,在每个注入器的个性(each injector personality)中,你只能定义15个总端口。一般来说,这不是一个问题,除了`XHCI`控制器,它的限制更容易到达。参见下面的关于`FakePCIID_XHCIMux` 的讨论,因为 `FakePCIID_XHCIMux` 可以用来将一些端口移动到`EHCI`,从而消除了该问题的限制。 一个端口注入器驱动程序中 `Info.plist` 里的大多数条目是“锅炉板”。建议您使用其中一个示例,并修改以适合您自己的硬件、SMBIOS等。 关于端口注入器属性的一些说明: * port-count:这个名字不太好,因为它根本就不是“数”。相反,它是最大的端口地址(由“端口”指定) * UsbConnector:描述USB端口的连接器类型。通常的值 是 0、3、255,(0:USB2 type-A,3:USB3 type-A,255:proprietary)。更多信息在 ACPI规范中的(_UPC)。 * port:必须在DSDT中匹配端口`_ADR`。你可以在 `IOACPIPlane` 中看到这个值。 # `_OSI` 和Windows版本的检查 ACPI代码可以使用 `_OSI`方法(由ACPI主机实现)来检查它正在运行的Windows版本。大多数DSDT实现将根据运行的Windows版本而改变USB配置。 当运行OS X时,DSDT可能不会对`_OSI`(“`Windows `”) 返回 `true` 做任何检查,因为它只对“Darwin”作出响应。这就是DSDT补丁的“`OS Check Fix`”系列的原因。当运行 Darwin 时,通过修补DSDT来模拟特定版本的Windows,我们可以获得在运行特定版本的Windows时通常会发生的行为。 于10.11,正确的Windows版本模拟是系统相关(system dependent)的。一些计算机需要“Windows 8”(“Windows 2012”),一些需要“Windows 7”(“Windows 2009”)和其他一些需要“Windows Vista”(“Windows 2006”)。所以进行一些试验可能是必要的。 ACPI 补丁是在这里:http://www.tonymacx86.com/yosemite-laptop-support/152573-guide-patching-laptop-dsdt-ssdts.html 如果你不需要修补DSDT(台式机),你可以通过`config.plist/ACPI/DSDT/Patches`和一个小的 `SSDT` 完成这个修复。 例如,是关于 `BRIX` 的,我使用下面的补丁将 `_OSI` 映射到 `XOSI`: ~~~ Comment: change _OSI to XOSI Find: <5f4f5349> Replace: <584f5349> ~~~ 这是在Xcode的编辑器中的样子: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/ce47f3aa73dfe97bed791fcec517b266_400x123.png) 我已经从 `SSDT-HACK.dsl` 中提取了相关部分,是为了这个目的而使用的: (`BRIX` `SSDT-HACK.dsl` 还有一些其他的东西在里面)。 ``` DefinitionBlock ("", "SSDT", 1, "hack", "XOSI", 0) { // All _OSI calls in DSDT are routed to XOSI... // XOSI simulates "Windows 2009" (which is Windows 7) // Note: According to ACPI spec, _OSI("Windows") must also return true // Also, it should return true for all previous versions of Windows. Method(XOSI, 1) { // simulation targets // source: (google 'Microsoft Windows _OSI') // http://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/WinACPI_OSI.docx Name(WINV, Package() { "Windows", // generic Windows query "Windows 2001", // Windows XP "Windows 2001 SP2", // Windows XP SP2 //"Windows 2001.1", // Windows Server 2003 //"Windows 2001.1 SP1", // Windows Server 2003 SP1 "Windows 2006", // Windows Vista "Windows 2006 SP1", // Windows Vista SP1 //"Windows 2006.1", // Windows Server 2008 "Windows 2009", // Windows 7/Windows Server 2008 R2 //"Windows 2012", // Windows 8/Windows Server 2012 //"Windows 2013", // Windows 8.1/Windows Server 2012 R2 //"Windows 2015", // Windows 10/Windows Server TP }) Return (Ones != Match(WINV, MEQ, Arg0, MTR, 0, 0)) } } ``` `USBInjectAll.kext` 开源项目也有 `_OSI->XOSI` 补丁 并且 `SSDT-XOSI.dsl` 包含了上面显示的 `XOSI`代码 通常,`_OSI` 的调用将由OS X (ACPI主机)来处理,但是通过补丁,`_OSI` 的调用被路由到 `XOSI`,因此可以模拟一个特定版本的Windows。 上面的XOSI的版本实现了“Windows 2009”(Windows 7)的模拟,我发现它可以与 `BRIX` 很好地工作。您可以根据需要修改代码来模拟任何其他版本的Windows(可以对所列出的Windows版本进行注释或取消注释)。 完整的`BRIX`开源项目`/config.plist/SSDT-hack.dsl`,等等在这里:https://github.com/RehabMan/Gigabyte-BRIX-s-DSDT-Patch # XWAK, XSEL 和 ESEL 通常这三种方法都在DSDT中并且倾向于操作 `XHCI` 寄存器与 `XCHI` 控制器的USB2端口路由有关 创建USB2端口路由,以在没有合适的`XHCI`驱动程序的情况下为操作系统提供向后兼容性。通过将`XHCI`上的USB2端口路由到`EHCI`控制器,仅使用`USB2(EHCI)`驱动的操作系统仍然可以在使用USB3端口的计算机上工作(当然,是以USB2的速度)。 这种路由通常在`XSEL`和`ESEL`中进行控制。当检测到较旧版本的Windows时,会调用`ESEL`,当检测到新版本的Windows时,会调用`XSEL`。当一个被选中这个情况是系统依赖(system dependent)的。 `XWAK`在 `_WAK` 中被调用,然后停止休眠醒来。如果您发现您的端口在之后没有工作,那可能是因为`XWAK`对`XCHI`控制器寄存器的注册表做了一些事情,而10.11的驱动程序没有预料到这一点。因此,禁用`XWAK`是很有用的。 例如,改变: ``` Method (XWAK, ...) { ... original code ... } ``` 为: ``` Method (XWAK, ...) { Return(0) ... original code ... } ``` 这个 return 会立即退出该方法,以避免任何可能采取的行动。 # USB2 端口的路由 (多路复用) 和 `FakePCIID_XHCIMux` 在10.11之前,Mieze 首先描述了,一些计算机从使用多路复用(Multiplex)的补丁中受益。由于DSDT代码的不同,这个复杂的补丁很难适应不同的计算机。 在10.11中不应该使用多路传输(multiplex)补丁。 为了完成同样的事情,我创建了 `FakePCIID_XHCIMux.kext` (需要`FakePCIID.kext`)。这个 kext 可以强制使用XHCI上的USB2设备被路由到 `EHCI` 控制器。 这很有用,有两个原因: - 有些设备在连接到`EHCI`时可能会表现得更好 - 要解决新USB驱动程序中存在的15个端口限制 尽管15个端口限制不太可能对`EHCI`控制器(`EH01/EH02`)或一个集线器(大多数内部集线器似乎包含8个端口)产生影响,但它可能是`XHCI`控制器的一个问题。因为XHCI控制器上的每个 USB3 端口实际上都是两个端口,所以可以很容易地达到这个限制。 想象一下一个主板的 `XHCI` 上有6 个 USB3 端口。每个端口都有一个USB2组件和一个USB3组件,总共有12个端口。另外,XHCI控制器可能有几个USB2的端口(通常是内部主板的头 | internal motherboard headers )。在XHCI上有6个 USB3 端口和8个 USB2 端口是不典型的(14个实际端口总数),总共有20个... 5个端口超过了极限。 但是,使用`XHCI`控制器的特性,可以将USB2端口从 `XHCI to EHC1`。`FakePCIID_XHCIMux` 利用这个特性并强制进行路由。它可以阻止`XHCI`驱动程序(the XHCI driver)在OS X中的任何有关更改路由配置的尝试。在我们的示例中,它可以将14个 USB2 端口中的一些从`XHCI`移到`EHCI`,为 `XHCI` 的其他端口保留空间,仍然保留在15个端口限制内。BIOS通过设置 `XHCIMux` 所授予的各种`XHCI`寄存器(`PR2M`)来限制此路由。因此,移动的端口可能因`BIOS/motherboard` 而不同。 它也比 多路复用补丁(the multiplex patch)更容易部署:简单地安装`FakePCIID.kext` 和 `FakePCIID_XHCIMux.kext`。 但是被移到`EH01`的端口(通常是`EH01` 端口1 的 集线器(hub)),仍然受到先前讨论的关于端口注入器的问题的影响。如果您的DSDT没有为这些端口(或集线器端口)返回正确的 `_UPC`,那么您需要一个注入器来修复它。 FakePCIID可以从我的github上获得。还是请一如既往地,**查看这个 README**。 https://github.com/RehabMan/OS-X-Fake-PCI-ID # 摘要(Summary) 快速概览大概是这样的: * DSDT包含USB端口和内置USB集线端口的信息 * DSDT 可能是错的 * 苹果可能在几款苹果产品中发现了DSDT的错误,因此他们实现了一种重载(override)DSDT(端口注入器)的机制。 * 苹果端口注入器与控制器和SMBIOS的 ACPI 名称匹配。 * 如果端口注入器匹配,苹果端口注入器将重载你的DSDT(正确的或者是错的) 。 * 重新命名控制器以防止匹配,可以避免苹果提供的端口注入器,在这种情况下,系统会返回DSDT(这仍然可能是错误的)。 * 在端口被重命名之后,如果您的DSDT提供关于 USB 端口拓扑的不准确的细节,您可以创建一个端口注入器,就像苹果为他们自己的计算机所做的那样(您也可以修复DSDT `_UPC`,但是更容易是做一个端口注入器)。 * `USBInjectAll.kext`可用于自动为每个 控制器/集线器 注入所有可能的端口。 * 无论如何,每个控制器(或集线器)有15个端口的限制。 * 15个端口的限制可以通过一个补丁来增加。这个补丁可能是危险的,所以它不是被长期使用的。 * 当USB3和USB3组件被路由到 `XHC` 控制器时,USB3端口是2。 * USB2 端口可以通过 `XHC` 芯片上的寄存器从 `XHC` 发送到 `EHC`。 * 内置的驱动程序支持这种路由(多路复用技术| muxing),但是还没有很好地理解(在特殊的 DSDT 方法和 USB 端口注入器数据之间存在一种关系)。 * 可以将 `FakePCIID_XHCIMux.kext` 用于将 `XHC` 的USB2 组件强制到 `EHC`。 * 当在OS X USB驱动程序中出现这样的写操作时,`FakePCIID_XHCIMux.kext` 可以阻塞对USB2路由寄存器的写入。 * BIOS设置影响了 `FakePCIID_XHCIMux` 所做的事情(它为 USB2 端口路由掩码提供了BIOS设置)。 * `FakePCIID_XHCIMux.kext` 不能阻止来自 ACPI 空间的写入(显然是苹果 `AppleACPIPlatform.kext` 不会通过`IOPCIDevice` 来完成这些写入操作)。 * 因此,在与 USB2 端口路由有关的情况下,可以使用DSDT来进行破坏,尤其是休眠醒来。 * 对来自 ACPI 空间的端口路由寄存器的写入操作可以通过 ACPI 补丁来修复,有时也可以通过模拟某个版本的Windows来实现(`_OSI->XOSI` 映射)。 所以…解决方案取决于实际发生的情况: * `XHC`上的 `USB2` 端口路由的BIOS设置("auto" vs. "smart auto" vs. "enabled")。 * 重命名 `EHCx->EH0x` 避免内置端口注入器 * `FakePCIID_XHCIMux` 在 `XHC` 上实施 USB2 端口路由 * 在运行 Darwin 时,DSDT补丁用于模拟Windows(各种版本)。 * DSDT补丁以避免在`XHC` 上写入端口路由寄存器(取消了 XWAK,ESEL,XSEL)。 * 自定义端口注入器驱动程序 以匹配 真实的端口配置 * 使用 `USBInjectAll.kext` 让事情正常工作,这样实际的端口就可以确定。 # 具体建议(Specific Recommendations) (7系列以前的) 在7系列之前,没有英特尔XHCI控制器,这里只讨论了USB2问题。 显而易见,第一步需要进行 `EHCx->EH0x` 重命名。 对于5系列,在 `config.plist/ACPI/DSDT/Fixes` 中勾选 `FixUSB_1000` 。 如果你仍然有端口不能工作,安装 `USBInjectAll.kext`。 Windows版本模拟不太可能有问题,但是如果您仍然有问题,那就一定要试一试。`_OSI->XOSI` 加上 SSDT方法 是最容易成功的。 # Specific Recommendations (7-series, 8-series, 9-series, X99) 显而易见,第一步需要进行 `EHCx->EH0x` 重命名。 对于 7系列,8系列,9系列,安装 `FakePCIID_XHCIMux.kext`(如果没有`FakePCIID.kext`,那`FakePCIID_XHCIMux` 就没有效果,这只适用于所提到的Intel芯片组)。 对于许多主板来说,假设`_UPC`在`XHC`上是正确的,那么这一切都将工作正常。 但是在这一点上有两项可能会引起问题: * 由于不正确的Windows模拟,您的DSDT可能会禁用USB3。应用`XOSI`补丁来解决这个问题。 * 你的SMBIOS内置的集线器端口注入器可能会被干扰。安装 `USBInjectAll.kext` 和使用内核标志 `-uia_exclude_xhc`。这将为`EH0x`和相关的集线器启用`USBInjectAll`端口注入器,覆盖内置的集线器端口注入器,但是保持`DSDT`对`XHC`的控制。 如果有一些端口仍然不能正常工作,则删除 `-uia_exclude_xhc` 内核标志。如果您的`XHC`有超过15个端口(设备id是8086:8xxx),您将需要端口限制补丁,或者需要将您的测试划分为几个阶段(使用`-uia_exclude_hs`, `-uia_exclude_ss`,`-uia_exclude_ssp`)。 注意:对于X99系统,原生的Intel XHC驱动程序不支持 8086:8d31。您需要一个注入器驱动程序(an injector kext)来启用它。通过查看`USBInjectAll.kext`的 README 来获得详细资料 # Specific Recommendations (200-series) 在10.12.3中,对于200系列芯片组上的`XHC`控制器是没有芯片组支持。因此,我们需要一个注入器驱动程序(an injector kext)来加载100系列驱动程序。根据 USBInjectAll README,来使用 `XHCI-200-series-injector.kext`。 另外,请参阅100系列(以下)的附加信息... # 具体建议 (100系列 100-series) 在100系列中没有`EHCI`控制器,因此 7/8/9 系列的几个解决方案(和问题)不适用于100系列。 Install USBInjectAll.kext. You will need the port limit patch as well as 100-series injection will always inject more than 15 ports. 安装`USBInjectAll.kext`。您将需要端口限制补丁以及100系列的注入将始终注入超过15个端口。 在这里,自定义 USBInjectAll 使用一个带有 `UIAC/RMCF`的SSDT。参阅USBInjectAll README。有一个专家已经创建了一个关于查找特定于您的主板的 SSDT ,这是值得花时间的。 一旦您对所有端口进行了注入,测试它们,确定您可以使用哪些端口,并使用内核标记 `uia_exclude` 排除它们。内核标记 `uia_exlude` 将通过 `RMCF` 来排除 甚至是来自自定义 `USBInjectAll` 配置的端口。在排除了足够的端口之后,将总端口限制在15以下,您可以取消 端口限制补丁。 # 注意系统信息(System Information) OS X中的系统信息应用程序可以显示USB设备的信息以及它们连接到的控制器的信息(System Information -> USB)。 该系统显示连接到 `EHCI#1` 或 `ECHI#2` 的USB设备,作为“USB 2.0总线(Bus)”;任何连接到`XHCI`的设备都是“USB 3.0总线(Bus)”。 如果您在“USB 3.0总线”下看到 USB2 设备,请不要感到惊讶。如果没有 `FakePCIID_XHCIMux`,USB2设备插入XHCI处理的端口将被显示为“USB 3.0总线”。XHCI可以同时处理 USB3 和 USB2 端口。 如果你“USB 2.0总线”下看到 USB2 设备插入到了USB3 端口。使用 `FakePCIID_XHCIMux`,任何 USB3 端口的 USB2 组件都被路由到`EHCI`。 # 错误报告 如果您有问题,请详细描述问题,确保您的概要文件准确描述您的硬件,并提供FAQ中所要求的所有数据。 阅读常见问题,“错误报告” https://www.tonymacx86.com/threads/faq-read-first-laptop-frequent-questions.164990/ # 背景知识 这里有很多信息(也有很多noise): http://www.insanelymac.com/forum/topic/306777-guide-usb-fix-el-capitan-1011/ 注意:在这个场景中不推荐使用所谓的虚拟`kexts`。这里不需要它们像 `AppleHDA` 例子中需要的那样。
';

[指南] 为Sierra(以及后来的版本)进行USB电源属性注入

最后更新于:2022-04-02 05:46:05

[TOC] # 【指南】为Sierra(以及后来的版本)进行USB功率特性注入 > 英文原文:[[Guide] USB power property injection for Sierra (and later)](https://www.tonymacx86.com/threads/guide-usb-power-property-injection-for-sierra-and-later.222266/) # 综述 看来Sierra已经改变了USB功率特性(USB power properties)的设置方式。在之前的版本中,我们已经直接对`XHC/EHCI`这个ACPI对象(on the XHC/EHCI ACPI objects),注入了AAPL,current-available, AAPL,current-extra, AAPL,current-extra-in-sleep, and AAPL,max-port-current-in-sleep。在`Sierra`中,这些似乎被注入到`ioreg`中的`AppleBusPowerControllerUSB`对象的新属性所取代。 让我们看一下所需的更改... # 跟踪证据(Tracing the evidence) 其中一些变化是在USBInjectAll.kext开发期间注意到的... 我还记得一些看起来很有趣的“`kUSB*`”属性,这些属性在一个USB kext 的 `Info.plist`文件中。一个简单的grep搜索就能揭示我们查看的位置: ``` SPEEDY-NUC:nuc.git rehabman$ grep -l kUSB.* -R /System/Library/Extensions/IOUSBHostFamily.kext /System/Library/Extensions/IOUSBHostFamily.kext/Contents/Info.plist /System/Library/Extensions/IOUSBHostFamily.kext/Contents/MacOS/IOUSBHostFamily /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBEHCI.kext/Contents/MacOS/AppleUSBEHCI /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBEHCIPCI.kext/Contents/Info.plist /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBEHCIPCI.kext/Contents/MacOS/AppleUSBEHCIPCI /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHostCompositeDevice.kext/Contents/MacOS/AppleUSBHostCompositeDevice /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHostMergeProperties.kext/Contents/Info.plist /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHub.kext/Contents/Info.plist /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHub.kext/Contents/MacOS/AppleUSBHub /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBOHCIPCI.kext/Contents/MacOS/AppleUSBOHCIPCI /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBUHCI.kext/Contents/MacOS/AppleUSBUHCI /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBUHCIPCI.kext/Contents/MacOS/AppleUSBUHCIPCI /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBXHCI.kext/Contents/MacOS/AppleUSBXHCI /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBXHCIPCI.kext/Contents/Info.plist /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBXHCIPCI.kext/Contents/MacOS/AppleUSBXHCIPCI /System/Library/Extensions/IOUSBHostFamily.kext/Contents/PlugIns/IOUSBHostHIDDevice.kext/Contents/MacOS/IOUSBHostHIDDevice ``` 嗯... 看起来`/System/Library/Extensions/IOUSBHostFamily.kext/Contents/Info.plist` 是个开始的好位置: 看看我们的发现了什么: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/dd36bd0f026dbe0468bc3d2f534b13f9_727x597.png) 正如你所看到的有各种属性(`kUSBSleepPortCurrentLimit`、`kUSBSleepPowerSupply`,`kUSBWakePortCurrentLimit`,`kUSBWakePowerSupply`),通过一个`AppleUSBHostMergeProperties`注射器,使它被注入到`AppleBusPOwerControllerUSB`提供者(provider)。 但是我检查自己的`ioreg`,发现`AppleBusPowerControllerUSB`并没有在任何地方被加载。那么问题是,是什么使它加载…另一个简单的grep搜索将告诉我们: ``` SPEEDY-NUC:nuc.git rehabman$ grep -l AppleBusPowerControllerUSB -R /System/Library/Extensions /System/Library/Extensions/AppleBusPowerController.kext/Contents/Info.plist /System/Library/Extensions/AppleBusPowerController.kext/Contents/MacOS/AppleBusPowerController /System/Library/Extensions/IOUSBHostFamily.kext/Contents/Info.plist ``` 现在看看`AppleBusPowerController.kext`的`Info.plist`: ![AppleBusPowerController.kext-Info.plist](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/d6f39785de98a1b35b3e47abe98802f1_596x157.png) 我们可以看到它匹配了一个名为“`EC`”的ACPI设备。有些电脑使用`EC`作为嵌入式控制器(Embedded Controller),但大多数使用`EC0`或`H_EC`。 有了这些知识,我们可以简单地重命名`H_EC->EC`,或者 `EC0->EC`,然后`AppleBusPowerControllerUSB`被加载,而且在`IOUSBHostFamily.kext/Contents/Info.plist`中,对每个支持的`SMBIOS`的相关注入也是如此。 现在,如果你仔细看 `IOUSBHostFamily`的`Info.plist`,你会发现新的SMBIOS不见了。例如`MacBookPro9,1`, `iMac17,1`, 和 `MacBookPro13,x`.。这些型号必须使用不同的方法来进行USB功率特性的注入。 `AppleBusPowerController`的反编译显示,它正在在`IOACPIPlane`中查找一个名为“`USBX`”的对象。然后,它似乎会从设备属性中提取必要的数据。如果我们看一个`iMac17,1`的`ioreg`,我们会发现这个: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/ff2961db4b186fce68ca37bb751e2e01_683x478.png) 还有我们的能量性能(power properties ) 看看 iMac17.1 中的`DSDT.aml `,我们找到`USBX` 的源代码: ``` Scope (_SB) { ... Device (USBX) { Name (_ADR, Zero) // _ADR: Address Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method { Store (Package (0x08) { "kUSBSleepPowerSupply", 0x13EC, "kUSBSleepPortCurrentLimit", 0x0834, "kUSBWakePowerSupply", 0x13EC, "kUSBWakePortCurrentLimit", 0x0834 }, Local0) DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0)) Return (Local0) } } ``` 嗯,不要惊讶这些... 四个USB能量性能(USB power properties)的标准的`_DSM`注入。 摘要: - 如果该电脑存在`EC`,那么命名为“'EC”并且`AppleBusPowerControllerUSB`将被加载。 - 如果SMBIOS匹配`IOUSBHostFamily.kext/Contents/Info.plist` 中的其中一个“legacy SMBIOS”,该Mac型号的能量性能将被注入(它们可能适合您的硬件,也可能不适合) - 如果在`IOUSBHostFamily.kext/Contents/Info.plist`没有SMBIOS存在,那`ACPI`中的`USBX`设备会通过正常的`_DSM`属性注入 来决定能量性能。 # 保证 AppleBusPowerControllerUSB 的加载 如果你有一个嵌入式控制器(大多数笔记本电脑,一些台式机),你只需确保ACPI设备被命名为`EC`。这很容易通过`config.plist`的ACPI hotpatch来完成。我已经将两个普通的`renames`添加到所有的笔记本指南`plist`文件中。 看起来就这样: ![renames](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/f7a1d50a065a361d8a3a7dd2f9faed8b_491x375.png) 注意:如果你正在使用静态的打补丁的SSDTs(就是说,`ACPI/patched`目录有打补丁的`OEM SSDTs`),你要确保在这些文件中都手动完成`EC`重命名。Clover的`config.plist/ACPI/DSDT/Patches`只对`ACPI/patched`的`DSDT.aml` 以及从BIOS中加载的`OEM DSDT`和`SSDTs`生效,…不会对`ACPI/patched`中的`SSDTs`生效。 如果你没有嵌入式控制器,可以使用下面的`SSDT-EC.dsl`(编译为AML)添加一个“假”的: ``` // Inject Fake EC device DefinitionBlock("", "SSDT", 2, "hack", "EC", 0) { Device(_SB.EC) { Name(_HID, "EC000000") } } //EOF ``` 注意: 您可能会发现您的`DSDT`中有一个`EC`:带有“`Name (_HID, EisaId ("PNP0C09"))`”的设备,即使它不活动。 例如,这是在我的NUC6i7KYK: ``` Scope (_SB.PCI0.LPCB) { Device (H_EC) { Name (_HID, EisaId ("PNP0C09")) // _HID: Hardware ID Name (_UID, One) // _UID: Unique ID Method (_STA, 0, NotSerialized) // _STA: Status { Store (0x03, ^^^IGPU.CLID) Return (Zero) } ... ``` 正如您所看到的,它从`_STA`返回`0`。根据ACPI规范,这是“不存在”的。这意味着`H_EC`设备被有效地忽略了。你会注意到它没有显示在`ioreg`,`IOService`板面上。 不要试图通过更改`_STA`的返回值来激活EC设备。这里返回`0`的原因是**该计算机没有`EC`** 。在这种情况下,您应该添加上面提到的“假”`EC`。 # 一个SSDT注入USBX设备 对于`IOUSBHostFamily.kext/Contents/Info.plist`中尚未覆盖的`SMBIOS` ,您将需要注入`USBX`设备来提供`AppleBusPowerControllerUSB`的能量性能。 下面是一个 `SSDT-USBX.dsl`示例: ``` // USB power properties via USBX device DefinitionBlock("", "SSDT", 2, "hack", "USBX", 0) { Device(_SB.USBX) { Name(_ADR, 0) Method (_DSM, 4) { If (!Arg2) { Return (Buffer() { 0x03 } ) } Return (Package() { // these values from iMac17,1 "kUSBSleepPortCurrentLimit", 2100, "kUSBSleepPowerSupply", 5100, "kUSBWakePortCurrentLimit", 2100, "kUSBWakePowerSupply", 5100, }) } } } //EOF ``` 你可能会认为你也可以重写(override) 该例子中`IOUSBHostFamily.kext/Contents/Info.plist`提供的值。在这种情况下,将使用支持的SMBIOS。但不幸的是,事实并非如此。`IOUSBHostFamily.kext/Contents/Info.plist`中的值重写了由`USBX`提供的那些。 还有,如果你已经有了`SSDT-UIAC.aml`(你本该如此),通过简单地添加`_SB.USBX`设备到那个`SSDT`,而不是创建一个新的,这可能会有意义的。 # 重载(override) `IOUSBHostFamily.kext/Contents/Info.plist` Although you could patch this kext Info.plist to provide different properties for any supported SMBIOS, it is desirable to do so without patching since patching would need to be redone after any update that provided a new copy of the file. 虽然可以修补这个`kext`的 `Info.plist`来为任何受支持的SMBIOS提供不同的属性,这样不需要修补还是需要的,因为在提供了新文件副本的任何更新之后,会需要重新修改补丁。 I have added support in to inject these properties. And, at least in my testing, the properties injected by USBInjectAll.kext are succesful in overriding those from IOUSBHostFamily.kext. 我增加了`USBInjectAll.kext`的支持,来注入这些属性。而且,至少在我的测试中,由`USBInjectAll.kext` 注入的属性成功地重载了那些来自`IOUSBHostFamily.kext`的。 通过`USBInjectAll.kext`指定功率特性(power property)重写,你必须在你的`UIAC.RMCF`中提供一个“`AppleBusPowerControllerUSB`” 。 例如: ``` DefinitionBlock ("", "SSDT", 2, "hack", "usb", 0) { // // Override for USBInjectAll.kext // Device(UIAC) { Name(_HID, "UIA00000") Name(RMCF, Package() { // USB Power Properties for Sierra (using USBInjectAll injection) "AppleBusPowerControllerUSB", Package() { // these values happen to be iMac14,2 values... "kUSBSleepPortCurrentLimit", 2100, "kUSBSleepPowerSupply", 4700, "kUSBWakePortCurrentLimit", 2100, "kUSBWakePowerSupply", 4700, }, // XHC overrides (8086:9cb1, NUC5) "8086_9cb1", Package() { // other UIAC.RMCF content follows (for custom port injection) ... } //EOF ``` 这个功能是在`USBInjectAll.kext`的v0.6.0版本中新增的,所以不要期望它在旧的版本中工作。 # 问题报告 阅读FAQ,“问题报告” https://www.tonymacx86.com/threads/faq-read-first-laptop-frequent-questions.164990/
';

[指南] hackintosh之hotpatch

最后更新于:2022-04-02 05:46:02

[TOC] **** # 【指南】使用Clover来热修补ACPI > 英文原文:[Using Clover to "hotpatch" ACPI](https://www.tonymacx86.com/threads/guide-using-clover-to-hotpatch-acpi.200137/) > 本文出处:http://bbs.pcbeta.com/viewthread-1745275-1-1.html # 前言 hotpatch在RehabMan大神维护的 elitebook 系列机型方面体现得很完美,我是翻elitebook机型的hotpatch后发现的,所以我决定来翻译这个教程,水平有限(大部分东西看不懂,靠有道翻译对付的,凑合吧),错漏之处请各位指出,谢谢。 先贴上国内的几个帖子,都写得很好,方便大家理解,版权归原作者。 1.华硕 VM510LEFI分享9CC3笔记本主板芯片通用 : https://blog.neroxps.cn/blog/macOS/9CC3-EFI-README.html 2.hotpatch学习笔记: http://bbs.pcbeta.com/forum.php?mod=viewthread&tid=1733965 3.暗影精灵2代Pro安装macOS Sierra 10.12.5全记录(hotpatch): http://bbs.pcbeta.com/viewthread-1742550-1-1.html 目前我认为第三篇帖子和RehabMan的hotpatch方法是比较接近的,不过只是个人主观意见。 最好之前先去看看**SSDT/DSDT**的部分。 # 介绍 在接近MAC配置的非MAC硬件上修补`ACPI`使之启用(接近)MAC的完整功能。 在这里有一份完整的指导:[guide-patching-laptop-dsdt-ssdts](http://www.tonymacx86.com/threads/guide-patching-laptop-dsdt-ssdts.152573/),这里的指导使用所谓的“ **静态修补(static patching)** ”,为了注入ACPI补丁文件,我们提取本机 ACPI ,将他们拆开,进行修改,然后重新编译放到`\EFI\Clover\ACPI\patched`目录下,这是使用 clover 注入修补 ACPI,而不是修改硬件 ACPI。使用本指南中详细介绍的技术,可以直接对 BIOS 提供的ACPI 二进制文件进行更改,而无需执行提取,反汇编和重新编译步骤。 在尝试进行 hotpatch 之前,您应该对 静态 ACPI 补丁有深入的了解。 您还应该了解 ACPI 规范,二进制修补程序,编程和 ACPI 概念。 # Clover的修补机制 Clover提供了一些方法来完成 ACPI hotpatch: - `config.plist/ACPI/DSDT/Fixes`(在 config.plist 文件 ACPI/DSDT/ 下添加修复) - `config.plist/ACPI/DSDT/Patches`(在 config.plist 文件ACPI/DSDT/ 下添加补丁) - `ability to inject additional SSDTs`(在ssdt 文件下注入额外的 SSDTs) (这一部分体现得最好的是在elitebook机型下面,elitebook机型的 hotpatch详见:https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch) DSDT/Fixes 提供了固定功能的ACPI修补。 每个 `Fixes` 都可以执行一种特定类型的修补程序,可以代替MaciASL和静态修补程序执行的典型修补程序。 例如,可以使用“ FixHPET”,“ FixIPIC”,“ FixRTC”和“ FixTMR”来完成“ IRQ Fix”。 作为另一个示例,可以使用“ FixWAK”完成 `Fix _WAK Arg0 v2`。 您可以阅读 Clover Wiki ,以获取有关每个补丁的更多信息。 大多数时候,基本功能不需要很多DSDT "Fixes”。 DSDT "Fixes" 对于实现难以或无法通过 `ACPI/DSDT/Patches` 或 additional SSDTs(其他SSDTS)实现的补丁程序很有用。 Clover允许在 `config.plst/DSDT/Patches`下搜索和替换二进制,Clove 加载本地ACPI文件时,会应用`config.plst/DSDT/Patches`下的 Patches 二进制文件进行搜索/替换,然后注入修补 ACPI。你需要了解AM L的二进制格式和常用的 ACPI规范。 ACPI 命名空间是通过在加载时合并 DSDT 和SSDTs 来构建的。 通过将其他 SSDTs 放入 `ACPI/patched`,可以从本质上向此 ACPI集 添加代码。 由于许多OS X 补丁程序都涉及通过 `_DSM`方法向 `ioreg`添加属性,因此只需添加包含附加 `_DSM`方法的 SSDT 通常就足够了,而不是修补本机 ACPI 文件。 您已经熟悉的一个完美示例是Pike的 `ssdtPRgen.sh` 生成的 SSDT.aml。 在某些情况下,必须使用多种机制来实现一个目标。 例如,您可以使用二进制补丁程序禁用或重命名本机 ACPI 集中的组件,然后将其替换为附加的 SSDTs。 # 重命名ACPI对象(Renaming ACPI objects) 因为OS X 可以依赖于mac使用的特定的ACPI对象名称,一个常见的补丁是在原始ACPI集合中重命名一个对象。例如,大多数PC笔记本电脑使用`GFX0`来表示集成的 Intel GPU 对象(Intel HD Graphics)。在OS X中,除非该设备被命名为`IGPU`,否则不会启用英特尔图形的电源管理。使用静态补丁,我们应用“Rename IGPU to GFX0”来重命名这个对象。补丁必须应用到DSDT和所有引用它的SSDTs。 有了 hotpatch,我们可以在 `ACPI/DSDT/Patches`中使用简单的 Clover 补丁将`GFX0`重命名为`IGPU`。这些补丁适用于DSDT 和所有本地 SSDTs(`DSDT/Patches`不适用于通过`ACPI/patched`添加的SSDTs)。重新命名的补丁将是 ``` Comment: Rename GFX0 to IGPU Find: <4746 5830> Replace: <4947 5055> ``` 查找和替换的十六进制值分别是 GFX0 和 IGPU 的 ASCII码。 注意: ``` u430:~ RehabMan$ echo -n GFX0|xxd 0000000: 4746 5830 GFX0 u430:~ RehabMan$ echo -n IGPU|xxd 0000000: 4947 5055 IGPU ``` 常见的重命名有很多,大多数在我的 `Clover/hoptpatch` 项目的 config.plist 中: https://github.com/RehabMan/OS-X-Clover-Laptop-Config/tree/master/hotpatch 事实上,同一项目的一部分的hotpatch SSDTs依赖于那些被实现的重命名。 常见的重命名: ``` GFX0 -> IGPU SAT0 -> SATA EHC1 -> EH01 EHC2 -> EH02 XHCI -> XHC HECI -> IMEI MEI -> IMEI LPC -> LPCB HDAS -> HDEF AZAL -> HDEF ``` 注意:所有 ACPI 标识符都是4个字符。短名称是用下划线填充的。例如,XHC 在 A ML二进制中表示为 `XHC_`,EC 为`EC__`,EC0 为 `EC_`,MEI 为 `MEI_`,等等。 # 删除方法(Removing methods) 使用 Clover 二进制补丁来删除 ACPI对象(方法、名称、设备等)非常困难。通常,我们必须添加 `_DSM` 方法来注入属性来描述各种硬件的属性。但是,添加的 `_DSM` 方法可能会与现有的 `_DSM` 方法相冲突,这些方法可能已经存在于本地 ACPI 文件中。进行静态修补时,将使用 `Remove _DSM methods`。 由于很难删除这些方法,但是我们不希望原始方法与添加的新 `_DSM` 方法相冲突,修复方法是将原始方法重命名为其他方法。 所以…同样,我们使用一个简单的重命名补丁: ~~~ Comment: Rename _DSM to XDSM Find: <5f44534d> Replace: <5844534d> ~~~ 有时,您可以重命名一个对象,以有效地禁用它,这样它就不会产生问题。例如,我的Intel DH67GD DSDT定义了一个`APSS`对象。如果这个对象留在DSDT中,它会干扰电源管理(引起恐慌)。我使用`APSS -> APXX`的重命名。因为AppleIntelCPUPowerManagement 正在寻找 APSS,它改名为`APXX`不会引起问题。 # 重定向和替换(Redirect and Replace) 在某些情况下,我们希望替换代码来改变行为。为此,我们可以重命名对象,并在SSDT中提供一个可替换的实现。 一个常见的解决方法是欺骗DSDT和SSDTs中的 ACPI 代码,这样它的行为就表现得像特定的 windows的 ACPI 代码。当静态修补时,我们可以使用“OS Check Fix (Windows 8)”。应用时,它会更改代码从: ~~~ If (_OSI("Windows 2012")) ~~~ 变为: ~~~ If (LOr(_OSI("Darwin"),_OSI("Windows 2012")) ~~~ 由于OS X中的 `_OSI` 实现只响应 “Darwin”,所以代码被更改,因此这个特定的`_OSI`检查也可以满足“Darwin”。 hotpatching 采取相反的方法,我们不使用 `_OSI`更改代码,而是更改代码,因此它调用了一个不同的方法来模拟Windows ACPI主机上的`_OSI`实现。 这项技术依赖于两种技术……一个补丁来改变所有从`_OSI`到`XOSI`的调用…以及`XOSI`的实现,它模仿Windows对一个特定Windows版本的操作。 首先,更改代码来 调用`XOSI` 而不是`_OSI`: ~~~ Comment: Change _OSI to XOSI Find: <5f4f 5349> Replace: <584f 5349> ~~~ 上面的十六进制编码不应该是神秘的(它们分别是`_OSI`和`XOSI`的ASCII码)。以上所述的代码,经过Clover的修补后,将会: ~~~ If (XOSI("Windows 2012")) ~~~ 现在我们需要一个实现`XOSI`的`SSDT`。您将在 rep 中找到这样的实现(`SSDT-XOSI.dsl`)。注意,如果没有实现`XOSI`方法的`SSDT`,对`XOSI`的调用会导致**ACPI中止**(ACPI abort导致ACPI方法的执行立即被错误终止)。如果没有`XOSI`方法,不要使用`_OSI -> XOSI`补丁。 # 重命名和替换(Rename and Replace) 第二种模式,类似于“重定向和替换”是“重命名和替换”。在这种情况下,我们将更改方法定义,以使该方法的名称与原始名称有所不同,而不是更改所有调用位置,而是将原始方法名称保留在调用位置。 这允许替换作为调用目标的方法。 例如,USB设备的“瞬间唤醒”非常常见。作为一种变通方案,在USB上唤醒可以被禁用。大多数笔记本电脑都没有BIOS选 项,所以控制这个特性的 `_PRW` 方法被修补了。 例如,原始的`_SB.PCI0.EHC1._PRW`方法可能被读取: ``` Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake { Return (GPRW (0x6D, 0x03)) } ``` 为了修补它,使USB设备在 EHCI#1 不会造成唤醒,它将被改变: ``` Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake { Return (GPRW (0x6D, 0)) } ``` 通常,有几个这样的调用站点需要更改`GPRW`(同时,请记住,并不是所有ACPI集都使用特定的名称`GPRW`)。相反,我们可以改为修补`GPRW`的方法定义,而不是像上面那样修补所有的调用站点: 原始代码: ``` Method (GPRW, 2, NotSerialized) { ... } ``` 如果我们改成: ``` Method (XPRW, 2, NotSerialized) { ... } ``` 由于您不希望更改任何调用站点,因此必须构造该补丁,以便它只影响方法本身,而不影响调用站点。根据 ACPI 规范,方法定义从字节码 14 开始,然后是方法大小、方法名称、参数计数/标志。您可以在`iasl`中使用“`- l`”选项来生成ACPI 文件的混合列表。例如,联想u430 `GPRW` 混合列表: ``` 4323: Method (GPRW, 2, NotSerialized) 00003F95: 14 45 08 47 50 52 57 02 ".E.GPRW." 4324: { 4325: Store (Arg0, Index (PRWP, Zero)) 00003F9D: 70 68 .................. "ph" 00003F9F: 88 50 52 57 50 00 00 ... ".PRWP.." ``` 我们可以使用方法**头字节**来代替查找: ``` Find: <14 45 08 47 50 52 57 02> Replace: <14 45 08 58 50 52 57 02> ``` 但是,如果不同版本的BIOS或相似但不完全相同的型号之间的方法略有不同,会发生什么? 在这种情况下,由于方法长度的变化,14之后的字节将发生变化。 我的想法是,开始的方法体不太可能与方法的总长度不同,因此有助于将方法主体中的一些额外字节添加到查找/替换规范中: ~~~ Find: <47 50 52 57 02 70 68> Replace: <58 50 52 57 02 70 68> ~~~ 您使用的后续字节数取决于进行查找/替换所需要的字节数仅影响方法定义。 您可以通过在Hex Fiend等十六进制编辑器中查看本机AML二进制文件进行验证(它是一个不错的十六进制编辑器,也是开源的)。 注意:尽管您只能搜索方法名称+ `arg count/ flags`,但相同的模式可能会找到您不想更改的方法的调用站点。 在u430 并非如此的情况下,因此我仅用方法名+标志即可查找/替换。 ``` Find: <47505257 02> Replace: <58505257 02> ``` 在ProBook UPRW 的情况下,需要使用方法主体部分的后续字节: ``` Find: <55505257 0a7012> Replace: <58505257 0a7012> ``` 现在,任何调用`GPRW`(或ProBook示例中的UPRW)的代码都不会调用 `XPRW`中的实现,因为它的名称不匹配。原始的XPRW现在是不可到达的代码。这意味着`GPRW` 的实现可以根据我们的目的而改变: ``` Method(GPRW, 2) { If (0x6d == Arg0) { Return(Package() { 0x6d, 0, }) } External(\XPRW, MethodObj) Return(XPRW(Arg0, Arg1)) } ``` 解释该代码:对于任何调用`GPRW`,将第一个参数设置为`0x6d` (我们正在尝试禁用的`GPE`),而不是返回原来的`GPRW`,我们返回的包为 `0x6d` 和 `0`(禁用唤醒),而不是返回原始 `GPRW` 的内容 。 对于其他 `GPE` 值,该代码仅调用原来的 `GPRW` 方法(现在称为 `XPRW` )。 另一个简单的例子是 修补 EC查询方法来修复亮度键。只需将所涉及的 `_Qxx`方法简单地重命名为 `XQxx`,并使用原始名称重新定义方法即可。 例如,在HP Envy Haswell 的 repo 中: ``` // _Q13 called on brightness/mirror display key Method (_Q13, 0, Serialized) // _Qxx: EC Query { External(\HKNO, FieldUnitObj) Store(HKNO, Local0) If (LEqual(Local0,7)) { // Brightness Down Notify(\_SB.PCI0.LPCB.PS2K, 0x0405) } If (LEqual(Local0,8)) { // Brightness Up Notify(\_SB.PCI0.LPCB.PS2K, 0x0406) } If (LEqual(Local0,4)) { // Mirror toggle Notify(\_SB.PCI0.LPCB.PS2K, 0x046e) } } ``` 和相关的补丁: ``` Comment: change Method(_Q13,0,S) to XQ13 Find: <5f513133 08> Replace: <58513133 08> ``` 同样的 “Rename and Rep lace”机制也可以用于比这复杂得多的情况。例如,它通常用于修补电池方法,需要对这些方法进行修补,以避免访问多字节EC字段。 # 对于复杂的重命名和替换的建议 您可能已经知道,修补电池状态(多字节的EC字段)可能非常复杂,并且可能涉及许多代码更改到许多方法。 本节将详细介绍一些用于电池修补的技术和程序,用于给电池打补丁。 最好先给电池打补丁,而不要先用hotpatch。工作完成后,尝试使用hotpatch。另外,未修补得电池代码和已修补电池代码之间的区别也很有帮助。您可以使用“diffmerge”这样的工具来比较它们。如果你的笔记本型号在我的笔记本电脑库里已经有了一个静态电池补丁,这一点尤其正确。 一般流程: ——从本地ACPI开始 ——使用静态修补电池状态(验证效果) ——使用diffmerge来比较未修补的代码与补丁代码 ——对于不同的方法,实现“重命名和替换”模式 ——对于EC字段,创建另一个EC OperationRegion(使用与原始的名称不同的名称)和字段定义作为一种“覆盖”,它只包含您需要修补的EC字段 ——要创建EC层,您可以在修补的DSDT中使用修补的`Field/OperationRegion`,然后删除未修补的字段 ——在SSDT中允许通过替换方法使用外部 访问ACPI集中其他地方定义的字段(通常是DSDT) ——让编译器指出需要使用外部的地方 ——注意不同范围内重复名称的符号 该贴中的2楼中提供了一个示例。 您可能已经知道,对电池状态(多字节EC字段)进行修补可能非常复杂,并且可能需要对许多方法进行大量代码更改。 本节将详细介绍一些用于电池修补的技术和步骤。 建议不先使用热修补程序来修补电池。 当它开始工作后,请尝试热补丁。 另外,未为电池打补丁的代码与为电池打补丁的代码之间的区别非常有用。 您可以使用“ diffmerge”之类的工具进行比较。 如果我的笔记本电脑存储库中已经有笔记本电脑的静电电池补丁,则尤其如此。 一般程序: \-从本地ACPI开始 \-使用静态修补程序修补电池状态(验证其是否有效) \-使用diffmerge将未修补的代码与修补的代码进行比较 \-对于每个不同的方法,实施“重命名和替换”模式 \-对于EC字段,创建另一个EC OperationRegion(使用与原始名称不同的名称),并将Field定义作为一种“叠加”,其中仅包含您需要修补的EC字段 \-要创建EC叠加层,您可以在修补的DSDT中使用修补的Field / OperationRegion,然后消除未修补的字段 \-使用外部来允许SSDT中的替换方法访问ACPI集中其他位置(通常是DSDT)定义的字段 \-让编译器指出您需要在哪里使用外部 \-注意在不同范围内名称重复的符号 此线程的帖子#2中提供了一个示例。 # 代码值修补(Code value patching) 考虑“Fix Mutex with non-zero SyncLevel”的这个补丁例子。这个补丁找到所有的互斥对象(Mutex objects)并替换同步级别(SyncLevel)为0。我们使用这个补丁,因为 OS X 不支持对互斥对象正确的调试,还会终止对任何非零同步级别的互斥对象的捕获。 举个例子,u430的互斥对象是这样的: ``` Mutex (MSMI, 0x07) ``` 要使它与OS X兼容,必须更改: ``` Mutex (MSMI, 0) ``` ACPI规范定义了一个互斥对象如何在AML中编码,但它可以帮助查看一个小ACPI文件的混合反编译: ``` DefinitionBlock ("", "DSDT", 2, "test", "test", 0) { Mutex(ABCD, 7) } ``` iasl编译器可以使用“`- l`”选项创建混合列表文件。 如果我们用`iasl - l`测试来编译上面的文件:`iasl -l test.dsl`,`test.lst` 包含如下: ``` 1: DefinitionBlock ("", "DSDT", 2, "test", "test", 0) 00000000: 44 53 44 54 2B 00 00 00 "DSDT+..." 00000008: 02 36 74 65 73 74 00 00 ".6test.." 00000010: 74 65 73 74 00 00 00 00 "test...." 00000018: 00 00 00 00 49 4E 54 4C "....INTL" 00000020: 10 04 16 20 ............ "... " 2: { 3: Mutex(ABCD, 7) 00000024: 5B 01 41 42 43 44 07 ... "[.ABCD." 4: } ``` 正如你所看到的;这个互斥对象`(ABCD, 7)`,被编码为 `<5B 01 41 42 43 44 07>`。 现在很容易为它构建一个补丁: ``` Comment: Change Mutex(ABCD,7) to Mutex(ABCD,0) Find: <5B 01 41 42 43 44 07> Replace: <5B 01 41 42 43 44 00> ``` # Clover的ACPI 配置(Clover ACPI configuration) 使用静态补丁,使用`DropOem = true`,并将DSDT和SSDTs添加到`ACPI / patched`中。使用hotpatch,使`DropOem = false`,并且只将附加SSDTs放在 `ACPI/patched`下。 需要注意`config.plist/ACPI/patches`只应用于原生的SSDTs,而不是`ACPI/patched`中的SSDTs。这意味着,如果您正在使用`config.plist`进行重命名对象,附加的SSDTs必须引用新的名称,而不是旧的名称。与`ACPI/patched`中的SSDTs不同,`ACPI/patched`中的二进制补丁对可能在`ACPI / patched`中的`DSDT.aml`有应用。如果您使用的是静态和热补丁的组合,你需要考虑到这一点。 另外,打静态补丁,可以使用`SortedOrder`来指定`ACPI/patched`中SSDTs的顺序。有了hotpatch,顺序就不是必要的,因为可以在每个SSDT中构造代码,这样代码就不依赖于顺序。特别是如果你将所有的附加代码放在一个SSDT中,比如关于我的笔记本电脑的git库中的许多例子。除非您的附加SSDTs是顺序相关的,否则您不必按`SortedOrder`方式命名每一个。 对于每个SSDT,也没有必要选择“数字编号的名称”。相反,你可以使用有意义的名字,比如"SSDT-USB.aml", SSDT-XOSI.aml"。使用数字名称会让你迷惑,请不要这样做。 # 解决问题 你可以使用补丁来查看你的完整的ACPI设置,如在修补后的Clover注射。通过运行 '`patchmatic -extract`',patchmatic将写入所有注入的`DSDT.aml`和`SSDT*.aml`按照他们被Clover注射的顺序。你可以用`iasl -da -dl *. aml`把它们拆开。如果`iasl`显示了反编译的错误(例如,重复符号),这就像OS X也在拒绝冲突的SSDTs。 如果您是一个新手,使用这种技术,一次实现一个补丁是一个好主意,并且慢慢地将它构建到一组完整的working patches + SSDTs中。试图一次做所有的事情会使你很难找到你的错误。 # 问题报告 下载 patchmatic: https://bitbucket.org/RehabMan/os-x-maciasl-patchmatic/downloads/RehabMan-patchmatic-2015-0107.zip 解压下载的patchmatic.zip 文件,把它复制到`/usr/bin`,这样二进制文件就是`/usr/bin/patchmatic`这样了。 在终端: ``` if [ -d ~/Downloads/RehabMan ]; then rm -R ~/Downloads/RehabMan; fi mkdir ~/Downloads/RehabMan cd ~/Downloads/RehabMan patchmatic -extract ``` 注意:为了简单,你可以直接复制/粘贴而不是手动输入上面的命令。 附上`Downloads/RehabMan`目录的内容(如ZIP)。 同时,附上`ioreg`:http://www.tonymacx86.com/audio/58368-guide-how-make-copy-ioreg.html 。请使用附件中的IORegistryExplorer v2.1!不要使用`ioregistryexplorer.app`的其他版本然后回复我~。 ``` kextstat|grep -y acpiplat kextstat|grep -y appleintelcpu kextstat|grep -y applelpc ``` 同时,在收集之前,附加上你的`EFI/Clover`文件夹(你可以在主Clover屏幕上按下`F4`提取)。请删除“themes”目录,特别是如果你安装了过多的主题。只提供`EFI/Clover`,而不是整个EFI文件夹。 也可以附上重建缓存日志: ``` sudo touch /System/Library/Extensions && sudo kextcache -u / ``` 翻译到此结束。但是后面是一些示例。 附上RehabMan大神的github: 1.OSX clover laptop config:https://github.com/RehabMan/OS-X-Clover-Laptop-Config 这里面提供了一些常见的补丁和说明,还有笔记本的通用config.plist。 2.elitebook/probook/zbook系列机型:https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch 3.Inter NUC 5/6/7系列:https://github.com/RehabMan/Intel-NUC-DSDT-Patch 4.Lenovo U330/U430/U530系列:https://github.com/RehabMan/Lenovo-U430-Touch-DSDT-Patch 5.HP envy J/K/Q/RHaswell系列:https://github.com/RehabMan/HP-Envy-DSDT-Patch 6.Lenovo Z50-70/Z40-70系列:https://github.com/RehabMan/Lenovo-Z50 7.Lenovo Y50/Y40-70系列:[url]https://github.com/RehabMan/Lenovo-Y50-DSDT-Patch # 参考 [祝贺远景开放,开启完美黑苹果新天地!(抛弃传统DSDT方法,完美黑苹果)](https://weibo.com/p/23041874f0e4330102x1sy) https://blog.daliansky.net/hotpatch-detailed-solution.html # [小小总结](http://bbs.pcbeta.com/viewthread-1766329-1-1.html) 传统 DSDT 方式,是提取机器的 DSDT,反编译后进行改错、编辑、打补丁,然后再次编译,最后把编译好的 DSDT 拿来用。 原理上来说没啥毛病,但是这个反编译和编译却是问题所在,否则为什么要排错啊。 然后,大神就提出这种方法,可以不提取 DSDT,免去了反编译带来的问题。 这种方法是其实可以理解为外挂。基于 Clover的 DSDT 二进制 patch 也就是二进制字符替换,再配合ssdt来实现的。 我们知道,对 DSDT 修改,总结来说就是改名、删除、修改代码,有些 DSDT 简单修改,在 Clover 里可以直接通过勾选相应 Fix 功能实现。 另外对于其他的改名和删除,还可以利用 clover 的 patch 功能,实现一些字符替换,直接实现对dsdt重命名和删除的修改。 但是还有一些是要修改对象和方法里的代码。这个怎么办。没关系,在上面的基础上,然后把要需改的代码放到单独的 SSDT 里,二进制字符替换和 SSDT 配合使用即可实现修改代码的操作。 更改调用时的方法名或者对象名,指向新 SSDT 里用新名字定义的对象或者方法,这叫重定向和替换。 直接把 DSDT 里的对象或方法的名字改掉,然后在SSDT 里重写该对象或方法的定义,这就是重命名和替换。 上面几点对应到Rehabman的教程里,就是hotpatch的四种修改类型: 1. 重命名ACPI对象(Renaming ACPI objects) 2. 删除方法(Removingmethods) 3. 重定向和替换(Redirectand Replace) 4. 重命名和替换Rename andReplace) (具体细节的在上面👆的教程里说的很清楚,我就不展开赘述了。) 这种方式免去了 DSDT 提取、反编译和编译的过程,从而减少了这几个过程出现的错误。 而且从方式上来说,hotpatch这种方式也比较“科学”。 # ======================= # 电池状态的Hotpatch 这第二篇文章致力于用Clover补丁修补电池状态。为了演示这个过程,我们将通过一个示例DSDT来工作。使用的示例文件来自于禁用独立显卡的指南,即“Asus UX303LN”:https://www.tonymacx86.com/threads/guide-disabling-discrete-graphics-in-dual-gpu-laptops.163772/ (我打算翻译) 您应该下载附加到该指南的 `ACPI/origin`文件, 以便您跟着我一起做。 如上面1楼的文章所发布的,一般操作流程如下: ——从原生的ACPI补丁开始。 ——使用静态打补丁方式修补电池状态(验证其效果) ——使用`diffmerge`比较修改代码与修补代码 ——为每个方法都是不同的,实现“Rename and Replace”模式 ——对于EC字段,创建另一个EC OperationRegion(操作区域)(使用与原来不同的名称)和字段定义作为一种“覆盖层”,它只包含您需要修补的EC字段 ——创建EC覆盖层,您可以在修补的DSDT中使用修补的Field/OperationRegion(字段/操作区域),然后删除未修补的字段。 ——使用外部(External)来允许SSDT中的替换方法访问ACPI集合中定义的字段(通常是DSDT)。 ——让编译器指出需要使用外部(External)的地方 ——注意不同范围(scopes)内重复名称的符号 ## 使用diffmerge来发现 打补丁的(patched)和原生的(native) 之间的差异 首先分解源文件:`iasl -da -dl *.aml`(你应该熟悉这个部分,因为它是正常ACPI打补丁的一部分) 接下来,只需要使用`MaciASL`和`dsdt.dsl`就可以应用电池补丁。在这种情况下,我们应用“ASUS N55SL/VivoBook”。没有必要修改任何错误,因为我们只关心应用电池补丁所产生的差异。将补丁文件保存为`dsdt_patch.dsl`。 现在您可以运行`diffmerge`以查看`DSDT.dsl` 和 `DSDT_patched.dsl`之间的区别。我通常是从终端来做这个的: ``` diffmerge DSDT.dsl DSDT_patched.dsl ``` 初始的diffmerge窗口将会是这样的: ![batthot_diffmerge_initial-png](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/bf4b11a92c8cd288160c1fdbbf77e0e8_1084x849.png) 从这里里,我们可以通过点击左边栏中的标记来检查那些发生变化的部分。 在这些例子中,你会发现: - 第1组: 是否对`EC`字段进行了更改 (多字节 VS 单一字节) - 第2组: 加入`RDBA`,`WRBA`,`RDBB`,`WRBB`方法 - 第3组: 打补丁的 `FBST`, `_BIX`, `B1FA `方法 - 第4组: 打补丁的 `SMBR`, `SMBW`, `ECSB` 方法 - 第5组: 打补丁的 `TACH` 方法 - 最后一组: 额外添加的 `B1B2` 方法 ## 构建初始SSDT 用 MaciASL开始一个空的SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { } ``` 接下来,添加补丁中添加的所有方法。在这个示例中,这包括`RDBA、WRBA、RDBB、WRBB`和`B1B2`方法。您可以直接从`dsdt_patch.dsl`中复制它们。 你要确定每个方法都放在同一个作用域(scope)内。例如,这里是“第2组”的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { Scope (_SB.PCI0.LPCB.EC0) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 并且 `B1B2`被添加: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } // added methods (group 2) Scope (_SB.PCI0.LPCB.EC0) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 不要担心,代码现在没有编译。由于在这个文件中没有定义的`EC`字段(和其他标识符),在这一点上它是不被期望的。它们需要通过外部(最终)被定义或引用。 现在让我们添加补丁方法。就像那些添加了方法的方法一样,补丁方法也只是从`DSDT_patched.dsl`中复制的: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { // patched methods Scope (_SB.PCI0) { Scope (BAT0) { Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) If (^^LPCB.EC0.ACAP ()) { Store (One, Local0) } If (Local0) { If (CHGS (Zero)) { Store (0x02, Local0) } Else { Store (Zero, Local0) } } Else { Store (One, Local0) } If (BLLO) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (And (^^LPCB.EC0.EB0S, 0x08)) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (LGreaterEqual (Local1, 0x8000)) { Subtract (0xFFFF, Local1, Local1) } Store (Arg2, Local2) If (LEqual (PUNT, Zero)) { Multiply (Local1, ^^LPCB.EC0.B0DV, Local1) Multiply (Local2, 0x0A, Local2) } And (Local0, 0x02, Local3) If (LNot (Local3)) { Subtract (LFCC, Local2, Local3) Divide (LFCC, 0xC8, Local4, Local5) If (LLess (Local3, Local5)) { Store (LFCC, Local2) } } Else { Divide (LFCC, 0xC8, Local4, Local5) Subtract (LFCC, Local5, Local4) If (LGreater (Local2, Local4)) { Store (Local4, Local2) } } If (LNot (^^LPCB.EC0.ACAP ())) { Divide (Local2, MBLF, Local3, Local4) If (LLess (Local1, Local4)) { Store (Local4, Local1) } } Store (Local0, Index (PBST, Zero)) Store (Local1, Index (PBST, One)) Store (Local2, Index (PBST, 0x02)) Store (Arg3, Index (PBST, 0x03)) } Method (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended { If (LNot (^^LPCB.EC0.BATP (Zero))) { Return (NBIX) } If (LEqual (^^LPCB.EC0.GBTT (Zero), 0xFF)) { Return (NBIX) } _BIF () Store (DerefOf (Index (PBIF, Zero)), Index (BIXT, One)) Store (DerefOf (Index (PBIF, One)), Index (BIXT, 0x02)) Store (DerefOf (Index (PBIF, 0x02)), Index (BIXT, 0x03)) Store (DerefOf (Index (PBIF, 0x03)), Index (BIXT, 0x04)) Store (DerefOf (Index (PBIF, 0x04)), Index (BIXT, 0x05)) Store (DerefOf (Index (PBIF, 0x05)), Index (BIXT, 0x06)) Store (DerefOf (Index (PBIF, 0x06)), Index (BIXT, 0x07)) Store (DerefOf (Index (PBIF, 0x07)), Index (BIXT, 0x0E)) Store (DerefOf (Index (PBIF, 0x08)), Index (BIXT, 0x0F)) Store (DerefOf (Index (PBIF, 0x09)), Index (BIXT, 0x10)) Store (DerefOf (Index (PBIF, 0x0A)), Index (BIXT, 0x11)) Store (DerefOf (Index (PBIF, 0x0B)), Index (BIXT, 0x12)) Store (DerefOf (Index (PBIF, 0x0C)), Index (BIXT, 0x13)) If (LEqual (DerefOf (Index (BIXT, One)), One)) { Store (Zero, Index (BIXT, One)) Store (DerefOf (Index (BIXT, 0x05)), Local0) Multiply (DerefOf (Index (BIXT, 0x02)), Local0, Index (BIXT, 0x02)) Multiply (DerefOf (Index (BIXT, 0x03)), Local0, Index (BIXT, 0x03)) Multiply (DerefOf (Index (BIXT, 0x06)), Local0, Index (BIXT, 0x06)) Multiply (DerefOf (Index (BIXT, 0x07)), Local0, Index (BIXT, 0x07)) Multiply (DerefOf (Index (BIXT, 0x0E)), Local0, Index (BIXT, 0x0E)) Multiply (DerefOf (Index (BIXT, 0x0F)), Local0, Index (BIXT, 0x0F)) Divide (DerefOf (Index (BIXT, 0x02)), 0x03E8, Local0, Index (BIXT, 0x02)) Divide (DerefOf (Index (BIXT, 0x03)), 0x03E8, Local0, Index (BIXT, 0x03)) Divide (DerefOf (Index (BIXT, 0x06)), 0x03E8, Local0, Index (BIXT, 0x06)) Divide (DerefOf (Index (BIXT, 0x07)), 0x03E8, Local0, Index (BIXT, 0x07)) Divide (DerefOf (Index (BIXT, 0x0E)), 0x03E8, Local0, Index (BIXT, 0x0E)) Divide (DerefOf (Index (BIXT, 0x0F)), 0x03E8, Local0, Index (BIXT, 0x0F)) } Store (B1B2(^^LPCB.EC0.XC30,^^LPCB.EC0.XC31), Index (BIXT, 0x08)) Store (0x0001869F, Index (BIXT, 0x09)) Return (BIXT) } } } Scope (_SB.PCI0.LPCB.EC0) { Method (BIFA, 0, NotSerialized) { If (ECAV ()) { If (BSLF) { Store (B1B2(B1S0,B1S1), Local0) } Else { Store (B1B2(B0S0,B0S1), Local0) } } Else { Store (Ones, Local0) } Return (Local0) } } Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } // added methods (group 2) Scope (_SB.PCI0.LPCB.EC0) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 注意,如何将`FBST`和`_BIX`添加到 `_SB.PCI0.BAT0`作用范围(scope)中。而`BIFA`被添加到`_SB.PCI0.LPCB.EC0`。把所有的方法都注入到原来的作用范围(scope)是很重要的。 现在,我们添加`SMBR`、`SMBW`、`ECSB`和`TACH`: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { // patched methods Scope (_SB.PCI0) { Scope (BAT0) { Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) If (^^LPCB.EC0.ACAP ()) { Store (One, Local0) } If (Local0) { If (CHGS (Zero)) { Store (0x02, Local0) } Else { Store (Zero, Local0) } } Else { Store (One, Local0) } If (BLLO) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (And (^^LPCB.EC0.EB0S, 0x08)) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (LGreaterEqual (Local1, 0x8000)) { Subtract (0xFFFF, Local1, Local1) } Store (Arg2, Local2) If (LEqual (PUNT, Zero)) { Multiply (Local1, ^^LPCB.EC0.B0DV, Local1) Multiply (Local2, 0x0A, Local2) } And (Local0, 0x02, Local3) If (LNot (Local3)) { Subtract (LFCC, Local2, Local3) Divide (LFCC, 0xC8, Local4, Local5) If (LLess (Local3, Local5)) { Store (LFCC, Local2) } } Else { Divide (LFCC, 0xC8, Local4, Local5) Subtract (LFCC, Local5, Local4) If (LGreater (Local2, Local4)) { Store (Local4, Local2) } } If (LNot (^^LPCB.EC0.ACAP ())) { Divide (Local2, MBLF, Local3, Local4) If (LLess (Local1, Local4)) { Store (Local4, Local1) } } Store (Local0, Index (PBST, Zero)) Store (Local1, Index (PBST, One)) Store (Local2, Index (PBST, 0x02)) Store (Arg3, Index (PBST, 0x03)) } Method (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended { If (LNot (^^LPCB.EC0.BATP (Zero))) { Return (NBIX) } If (LEqual (^^LPCB.EC0.GBTT (Zero), 0xFF)) { Return (NBIX) } _BIF () Store (DerefOf (Index (PBIF, Zero)), Index (BIXT, One)) Store (DerefOf (Index (PBIF, One)), Index (BIXT, 0x02)) Store (DerefOf (Index (PBIF, 0x02)), Index (BIXT, 0x03)) Store (DerefOf (Index (PBIF, 0x03)), Index (BIXT, 0x04)) Store (DerefOf (Index (PBIF, 0x04)), Index (BIXT, 0x05)) Store (DerefOf (Index (PBIF, 0x05)), Index (BIXT, 0x06)) Store (DerefOf (Index (PBIF, 0x06)), Index (BIXT, 0x07)) Store (DerefOf (Index (PBIF, 0x07)), Index (BIXT, 0x0E)) Store (DerefOf (Index (PBIF, 0x08)), Index (BIXT, 0x0F)) Store (DerefOf (Index (PBIF, 0x09)), Index (BIXT, 0x10)) Store (DerefOf (Index (PBIF, 0x0A)), Index (BIXT, 0x11)) Store (DerefOf (Index (PBIF, 0x0B)), Index (BIXT, 0x12)) Store (DerefOf (Index (PBIF, 0x0C)), Index (BIXT, 0x13)) If (LEqual (DerefOf (Index (BIXT, One)), One)) { Store (Zero, Index (BIXT, One)) Store (DerefOf (Index (BIXT, 0x05)), Local0) Multiply (DerefOf (Index (BIXT, 0x02)), Local0, Index (BIXT, 0x02)) Multiply (DerefOf (Index (BIXT, 0x03)), Local0, Index (BIXT, 0x03)) Multiply (DerefOf (Index (BIXT, 0x06)), Local0, Index (BIXT, 0x06)) Multiply (DerefOf (Index (BIXT, 0x07)), Local0, Index (BIXT, 0x07)) Multiply (DerefOf (Index (BIXT, 0x0E)), Local0, Index (BIXT, 0x0E)) Multiply (DerefOf (Index (BIXT, 0x0F)), Local0, Index (BIXT, 0x0F)) Divide (DerefOf (Index (BIXT, 0x02)), 0x03E8, Local0, Index (BIXT, 0x02)) Divide (DerefOf (Index (BIXT, 0x03)), 0x03E8, Local0, Index (BIXT, 0x03)) Divide (DerefOf (Index (BIXT, 0x06)), 0x03E8, Local0, Index (BIXT, 0x06)) Divide (DerefOf (Index (BIXT, 0x07)), 0x03E8, Local0, Index (BIXT, 0x07)) Divide (DerefOf (Index (BIXT, 0x0E)), 0x03E8, Local0, Index (BIXT, 0x0E)) Divide (DerefOf (Index (BIXT, 0x0F)), 0x03E8, Local0, Index (BIXT, 0x0F)) } Store (B1B2(^^LPCB.EC0.XC30,^^LPCB.EC0.XC31), Index (BIXT, 0x08)) Store (0x0001869F, Index (BIXT, 0x09)) Return (BIXT) } } } Scope (_SB.PCI0.LPCB.EC0) { Method (BIFA, 0, NotSerialized) { If (ECAV ()) { If (BSLF) { Store (B1B2(B1S0,B1S1), Local0) } Else { Store (B1B2(B0S0,B0S1), Local0) } } Else { Store (Ones, Local0) } Return (Local0) } Method (SMBR, 3, Serialized) { Store (Package (0x03) { 0x07, Zero, Zero }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, RDBL)) { If (LNotEqual (Arg0, RDWD)) { If (LNotEqual (Arg0, RDBT)) { If (LNotEqual (Arg0, RCBT)) { If (LNotEqual (Arg0, RDQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { ShiftLeft (Arg1, One, Local3) Or (Local3, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, RDQK)) { If (LNotEqual (Arg0, RCBT)) { Store (Arg2, CMDB) } } WRBA(Zero) Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) If (LEqual (DerefOf (Index (Local0, Zero)), Zero)) { If (LEqual (Arg0, RDBL)) { Store (BCNT, Index (Local0, One)) Store (RDBA(), Index (Local0, 0x02)) } If (LEqual (Arg0, RDWD)) { Store (0x02, Index (Local0, One)) Store (B1B2(T2B0,T2B1), Index (Local0, 0x02)) } If (LEqual (Arg0, RDBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } If (LEqual (Arg0, RCBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } } } Release (MUEC) Return (Local0) } Method (SMBW, 5, Serialized) { Store (Package (0x01) { 0x07 }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, WRBL)) { If (LNotEqual (Arg0, WRWD)) { If (LNotEqual (Arg0, WRBT)) { If (LNotEqual (Arg0, SDBT)) { If (LNotEqual (Arg0, WRQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { WRBA(Zero) ShiftLeft (Arg1, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, WRQK)) { If (LNotEqual (Arg0, SDBT)) { Store (Arg2, CMDB) } } If (LEqual (Arg0, WRBL)) { Store (Arg3, BCNT) WRBA(Arg4) } If (LEqual (Arg0, WRWD)) { Store(Arg4,T2B0) Store(ShiftRight(Arg4,8),T2B1) } If (LEqual (Arg0, WRBT)) { Store (Arg4, DAT0) } If (LEqual (Arg0, SDBT)) { Store (Arg4, DAT0) } Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) } Release (MUEC) Return (Local0) } Method (ECSB, 7, NotSerialized) { Store (Package (0x05) { 0x11, Zero, Zero, Zero, Buffer (0x20){} }, Local1) If (LGreater (Arg0, One)) { Return (Local1) } If (ECAV ()) { Acquire (MUEC, 0xFFFF) If (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } Store (Zero, Local2) While (LNotEqual (Local0, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local1, Zero)) Store (Zero, Local0) } ElseIf (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } } If (LLessEqual (Local2, 0x03E8)) { If (LEqual (Arg0, Zero)) { Store (Arg2, ADDR) Store (Arg3, CMDB) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCNT) WRBA(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DAT0) Store (Arg5, DAT1) } Store (Arg1, PRTC) } Else { Store (Arg2, ADD2) Store (Arg3, CMD2) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCN2) WRBB(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DA20) Store (Arg5, DA21) } Store (Arg1, PRT2) } Store (0x7F, Local0) If (LEqual (Arg0, Zero)) { While (PRTC) { Sleep (One) Decrement (Local0) } } Else { While (PRT2) { Sleep (One) Decrement (Local0) } } If (Local0) { If (LEqual (Arg0, Zero)) { Store (SSTS, Local0) Store (DAT0, Index (Local1, One)) Store (DAT1, Index (Local1, 0x02)) Store (BCNT, Index (Local1, 0x03)) Store (RDBA(), Index (Local1, 0x04)) } Else { Store (SST2, Local0) Store (DA20, Index (Local1, One)) Store (DA21, Index (Local1, 0x02)) Store (BCN2, Index (Local1, 0x03)) Store (RDBB(), Index (Local1, 0x04)) } And (Local0, 0x1F, Local0) If (Local0) { Add (Local0, 0x10, Local0) } Store (Local0, Index (Local1, Zero)) } Else { Store (0x10, Index (Local1, Zero)) } } Release (MUEC) } Return (Local1) } Method (TACH, 1, Serialized) { If (ECAV ()) { Switch (Arg0) { Case (Zero) { Store (B1B2(TH00,TH01), Local0) Break } Case (One) { Store (B1B2(TH10,TH11), Local0) Break } Default { Return (Ones) } } Multiply (Local0, 0x02, Local0) If (LNotEqual (Local0, Zero)) { Divide (0x0041CDB4, Local0, Local1, Local0) Return (Local0) } Else { Return (Ones) } } Else { Return (Ones) } } } Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } // added methods (group 2) Scope (_SB.PCI0.LPCB) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } ``` 在MaciASL中扩展了所有的节点,我们的工作如下: ![ssd_with_nodes_expanded-png](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/3868c8f8fe35292367119dafbdf2eb6e_973x639.png) ## 解决错误(Resolving errors) 现在,我们需要开始使用外部的方法来解决错误,或者根据需要定义修补的EC字段。我们可以使用编译器来提供帮助。单击Compile将显示第一个错误:“`3, 6085, Object not found or not accessible from scope (_SB.PCI0)`“,在这一行: ``` Scope (_SB.PCI0) ``` 编译器表明`_SB.PCI0`没有被声明,所以您不能在作用域操作符(Scope operator)中使用它。 我们需要向外部声明它,因为作用域实际上是在另一个文件(`dsdt.aml`)中定义的:将它添加到文件的顶部 ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) Scope (_SB.PCI0) { ... ``` 现在,下一个错误是“`Scope(BAT0)`”,因此,再一次: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) Scope (_SB.PCI0) { Scope (BAT0) { ... ``` 下一个错误是“`13, 6085, Object not found or not accessible from scope (^^LPCB.EC0.ACAP)`",我们可以从引用ACAP的代码中看出它是一个方法: ``` If (^^LPCB.EC0.ACAP ()) ``` 注意:方法调用由`()`表示(本例中为空参数列表)。因此,我们知道我们可以添加一个外部的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) ... } ``` 注意:路径`^^LPCB.EC0.ACAP`等于`_SB.PCI0.LPCB.EC0.ACAP`,因为引用在`_SB.PCI0.BAT0.FBST`(`FBST`方法的路径)的范围。每个`^`(父)操作符将当前的范围由一个项向上移动,所以`^`表示了`_SB.PCI0.BAT0`。 `^^`表示了`_SB.PCI0`。 在某些情况下,您需要查看DSDT来查找给定标识符的路径和/或类型。例如,下一个错误与`CHGS`有关。同样,我们知道它是一个方法,因为它是方法调用的目标,但是对于路径,我们必须参考`DSDT`: ``` Scope (\) { Method (CHGS, 1, Serialized) { Store (\_SB.PCI0.LPCB.EC0.BCHG (Arg0), Local0) Return (Local0) } ``` 所以,它在根(root)中: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) ... ``` 下一个未定义的符号`BLLO`,是一种方法以外的东西: ``` If (BLLO) { ``` 在DSDT中,我们发现它是用名称定义的(它恰好在根范围(root scope)内): ``` Name (BLLO, Zero) ``` 这使得它成为了一种IntObj: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) ... ``` 修正`FBST`方法中的所有错误: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) ... ``` 现在继续这个过程。 最终,得到: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) ... ``` 将会出现`XC30/XC31`的错误:“153, 6085, Object not found or not accessible from scope (^^LPCB.EC0.XC30)” 这是一个被一分为二的16位字段之一。 这就是创建EC覆盖层(the EC overlay)的必要地方。 为此,我们在EC范围内使用另一个OperationRegion,它的名称与我们在DSDT中发现的名称不同: ``` External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { } } ``` 从`DSDT_patched.dsl`,我们可以得到各种补丁的字段(再次提到`diffmerge`)。这是`DSDT_patched.dsl`中来自`EC`的整个集合: ``` Offset (0x04), CMD1, 8, CDT1, 8, CDT2, 8, CDT3, 8, Offset (0x80), Offset (0x81), Offset (0x82), Offset (0x83), EB0R, 8, EB1R, 8, EPWF, 8, Offset (0x87), Offset (0x88), Offset (0x89), Offset (0x8A), HKEN, 1, Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, TSTP, 8, Offset (0x9C), CDT4, 8, CDT5, 8, Offset (0xA0), Offset (0xA1), Offset (0xA2), Offset (0xA3), EACT, 8, TH1R, 8, TH1L, 8, TH0R, 8, TH0L, 8, Offset (0xB0), B0PN, 16, Offset (0xB4), Offset (0xB6), Offset (0xB8), Offset (0xBA), Offset (0xBC), Offset (0xBE), B0TM, 16, B0C1, 16, B0C2, 16, XC30,8,XC31,8, B0C4, 16, Offset (0xD0), B1PN, 16, Offset (0xD4), Offset (0xD6), Offset (0xD8), Offset (0xDA), Offset (0xDC), Offset (0xDE), B1TM, 16, B1C1, 16, B1C2, 16, YC30,8,YC31,8, B1C4, 16, Offset (0xF0), Offset (0xF2), Offset (0xF4), B0S0,8,B0S1,8, Offset (0xF8), Offset (0xFA), Offset (0xFC), B1S0,8,B1S1,8 ``` 如果我们去掉未修补的标识符,但是保持偏移量(offsets)正确(非常重要!): ``` Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xBE), /*B0TM*/, 16, /*B0C1*/, 16, /*B0C2*/, 16, XC30,8,XC31,8, Offset (0xDE), /*B1TM*/, 16, /*B1C1*/, 16, /*B1C2*/, 16, YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 ``` 同样的事情可以写成如下: ``` Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 ``` 所以,加入到SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 } } ``` 然后在修正更多错误的时候,我们增加了一些外部(External)的: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB.EC0.ECAV, MethodObj) External(BSLF, IntObj) External(_SB.PCI0.LPCB.EC0.RDBL, IntObj) External(_SB.PCI0.LPCB.EC0.RDWD, IntObj) External(_SB.PCI0.LPCB.EC0.RDBT, IntObj) External(_SB.PCI0.LPCB.EC0.RCBT, IntObj) External(_SB.PCI0.LPCB.EC0.RDQK, IntObj) External(_SB.PCI0.LPCB.EC0.MUEC, MutexObj) External(_SB.PCI0.LPCB.EC0.PRTC, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SBBY, IntObj) External(_SB.PCI0.LPCB.EC0.ADDR, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMDB, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SWTC, MethodObj) External(_SB.PCI0.LPCB.EC0.BCNT, FieldUnitObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { ... ``` 然后我们有T2B0和T2B1的错误。这些又被分解为16位的`EC`字段,需要在我们的`EC`覆盖层中定义。事实上,不妨定义我们所需要的剩余部分(来自diffmerge的数据)。 在SMBX中的补丁数据: ``` OperationRegion (SMBX, EmbeddedControl, 0x18, 0x28) ``` 因此,我们创建了一个类似的覆盖层,并有一个唯一的名称: ``` OperationRegion (RMB1, EmbeddedControl, 0x18, 0x28) Field (RMB1, ByteAcc, NoLock, Preserve) { /* Note: disabling these fields (already defined in DSDT, referenced with External if needed, but keeping the correct offset! (very important!) */ /* PRTC, 8, SSTS, 5, , 1, ALFG, 1, CDFG, 1, ADDR, 8, CMDB, 8, */ Offset(4), // the data above is 4 bytes offset from the start of this region! //BDAT, 256, BA00,8,BA01,8,BA02,8,BA03,8, BA04,8,BA05,8,BA06,8,BA07,8, BA08,8,BA09,8,BA0A,8,BA0B,8, BA0C,8,BA0D,8,BA0E,8,BA0F,8, BA10,8,BA11,8,BA12,8,BA13,8, BA14,8,BA15,8,BA16,8,BA17,8, BA18,8,BA19,8,BA1A,8,BA1B,8, BA1C,8,BA1D,8,BA1E,8,BA1F,8 } ``` 与 SMB2有类似的作用域: ``` OperationRegion(RMB2, EmbeddedControl, 0x40, 0x28) Field (RMB2, ByteAcc, NoLock, Preserve) { /* PRT2, 8, SST2, 5, , 1, ALF2, 1, CDF2, 1, ADD2, 8, CMD2, 8, */ Offset(4), //BDA2, 256, BB00,8,BB01,8,BB02,8,BB03,8, BB04,8,BB05,8,BB06,8,BB07,8, BB08,8,BB09,8,BB0A,8,BB0B,8, BB0C,8,BB0D,8,BB0E,8,BB0F,8, BB10,8,BB11,8,BB12,8,BB13,8, BB14,8,BB15,8,BB16,8,BB17,8, BB18,8,BB19,8,BB1A,8,BB1B,8, BB1C,8,BB1D,8,BB1E,8,BB1F,8 } ``` `T2B0`和`T2B1` 存在于 原生的`SMBX`中,但现在`RMB1`是: ``` Field (RMB1, ByteAcc, NoLock, Preserve) { Offset (0x04), T2B0,8,T2B1,8 } ``` 就得到: ``` External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB.EC0.ECAV, MethodObj) External(BSLF, IntObj) External(_SB.PCI0.LPCB.EC0.RDBL, IntObj) External(_SB.PCI0.LPCB.EC0.RDWD, IntObj) External(_SB.PCI0.LPCB.EC0.RDBT, IntObj) External(_SB.PCI0.LPCB.EC0.RCBT, IntObj) External(_SB.PCI0.LPCB.EC0.RDQK, IntObj) External(_SB.PCI0.LPCB.EC0.MUEC, MutexObj) External(_SB.PCI0.LPCB.EC0.PRTC, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SBBY, IntObj) External(_SB.PCI0.LPCB.EC0.ADDR, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMDB, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SWTC, MethodObj) External(_SB.PCI0.LPCB.EC0.BCNT, FieldUnitObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 } OperationRegion (RMB1, EmbeddedControl, 0x18, 0x28) Field (RMB1, ByteAcc, NoLock, Preserve) { /* Note: disabling these fields (already defined in DSDT, referenced with External if needed, but keeping the correct offset! (very important!) */ /* PRTC, 8, SSTS, 5, , 1, ALFG, 1, CDFG, 1, ADDR, 8, CMDB, 8, */ Offset(4), // the data above is 4 bytes offset from the start of this region! //BDAT, 256, BA00,8,BA01,8,BA02,8,BA03,8, BA04,8,BA05,8,BA06,8,BA07,8, BA08,8,BA09,8,BA0A,8,BA0B,8, BA0C,8,BA0D,8,BA0E,8,BA0F,8, BA10,8,BA11,8,BA12,8,BA13,8, BA14,8,BA15,8,BA16,8,BA17,8, BA18,8,BA19,8,BA1A,8,BA1B,8, BA1C,8,BA1D,8,BA1E,8,BA1F,8 } OperationRegion(RMB2, EmbeddedControl, 0x40, 0x28) Field (RMB2, ByteAcc, NoLock, Preserve) { /* PRT2, 8, SST2, 5, , 1, ALF2, 1, CDF2, 1, ADD2, 8, CMD2, 8, */ Offset(4), //BDA2, 256, BB00,8,BB01,8,BB02,8,BB03,8, BB04,8,BB05,8,BB06,8,BB07,8, BB08,8,BB09,8,BB0A,8,BB0B,8, BB0C,8,BB0D,8,BB0E,8,BB0F,8, BB10,8,BB11,8,BB12,8,BB13,8, BB14,8,BB15,8,BB16,8,BB17,8, BB18,8,BB19,8,BB1A,8,BB1B,8, BB1C,8,BB1D,8,BB1E,8,BB1F,8 } Field (RMB1, ByteAcc, NoLock, Preserve) { Offset (0x04), T2B0,8,T2B1,8 } } ``` 然后,通过添加这些外部声明,继续处理更多的外部错误(它最终会结束!): ``` External(_SB.PCI0.LPCB.EC0.DAT0, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.WRBL, IntObj) External(_SB.PCI0.LPCB.EC0.WRWD, IntObj) External(_SB.PCI0.LPCB.EC0.WRBT, IntObj) External(_SB.PCI0.LPCB.EC0.SDBT, IntObj) External(_SB.PCI0.LPCB.EC0.WRQK, IntObj) External(_SB.PCI0.LPCB.EC0.PRT2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DAT1, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.ADD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.BCN2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA20, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA21, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SSTS, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SST2, FieldUnitObj) ``` 注意:使用`DAT0`时,不要在不同的作用域内对“其他”的`DAT0`感到迷惑! 此时,SSDT编译没有任何错误: ``` DefinitionBlock("", "SSDT", 2, "hack", "batt", 0) { External(_SB.PCI0, DeviceObj) External(_SB.PCI0.BAT0, DeviceObj) External(_SB.PCI0.LPCB.EC0.ACAP, MethodObj) External(CHGS, MethodObj) External(BLLO, IntObj) External(_SB.PCI0.LPCB.EC0.EB0S, FieldUnitObj) External(_SB.PCI0.BAT0.PUNT, IntObj) External(_SB.PCI0.LPCB.EC0.B0DV, FieldUnitObj) External(_SB.PCI0.BAT0.LFCC, IntObj) External(MBLF, IntObj) External(_SB.PCI0.BAT0.PBST, PkgObj) External(_SB.PCI0.LPCB.EC0.BATP, MethodObj) External(_SB.PCI0.BAT0.NBIX, PkgObj) External(_SB.PCI0.LPCB.EC0.GBTT, MethodObj) External(_SB.PCI0.BAT0._BIF, MethodObj) External(_SB.PCI0.BAT0.PBIF, PkgObj) External(_SB.PCI0.BAT0.BIXT, PkgObj) External(_SB.PCI0.LPCB.EC0.ECAV, MethodObj) External(BSLF, IntObj) External(_SB.PCI0.LPCB.EC0.RDBL, IntObj) External(_SB.PCI0.LPCB.EC0.RDWD, IntObj) External(_SB.PCI0.LPCB.EC0.RDBT, IntObj) External(_SB.PCI0.LPCB.EC0.RCBT, IntObj) External(_SB.PCI0.LPCB.EC0.RDQK, IntObj) External(_SB.PCI0.LPCB.EC0.MUEC, MutexObj) External(_SB.PCI0.LPCB.EC0.PRTC, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SBBY, IntObj) External(_SB.PCI0.LPCB.EC0.ADDR, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMDB, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SWTC, MethodObj) External(_SB.PCI0.LPCB.EC0.BCNT, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DAT0, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.WRBL, IntObj) External(_SB.PCI0.LPCB.EC0.WRWD, IntObj) External(_SB.PCI0.LPCB.EC0.WRBT, IntObj) External(_SB.PCI0.LPCB.EC0.SDBT, IntObj) External(_SB.PCI0.LPCB.EC0.WRQK, IntObj) External(_SB.PCI0.LPCB.EC0.PRT2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DAT1, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.ADD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.CMD2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.BCN2, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA20, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.DA21, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SSTS, FieldUnitObj) External(_SB.PCI0.LPCB.EC0.SST2, FieldUnitObj) External(_SB.PCI0.LPCB, DeviceObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion (ERM2, EmbeddedControl, Zero, 0xFF) Field(ERM2, ByteAcc, NoLock, Preserve) { Offset (0x93), TH00,8,TH01,8, TH10,8,TH11,8, Offset (0xc4), XC30,8,XC31,8, Offset (0xe4), YC30,8,YC31,8, Offset (0xF4), B0S0,8,B0S1,8, Offset (0xFC), B1S0,8,B1S1,8 } OperationRegion (RMB1, EmbeddedControl, 0x18, 0x28) Field (RMB1, ByteAcc, NoLock, Preserve) { /* Note: disabling these fields (already defined in DSDT, referenced with External if needed, but keeping the correct offset! (very important!) */ /* PRTC, 8, SSTS, 5, , 1, ALFG, 1, CDFG, 1, ADDR, 8, CMDB, 8, */ Offset(4), // the data above is 4 bytes offset from the start of this region! //BDAT, 256, BA00,8,BA01,8,BA02,8,BA03,8, BA04,8,BA05,8,BA06,8,BA07,8, BA08,8,BA09,8,BA0A,8,BA0B,8, BA0C,8,BA0D,8,BA0E,8,BA0F,8, BA10,8,BA11,8,BA12,8,BA13,8, BA14,8,BA15,8,BA16,8,BA17,8, BA18,8,BA19,8,BA1A,8,BA1B,8, BA1C,8,BA1D,8,BA1E,8,BA1F,8 } OperationRegion(RMB2, EmbeddedControl, 0x40, 0x28) Field (RMB2, ByteAcc, NoLock, Preserve) { /* PRT2, 8, SST2, 5, , 1, ALF2, 1, CDF2, 1, ADD2, 8, CMD2, 8, */ Offset(4), //BDA2, 256, BB00,8,BB01,8,BB02,8,BB03,8, BB04,8,BB05,8,BB06,8,BB07,8, BB08,8,BB09,8,BB0A,8,BB0B,8, BB0C,8,BB0D,8,BB0E,8,BB0F,8, BB10,8,BB11,8,BB12,8,BB13,8, BB14,8,BB15,8,BB16,8,BB17,8, BB18,8,BB19,8,BB1A,8,BB1B,8, BB1C,8,BB1D,8,BB1E,8,BB1F,8 } Field (RMB1, ByteAcc, NoLock, Preserve) { Offset (0x04), T2B0,8,T2B1,8 } } Scope (_SB.PCI0) { Scope (BAT0) { Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) If (^^LPCB.EC0.ACAP ()) { Store (One, Local0) } If (Local0) { If (CHGS (Zero)) { Store (0x02, Local0) } Else { Store (Zero, Local0) } } Else { Store (One, Local0) } If (BLLO) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (And (^^LPCB.EC0.EB0S, 0x08)) { ShiftLeft (One, 0x02, Local2) Or (Local0, Local2, Local0) } If (LGreaterEqual (Local1, 0x8000)) { Subtract (0xFFFF, Local1, Local1) } Store (Arg2, Local2) If (LEqual (PUNT, Zero)) { Multiply (Local1, ^^LPCB.EC0.B0DV, Local1) Multiply (Local2, 0x0A, Local2) } And (Local0, 0x02, Local3) If (LNot (Local3)) { Subtract (LFCC, Local2, Local3) Divide (LFCC, 0xC8, Local4, Local5) If (LLess (Local3, Local5)) { Store (LFCC, Local2) } } Else { Divide (LFCC, 0xC8, Local4, Local5) Subtract (LFCC, Local5, Local4) If (LGreater (Local2, Local4)) { Store (Local4, Local2) } } If (LNot (^^LPCB.EC0.ACAP ())) { Divide (Local2, MBLF, Local3, Local4) If (LLess (Local1, Local4)) { Store (Local4, Local1) } } Store (Local0, Index (PBST, Zero)) Store (Local1, Index (PBST, One)) Store (Local2, Index (PBST, 0x02)) Store (Arg3, Index (PBST, 0x03)) } Method (_BIX, 0, NotSerialized) // _BIX: Battery Information Extended { If (LNot (^^LPCB.EC0.BATP (Zero))) { Return (NBIX) } If (LEqual (^^LPCB.EC0.GBTT (Zero), 0xFF)) { Return (NBIX) } _BIF () Store (DerefOf (Index (PBIF, Zero)), Index (BIXT, One)) Store (DerefOf (Index (PBIF, One)), Index (BIXT, 0x02)) Store (DerefOf (Index (PBIF, 0x02)), Index (BIXT, 0x03)) Store (DerefOf (Index (PBIF, 0x03)), Index (BIXT, 0x04)) Store (DerefOf (Index (PBIF, 0x04)), Index (BIXT, 0x05)) Store (DerefOf (Index (PBIF, 0x05)), Index (BIXT, 0x06)) Store (DerefOf (Index (PBIF, 0x06)), Index (BIXT, 0x07)) Store (DerefOf (Index (PBIF, 0x07)), Index (BIXT, 0x0E)) Store (DerefOf (Index (PBIF, 0x08)), Index (BIXT, 0x0F)) Store (DerefOf (Index (PBIF, 0x09)), Index (BIXT, 0x10)) Store (DerefOf (Index (PBIF, 0x0A)), Index (BIXT, 0x11)) Store (DerefOf (Index (PBIF, 0x0B)), Index (BIXT, 0x12)) Store (DerefOf (Index (PBIF, 0x0C)), Index (BIXT, 0x13)) If (LEqual (DerefOf (Index (BIXT, One)), One)) { Store (Zero, Index (BIXT, One)) Store (DerefOf (Index (BIXT, 0x05)), Local0) Multiply (DerefOf (Index (BIXT, 0x02)), Local0, Index (BIXT, 0x02)) Multiply (DerefOf (Index (BIXT, 0x03)), Local0, Index (BIXT, 0x03)) Multiply (DerefOf (Index (BIXT, 0x06)), Local0, Index (BIXT, 0x06)) Multiply (DerefOf (Index (BIXT, 0x07)), Local0, Index (BIXT, 0x07)) Multiply (DerefOf (Index (BIXT, 0x0E)), Local0, Index (BIXT, 0x0E)) Multiply (DerefOf (Index (BIXT, 0x0F)), Local0, Index (BIXT, 0x0F)) Divide (DerefOf (Index (BIXT, 0x02)), 0x03E8, Local0, Index (BIXT, 0x02)) Divide (DerefOf (Index (BIXT, 0x03)), 0x03E8, Local0, Index (BIXT, 0x03)) Divide (DerefOf (Index (BIXT, 0x06)), 0x03E8, Local0, Index (BIXT, 0x06)) Divide (DerefOf (Index (BIXT, 0x07)), 0x03E8, Local0, Index (BIXT, 0x07)) Divide (DerefOf (Index (BIXT, 0x0E)), 0x03E8, Local0, Index (BIXT, 0x0E)) Divide (DerefOf (Index (BIXT, 0x0F)), 0x03E8, Local0, Index (BIXT, 0x0F)) } Store (B1B2(^^LPCB.EC0.XC30,^^LPCB.EC0.XC31), Index (BIXT, 0x08)) Store (0x0001869F, Index (BIXT, 0x09)) Return (BIXT) } } } Scope (_SB.PCI0.LPCB.EC0) { Method (BIFA, 0, NotSerialized) { If (ECAV ()) { If (BSLF) { Store (B1B2(B1S0,B1S1), Local0) } Else { Store (B1B2(B0S0,B0S1), Local0) } } Else { Store (Ones, Local0) } Return (Local0) } Method (SMBR, 3, Serialized) { Store (Package (0x03) { 0x07, Zero, Zero }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, RDBL)) { If (LNotEqual (Arg0, RDWD)) { If (LNotEqual (Arg0, RDBT)) { If (LNotEqual (Arg0, RCBT)) { If (LNotEqual (Arg0, RDQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { ShiftLeft (Arg1, One, Local3) Or (Local3, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, RDQK)) { If (LNotEqual (Arg0, RCBT)) { Store (Arg2, CMDB) } } WRBA(Zero) Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) If (LEqual (DerefOf (Index (Local0, Zero)), Zero)) { If (LEqual (Arg0, RDBL)) { Store (BCNT, Index (Local0, One)) Store (RDBA(), Index (Local0, 0x02)) } If (LEqual (Arg0, RDWD)) { Store (0x02, Index (Local0, One)) Store (B1B2(T2B0,T2B1), Index (Local0, 0x02)) } If (LEqual (Arg0, RDBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } If (LEqual (Arg0, RCBT)) { Store (One, Index (Local0, One)) Store (DAT0, Index (Local0, 0x02)) } } } Release (MUEC) Return (Local0) } Method (SMBW, 5, Serialized) { Store (Package (0x01) { 0x07 }, Local0) If (LNot (ECAV ())) { Return (Local0) } If (LNotEqual (Arg0, WRBL)) { If (LNotEqual (Arg0, WRWD)) { If (LNotEqual (Arg0, WRBT)) { If (LNotEqual (Arg0, SDBT)) { If (LNotEqual (Arg0, WRQK)) { Return (Local0) } } } } } Acquire (MUEC, 0xFFFF) Store (PRTC, Local1) Store (Zero, Local2) While (LNotEqual (Local1, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local0, Zero)) Store (Zero, Local1) } Else { Store (PRTC, Local1) } } If (LLessEqual (Local2, 0x03E8)) { WRBA(Zero) ShiftLeft (Arg1, One, Local3) Store (Local3, ADDR) If (LNotEqual (Arg0, WRQK)) { If (LNotEqual (Arg0, SDBT)) { Store (Arg2, CMDB) } } If (LEqual (Arg0, WRBL)) { Store (Arg3, BCNT) WRBA(Arg4) } If (LEqual (Arg0, WRWD)) { Store(Arg4,T2B0) Store(ShiftRight(Arg4,8),T2B1) } If (LEqual (Arg0, WRBT)) { Store (Arg4, DAT0) } If (LEqual (Arg0, SDBT)) { Store (Arg4, DAT0) } Store (Arg0, PRTC) Store (SWTC (Arg0), Index (Local0, Zero)) } Release (MUEC) Return (Local0) } Method (ECSB, 7, NotSerialized) { Store (Package (0x05) { 0x11, Zero, Zero, Zero, Buffer (0x20){} }, Local1) If (LGreater (Arg0, One)) { Return (Local1) } If (ECAV ()) { Acquire (MUEC, 0xFFFF) If (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } Store (Zero, Local2) While (LNotEqual (Local0, Zero)) { Stall (0x0A) Increment (Local2) If (LGreater (Local2, 0x03E8)) { Store (SBBY, Index (Local1, Zero)) Store (Zero, Local0) } ElseIf (LEqual (Arg0, Zero)) { Store (PRTC, Local0) } Else { Store (PRT2, Local0) } } If (LLessEqual (Local2, 0x03E8)) { If (LEqual (Arg0, Zero)) { Store (Arg2, ADDR) Store (Arg3, CMDB) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCNT) WRBA(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DAT0) Store (Arg5, DAT1) } Store (Arg1, PRTC) } Else { Store (Arg2, ADD2) Store (Arg3, CMD2) If (LOr (LEqual (Arg1, 0x0A), LEqual (Arg1, 0x0B))) { Store (DerefOf (Index (Arg6, Zero)), BCN2) WRBB(DerefOf (Index (Arg6, One))) } Else { Store (Arg4, DA20) Store (Arg5, DA21) } Store (Arg1, PRT2) } Store (0x7F, Local0) If (LEqual (Arg0, Zero)) { While (PRTC) { Sleep (One) Decrement (Local0) } } Else { While (PRT2) { Sleep (One) Decrement (Local0) } } If (Local0) { If (LEqual (Arg0, Zero)) { Store (SSTS, Local0) Store (DAT0, Index (Local1, One)) Store (DAT1, Index (Local1, 0x02)) Store (BCNT, Index (Local1, 0x03)) Store (RDBA(), Index (Local1, 0x04)) } Else { Store (SST2, Local0) Store (DA20, Index (Local1, One)) Store (DA21, Index (Local1, 0x02)) Store (BCN2, Index (Local1, 0x03)) Store (RDBB(), Index (Local1, 0x04)) } And (Local0, 0x1F, Local0) If (Local0) { Add (Local0, 0x10, Local0) } Store (Local0, Index (Local1, Zero)) } Else { Store (0x10, Index (Local1, Zero)) } } Release (MUEC) } Return (Local1) } Method (TACH, 1, Serialized) { If (ECAV ()) { Switch (Arg0) { Case (Zero) { Store (B1B2(TH00,TH01), Local0) Break } Case (One) { Store (B1B2(TH10,TH11), Local0) Break } Default { Return (Ones) } } Multiply (Local0, 0x02, Local0) If (LNotEqual (Local0, Zero)) { Divide (0x0041CDB4, Local0, Local1, Local0) Return (Local0) } Else { Return (Ones) } } Else { Return (Ones) } } } Method (B1B2, 2, NotSerialized) { Return (Or (Arg0, ShiftLeft (Arg1, 8))) } Scope (_SB.PCI0.LPCB) { Scope (EC0) { Method (RDBA, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BA00, Index(TEMP, 0x00)) Store (BA01, Index(TEMP, 0x01)) Store (BA02, Index(TEMP, 0x02)) Store (BA03, Index(TEMP, 0x03)) Store (BA04, Index(TEMP, 0x04)) Store (BA05, Index(TEMP, 0x05)) Store (BA06, Index(TEMP, 0x06)) Store (BA07, Index(TEMP, 0x07)) Store (BA08, Index(TEMP, 0x08)) Store (BA09, Index(TEMP, 0x09)) Store (BA0A, Index(TEMP, 0x0A)) Store (BA0B, Index(TEMP, 0x0B)) Store (BA0C, Index(TEMP, 0x0C)) Store (BA0D, Index(TEMP, 0x0D)) Store (BA0E, Index(TEMP, 0x0E)) Store (BA0F, Index(TEMP, 0x0F)) Store (BA10, Index(TEMP, 0x10)) Store (BA11, Index(TEMP, 0x11)) Store (BA12, Index(TEMP, 0x12)) Store (BA13, Index(TEMP, 0x13)) Store (BA14, Index(TEMP, 0x14)) Store (BA15, Index(TEMP, 0x15)) Store (BA16, Index(TEMP, 0x16)) Store (BA17, Index(TEMP, 0x17)) Store (BA18, Index(TEMP, 0x18)) Store (BA19, Index(TEMP, 0x19)) Store (BA1A, Index(TEMP, 0x1A)) Store (BA1B, Index(TEMP, 0x1B)) Store (BA1C, Index(TEMP, 0x1C)) Store (BA1D, Index(TEMP, 0x1D)) Store (BA1E, Index(TEMP, 0x1E)) Store (BA1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBA, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BA00) Store (DerefOf(Index(TEMP, 0x01)), BA01) Store (DerefOf(Index(TEMP, 0x02)), BA02) Store (DerefOf(Index(TEMP, 0x03)), BA03) Store (DerefOf(Index(TEMP, 0x04)), BA04) Store (DerefOf(Index(TEMP, 0x05)), BA05) Store (DerefOf(Index(TEMP, 0x06)), BA06) Store (DerefOf(Index(TEMP, 0x07)), BA07) Store (DerefOf(Index(TEMP, 0x08)), BA08) Store (DerefOf(Index(TEMP, 0x09)), BA09) Store (DerefOf(Index(TEMP, 0x0A)), BA0A) Store (DerefOf(Index(TEMP, 0x0B)), BA0B) Store (DerefOf(Index(TEMP, 0x0C)), BA0C) Store (DerefOf(Index(TEMP, 0x0D)), BA0D) Store (DerefOf(Index(TEMP, 0x0E)), BA0E) Store (DerefOf(Index(TEMP, 0x0F)), BA0F) Store (DerefOf(Index(TEMP, 0x10)), BA10) Store (DerefOf(Index(TEMP, 0x11)), BA11) Store (DerefOf(Index(TEMP, 0x12)), BA12) Store (DerefOf(Index(TEMP, 0x13)), BA13) Store (DerefOf(Index(TEMP, 0x14)), BA14) Store (DerefOf(Index(TEMP, 0x15)), BA15) Store (DerefOf(Index(TEMP, 0x16)), BA16) Store (DerefOf(Index(TEMP, 0x17)), BA17) Store (DerefOf(Index(TEMP, 0x18)), BA18) Store (DerefOf(Index(TEMP, 0x19)), BA19) Store (DerefOf(Index(TEMP, 0x1A)), BA1A) Store (DerefOf(Index(TEMP, 0x1B)), BA1B) Store (DerefOf(Index(TEMP, 0x1C)), BA1C) Store (DerefOf(Index(TEMP, 0x1D)), BA1D) Store (DerefOf(Index(TEMP, 0x1E)), BA1E) Store (DerefOf(Index(TEMP, 0x1F)), BA1F) } Method (RDBB, 0, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (BB00, Index(TEMP, 0x00)) Store (BB01, Index(TEMP, 0x01)) Store (BB02, Index(TEMP, 0x02)) Store (BB03, Index(TEMP, 0x03)) Store (BB04, Index(TEMP, 0x04)) Store (BB05, Index(TEMP, 0x05)) Store (BB06, Index(TEMP, 0x06)) Store (BB07, Index(TEMP, 0x07)) Store (BB08, Index(TEMP, 0x08)) Store (BB09, Index(TEMP, 0x09)) Store (BB0A, Index(TEMP, 0x0A)) Store (BB0B, Index(TEMP, 0x0B)) Store (BB0C, Index(TEMP, 0x0C)) Store (BB0D, Index(TEMP, 0x0D)) Store (BB0E, Index(TEMP, 0x0E)) Store (BB0F, Index(TEMP, 0x0F)) Store (BB10, Index(TEMP, 0x10)) Store (BB11, Index(TEMP, 0x11)) Store (BB12, Index(TEMP, 0x12)) Store (BB13, Index(TEMP, 0x13)) Store (BB14, Index(TEMP, 0x14)) Store (BB15, Index(TEMP, 0x15)) Store (BB16, Index(TEMP, 0x16)) Store (BB17, Index(TEMP, 0x17)) Store (BB18, Index(TEMP, 0x18)) Store (BB19, Index(TEMP, 0x19)) Store (BB1A, Index(TEMP, 0x1A)) Store (BB1B, Index(TEMP, 0x1B)) Store (BB1C, Index(TEMP, 0x1C)) Store (BB1D, Index(TEMP, 0x1D)) Store (BB1E, Index(TEMP, 0x1E)) Store (BB1F, Index(TEMP, 0x1F)) Return (TEMP) } Method (WRBB, 1, Serialized) { Name (TEMP, Buffer(0x20) { }) Store (Arg0, TEMP) Store (DerefOf(Index(TEMP, 0x00)), BB00) Store (DerefOf(Index(TEMP, 0x01)), BB01) Store (DerefOf(Index(TEMP, 0x02)), BB02) Store (DerefOf(Index(TEMP, 0x03)), BB03) Store (DerefOf(Index(TEMP, 0x04)), BB04) Store (DerefOf(Index(TEMP, 0x05)), BB05) Store (DerefOf(Index(TEMP, 0x06)), BB06) Store (DerefOf(Index(TEMP, 0x07)), BB07) Store (DerefOf(Index(TEMP, 0x08)), BB08) Store (DerefOf(Index(TEMP, 0x09)), BB09) Store (DerefOf(Index(TEMP, 0x0A)), BB0A) Store (DerefOf(Index(TEMP, 0x0B)), BB0B) Store (DerefOf(Index(TEMP, 0x0C)), BB0C) Store (DerefOf(Index(TEMP, 0x0D)), BB0D) Store (DerefOf(Index(TEMP, 0x0E)), BB0E) Store (DerefOf(Index(TEMP, 0x0F)), BB0F) Store (DerefOf(Index(TEMP, 0x10)), BB10) Store (DerefOf(Index(TEMP, 0x11)), BB11) Store (DerefOf(Index(TEMP, 0x12)), BB12) Store (DerefOf(Index(TEMP, 0x13)), BB13) Store (DerefOf(Index(TEMP, 0x14)), BB14) Store (DerefOf(Index(TEMP, 0x15)), BB15) Store (DerefOf(Index(TEMP, 0x16)), BB16) Store (DerefOf(Index(TEMP, 0x17)), BB17) Store (DerefOf(Index(TEMP, 0x18)), BB18) Store (DerefOf(Index(TEMP, 0x19)), BB19) Store (DerefOf(Index(TEMP, 0x1A)), BB1A) Store (DerefOf(Index(TEMP, 0x1B)), BB1B) Store (DerefOf(Index(TEMP, 0x1C)), BB1C) Store (DerefOf(Index(TEMP, 0x1D)), BB1D) Store (DerefOf(Index(TEMP, 0x1E)), BB1E) Store (DerefOf(Index(TEMP, 0x1F)), BB1F) } } } } //EOF ``` 最后文件可以保存为AML(建议名称:`SSDT-BATT.aml`),并放置在`ACPI/patched`中。 但是你不能期望电池状态与原生的DSDT一起工作。 ## 重新命名现有的方法(Renaming existing methods) 在DSDT和这个`SSDT-BATT.aml`中有重复的方法。对于DSDT中的每个方法,`SSDT-BATT.aml`版本将替换,我们必须将DSDT中的方法重命名为其他的,来允许SSDT版本进行重载(override)。 就像在第一篇文章中一样,这个部分遵循“Rename/Replace”模式。 需要替换的方法有FBST、_BIX、BIFA、SMBR、SMBW、ECSB和TACH。 对于这个步骤,为原生的`dsdt.aml`创建一个混合字节码列表非常有用。 它可以用:“`iasl -l -dl DSDT`”来创建,会在在`dsdt.dsl`中创建一个混合列表。 FBST的方法: ``` Method (FBST, 4, NotSerialized) { And (Arg1, 0xFFFF, Local1) Store (Zero, Local0) FF74: 14 43 12 46 42 53 54 04 7B 69 0B FF FF 61 70 00 // .C.FBST.{i...ap. FF84: 60 ``` 一个可能的重命名补丁 (`FBST->XBST`): ~~~ Find: <46 42 53 54 04> Replace: <58 42 53 54 04> ~~~ 通过在`hex Fiend`这样的hex编辑器中搜索,验证找到的十六进制数据只有一个匹配,这是一个好主意。 因为这个补丁**只**适用于方法定义,而不是其他可能出现在`DSDT`(或原生的`SSDTs`)中的代码。 您选择的目标名称必须在该方法所在的范围内惟一。创建重复的方法会引起内核恐慌(kernel panic)。把第一个字母改成' X '通常是可以的,但不能保证。 其他方法的补丁: ~~~ _BIX->XBIX: Find: <5F 42 49 58 00> Replace: <58 42 49 58 00> BIFA->XIFA: Find: <42 49 46 41 00> Replace: <58 49 46 41 00> SMBR->XMBR: Find: <53 4D 42 52 0B> Replace: <58 4D 42 52 0B> SMBW->XMBW: Find: <53 4D 42 57 0D> Replace: <58 4D 42 57 0D> ECSB->XCSB: Find: <45 43 53 42 07> Replace: <58 43 53 42 07> TACH->XACH: Find: <54 41 43 48 09> Replace: <58 41 43 48 09> ~~~ 将这些补丁添加到`config.plist/ACPI/DSDT/Patches`,原生的DSDT的方法将被Clover重命名。由于重命名,所以会使在`SSDT-BATT.aml`中定义的已经打了补丁的方法被重载(override)。 ## 总结(Conclusion) 电池状态的热修补可能是最复杂的热补丁操作之一。写所有“外部”参考的过程是冗长乏味的。 这需要一些时间(你在这里阅读的文本要花上几个小时)。慢慢看吧~。 # ======================= # 使用Hotpatch 来禁用独显(Disabling discrete)/切换GPU 这第三个帖子专门用于在一个切换的双GPU笔记本中禁用独显,使用的是相同的示例ACPI 文件作为静态补丁指南:https://www.tonymacx86.com/threads/guide-disabling-discrete-graphics-in-dual-gpu-laptops.163772/ 。 您应该下载附加到该指南的 ACPI/origin文件, 以便您跟着我一起做。 与静态补丁指南一样,目的是相对简单:在ACPI初始化过程中,为独立的GPU调用`_OFF`方法(来自`_INI`方法)。 但是由于`_OFF`可以包含`EC`相关的代码,而这些代码需要在`_REG`中执行,而不是`_INI`,所以这些细节使得它更加复杂。 ## 构建替换`_INI/_OFF/_REG`方法(Building the replacement _INI/_OFF/_REG methods) 在这个例子中,目标`_INI`方法在`SSDT-7`中,`_OFF`方法在`SSDT-8`中。这个独显设备的路径是`_SB.PCI0.RP05.PEGP`。在示例文件中,`_OFF`包含的`EC`相关代码必须移动到`_REG`。为了完成这个补丁程序,我们需要替换`_INI`、`_OFF`和`_REG`,因此每个都需要重新命名为`XINI`、`XOFF`和`XREG`。 注意:实际上您需要修补的方法可能是不同的。这完全取决于`_OFF`路径中的代码。例如,在其他ACPI集合中,碰巧地`SGOF`(可能是其他名称)有`EC`相关的代码,而这些代码又必须移动到`_REG`。在这种情况下,您需要为这个`SGOF`使用rename/replace,也许不需要使用`_OFF`方法。仔细分析你现有的代码。 Clover的`config.plist`中补丁将会在后面进行。现在,让我们来看一下替换方法的SSDT: 这SSDT将包括打了补丁的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "D-GPU", 0) { External(_SB.PCI0.RP05.PEGP, DeviceObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.RP05.PEGP.XOFF, MethodObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.LPCB.EC0.SPIN, MethodObj) Scope(_SB.PCI0.RP05.PEGP) { Method(_INI) { XINI() // call original _INI, now renamed XINI _OFF() // call (patched) _OFF } Method(_OFF, 0, Serialized) { If (LEqual (CTXT, Zero)) { /* \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) */ If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } SGOF () } } Scope(_SB.PCI0.LPCB.EC0) { Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) // code that was removed from _OFF } } } } ``` 此时,代码不会编译,因为在`_OFF`中引用的一些符号是不可用的。就像电池打补丁指南一样,我们必须添加适当的外部声明。 使用编译器产生的错误来确定需要查找的符号,然后添加适当的外部声明。在这个示例案例: ``` External(_SB.PCI0.RP05.PEGP.CTXT, IntObj) External(_SB.PCI0.RP05.PEGP.GPRF, IntObj) External(_SB.PCI0.RP05.PEGP.VGAR, FieldUnitObj) External(_SB.PCI0.RP05.PEGP.VGAB, BuffObj) External(_SB.PCI0.RP05.PEGP.SGOF, MethodObj) ``` 然后结果的SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "D-GPU", 0) { External(_SB.PCI0.RP05.PEGP, DeviceObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.RP05.PEGP.XOFF, MethodObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.LPCB.EC0.SPIN, MethodObj) External(_SB.PCI0.RP05.PEGP.CTXT, IntObj) External(_SB.PCI0.RP05.PEGP.GPRF, IntObj) External(_SB.PCI0.RP05.PEGP.VGAR, FieldUnitObj) External(_SB.PCI0.RP05.PEGP.VGAB, BuffObj) External(_SB.PCI0.RP05.PEGP.SGOF, MethodObj) Scope(_SB.PCI0.RP05.PEGP) { Method(_INI) { XINI() // call original _INI, now renamed XINI _OFF() // call (patched) _OFF } Method(_OFF, 0, Serialized) { If (LEqual (CTXT, Zero)) { /* \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) */ If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } SGOF () } } Scope(_SB.PCI0.LPCB.EC0) { Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) // code that was removed from _OFF } } } } ``` 现在编译没有错误,但是有一个警告:"`39, 3079, _REG has no corresponding Operation Region`"。这个警告很重要。除非我们添加一个假冒的EC操作区域(EC OperationRegion),否则不会调用`_REG`。 我们来添加它: ``` ... Scope(_SB.PCI0.LPCB.EC0) { OperationRegion(RME3, EmbeddedControl, 0x00, 0xFF) Method(_REG, 2) { ... ``` 然后完整的SSDT: ``` DefinitionBlock("", "SSDT", 2, "hack", "D-GPU", 0) { External(_SB.PCI0.RP05.PEGP, DeviceObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.RP05.PEGP.XOFF, MethodObj) External(_SB.PCI0.RP05.PEGP.XINI, MethodObj) External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.LPCB.EC0.SPIN, MethodObj) External(_SB.PCI0.RP05.PEGP.CTXT, IntObj) External(_SB.PCI0.RP05.PEGP.GPRF, IntObj) External(_SB.PCI0.RP05.PEGP.VGAR, FieldUnitObj) External(_SB.PCI0.RP05.PEGP.VGAB, BuffObj) External(_SB.PCI0.RP05.PEGP.SGOF, MethodObj) Scope(_SB.PCI0.RP05.PEGP) { Method(_INI) { XINI() // call original _INI, now renamed XINI _OFF() // call (patched) _OFF } Method(_OFF, 0, Serialized) { If (LEqual (CTXT, Zero)) { /* \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) */ If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } SGOF () } } Scope(_SB.PCI0.LPCB.EC0) { OperationRegion(RME3, EmbeddedControl, 0x00, 0xFF) Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) // code that was removed from _OFF } } } } ``` 此时,您可以保存SSDT(建议:`SSDT-DGPU.aml`)。 准备好放入`ACPI/patched`。 但是我们仍然需要在原生的`ACPI`中重命名原始方法。 ## 重命名方法 如前所述,以下方法需要重新命名: ~~~ _SB.PCI0.RP05.PEGP._INI -> XINI _SB.PCI0.RP05.PEGP._OFF -> XOFF _SB.PCI0.LPCB.EC0._REG -> XREG ~~~ 为了确定所需的二进制补丁,我们需要一个DSDT的混合列表`DSDT.aml`, `SSDT-7.aml`, 和 `SSDT-8.aml`。 用下面的方法创建: ~~~ iasl -dl -l DSDT.aml SSDT-7.aml SSDT-8.aml ~~~ 产生的混合列表在`DSDT.dsl`, `SSDT-7.dsl`, 和 `SSDT-8.dsl`中。 这里是`DSDT.dsl`中的`_REG`的混合清单 ``` Method (_REG, 2, NotSerialized) // _REG: Region Availability { D2B8: 14 12 5F 52 45 47 02 // .._REG. If (LEqual (Arg0, 0x03)) { D2BF: A0 0B 93 68 0A 03 // ...h.. Store (Arg1, ECFL) } } } } D2C5: 70 69 45 43 46 4C ``` 使用的补丁应该只重命名这个`_REG`,而不是ACPI集中的其他`_REG`方法。我们可以通过从代码中获取名称/头(name/header )加上几个字节(bytes)来重命名它。 这个模式可以获取足够的字节来唯一确定: ``` Find: <5F 52 45 47 02 A0 0B 93 68 0A 03 70 69 45 43 46 4C> Replace: <58 52 45 47 02 A0 0B 93 68 0A 03 70 69 45 43 46 4C> ``` `SSDT-7.dsl`的`_INI`方法的混合列表: ``` Method (_INI, 0, NotSerialized) // _INI: Initialize { 03D1: 14 1F 5F 49 4E 49 00 // .._INI. Store (Zero, \_SB.PCI0.RP05.PEGP._ADR) } 03D8: 70 00 5C 2F 05 5F 53 42 5F 50 43 49 30 52 50 30 // p.\/._SB_PCI0RP0 03E8: 35 50 45 47 50 5F 41 44 52 // 5PEGP_ADR ``` 产生的补丁... ~~~ Find: <5F 49 4E 49 00 70 00 5C 2F 05 5F 53 42 5F 50 43 49 30 52 50 30 35 50 45 47 50> Replace: <58 49 4E 49 00 70 00 5C 2F 05 5F 53 42 5F 50 43 49 30 52 50 30 35 50 45 47 50> ~~~ 再来看`SSDT-8.dsl`中的`_OFF`: ``` Method (_OFF, 0, Serialized) // _OFF: Power Off { 032B: 14 45 04 5F 4F 46 46 08 // .E._OFF. If (LEqual (CTXT, Zero)) { \_SB.PCI0.LPCB.EC0.SPIN (0x96, Zero) 0333: A0 39 93 43 54 58 54 00 5C 2F 05 5F 53 42 5F 50 // .9.CTXT.\/._SB_P 0343: 43 49 30 4C 50 43 42 45 43 30 5F 53 50 49 4E 0A // CI0LPCBEC0_SPIN. 0353: 96 00 ``` 产生的补丁... ~~~ Find: <5F 4F 46 46 08 A0 39 93 43 54 58 54> Replace: <58 4F 46 46 08 A0 39 93 43 54 58 54> ~~~ 注意:每个补丁都可能会被减少,但是您需要仔细检查所有原生的DSDT和SSDTs中的**查找**模式,因为您不想和除了目标方法外的其他方法进行匹配。因为`_REG`、`_INI`和`_OFF`是其他作用域中方法的常用名称,所以我们需要小心。 ## 简单例子 由于需要修补 `_OFF`, `_INI`, 和`_REG`,所以上面提到的ASUS文件是相对复杂的。 让我们看一个简单得多的例子。这些是用于`Asus K550VX-DM406T`的文件,并附在这个帖子上。请下载他们,以便你能一起实践。 当我们在`SSDT-14`中查看`_OFF`方法时,没有与`EC`相关的代码。它调用这个`PGOF`,但是这个在`SSDT-3`中定义的`PGOF`方法也没有与`EC`相关的代码: ``` Method (_OFF, 0, Serialized) // _OFF: Power Off { If (LEqual (CTXT, Zero)) { If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } Store (One, CTXT) } PGOF (Zero) } ``` 这意味着`_OFF`方法可以直接在`_INI`中被调用。 如果你查看在ACPI集合中的所有`_INI`方法,你会发现在`_OFF`的路径(`_SB.PCI0.PEG0.PEGP`)中是没有`_INI`的。 这意味着我们可以简单地在正确的路径上添加一个带有`_INI`的`SSDT`,而`_INI`只需调用`_OFF`。 这是一种简单的方法: ``` DefinitionBlock("", "SSDT", 2, "hack", "DGPU", 0) { External(_SB.PCI0.PEG0.PEGP._OFF, MethodObj) Method(_SB.PCI0.PEG0.PEGP._INI) { _OFF() } } ``` 正如在主要的禁用独显指南(静态补丁)中所提到的,有时您需要调用`_PS3`而不是`_OFF`。这是一个尝试和误差处理,以确定哪个是最好的。 和上面相同的代码,但是调用` _PS3`: ``` DefinitionBlock("", "SSDT", 2, "hack", "DGPU", 0) { External(_SB.PCI0.PEG0.PEGP._PS3, MethodObj) Method(_SB.PCI0.PEG0.PEGP._INI) { _PS3() } } ``` 保存为`SSDT-DGPU.aml` 并且 NVIDIA应该被禁用。 ## 简单的例子变得没那么简单了 尽管上面提到的方法通常会在这个场景中使用(即使是在其他出现相同场景的笔记本上:在`_OFF`路径中没有`EC`访问,在该路径中不存在`_INI`),为了关掉专用的Nvidia风扇,这台特定的笔记本电脑需要额外的补丁。 所以需要进行一些调查。通过查看`_OFF`代码可以看到,它调用`PGOF(0)`来完成大部分工作。如果我们搜索通过`Arg0==Zero`参数调用`PGOF`的其他示例,我们会在`SSDT-3.dsl`中找到这段代码: ``` ElseIf (LAnd (LGreater (OSYS, 0x07D9), PEGS ())) { FAOF () PGOF (Zero) ... ``` 注意`FAOF`的调用。这是为了“FAN OFF(风扇关闭)”吗?似乎是可能的。 再看,`SSDT-3`中的`FAOF`和`FAON`: ``` Method (FAON, 0, Serialized) { \_SB.PCI0.LPCB.EC0.WRAM (0x052B, 0x9E) \_SB.PCI0.LPCB.EC0.WRAM (0x0520, 0x8B) Store (\_SB.PCI0.LPCB.EC0.RRAM (0x0521), Local0) And (Local0, 0xCF, Local0) Or (Local0, 0x20, Local0) \_SB.PCI0.LPCB.EC0.WRAM (0x0521, Local0) } Method (FAOF, 0, Serialized) { Store (\_SB.PCI0.LPCB.EC0.RRAM (0x0521), Local0) And (Local0, 0xCF, Local0) \_SB.PCI0.LPCB.EC0.WRAM (0x0521, Local0) \_SB.PCI0.LPCB.EC0.WRAM (0x0520, 0x89) \_SB.PCI0.LPCB.EC0.WRAM (0x03A4, Zero) \_SB.PCI0.LPCB.EC0.WRAM (0x03A5, Zero) } ``` 你可以看到它做了很多EC操作(manipulations)。典型的`EC`控制系统的风扇,所以这似乎证实这些方法是为了“FAN ON(风扇打开)”和“FAN OFF(风扇关闭)”。 由于这些方法操作了`EC`,所以我们不能在没有`EC`的情况下调用`FAOF`。要做到这一点,我们需要修补`_REG`。 因此,将必要的代码添加到我们的`SSDT`中: ``` DefinitionBlock("", "SSDT", 2, "hack", "DGPU", 0) { External(_SB.PCI0.PEG0.PEGP._OFF, MethodObj) Method(_SB.PCI0.PEG0.PEGP._INI) { _OFF() } External(_SB.PCI0.LPCB.EC0, DeviceObj) External(_SB.PCI0.LPCB.EC0.XREG, MethodObj) External(_SB.PCI0.PEG0.FAOF, MethodObj) Scope(_SB.PCI0.LPCB.EC0) { OperationRegion(RME3, EmbeddedControl, 0x00, 0xFF) Method(_REG, 2) { XREG(Arg0, Arg1) // call original _REG, now renamed XREG If (3 == Arg0 && 1 == Arg1) // EC ready? { \_SB.PCI0.PEG0.FAOF() // turn dedicated Nvidia fan off } } } } ``` 我们需要重命名`_REG to XREG`的补丁(同样,是基于`DSDT.aml`的混合清单): ~~~ Find: <5F 52 45 47 02 A0 0B 93 68 0A 03> Replace: <58 52 45 47 02 A0 0B 93 68 0A 03> ~~~ 通过`config.plist`中的该补丁,`EC0._REG`更名为`XREG`。系统最终调用我们修改的`_REG`,反过来它将调用原始的`_REG`(重命名为`XREG`)并且调用`FAOF`来关闭风扇。 ## 总结 与电池状态相比,通过热修补来禁用独显,代码要简单一些,但涉及到的概念都是类似的。 # ~~4楼为未来预留~~ # ======================= # 如果你还看不懂? [Acer VN7-591G-50LW抛弃传统静态dsdt使用hotpatch方式配置](http://bbs.pcbeta.com/viewthread-1753771-1-1.html) [Hotpatch简易教程(修复声卡、屏蔽独显、驱动核显、快捷键调节亮度)](http://bbs.pcbeta.com/viewthread-1766329-1-1.html) # 常用 hotpatch 1. SSDT-Disable-DGPU.aml 屏蔽独显 2. SSDT-PluginType1.dsl intel 4代及更高平台变频使用,或者你可以使用ssdtPRGen来生成,论坛找,不多说。 3. SSDT-PNLF.dsl 有了这个才能实现快捷键亮度调节 4. SSDT-HDAU.dsl 声卡相关,SSDT-Config.dsl中写入了ID,这里也要写,config.plist中就不需要声卡id了
';

[指南] hackintosh之SSDT/DSDT

最后更新于:2022-04-02 05:46:00

[TOC] **** # 【指南】 给笔记本的 DSDT/SSDTs 打补丁 英文原文:[Patching LAPTOP DSDT/SSDTs](https://www.tonymacx86.com/threads/guide-patching-laptop-dsdt-ssdts.152573/) # 开始学习SSDT/DSDT 常见论坛上的大神们谈论 DSDT、SSDT、AML、DSL 不明觉厉,曾遍寻论坛求解释未果。 我更喜欢通过 DSDT 进行设备注入的**SSDT**,因为**更新 BIOS,移动 PCI 卡或添加/移除 PCI卡可能需要您提取和编辑新的DSDT**。 很多人都知道使用 DSDT 补丁可以开双核,但 DSDT 的功能不仅仅如此,除了开双核,还可以可以修复 ACPI 缺陷(不需要 Disabler.kext ,原版cpupowermanagement 正常使用),RTC,HPET 缺陷(原版 kext 正常工作),显卡(代替 efistring),声卡(只是代替了 HDAEnabler.kext ),网卡(包括 TimeMachine 问题),此外还可以解决其他很多奇奇怪怪的问题,因此建议尽可能使用 DSDT 补丁。 # ACPI ACPI 是 Hewlett-Packard, Intel, Microsoft, Phoenix 和 Toshiba 共同制定的一个开放的行业规范。是 The Advanced Configuration and Power Interface 的缩写,也就是“电源管理模式和配置管理的接口规范”。从名字可以看出主要是“电源管理”和“配置管理”。是 BIOS 的一个高级功能模块。 它帮助操作系统合理控制和分配计算机硬件设备的电量,有 了ACPI,操作系统可以根据设备实际情况,根据需要把不同的硬件设备关闭。如Win7或者Win8系统,系统睡眠时,系统把当前信息储存在内存中,只保留内存等几个关键部件硬件的通电,使计算机处在高度节电状态。当然这只是它功能中的很少一部分。 它主要涵盖的功能包括: 1. System power management(系统电源管理) 2. Device power management(设备电源管理) 3. Processor power management(处理器电源管理) 4. Device and processor performance management(设备及处理器性能管理) 5. Configuration / Plug and Play(配置/即插即用) 6. System Events(系统事件) 7. Battery management(电池管理) 8. Thermal management(温度管理) 9. Embedded Controller(嵌入式控制器) 10. SMBus Controller(SMBus控制器) 在计算机应用平台,ACPI 越来越重要。ACPI由很多表组成,包括:RSDP,SDTH,RSDT,FADT,FACS,**DSDT**,**SSDT**,MADT,SBST,XSDT,ECDT,SLIT,SRAT。其中**DSDT**就是它的一个重要的描述表。 DSDT 包含了所有和基本系统(basesystem)不同的设备的信息,basesystem 每台机器都是一样的,这个是在 acpispec 里指定的,但是每台机器都是不相同的,所以不相同的设备大都是由 DSDT 表来描述。它包含了很多AML代码。大多数 BIOS 是针对 windows 开发的,而 windows 自己也不完全遵循 acpi 规范,所以因为 BIOS 的 bug,这些代码本身可能有错,导致其他的系统,如 linux,mac os 出错。 **Mac OS X不完整支持ACPI规范,仅支持它的子集DSDT**。 [[指南] Intel IGPU HDMI/DP audio (Sandy/Ivy/Haswell/Broadwell/Skylake)](%5B%E6%8C%87%E5%8D%97%5DIntelIGPUHDMI-DPaudioSandy-Ivy-Haswell-Broadwell-Skylake.md)我们可以手动修复这些bug**使之兼容MAC系统**。 DSDT在bios里是以编译后的`aml`文件存在,需要把它解出来,反编译成`aml`代码形式(dsl文件,文本文件),代码修改完毕再重新编译,替换掉bios里原来的dsdt表。 **对于非苹果电脑,要使用上尽可能完美的OS X系统,可以说修改DSDT是最有效的方法。** # DSDT DSDT 是 The Differentiated System Description Table 的简写。字面上就可以知道它是一个描述系统不同信息的表。它包含了所有除基本系统以外所有不同设备的信息,也就是**每台计算机设备的基本系统是相同的,而不相同的设备用 DSDT 来描述**。 DSDT 表代码为 ACPI Machine Language (AML)。 用户通过修改DSDT可以得到更好的硬件支持,最简单的理解就是DSDT是描述硬件的。 修改 DSDT 的主要目的就是让 mac系统识别存在这个硬件并告诉 mac 系统你的硬件位置,以便让 mac 系统内置的驱动来驱动硬件工作。 修改 DSDT 的基本过程: 提取 bios 的 AML 文件,反编译为 dsl text 文件,修改完毕后,编译到 Aml,然后替换 BIOS 中的 DSDT。 # 基本步骤 如果下面选项会对原始ACPI产生显著的改变(尤其是系统内存区域),你需要重新提取,重新打补丁: - 更新 BIOS - 更改 BIOS 选项 - 更改硬件和内存设置。 使用补丁修改 DSDT/SSDT 包含了以下步骤: - 提取原始ACPI文件 - 反编译原始文件 - 分析并筛选这些原始文件 - 使用补丁修改 - 编译并保存,再放到启动引导的特定目录 ## 提取原始ACPI文件(推荐) 使用 Clover 的 `F4`进行提取,因为易于提取,并且易于比较 `ACPI/origin` 和 `ACPI/patch`(用于故障排除)。 所有BIOS实现都向操作系统提供 ACPI 文件。 因此,在任何操作系统上,您都可以提取它们以便以后进行修补。 因此,可以在 Linux,OS X,Windows甚至 Clover 引导加载程序中进行提取。 在Clover主引导程序屏幕上,您可以按**F4**,Clover 会将本地ACPI文件转储到`EFI/Clover/ACPI/origin`。 进入系统后对它们以进行反汇编和修补。 注意,有的 BIOS 可能按`F4` 键没用,而需要 `Fn+F4`,所以,如果不确定的话,`F4` 和 `Fn+F4` 都按一次。提取的时候,你不会看到任何是否完成的提示,只是会因为正在写文件而出现一点延迟现象,你可以等待5s。如果是用Clover的USB设备(U盘、硬盘)启动的,文件会被提取到USB设备,这样会感到比较明显的延迟。 有时候,Clover 提取的 SSDT 可能会重复。重复的文件,会影响到反编译。如果你反编译的时候看到了这样的提示信息(duplicate definitions),则需要分析所有 SSDT 以消除重复的文件。通过查看文件大小很容易看出哪些是重复的。大小相同的文件可能是重复的。 您可以在终端中查看所有SSDT的文件大小(以字节为单位): ``` ls -l SSDT*.aml ``` ## 在Linux提取(可以顺便提取声卡codec) 在Linux系统里,可以直接在系统分区里找到原始ACPI文件。你可以在 `/sys/firmware/acpi/tables` 和 `/sys/firmware/acpi/tables/dynamic` 看到。可以简单地用命令进行拷贝。 Linux系统不需要安装,做一个启动U盘(推荐 Ubuntu Desktop 版本)就可以了:http://www.ubuntu.com/download/desktop/create-a-usb-stick-on-windows 打开Linux的终端输入: ~~~ sudo cp -R /sys/firmware/acpi/tables DEST ~~~ **注意: 用FAT32格式的USB设备(U盘、硬盘)的挂载点的路径,替换命令里的 `DEST`** (Xee:出现文件权限问题,可以先拷到桌面,在从桌面复制到U盘) 你的U盘或硬盘需要是FAT32格式的。FAT32格式可以避免出现文件权限问题,因为FAT32格式在Linux系统里没有文件权限的问题。用于替换DEST的 自动挂载的USB设备的名字,取决于你的Linux版本和它的启动方式。你可以在终端输入`mount`命令,来查看当前的挂载点。或者,在图形界面,把鼠标移到文件管理器上相应的USB设备名上。 Mac下提取也是非常容易的。比如使用:`DSDT Editor` 等工具。 ## 准备反汇编工具 > [Compiling and decompiling ACPI Tables](https://khronokernel.github.io/Getting-Started-With-ACPI/Manual/compile.html) > [https://github.com/acidanthera/MaciASL/releases](https://github.com/acidanthera/MaciASL/releases) 要正确反汇编解压缩的文件,您需要从终端运行的 iasl 编译器。 您将需要最近的 `iasl` 版本才能正确反汇编它们。这里有一个[适当的版本](https://bitbucket.org/RehabMan/acpica/downloads/)。将 iasl 二进制文件复制到你的路径(例如`/usr/bin`)是一个好主意,所以很容易从终端访问。 例如,如果您将其下载到 `~/Downloads/iasl.zip`,则可以在终端中提取并复制它: ``` cd ~/Downloads unzip iasl.zip sudo cp iasl /usr/bin ``` ### 从github上构建最新的`iasl` 你也可以从我的github构建我的 iasl 的最新版本。iasl 的最新版本最终将在 bitbucket 链接上提供,但对于那些想要处于“作死边缘”的用户,您可以自己构建。最新的版本总是倾向于有实验性的和没有经过良好测试的代码。 假设你已经安装了 Xcode: ``` mkdir ~/Projects && cd ~/Projects git clone https://github.com/RehabMan/Intel-iasl.git iasl.git cd iasl.git ``` 然后build它: ``` make ``` 在这一点上,你可以安装它: ``` sudo make install ``` 假设您已将 `MaciASL.app` 安装到 `/Applications`,那么您可以在 `MaciASL`中使用新版本(您刚刚构建并安装到 `/usr/bin`): 代码(文本): ``` sudo cp /usr/bin/iasl /Applications/MaciASL.app/Contents/MacOS/iasl62 ``` ## 反编译ACPI文件 虽然提取到的 aml 文件可以用 MaciASL 直接打开,但不建议这样做。用MaciASL直接打开aml文件,是软件在做对打开的这个文件的单独反编译。然而,ACPI文件之间有着紧密的联系,只对一个文件单独反编译,得到的文件会包含许多难于修复的错误。 所以,最好的方法是,**使用iasl编译器,同时反编译所有文件**。要做的准备工作有,新建一个文件夹用于存放所有DSDT和SSDT文件,并重命名所有文件,例如加上`.aml`扩展名。 然后在OS X Terminal中反汇编: ``` cd "to directory where you placed all SSDT/DSDT" iasl -da -dl DSDT.aml SSDT*.aml ``` 对于较新的ACPI集(通常\[但不总是\]与Skylake和以后),不需要 `-da`,因为它们已经嵌入了外部操作码: ``` cd "to directory where you placed all SSDT/DSDT" iasl -dl DSDT.aml SSDT*.aml ``` **注意**:**不要用`-da`命令去反编译 DSDT和 SSDT 以外的 ACPI文件,那将是无效的(Xee:所以还是把多余的文件先清掉!)**。 **注意**:请阅读下面有关`refs.txt`的部分。使用`refs.txt`需要更多的努力,但可以消除许多常见的错误。 反编译成功后,你将得到 所有文件的 dsl 形式,修改就是使用 dsl 文件进行。修改好 dsl 文件后,使用 MaciASL 的另存为,并选择 文件格式 "ACPI Machine Language Binary” ,再在文件名那里加上 .aml 扩展名,保存。编译保存为aml之后,把它们放到引导程序规定的加载目录(变色龙 `/Extra`,`Clover /EFI/Clover/ACPI/patched`)。保存好 dsl 文件,以防将来需要应用更多的修补程序。 **让我再次陈述它(因为很多人会出现这样问题):如果您直接在MaciASL 中打开一个AML文件,然后单击Compile,你做错了。你们要记住,不要左耳朵进右耳朵出!!!!** 该规则的唯一例外是使用最新的iasl编译的AML文件,该文件中嵌入了外部操作码。这包括您自己用当前的iasl和原始设备制造商(通常是Skylake或更高版本)编译的本地ACPI编译的文件。 注意:使用 ACPI 6.1 的新工具在处理使用新版iasl编译的AML文件时更加健壮。ACPI 6.1为编译器添加了一个功能,将外部引用的操作码添加到AML二进制文件中。ACPI 解释器会忽略这些数据,但这些数据对于反汇编程序(也只有 iasl 的 ACPI 6.1 版本)非常有用,可以从独立的AML中创建更好的反汇编。因此,您可能会发现使用最新工具重新编译的 AML 文件可能会更可靠地直接打开。当然,现在的 OEM ACPI DSDT和 SSDT 目前还没有未使用新工具,所以如本指南中所述,您仍然必须首先使用选项 `-da`将所有 DSDT / SSDT 反编译。 留意一下 苹果的Snow Leopard 系统的相关实现:不幸的是,10.6.8的`ACPI`太过时了,以至于它用外部操作码(the external opcode)会阻塞AMLs。如果您计划在 Snow Leopard 上使用您的`ACPI`文件,那么您就可以在编译您的AML文件时需要对 `iasl` 使用无证的 `-oe` 选项。当您从MaciASL编译(另存为)时,这个选项是不设置的,所以您需要在终端中编译您的文件。“`-oe`”选项会禁止在输出AML文件中生成外部的操作码。 # 使用 `refs.txt` 反汇编 有时还有其他未解决的外部因素(任何文件中都未定义的符号)。 iasl 反汇编程序将尝试猜测参数的数量,但通常猜测不正确。 您可以通过在文本文件中提供外部声明来更正它。 SGPO,ECRD,ECWT 和 MMTB 是一些常见的未解析符号。 下面的 `refs.txt` 内容有一些常见的(但不太常见)缺少的符号(正如该贴中有些用户所报告的),反汇编程序容易使它们混淆。 首先在您的 `DSDT/SSDT` 文件所在的目录中创建 `refs.txt`: ``` External(MDBG, MethodObj, 1) External(_GPE.MMTB, MethodObj, 0) External(_SB.PCI0.LPCB.H_EC.ECWT, MethodObj, 2) External(_SB.PCI0.LPCB.H_EC.ECRD, MethodObj, 1) External(_SB.PCI0.LPCB.H_EC.ECMD, MethodObj, 1) External(_SB.PCI0.PEG0.PEGP.SGPO, MethodObj, 2) External(_SB.PCI0.GFX0.DD02._BCM, MethodObj, 1) External(_SB.PCI0.SAT0.SDSM, MethodObj, 4) External(_GPE.VHOV, MethodObj, 3) External(_SB.PCI0.XHC.RHUB.TPLD, MethodObj, 2) ``` 注意:创建 `refs.txt` 的一个方便的方法是在终端中使用 `pbpaste` 命令。复制上面的文本到剪贴板(我假设你知道如何做到这一点),然后: 代码(文本): ``` pbpaste>refs.txt /* 利用了mac上的两个命令行工具,pbcopy 可以把管道输入复制到剪贴板,pbpaste 可以把剪贴板内容导出 */ ``` 这将在您当前的目录中创建 `refs.txt`。 然后在反汇编过程中使用它: 代码(文本): ``` iasl -da -dl -fe refs.txt DSDT.aml SSDT*.aml ``` ~~较早版本的`iasl`反汇编程序会将这些外部声明*放在所有其他外部声明之前*。这也是一个糟糕的选择。大多数情况下,您需要移动它们,以便它们遵循其他外部声明而不是前面的声明。这将是显而易见的,因为你会从外部声明,从 `refs.txt` 插入后面的错误。在目前支持ACPI 6.1的`iasl`中,这个bug已经修复了。~~ # 分析原生的ACPI 在反编译之后,您可能想要查看每个 `dsl` 文件的内容。使用来熟悉每个内容。某些修补取决于内容。 例如,如果要修补以禁用离散图形设备,则可能正在寻找与该设备相关的 `_OFF` 方法(此过程在单独的指南中介绍,在本指南的后面部分进行了介绍)。 除了给独显打禁用补丁之外,没有必要对所有的 SSDTs 进行打补丁,因为在[Clover笔记本指南](https://www.tonymacx86.com/threads/guide-booting-the-os-x-installer-on-laptops-with-clover.148093/)中已经完成了常见的重命名操作。重命名最好通过 `config.plist/ACPI/DSDT/Patches` 进行,因为它和手动进行操作相比,可以避免很多的错误。 在大多数情况下,您应该只关注 `DSDT.aml`。 # 筛选ACPI文件 对于较旧的计算机(Sandy Bridge和之前),与 CPU 相关的 SSDT 可能会导致问题。如果是这种情况(您已经不得不使用备用的DropTables,`DropOem = true`或`DropSSDT = Yes`),那么您不应该在 `ACPI/patch` 中包含这样的 SSDT。 我喜欢把所有的 SSDT 按原来的顺序包括在内,除非已知会导致问题。请记住,SSDT 不需要任何补丁,不需要重新编译。您可以直接使用未经修改的原始 AML 文件。 注意:使用当前的[ Clover 笔记本指南](https://www.tonymacx86.com/threads/guide-booting-the-os-x-installer-on-laptops-with-clover.148093/),您需要应用于SSDT的大多数修补程序已经在 `config.plist/ACPI/DSDT/Patches`(IGPU重命名,IMEI重命名,HDAS重命名,EH0x重命名等)中完成。因此,您不大可能需要修补 SSDT。相反,您可以从`ACPI/patched`中省略所有这些元素,并使 `DropOem=false`。在大多数情况下,您只需要修补`DSDT.aml`。 注:从Clover 转储的“x” SSDTs文件并同样地 从 Linux 转储的动态子目录地 SSDTs 动态加载和永远不会包含在 `ACPI/patched`(这些 SSDTs 和来自SystemMemory 的 ACPI 按需加载)。 所以...假设你认为你可能需要做一些过滤... 在你成功的反汇编你的文件后,看看每一个试图确定SSDT的目的。如果它与 CPU 相关并且已知会引起问题,就把它拖到其它地方(也可以直接删除)并且不要通过引导加载程序注入含有它的设置。在大多数情况下,和 CPU 相关的 SSDT 包含了 `Scope _PR.CPUx` 这样的声明。 以下是常见的SSDT的特点和功能: - CPU相关:上面已经讨论过。包括除非知道会导致问题的。 - SATA:可以留,也可以不留,自己决定就好。 - PTID:一般对苹果系统来说,是没用的。也许这个文件还会有很多错误。一种比较少的应用情况是,在这个文件里,可以找到 读取风扇转速,温度,或者其它系统状态 的线索。 - IAOE:如果存在这个文件,通常来讲,它会在DSDT里的 `_PTS` 和 `_WAK` 方法被调用。如果删除这个文件,就会影响到睡眠。 - GFX0:通常包含了 Device GFX0 的SSDT,是和 集成显卡 相关的。亮度补丁就是针对这样的文件的。老的笔记本(Haswell以前的),GFX0一般是定义在DSDT里。对于较新的Haswell笔记本电脑,通常在SSDT中定义(尽管它也可以在DSDT中)。 - PEGP:包含PEGP的文件,一般是和 独显 和 双显卡切换 有关。有时候不只有一个这样的SSDT,为了实现 屏蔽独显 等功能,你需要保留所有包含PEGP的SSDT,并对它们做一些修改。 我们需要弄清楚,每个SSDT的大概是做什么的,哪些需要删除,哪些需要不做修改地保留,哪些需要修改。 # 修复错误 即使同时反编译所有文件(使用 `iasl` 的 `-da` 参数),还是难免存在错误。反编译后的文件之所以还会有错误,是因为一直以来`iasl` 编译器的版本都在更新、iasl 的实现细节变化了、不同的电脑与系统环境。存在这些错误的原因可能是(Rehabman认为),里面调用到的一些方法,实际上是Windows内部实现的(例如 `MMTB`方法和`MDBG`方法)。实际也有这样的情况,ACPI 文件的代码原本就存在缺陷或者某些代码本来就是无效的(有时候很难区分)。 所以..在确定你需要哪些文件之后,你必须对它们进行补丁,以便它们无错地编译。在我的记本 MaciASL 补丁存储库中有许多这种错误的常见补丁。 * MaciASL:https://github.com/RehabMan/OS-X-MaciASL-patchmatic * 笔记本电脑补丁:https://github.com/RehabMan/Laptop-DSDT-Patch 注意:以上补丁源里的补丁,没有在 DSDT Editor 软件里测试过。DSDT Editor 软件存在着很多bug,内置的 `iasl` 编译器也很老了。这个就不要问我了。 在看别人的项目页面的时候,都请仔细阅读作者提供的README,到正确的地址下载软件,学习配置 MaciASL。修复语法错误的补丁的名字,以`[syn]`开头。例如,对于一些比较老的电脑,提供了"`Fix _PLD Buffer/Package Error`", "`Fix TNOT Error`", 和 "`Fix FPED Parse Error`”补丁。为了确定你需要用哪个补丁,需要看 编译结果 窗口给出的 提示信息,再定位到提示的行,查看错误行前后都有什么样的代码。您也可以尝试应用修补程序,以查看它是否进行了更改,如 MaciASL 的“Preview 预览”窗口中所示。 如果您不熟悉每种错误类型,则可能需要进行一些试验和尝试/错误。 对于一些错误,你可以简单地删除造成错误的那行代码来解决。当然,这要取决于这一行代码对于功能的实现,是否是必需的。例如,对于由External语句造成的错误,一般可以删除那行代码以修复错误。如果需要,你自己可以做一个删除这样的错误行代码的补丁。 学习一下 ACPI 规范 和 具有一些编程经验,有助于处理 DSDT 和 SSDT。 你的目标是让每个 `.dsl` 文件无误地编译( warnings/remarks/optimizations 都不用管)。一旦你有没有错误编译的文件,你可以继续打补丁,以解决你的 OS X 安装问题。 具有多余/不必要的外部声明是很常见的。 例如,我查看的最近的 DSDT 有很多 `Name already exists in scope` 错误​​。 对于DTSE,DTS1,DTS2,DTS4,BNUM,PDTS,PKGA,SPST。 解决方法是简单地注释掉相关的外部声明。 例如: ``` // External (DTS1, FieldUnitObj) // (from opcode) // External (DTS2, FieldUnitObj) // (from opcode) // External (DTS3, FieldUnitObj) // (from opcode) // External (DTS4, FieldUnitObj) // (from opcode) // External (DTSE, FieldUnitObj) // (from opcode) ... and so on ... ``` 注意:最近 DSDT 中的一个常见错误是 `ECRW`(在 `_CRS` 方法中)。这是 `iasl` 错误导致的一个非常常见的错误。我不打算为它添加一个 MaciASL 补丁,因为它最终将由 Intel 修复(这是一种复原)。 容易修复。 替换下面的: ``` If (LEqual (PM6H, One)) { CreateBitField (BUF0, \_SB.PCI0._Y0C._RW, ECRW) // _RW_: Read-Write Status Store (Zero, ECRW (If (PM0H) { CreateDWordField (BUF0, \_SB.PCI0._Y0D._LEN, F0LN) // _LEN: Length Store (Zero, F0LN) })) } ``` 使用下面的: ``` If (LEqual (PM6H, One)) { CreateBitField (BUF0, \_SB.PCI0._Y0C._RW, ECRW) // _RW_: Read-Write Status Store (Zero, ECRW) } If (PM0H) { CreateDWordField (BUF0, \_SB.PCI0._Y0D._LEN, F0LN) // _LEN: Length Store (Zero, F0LN) } ``` # 常见的补丁 一般,你需要先弄清自己的需求,再根据需求选择要用的补丁。但也有一些补丁是通用的,并且这些补丁一般不会造成什么问题。它们在Rehabman的[补丁源 repo ](https://github.com/RehabMan/Laptop-DSDT-Patch/blob/master/.maciasl)里,这里列出: ~~~ "Fix _WAK Arg0 v2" "HPET Fix" "SMBUS Fix" "IRQ Fix" "RTC Fix" "OS Check Fix" "Fix Mutex with non-zero SyncLevel" "Fix PNOT/PPNT"(只在丢弃与CPU相关的SSDT时使用) "Add IMEI" (如果DSDT或SSDT已经有 IMEI/HECI/MEI 设备,请勿使用) ~~~ 注意:您使用的 `OS Check Fix` 补丁与笔记本电脑随附的 Window s版本或当前使用的 Windows 版本无关。 注意:如果包含了所有 OEM SSDTs,请不要使用 `Fix PNOT/PPNT` 补丁。它仅适用于您省略与OEM CPU相关的 SSDTs 的情况。 USB 补丁可以用来修复“睡眠自动唤醒”,即在睡眠开始之后几秒钟内没有唤醒的情况下,笔记本电脑将不会睡眠。 这些补丁可用于注入 USB 的电源属性: `6-series USB` `7-series/8-series USB` 使用`AppleUSBXHCI.kext`的“睡眠自动唤醒”的替代解决方案是使用“`USB _PRW 0x6D`(即时唤醒)”。您应该检查您的DSDT,以确定相关的`_PRW`方法返回什么,以确定补丁适合您的DSDT。在repo中也提供了“`USB _PRW 0x0D`(即时唤醒”)(0x0D和0x6D都是`XHC/EHC/HDEF`从`_PRW`返回的常见值)。 `_PRW` 修补程序可用于修复"即时唤醒(instant wake)",在这种情况下,笔记本电脑将在睡眠开始后的几秒钟内,笔记本电脑无法入睡。只使用“`USB _PRW 0x6D (instant wake)`”或者“`USB _PRW 0x0D (instant wake)`”,因为它与DSDT中的现有代码相关(也请注意适用于Skylake和更高版本的这些补丁的特定版本)。 您应该检查您的DSDT,以确定相关的 `_PRW`方法返回什么,以确保该补丁适合您的DSDT。“`USB _PRW 0x0D (instant wake)`”(`0x0D` 和 `0x6D`是`XHC/EHC/HDEF`从`_PRW`返回的常见值) USB3 Mutliplex补丁,有助于加载`AppleUSBXHCI.kext`(原生USB3.0驱动),于是就不需要安装第三方的`GenericUSBXCHI.kext`了。这个补丁是基于Mieze的发现而制作的。大部分DSDT需要对它做一些修改,才能使用(不然可能会提示有错误)。例如,对于惠普的Probook,Rehabman制作了这个补丁的修改版本。联想u310/u410可以直接使用这个补丁:"`7-series USB3 Multiplex`” 如果您具有Haswell CPU / 8系列芯片组,并且 `AppleLPC.kext` (电源管理的一种)未加载,则应使用此修补程序注入兼容的ID,以允许其加载: “`Haswell LPC`” 如果您具有Skylake CPU / 100系列芯片组,并且 `AppleLPC.kext` 未加载,则应使用此修补程序注入兼容的ID,以允许其加载: “`Skylake LPC`” 注意:Skylake及更高版本可能不需要AppleLPC。 关于重命名的注意事项:重命名必须是“平衡的”。 重命名对象以更好地匹配OS X的期望是很常见的(例如,将“将`GFX0`重命名为`IGPU`”以进行正确的IGPU电源管理)。 在这种情况下,所有引用该名称的DSDT / SSDT也必须重命名。 这就是为什么最好使用 `config.plist / ACPI / DSDT / Patches` 完成重命名的原因。 注意重复标识符:您必须确保您的补丁文件不包含重复标识符。一个常见的例子是在一个SSDT中添加一个`_DSM`方法到指定的路径,在那里,OEM已经在另一个SSDT的路径上定义了一个`_DSM`。为了避免这个问题,您可以使用“`Remove _DSM methods`”补丁作为您对所有 DSDT/SSDT 的第一个补丁。也可以使用“`Rename _DSM methods to XDSM`”也是可以的(有时“`Remove _DSM methods`”在`MaciASL`中暴露一个缺陷)。 # 问题具体修补 电池状态:http://www.tonymacx86.com/yosemite-laptop-support/116102-guide-how-patch-dsdt-working-battery-status.html 中文翻译:http://bbs.pcbeta.com/viewthread-1521462-1-1.html 背光控制:http://www.tonymacx86.com/yosemite-laptop-support/152659-patching-dsdt-ssdt-laptop-backlight-control.html 中文翻译:http://bbs.pcbeta.com/viewthread-1571456-1-1.html 禁用 NVidia / Radeon 独立显卡 :http://www.tonymacx86.com/yosemite-laptop-support/163772-guide-disabling-discrete-graphics-dual-gpu-laptops.html 当你在看针对某个特定型号的笔记本教程的时候,作者都会介绍用了哪些补丁,或者直接提供下载。你能容易的看出来,他们的补丁和Rehabman的补丁,在语法上是相似的。(例如这样的语法:'into_all method label FOO code_regex xxyy removeall_matched;')。这些补丁语句需要粘贴到MaciASL的补丁窗口,再应用。 如果你对制作补丁有兴趣,可以去看有关MaciASL修补程序语法的文档:http://sourceforge.net/p/maciasl/wiki/Patching%20Syntax%20Grammar/ 注意:在许多情况下,DSDT补丁与其他kexts,已打补丁的kexts或 Clover `config.plist`补丁一起结合使用,在系统的kext被加载时,这些补丁会对这些系统的kext进行打补丁。 # 打过补丁的AppleHDA 的相关补丁(仿冒声卡驱动相关的补丁) 有两个和仿冒声卡驱动相关的补丁,需要和仿冒的声卡kext一起使用: `Audio Layout 12` (根据实际情况,自己修改 layout-id,例如把 12 改成 28 等) `IRQ Fix`(解决需要`-f`才能加载声卡驱动的问题) 注意,您必须有一个与您的编解码器匹配的AppleHDA,并且必须确定选择了哪个layouid-id。对于已修补的AppleHDA的创建者来说,layout-id是一个任意的选择。 要查看别人修改的AppleHDA用的`layout-id`是哪个值,首先,你需要知道自己声卡的`codec id`的十进制形式(例如,`0x10ec0269 = 283902569`)。 再去查看 `AppleHDA.kext/Contents/PlugIns/AppleHDAHardwareConfigDriver.kext/Contents/Info.plist`,查看HDAConfigDefault 节点下面的`codec id`(可能有许多条目在一个草率修补的AppleHDA或只有一个)。 和你的`codec id`匹配的那组里,LayoutID的值,就是你需要的 layout id 值。 有的驱动修改者,同一个`codec id`可能会对应多个`layout-id`,选择一个你需要的 id 注入。 # 保存由引导装载程序装载的文件 为了使用你修改、编译好的DSDT/SSDT,你需要把它们放到Clover引导能加载它们的目录。每种引导的加载目录是唯一的,且对文件的命名要求也不同。 如果用 **MaciASL** 保存,另存为的时候,文件格式一定要选择"ACPI Machine Language Binary”(文件-另存为-文件格式)`.aml` 后缀。如果不选择文件格式,就相当于,硬是把`dsl`文本文件,存成了`aml`字节码文件(没有经过编译器转换),这会造成无法预知稀奇古怪的问题。 Clover(推荐):aml 文件应该放到 Clover 所在的分区(通常是EFI分区),如果存在 `EFI/Clover/ACPI/patched`。 DSDT.aml(如果存在)将自动替换OEM DSDT。 本指南(以及与本指南链接的其他指南)假定您使用的是`config.plist / ACPI / AutoMerge = true`,`config.plist / ACPI / SSDT / DropOem = false`。 使用 `AutoMerge = true` 时,可以将打好补丁的 SSDTs 按照原来的名称( `ACPI/origin` 中的名称)放置在 `ACPI/patched`中进行修补,会自动将其插入,以免影响SSDT的原始顺序。 不需要(或建议)将 `SortedOrder` 与`AutoMerge = true`一起使用。 其他配置在下面的“推荐配置”中会介绍。 Clover 3062版本以前,SSDT的命名必须是这样的:SSDT-x 或 SSDT-xx,x是一个整数(一直支持到SSDT-19)。Clover允许SSDT的名字不连续(例如,SSDT-1.aml, SSDT-5.aml, SSDT-6.aml是可以的)。Clover 3062以后的版本,会加载所有在ACPI/patched里的aml文件,对名字没有严格限制了。一定要注意,SSDT的加载顺序非常重要,你留下来的SSDT,要保持提取的时候的顺序。 Clover 3062版本以后的注意事项:`ACPI/patched` 里SSDT的加载方式的改变,造成了加载顺序的不确定性。你应该要使用 `config.plist/ACPI/SortedOrder` 功能,指定SSDT的加载顺序。Clover 3088 版本以后,实现了`SortedOrder`参数。从我的 Clover 指南链接的config.plist 文件对SortedOrder有一个很好的默认值:http://www.tonymacx86.com/yosemite-laptop-support/148093-guide-booting-os-x-installer-laptops-clover.html 注意:SSDTs必须由引导加载器按其原始顺序加载。原始的顺序是由名称后面的数字指定的。例如,如果您使用Clover `F4`来提取您可能会有类似的东西:SSDT-0.aml, SSDT-1.aml, SSDT-2.aml, SSDT-3.aml,表示SSDTs必须以该顺序加载(0/1/2/3)。 ~~变色龙(或Chimera 不推荐):修改、编译好的DSDT/SSDT,应该放到 系统盘的 /Extra(或者你的引导程序所在的其它地方的 `/Extra`)。如果/Extra里存在DSDT.aml,引导程序就会用这里的DSDT,替代掉原始的DSDT,提交给系统。变色龙要求,SSDT的名字是连续的。这样的情况,文件都会被加载:SSDT.aml, SSDT-1.aml, SSDT-2.aml, SSDT-3.aml,直到引导找不到接下来的名字的文件。另外,这样的情况:SSDT.aml, SSDT-1.aml, SSDT-4.aml, SSDT-5.aml,只会加载SSDT.aml 和 SSDT-1.aml。SSDT-4.aml 和 SSDT-5.aml不会被加载(变色龙会忽略这些文件)。~~ ~~最后,如果不先屏蔽原始的OEM SSDT,就不能放自己修改的SSDT。最简单的方法,是设置`DropSSDT=Yes`(变色龙) 或者 `ACPI/SSDT/DropOem=true`(Clover),从而在系统启动的时候,先屏蔽原始的SSDT,之后再把目录里的SSDT(没有修改或修改过)提交给系统。~~ 如上所述,Clover的RehabMan分支中的一项新功能允许您在不使用 `DropOem = true`且不使用 `SortedOrder` 的情况下替换 OEM SSDT,同时始终保持四叶草注入的未打补丁和打补丁的SSDT的原始顺序。通过设置 `config.plist/ACPI/AutoMerge=true`,启用此功能。 当放置在 `ACPI/patched` 中时,SSDT必须保留其原始编号方案。 从2017年12月15日起,此功能已在 RehabMan bitbucket 网站上的Clover_v2.4k_r4359.RM-4506.c5fc0346.zip 中全面运行。 自 r4334 起,所需的更改已在官方Clover (在 sourceforge 上)中实现(但您可能会遇到一些错误,请使用 RehabMan fork 的版本 )。笔记本电脑主指南中链接的每个 plists 默认情况使用 `AutoMerge = true`。 RehabMan fork 的 Clover::https://github.com/RehabMan/Clover 笔记本电脑主指南:https://www.tonymacx86.com/threads/guide-booting-the-os-x-installer-on-laptops-with-clover.148093/ # 推荐的配置 以下是有效的配置,其他任何配置都可能是错误的(有些情况我不希望涉足,因此使用了‘可能” likely’)。首先列出的配置更可取。 全部 hotpatch: - 所有的补丁都是通过`config.plist`完成的 - 在 `ACPI/patched` 中只有附加的 SSDTs(例如,没有打补丁的 `DSDT`, 没有打补丁的`SSDTs`) - `SortedOrder` 可以不指定 - `DropOem=false` 部分 hotpatch: - 打补丁的`DSDT.aml`放置在 `ACPI/patched` - 在 `ACPI/patched` 中只有附加的 SSDTs (例如,没有打补丁的 `SSDTs`) - 通过`config.plist`来进行重命名(会对原生的 SSDTs 和 `ACPI/patched` 下的 `DSDT.aml` 应用) - 不指定 `SortedOrder` - `DropOem=false` 部分 hotpatchh 和打补丁的SSDTs: - 需要 RehabMan 构建的Clover - 打补丁的`DSDT.aml`放置在 `ACPI/patched` - 在 `ACPI/patched` 中选择打了补丁的的 SSDTs (必须以提取到 `ACPI/origin` 的名称来命名) - 附加的 `SSDTs` 也放置在 `ACPI/patched` 中 - 仍然可以使用`config.plist` 来完成重命名 - 不指定`SortedOrder` - `config.plist/ACPI/AutoMerge=true` - `DropOem=false` 全部打补丁的 DSDT + SSDTs: - 打补丁的`DSDT.aml`放置在 `ACPI/patched` - 完整的一组打了静态补丁的 OEM SSDTs 放置在 `ACPI/patched`(还是以原本 `ACPI/origin` 下的原始名称) - 附加的`SSDTs` 也放置在 `ACPI/patched` 中 - `config.plist`中的重命名是不推荐的(它们只适用于 `DSDT.aml`) - `SortedOrder`需要设置 `SSDT` 加载顺序 - `DropOem=true` # Floating regions 在ACPI中,OperationRegion可以定义MMIO 区域(region),SystemMemory区域,EmbeddedControl区域等。这些区域通常具有固定的地址,这些地址仅取决于计算机配置,BIOS版本或BIOS选项。 有时,这些区域可能会随机或意外更改。 这被称为“浮动区域”。 由于通过修补DSDT和/或SSDT,我们在给定的时间点提供了这些地址的快照,当BIOS发出命令,需要变动地址值时,我们提取的文件是做不到这样的变动的。在这样的情况下,你也许能注意到,某一个特定的功能变得断断续续,或者可能随机地出现一些稳定性问题。 如果您具有随机浮动的区域,则**可以尝试** Clover 的 FixRegions 功能(`config.plist / ACPI / DSDT / Fixes / FixRegions = true`)。 您可以在Clover Wiki中找到详细信息。 注意:FixRegions 只能固定 DSDT 中的浮动区域。 SSDT中的浮动区域存在问题,除了为受随机浮动区域影响的SSDT 不提供修补的SSDT之外,没有其他好的解决方案。 解决修补的SSDT中的浮动区域超出了本指南的范围。 请注意,FixRegions 是相对有问题的。 它无法修复所有区域,有时可能会错误地“修复”区域。 # 资源 MaciASL(RehabMan fork):https://github.com/RehabMan/OS-X-MaciASL-patchmatic patchmatic:https://github.com/RehabMan/OS-X-MaciASL-patchmatic iasl(RehabMan fork):https://bitbucket.org/RehabMan/acpica/downloads ACPI spec: 5.0a:[http://acpi.info/spec.htm](http://acpi.info/spec.htm) Latest:[http://www.uefi.org/specifications](http://www.uefi.org/specifications) RehabMan github:https://github.com/RehabMan?tab=repositories Clove r笔记本电脑指南:http://www.tonymacx86.com/yosemite-laptop-support/148093-guide-booting-os-x-installer-laptops-clover-uefi.html 笔记本电脑的 Clover `config.plist`文件:https://github.com/RehabMan/OS-X-Clover-Laptop-Config Clover 跟帖:http://www.insanelymac.com/forum/topic/284656-clover-general-discussion/ Clover 变化:http://www.insanelymac.com/forum/topic/304530-clover-change-explanations/ # 提供反馈 请勿将此线程视为您的专用疑难解答线程。 如果您的特定笔记本电脑有特定问题,请打开单独的线程。 如果您发现此处有错误或希望做出贡献,请回复此主题。 # 问题报告 请阅读上面的“提供反馈”。最好打开一个单独的帖子。 在那个单独的帖子中,清楚地描述你的问题。并提供相关数据... 阅读常见问题,“Problem Reporting” https://www.tonymacx86.com/threads/faq-read-first-laptop-frequent-questions.164990/ **** # 使用Clover Fix 也许有的同学会说,有的电脑不用 DSDT 也可以完美,其实,这样的说法不太严谨。因为,虽然没有在相关文件夹放自己修改过的 DSDT 文件,但是,系统启动时,其实是会自动从BIOS 读取出厂时的原始 DSDT的。 由于 **Clover 的强大功能**,使得不需要手工修改原始的 DSDT: 比如`Fix ****`参数,就是在启动读取原始 DSDT 文件时,由 Clover 程序根据相应的`Fix参数`,向 DSDT 里添加对应的通用性代码,再把修改后的DSDT,提交给系统。这样,修改 DSDT 的动作,是发生在系统启动时。也就给大家一个似乎不需要自己修改的DSDT的印象。 # 参考 相关:[SSDT GPU (Graphics Card) Injection](https://www.tonymacx86.com/threads/ssdt-gpu-graphics-card-injection.183354/) 其他翻译: [DSDT 有什么?如何提取黑苹果系统里的 DSDT 文件](http://www.xp988.com/tech/6028.html) [[教程]](http://bbs.pcbeta.com/forum.php?mod=forumdisplay&fid=546&filter=typeid&typeid=1199)[\[授权翻译\] 使用补丁修改 DSDT/SSDT \[DSDT/SSDT 综合教程\]](http://bbs.pcbeta.com/viewthread-1571455-1-1.html) [对笔记本的 DSDT/SSDT 打补丁](http://blog.csdn.net/wr132/article/details/54798754) [教程 运用MaciASL软件的补丁源-帮你完善DSDT](http://www.memacx.com/thread-5726-1-1.html) [关于DSDT修改-提取软件以及使用方法【详解】](http://www.memacx.com/thread-718-1-1.html) http://www.sdifen.com/getdsdt.html http://bbs.pcbeta.com/viewthread-1571455-1-1.html https://www.maoshu.cc/1168.html DSDT SE链接: http://pan.baidu.com/s/1gfbthlD 密码: r6c4DSDTeditor链接: http://pan.baidu.com/s/1bpcNhTl 密码: hag8IDSDT链接: http://pan.baidu.com/s/1qYAS4XY 密码: qwvwMACIASL链接: http://pan.baidu.com/s/1c1I2ucC 密码: 99x9
';

[FAQ] 开始必读!笔记本电脑常见问题

最后更新于:2022-04-02 05:45:58

[TOC] # 【FAQ】开始必读!笔记本电脑常见问题 英文原文:https://www.tonymacx86.com/threads/faq-read-first-laptop-frequent-questions.164990/ * 1:May 30, 2015 at 10:35 AM # 开始 Before asking a question, many common questions are already commonly asked and answered, and many answers exist in the sticky threads in this forum. Read this post before and any relevant guide before asking a question... If you ask a question that is answered by this FAQ, you'll likely be directed right back to this FAQ. Finally, this is NOT a troubleshooting thread. Please do not ask questions regarding your specific problem in this thread. Open a separate thread instead. Only if you have a question regarding the content of this FAQ, or have a an idea for an additional Q/A in this thread, reply here. 问. 我要从哪里开始? Read compatibility overview: http://www.tonymacx86.com/laptop-compatibility/106791-laptop-compatibility.html If you have UEFI capability, use the Clover Guide: http://www.tonymacx86.com/el-capita...de-booting-os-x-installer-laptops-clover.html You can use Clover without UEFI, and you may want to try that. There are still many advantages to using Clover, even with a computer that lacks UEFI. In fact, Clover is the only option with 10.11+. Unibeast/Chimera (or Chameleon), read here: http://www.tonymacx86.com/yosemite-...-booting-os-x-installer-laptops-unibeast.html Also, you will find many of the stickies here useful: http://www.tonymacx86.com/el-capitan-laptop-support/ It is a good idea to collect complete hardware information before you even start. Use CPU-Z on Windows to find CPU (Core iX-xxx) and motherboard chipset (HMxx), and graphics capabilities. For a laptop, these details are important and affect critical installation procedures. Make sure your profile/signature reflects your hardware details. Please provide complete details in your profile. If your profile is already used, use the signature. DO NOT use the signature if your profile is currently unused. That is, use the signature only if you have multiple systems. To edit your profile: https://www.tonymacx86.com/account/personal-details The profile has 3 fields which are visible with each post you make. The three fields should be filled out as follows: Mobo: manufacturer/model + bootloader(Clover/Chameleon/Chimera) CPU: detailed CPU model + motherboard chipset Graphics: all graphics devices + laptop internal screen resolution For example, typical Ivy laptop: Mobo: HP ProBook 4540s (Clover) CPU: i5-3320m/HM76 Graphics: HD4000, 1366x768 As mentioned above, if you have multiple systems, use the signature to place details for the second system. It is best to have your profile represent the primary system you are working with. To edit your signature: https://www.tonymacx86.com/account/signature Please keep your signature details for each system within a single line. For example, same system as was mentioned for the profile, but represented in the signature: HP ProBook 4540s (Clover), i5-3320m/HM76, HD4000 1366x768 Note: When specifying your bootloader, if using Clover legacy, please be sure to specify "Clover legacy"). Specifying "Clover" will be assumed as "Clover UEFI"
';

黑苹果指南

最后更新于:2022-04-02 05:45:56

[TOC] # 我的黑苹果之路 https://www.qiuzhi99.com/articles/fen-xiang/911.html # 开始 Tips:黑苹果尽量采取最轻量化原则,能不加载的就不加载,不论是在`config.plist`里还是在驱动的加载上。 ## [我是新手,我从哪里开始](https://www.tonymacx86.com/threads/im-new-to-everything-where-do-i-start.104542/)? 首先,恭喜!你正在学习新的东西 - 总是一个挑战,但值得努力。在通用PC硬件上安装Mac OS X并不像以前那么辛苦,但是因为有太多的方法,引导加载程序和指南,所以新用户可能会感到非常困惑。 下面是一些开始可能要做的事情。 1. 仔细阅读我们的[规则](http://www.tonymacx86.com/rules/)。与大多数互联网社区不同,我们的规则严格执行。这是为了每个人的利益。 2. 一个好的开始是[最简单的Mac OS X安装指南](http://www.tonymacx86.com/threads/simplest-mac-os-x-installation-guide.60255/),以熟悉过程的鸟瞰图。之后,请查看我们的[安装>基础知识](http://www.tonymacx86.com/basics/)论坛。 3. 阅读最新的[CustoMac买家指南](http://www.customac.com/)以获取自己组装Mac的兼容性建议。 4. 使用[搜索](http://www.tonymacx86.com/search) - 我们已经存在多年。很可能你的问题已经被回答了。 5. 通过阅读[活动流](http://www.tonymacx86.com/activity/),熟悉论坛。 6. 阅读[CustoMac词汇表](http://www.tonymacx86.com/basics/177012-customac-glossary-explanations-common-terms.html)以获取相关术语的详细定义。 7. 学习如何使用[WYSIWYG编辑器的“用户指南”](http://www.tonymacx86.com/threads/wysiwyg-editor-users-guide.192365/)进行发布。 你会很快成为一名老手。Be Happy! ## 简述 mac系统的驱动程序,其实(该有的)就都有了,但是你不把它叫醒它就不给你工作。一个白苹果的电脑,都使用了哪些硬件,苹果公司如数家珍,系统装好后打开就能用,各种设备让你妥妥帖帖;但是在它合法硬件之外的其他硬件,它就算是有相应的驱动也不会让你使用,因为怕引起系统的不稳定。 mac系统的绝大部分驱动,存放在`\System\Library\Extensions`,一般简称`\S\L\E`。后缀名一般为kext,实际上它是个指令,授权苹果系统加载相应的硬件。在黑苹果发展早期,要添加新的驱动程序就要往`\S\L\E`里硬加,会导致mac系统的排异反应,还要用修改权限重建缓存等等一些手段来霸王硬上弓。现在基本上用不着这么硬来了。 clover帮你在它的自己一套体系里添加。具体方法是,可以将你用到的kext文件扔到一个目录里,clover使它们变得有效。这个目录`EFI>CLOVER>kext>other`(只保留该文件夹!)。 # 相关术语 ## NVMe 简单科普一下:SSD固态硬盘刚开始也跟机械硬盘一样使用SATA接口,SATA接口理论上的传输速度最大为6Gbps(600MB每秒),看起来也还好,但慢慢地这个速度不被科技大佬们接受了,于是科xiao家们研发出了基于NVMe接口的固态硬盘,目前最高端的NVMe固态硬盘通过PCI-E 3.0x4通道传输数据,理论上可以达到32Gbps,也就是3GB每秒的速度。 恰好有一块三星SM951 NVMe的固态硬盘,那么就可以来感受一下飙车的乐趣。 就是添加一些驱动使clover启动时支持NVMe固态硬盘。 把下面的文件解压放到启动U盘的EFI>CLOVER>drivers64UEFI里去。 下载下面的文本文件,双击打开,全选,复制,然后用文本编辑打开config.plist,找到“KernelAndKextPatches”的部分,在“KextsToPatch”之后,粘贴。 正本溯源一下,在不久之前,想驱动NVMe硬盘,还需要在kext里添加名为NVMeGeneric.kext的驱动,今年8月,国外大神搞出了修改config.plist的方法。 原贴地址如下: https://pikeralpha.wordpress.com/2016/08/02/ionvmefamily-kext-changes-in-sierra-dp4-build-16a270f/ 做好了这两步,就可以与NVMe SSD一起玩耍了。 ## LPC 百度给出的回答是这样的:LPC = Low Pin Count,是连接南桥和super I/O(该IC连接一些低速外设,如mouse,KB,Printer)的一根BUS。LPC由Intel所提出. 是为了在PC上把ISA取消而制定的一个新规格. 其目的是把非常慢速的ISA总线取消. 而为了让一些原本在ISA上跑的硬件在没有ISA的机器上能够运作所以制定了此一规格, 例如一般 K/B , MOUSE , FDD, COM PORT, PRINTER PORT 等慢速外围即可用支持LPC的SUPER IO芯片控制,而且在软件上是完全兼容的。 # 使用 Clover 在笔记本上安装 Mac RehabMan: https://www.tonymacx86.com/threads/guide-booting-the-os-x-installer-on-laptops-with-clover.148093/ # 参考 [Laptop Compatibility](https://www.tonymacx86.com/threads/laptop-compatibility.106791/) [High Sierra Laptop Support](https://www.tonymacx86.com/forums/high-sierra-laptop-support.192/) https://www.tonymacx86.com/threads/faq-read-first-laptop-frequent-questions.164990/ # B站视频
';

工具集合

最后更新于:2022-04-02 05:45:53

[TOC] # [最新系统下载器 gibMacOS](http://bbs.pcbeta.com/viewthread-1877108-1-1.html) # OpenCore Configurator ```shell brew cask install opencore-configurator ``` # Clover Configurator 4.40 http://mackie100projects.altervista.org/download-clover-configurator/ 四叶草设置助手 方便设置 Config.plist(英文版) # [Kext Utility](http://cvad-mac.narod.ru) ```shell brew cask install kext-utility ``` 打开 [Kext Utility](http://cvad-mac.narod.ru) 后,会自动重建缓存、修复权限,等右下角的按钮显示为quit后,就把你需要的驱动拖到程序窗口,然后程序会自动安装驱动,并重建缓存、修复权限,等右下角的按钮显示为quit后,就可以退出程序,重启电脑即可安装完成。 # MaciAsl ```shell brew cask install MaciAsl ``` # kext updater [一款联网更新 Kext 驱动的软件](https://bitbucket.org/profdrluigi/kextupdater/downloads/) 常用驱动https://bitbucket.org/RehabMan/cloverhttps://github.com/CloverHackyColor/CloverBootloader/releasesLilu 插件https://github.com/acidanthera/Lilu/blob/master/KnownPlugins.mdLilu.kexthttps://github.com/acidanthera/Lilu/releases # 危险操作 虽说在Windows下安装 HFS+ For Windows 10.0 或者 MacDrive 9 可以很方便地操作Mac分区 (需要激活 激活失败的话 是无法显示Mac分区) 但是在Windows读写Mac分区数据比较危险 最坏的情况下 (看到过以前果友们写的帖子)可能导致Mac分区损坏, 无法修复, 只能重装, 所以只要你能进到系统无论是安全模式还是正常模式,都尽量在OS X下对Mac所在分区操作; # gfxCardStatus 显示系统当前正在使用集成显卡还是独立显卡,并给出触发切换的相关程序,让你对哪些程序需要使用集成显卡或独立显卡有一个准确的认识;而如果你觉得当前运行的程序还不需要独立显卡“出马”,可以手动切换到“仅使用集成显卡”来节省电量,或是选择“动态切换”让机器根据实际情况自行切换显卡使用。 ## 参考 http://bbs.feng.com/read-htm-tid-6347358.html # [KCPM Utility Pro](https://pan.lanzou.com/b54629) # [DPCIManager](https://www.tonymacx86.com/threads/dpcimanager-1-5-release.107586/) # macOS-USB盘 Windows 下安装制作macOS安装USB盘: 1. TransMac 2. R-Drive Image # DarwinDumper # Clover RehabMan的fork版本:[RehabMan / Clover — Bitbucket](https://github.com/RehabMan/Clover) https://clover-wiki.zetam.org/zh-CN/zh-CN.home 可引导mac os 10.4-10.8,win efi,linux efi 可引导传统操作系统 (WindowsXP,Linux,DOS)的启动扇区 (mbr) EFI bootloader 提供 RuntimeServices 与 OS 运行,不可用于传统的引导器 默认侦测并设置硬件的大部份的属性,并且用户可以在 config 中自己设置 可在在启动面板中重启进入其他操作系统 通过oem名称自动侦测配置 config 写入 config 的 uuid 和 os 的一样 自动补丁功能 smbios 更新为 standard 2.6 更新 ACPI 至 standard 4.0 版本. 支持从开机分区或 EFI 文件夹加载定制的 DSDT MADT表更新,解决在某些硬件 NMI 的问题加载APCI表单 (SSDT-xx, APIC, BOOT, SLIC, SLIT, SRAT, UEFI) 正确设置电源属性为笔记本,台式,服务器 可选重启修复功能⁃支持睡眠唤醒功能 可用 PCIRootUID 设备属性注入功能,为那些无法编辑 dsdt 的人准备的 显卡属性注入,为大多数 A 卡和 N 卡 可选 EDID 注入 usb3.0修复 (LegacyOff,Ownership, Builtin, clock-id) HDA 注入, HDMI 修复 网卡内建 cpu 睿频 自动生成 P-State 及 C-State 的功能 cpu变频档位和电压控制 自动给内核打补丁为那些不支持的 CPU 像 Atom and Ivy Bridge (amd那是不可能的) 自动为不支持的硬件给 kext 打补丁 第三方 kext 加载 支持火线下的安全模式 支持默认分区引导 界面可自选,主题,图标,字体 1. 按 F1 获得详情,未来可能提供更多语言和字体支持. 2. 按 F2 储存GUI 的开机纪录 preboot.log 自动保存在 EFI/clover/misc 文件夹 3. 按 F4 获取原始的ACPI表单,自动保存在 EFI/clover/ACPI/origin 文件夹 4. 按 F5 测试dsdt path功能 5. 按 F6 可获取显卡rom,自动保存在 EFI/clover/misc 文件夹 6. 按 F10 截取开机引导界面图,自动保存在 EFI/clover/misc 文件夹 7. 按 F12 推出 CD/DVD 并更新引导菜单当放入CD后 [黑苹果引导工具 Clover 配置详解及Clover Configurator使用](http://www.cnblogs.com/SemiconductorKING/p/6534821.html) [黑苹果引导工具 Clover 配置详解](http://blog.sina.com.cn/s/blog_4ddc30040102wqnp.html) # Kext Wizard Kext Wizard 是一款集Mac系统驱动安装、重建系统缓存、权限修复的工具,在黑苹果的系统中是一款脍炙人口的工具。 Kext Wizard可以让用户可视化轻松解压、查看一个MAC kext文件信息。它包括强大的功修复权限功能和重建系统缓存,以及安装kext。最重要的是,该应用程序还允许您查看的kext依赖也允许你查看你的MAC中当前加载的kext列表。 在维护标签里,你可以选择重建系统缓存或修复kext,同时对整个磁盘进行权限修复。当然,你需要选择一个目标磁盘执行这些操作。 软件会让安装kext变成一件容易的事情,你只需要选择你想安装的系统位置。 # PlistEdit Pro 1.7.4 属性表编辑器 方便编辑 *.plist 等(多语言版本) # RehabMan 维护的项目: https://bitbucket.org/RehabMan/ https://github.com/RehabMan # MultiBeast MultiBeast是一款常用的黑苹果驱动包文件,程序包含了众多黑苹果常用的驱动文件并且含有最新的启动引导工具,比如四叶草,变色龙等! MultiBeast 集成的系统工具有:重建Cache、修复权限、大量驱动、引导、补丁内核、引导时间配置文对于黑苹果而言,MultiBeast就像是Windows下的驱动精灵。 类似工具有:Hackintosh Vietnam Tool [黑苹果驱动高手篇 MultiBeast用法进阶](http://notebook.it168.com/a2012/0117/1303/000001303433.shtml) # [Hackintosh Vietnam Tool](http://www.insanelymac.com/forum/files/file/210-hackintosh-vietnam-ultimate-aio-tool/) 驱动优化配置利器 Hackintosh Vietnam Tool 是一个集所有流行的黑苹果系统工具为一身的综合配置。这个工具包含很多 CPU 电源管理, 音频,有线网卡,无线网卡,触控板,USB3.0 驱动及补丁,还包括很多其他实用工具。它将帮助您更快速更简便地配置您的黑苹果电脑。 百度网盘:[Hackintosh Vietnam Tool 1.9.6](https://pan.baidu.com/s/1ntMRQbR) # HWSensors :(安装HWMonitor之外的驱动,可能启动不了) 官方下载地址:http://www.hwsensors.com/releases 项目开源地址:https://github.com/kozlek/HWSensors HWSensors 包括 HWMonitor ,和其他一系列的传感器。 HWSensors 软件自带了`FakeSMC.kext`和一些监控插件程序,用户安装后**可以利用HWSensors查看当前系统硬件的工作情况,比如CPU温度、变频和显卡内存等等信息**,软件一目了然是黑苹果用户必备良药。 可以运行HWMonitor.app进行相关设置。 ## 使用教程: http://news.softpedia.com/news/How-to-check-the-temperature-of-your-Mac-472725.shtml # IStat Menus 一款在运行在Mac下的硬件监控软件,可以在Finder菜单栏显示CPU使用率, 内存使用, 硬盘读写速度, 网络上传下载速率使用情况, 温度传感器温度等数据的软件。软件可以常驻菜单栏右侧的小工具。iStat Menus 的开发非常不容易,开发者曾经在博客上提到因为每次新款 Mac 电脑传感器都不同,所以需要购买机器进行测试! 类似的软件还有iStatistica都是不错的选择,当然还有HWSensors可以使用 # Geekbench Mac上的一款硬件性能跑分工具,Geekbench的是一种流行的基准,其允许确定处理器和RAM的性能。该方案同样适用同时与32位和64位版本的操作系统。对于不同的版本甚至设有不同的分析模式。软件还支持其他设备,如IOS何Android都有版本,你可以详细得到你设备的性能情况。 # MenuMeters Mac平台上系统状态显示工具,软件可以在顶部菜单栏中显示硬件的温度、网络状态等信息。MenuMeters是用于Mac OS X的一组CPU,内存,磁盘和网络监控工具。尽管有许多其他程序也执行相同的操作,但没有一个具有我正在寻找的功能。大多数是坐在角落或桌面上的窗户,这些窗口不可避免地被笔记本电脑的小屏幕上的文档窗口遮蔽。那些使用菜单栏的显示器主要使用NSStatusItem API,这在每次登录时都有令人讨厌的倾向,对我的菜单进行完全重新排序。 MenuMeters监视器是真正的SystemUIServer插件(也称为菜单附件)。这意味着它们可以使用命令拖动进行重新排序,并记住他们在菜单栏中的位置,通过登录和重新启动。 # Temperature Gauge Pro 一款专业显示你的Mac实时温度的软件,软件简称 TG Pro。可以在系统内的菜单栏,独立菜单栏等位置显示出各个硬件的温度。如果你对电脑温度比较在意的,可以下载安装一个试试。查一下你的MAC通过查看电流和最大记录温度传感器。摄氏或华氏度之间选择,并且软件还可以调整风扇的速度,让你的MAC可以运行在手动控制风扇冷却器。 # Intel Power Gadget Intel Cpu 能耗监测软件. 显示Intel CPU的实时频率与功耗,查看自动变频。
';

驱动集合

最后更新于:2022-04-02 05:45:51

[TOC] 黑苹果是否完美就三个指标,三卡(显卡、声卡、网卡)驱动了 # kexts [HACKINTOSHER-Build Your Own](https://hackintosher.com/downloads/kexts/) # 安装驱动 You should install all kexts you need (including FakeSMC, VoodooPS2Controller, etc) to /System/Library/Extensions (/S/L/E) using a kext installer (such as Kext Wizard). Think carefully about "kexts you need". For example, if you needed HPRAIDInjector.kext for a SATA chip locked in RAID mode, you'll need to install it in order to boot (without it, the system would be unable to mount root and would get stuck early in the boot process). Of course, essential kexts should be installed to EFI/Clover/kexts/Other as they are needed to boot the installer (during updates) or the recovery partition. It is a mistake to install everything to Clover/kexts. Contrary to popular hackintosh myth, it does not result in a cleaner install (the opposite is true). Many kexts will not work from Clover/kexts, so installing them to /S/L/E where they can be included in kernel cache is the best approach. People often ask me why I install kexts to /S/L/E (or /L/E on 10.11). I have many reasons: - placing them in /S/L/E (or /L/E on 10.11) and including in kernel cache, makes kextcache do a lot of error checking. - if you develop kexts, error checking is very important! - some kexts don't work from Clover/kexts (AppleHDA injector, CodecCommander, BrcmFirmware*) - the idea behind Clover/kexts is to have a set of *stable* and *minimalistic* kexts that will allow booting of the installer/recovery, not full functionality - so...the kexts there I tend to not update as often and the full set is not there (less unneeded kexts, less problems) - placing kexts into kernel cache for day-to-day use is "more native" (as it would be on a real Mac) vs. injection (which is very non-Mac) IMO, placing kexts in Clover/kexts for injection when not needed is like "flying blind." I don't know about you, but I would not board a plane with a blind pilot (no offense to the blind). You might be wondering if this will result in duplicate kexts being loaded due to the kexts in EFI/Clover/kexts being injected when they are also installed to the system volume. The answer is no, not generally. With config.plist/SystemParameters/InjectKexts="Detect", kexts in EFI/Clover/kexts are not injected when FakeSMC.kext is in kernel cache. Because FakeSMC.kext is always a "kext you need", you will always install it to the system volume, which will put it in kernel cache. Kernel cache, of course, will not have FakeSMC.kext when booting the installer or recovery, so in these cases the kexts in EFI/Clover/kexts *will* be injected as you would expect. ---(来自:RM的[Booting the OS X installer on LAPTOPS with Clover](https://www.tonymacx86.com/threads/guide-booting-the-os-x-installer-on-laptops-with-clover.148093/)) 原则:所需驱动越少越好!!! 通过Clover加载的驱动程序位于`EFI/CLOVER/kexts/Other `,也有可能位于 `EFI/CLOVER/kexts/10.13`等其他目录中。需要安装在系统,推荐把第三方驱动安装到 `/Library/Extensions`,而不是`/System/Library/Extensions`。 重建一下系统的缓存,命令为: ```shell sudo rm -rf /System/Library/Caches/com.apple.kext.caches/Startup/kernelcache sudo rm -rf /System/Library/PrelinkedKernels/prelinkedkernel sudo touch /System/Library/Extensions/ && sudo kextcache -u / ``` 重启你的系统。 # 核心驱动 ## Lilu.kext [Lilu插件列表[持续更新]](http://www.jianshu.com/p/5bb1188c6d6f) Lilu 是 vit9696 开发的一个内核扩展 (kext),可对”任意” 内核扩展(kext)/进程(process)/运行库(framework/library)等 进行打补丁。(但其实某些比较底层的 kext 仍无法修改,如基本硬件驱动、底层重要依赖等)。 它的作用主要体现于为 kext 打补丁,为 进程 打补丁 (目前仅支持 64 位) ,为 运行库 打补丁 (目前仅支持 64 位),提供一套统一的 API 接口。 # WhateverGreen > [使用 WhateverGreen 对英特尔 ® 核芯显卡 Framebuffer 进行修补](https://www.misonsky.cn/61.html) WhateverGreen 显卡综合修复,整合了核显、AMD、NVIDIA 的综合修复,包括 (单卡启动黑屏,唤醒黑屏 等等)(依赖于 Lilu) ## FakeSMC.kext https://bitbucket.org/RehabMan/os-x-fakesmc-kozlek/downloads/ 来自tonymacx86 官方提供的黑苹果破解驱动FakeSMC.kext. 安装黑苹果必须要有的一个驱动程序,大家都知道苹果系统是不允许用户安装在出苹果公司以外的其他设备上的,FakeSMC.kex t用来欺骗OSX系统要安装的PC是SMC硬件,所以说没有他你是不可能安装好的。此版驱动提取自HWSensors 软件中,建议所有黑苹果用户更新到最新版本,可以解决不少问题。 RM 的版本可能会包含4个传感器。 ## AHCIPortInjector.kext 什么是AHCI?AHCI(Serial ATA Advanced Host Controller Interface)串行ATA高级主控接口/高级主机控制器接口,众所周知安装黑苹果时需要开启BIOS的AHCI功能,不过有些老的主板并不支持此选项,所以要用的免AHCI的补丁,此补丁可以免去没有AHCI选项的苦恼。 ## FakePCIID.kext 因为macOS系统会对`PCI device-id`进行验证,但是黑苹果的硬件不能通过这一验证,所以需要仿冒`PCIID` ## FakePCIID_Intel_HD_Graphics.kext Intel HD Graphic显卡的device-id的仿冒驱动,适用于HD4200/HD4400/HD4600/HD5600系列 # 显卡驱动 ## NVIDIA 显卡 https://gfe.nvidia.com/mac-update [NVIDIA webDriver](https://driver.wyr.me/) More about OS:[https://www.tonymacx86.com/nvidia-drivers/](https://www.tonymacx86.com/nvidia-drivers/) # 电源 ## ACPIBatteryManager.kext 推荐 采用RehabMan 的 ACPIBatteryManager.kext 可以很好的进行电源管理。但由于每型号的笔记本对于电池的Method都不尽相同,你也可以打适合自己的DSDT Patch。 ## NullCPUPowerManagement.kext 不少主板都需要用 NullCPUPowerManagement.kext(Disabler.kext)来禁用原生的AppleIntelCPUPowerManagement.kext,否则,CPU的温度会比正常高出十度左右。当然,有些品牌的主板(比如华硕的P5K)原生就可以加载AppleLPC,所以,这些主板的CPU温度是正常的,也就没必要禁用AppleIntelCPUPowerManagement了。 当然也有其他的解决方法比如说通过ACPI表DSDT来解决等等。 参考:http://www.360doc.com/content/12/0214/10/8539097_186486767.shtml # 声音 ## AppleALC的作用是加载原生声卡驱动的 这种驱动方式的好处是升级更新也不需要重新安装声卡驱动 AppleALC安装条件是你的没动过原生的声卡驱动和按其他任何有关于声卡的驱动 s/l/e下的applehda.kext必须保证是原生的 ## VoodooHDA.kext VoodooHDA是一个开源的声卡驱动程序,支持大部分声卡程序,跟AppleHDA Patcher差不多,此声卡可能会爆音,如果你不介意。 ## AppleHDA Patcher AppleHDA Patcher v1.8是黑苹果乐园搜集到的一款黑苹果仿冒声卡驱动,支持10.12,集合了众多黑苹果声卡驱动,早 ## CodecCommander.kext 解决睡眠唤醒无声问题 ## EAPDFix.kext 解决:睡眠唤醒后扬声器或耳机无声的问题。 # 触摸板 ## [VoodooPS2Controller.kext](https://github.com/RehabMan/OS-X-Voodoo-PS2-Controller) RehabMan维护的 黑苹果键盘鼠标触摸板驱动万能驱动程序 - VoodooPS2Controller ## ApplePS2SmartTouchPad.kext Smart TouchPad适用于黑苹果笔记本,支持多点触摸的touchpad(触摸板)驱动程序,支持ELAN, FocalTech 和 Synaptics的触控板。驱动来源于VoodooPS2和ApplePS2的Linux驱动开源代码,作者已经添加了更多的功能,可以充分利用触摸板,使其在各方面都接近苹果触摸板。 **台式机就算了,没有触控的。** # USB ## USBInjectAll.kext 苹果系统在OS X 10.11之后改变了USB驱动的加载方式,以至于大多数USB端口无法被驱动,对于黑苹果用户来说是个致命问题,USB无法驱动也就意味着你的键盘鼠标等USB设备无法使用,还有奇葩的摄像头问题。USBInjectAll.kext驱动文件可以帮助黑苹果驱动你的USB设备,包括3.0的端口和摄像头等问题。 https://imac.hk/usbinjectall-kext-os-x-usb3.html ## GenericUSBXHCI.kext 系统的USB3.0驱动,10.8.x以上都支持! # 无线 ## AppleIntelWiFiMVM.kext intel无线网卡驱动试试 # 有限网卡 ## [AppleIGB.kext](http://sourceforge.net/projects/osx86drivers/files/Kext/Snow_Lion/AppleIGB.kext.zip/download) I have just ported Intel igb ethernet driver ( for server adapters), which works with 82575, 82576, 82580, dh89xxcc, i350 and i210, though I have tested with 82580 quad port adapter only - tell me the result if you have different ones. It supports basic functions only ( for example, no WOL), probably the performance is lower than the Linux version as it does not utilize available sophisticated hardware features. 基于 NIC 的 Intel 有线网卡驱动,支持 82575, 82576, 82580, i350, i210 等 ## IntelMausiEthernet.kext 英特系列 82578LM、82578LC、82578DM、82578DC、 82579LM、82579V、I217LM、I217V、I218LM、 I218V、I218LM2、I218V2、I218LM3、I219V、 I219LM、I219V2、I219LM2、I219LM2 网卡驱动 ,适用于Intel主板自带的黑苹果网卡驱动程序,支持大部分网卡型号IntelMausiEthernet.kext驱动程序同时支持IPV4和IPV6的TCP、UDP和的校验接受和发送。同时驱动程序在发包率大的情况下减少了CPU的负载,也就是说你看电影下载东西玩游戏联网什么的减少了系统负载。 ## AppleIntelE1000e.kext Intel 系列 82540, 82541, 82542, 82543, 82544, 82545, 82546, 82547, 82578 (P55/H55), 82579 (P67/H67), 82574L ,82571 ,82572 ,82573 ,82574, 82583, I217V 网卡驱动,如果你网卡硬件是Atheros,可以下载使用。 ## AtherosE2200Ethernet.kext 支持高通Qualcomm Atheros AR816x, AR817x,Killer E220x 和 Killer E2400的黑苹果网卡驱动程序。 ## RealtekRTL8100.kext RTL8101E、RTL8102E、RTL8103E、RTL8401E、RTL8105E、RTL8402、RTL8106E、RTL8106EUS、RTL8107E、RTL8139 有线网卡驱动。 ## RealtekRTL8111.kext Realtek RTL8111X/8168X (X = 无 / B/C/D/E/F/G)系列有线网卡驱动 # 其他 ## Shiki.kext 如果您有一台 Ivy Bridge 或者更新的平台机器,并且无法使用 iTunes DRM 播放但您的显卡可以在 HDCP 模式下工作的话,您可以尝试使用 Shiki 。 有时 Shiki 也可以修复 Sandy Bridge 平台的这些问题。 Don't set Lilu and these plug-ins in SLE or LE, it won't work. Use kexts injection from Clover. ## IntelGraphicsFixup Fixes boot logo on all known Intel Graphics. Fixes PAVP freezes on Intel Azul, Skl, Kbl Graphics. Fixes display initialization issues for Azul, Skl, Kbl Graphics. ## NvidiaGraphicsFixup Fixes an issue in AppleGraphicsDevicePolicy.kext so that we could use any ProductName, without the usual hang with a black screen. Modifies macOS to recognize NVIDIA's web drivers as platform binaries. This resolves the issue with transparent windows without content, which appear for applications that use Metal and have Library Validation enabled. Common affected applications are iBooks and Little Snitch Network Monitor, though this patch is universal and fixes them all. Injects IOVARendererID into GPU properties (required for Shiki-based solution for non-freezing Intel and/or any discrete GPU) NVidiaAudio device to add connector-type, layout-id and other properties for HDMI audio (allows audio for HDMI, DP, Digital DVI ports) ## HibernationFixup Enable 3 & 25 mode hibernation on certain hardware. Patching of IOPCIFamily to avoid hang & black screen after resume. (Option) (Use the last FakeSMC.kext from @slice) ## AirportBrcmFixup Supports AirPort_Brcm4360, AirPort_BrcmNIC and AirPort_BrcmNIC_MFG Implements patch for passing chip id checking, in <=10.12 it's required for successful driver starting Implements patch for "Third Party Device" (returns vendor name "Apple") Implements patch for removing of white-list check ## BT4LEContiunityFixup
';

黑苹果资源

最后更新于:2022-04-02 05:45:49

[TOC] # 黑苹果清单 [10.14.2 完美黑苹果完成,分享一下配件+成本+心得](https://www.v2ex.com/t/531539) # [苹果系统之家](http://www.macoshome.com/) # [苹果软件盒子](https://www.macappbox.com) # PinConfigurator https://github.com/headkaze/PinConfigurator PinConfigurator 是一款声卡仿冒工具,出自 headkaze 大佬。 https://khronokernel-2.gitbook.io/opencore-vanilla-desktop-guide/opencore-efi # 黑苹果主机 [pcspecialist](https://www.pcspecialist.co.uk/) # EFI 资源 [黑苹果EFI - 免费分享黑苹果EFI](https://macefi.com/) [黑苹果镜像DMG下载-思羽布丁](https://www.mfpud.com/topics/3733/) [苹果的EFI集合](https://zhih.me/hackintosh/) [http://imacosx.com/efi](http://imacosx.com/efi) 机械师 F57D1T 黑苹果 10.15 + i5 6300HQ + HD630 + ALC 269 [https://macx.top/2094.html](https://macx.top/2094.html) 华硕 fxpro Thunderobot-G150H [https://github.com/search?q=thunderobot](https://github.com/search?q=thunderobot) 联想 Y700-15-ISE (尊享版) ## 写入 U 盘 下载 Etcher, 再用它把 dmg 镜像 写入 U 盘 [黑苹果镜像DMG下载](https://www.mfpud.com/macos/dmg/) [macOS完整安装包下载方法](https://www.newlearner.site/2019/07/22/full-size-macos.html) [黑苹果镜像 DMG列表](https://mirrors.dtops.cc/iso/MacOS/daliansky_macos/) ## 其他机型案例 https://github.com/syscl/M3800 https://github.com/darkhandz/XPS15-9550-High-Sierra https://github.com/daliansky/dell7000 https://github.com/darkhandz/XPS15-9550-Sierra https://github.com/corenel/XPS9550-macOS https://github.com/shmilee/T450-Hackintosh [XPS15-9560-High-Sierra](https://github.com/gunslinger23/XPS15-9560-High-Sierra) [XPS15-9550-High-Sierra](https://github.com/darkhandz/XPS15-9550-High-Sierra) [微星MSI-GP62 6QG-1281CN升级到10.13 新问题完全解决,开启Hidpi,99%完美](http://bbs.pcbeta.com/viewthread-1760262-1-1.html) [Y480 完美黑苹果全套驱动分享](http://www.jianshu.com/p/4044c7091f1f) [ASUS K55VD](https://github.com/southernvevo/ASUS-K55VD-HACKINTOSH) [黑苹果长期维护机型整理清单 | 黑果小兵](https://github.com/daliansky/daliansky.github.io/issues/127)
';