UEFI编程从入门到变砖跑路——ALC888集成声卡替代VT1708S

起因是VT1708S的Win10驱动做得太烂了,准备做HTPC但房间校正却不能用,换了N个驱动都不行最后只能放弃。正好手上有块坏板,上面是ALC888,所以打算把P8Q77-M声卡换成ALC888。

查看芯片Datasheet并参考其他原理图后发现,两个芯片基本是Pin2Pin兼容的外围也基本一样,但Pin40 JDREF上的阻值不一样。1708是5.1k而888是20k,这个需要注意。

直接更换Codec后,主板可以直接起来,Codec也能认出来,Windows驱动也能挂上,声音也没问题,但是Realtek(螃蟹)控制面板的插孔数量、功能及颜色不对,更重要的是不能做插孔功能映射。经过多次尝试确认,Realtek控制面板的这些属性是由Codec的配置信息(Verb Table)及SUBSYS共同决定的,直接更换CODEC后SUBSYS为默认的0x10EC0888 而螃蟹也没有帮这个SUBSYS做过多的配置。所以要完美使用还需要写Verb Table和SUBSYS。

转载请注明出处 https://racede.me/uefi-get-start-codec-alc888-replace-vt1708s.html

最终的螃蟹面板

一开始是自己看着编,但是怎么都有些小问题。刚好我有一块K9A2-CF也是ALC888,但是插孔数量不一样,这块后面板6孔的,现在的P8Q77-M是3孔的,但是考虑到3孔是6孔的子集关系,所以直接写6孔的Verb Table和SUBSYS。

RW读取到的信息

Verb Table可以直接通过RW-Everything读出来,也可以用这个软件写入。但是需要用它的命令行或脚本实现。简单来说就是通过RW-Everything PCI访问南桥的HDAudio控制器,然后通过控制器在内存里映射的接口(HDBAR),通过ICS及IC两个寄存器实现,这些寄存器的定义可以在桥片的Datasheet里查到。Verb Table的操作指令可以在ALC888的Datasheet里查到。我用的这个 RW-Everything 脚本可以在最下面的找到。

要在Windows里写入Verb Table,需要先在设备管理器把声音控制器里对应的螃蟹Codec卸载,然后用RW-Everything脚本写入Verb Table,再在系统设备里把HDAudio控制器卸载,最后再刷新一下设备,安装驱动后Codec就是我们写入的配置。但是这只能保证重启前这些配置是可靠的,要想像原生的声卡一样使用,还需要修改BIOS,在里面加一个我们的驱动。

转载请注明出处 https://racede.me/uefi-get-start-codec-alc888-replace-vt1708s.html

UEFI_APPLICATION 测试及”ver”读取

在修改BIOS前先确认自己BIOS的UEFI版本,通过下载Shell.efi并用它启动,通过ver命令查看UEFI版本,并用UEFITool 确认DXE “PE32 Image” 是x64的还是x32的,然后在UEFI.org查询版本对应的时间,然后在github clone对应的edk2,以我的P8Q77-M为例,”ver”出来的UEFI版本是2.31(上面图片是虚拟机截的不是实机),所以选择使用UDK2010.SR1。注意git clone 时需要用 –recursive 保证clone完整。

进入clone出来的目录。按照README,”. edksetup.sh BaseTools”,”make -C BaseTools”,在Conf文件夹修改target.txt,并查看tools_def.txt,选择并按装对应的编译工具,我用的是”ACTIVE_PLATFORM = OvmfPkg/OvmfPkgIa32X64.dsc”,”TARGET_ARCH = IA32 X64″, “TOOL_CHAIN_TAG = GCC47″,注意”TARGET_ARCH”需要和主板的BIOS对应。配置好后”build”一下,通过后可以开始写驱动(DXE)。

下面只是粗略的描述,具体的各种文件规范、操作指导等都可以在UEFI.org或edk2 Github的wiki里找到。

BIOS需要执行的操作和rw脚本是一样的,不过这些操作会在BIOS(UEFI)里面执行。我用的是”MODULE_TYPE = DXE_DRIVER”,模块的执行通过inf文件的depex区段控制,在UEFI流程中驱动的加载是没有先后的概念的,UEFI会一遍一遍地扫描所有模块的依赖,从不需要依赖的模块开始,谁的依赖满足了就执行谁,当然这里说得不完全准确,UEFI_DRIVER不一定是这样的,但是DXE_DRIVER基本就是这样。但由于我们是修改BIOS、没有源码,所以依赖只能在原来的BIOS里抽取。

写.inf,inf的[depex]先写成TRUE,inf会涉及一个”GUID”的概念,可以先简单地认为是组件ID就可以了,不同的组件不能重复。把inf路径加入到”OvmfPkgIa32X64.dsc”的”[Components]”这决定了edk2要编译哪些文件。然后再把inf加入到”OvmfPkgIa32X64.fdf”的”DXE Phase”这决定了edk2在打包时要处理哪些文件。

写.c,程序会从inf定义的”ENTRY_POINT”开始执行,其他的不详细说了,可以看最下面的模板。搞定后执行”build”,在Build文件夹找到你的模块文件夹,把对应的.ffs拷贝出来。

这里要注意,在加到BIOS前要像上图的一样写个UEFI_APPLICATION,验证edk2的接口是否和你的主板BIOS兼容、代码是否有问题。比较简单,修改一下inf的”MODULE_TYPE”和相关的”Library”就行,有条件的还可以用QEMU或者VMware先测试。一旦没搞好。你又没用编程器备份BIOS,你的主板很有可能会变砖。这个自己负责,我不承担任何责任。

UEFITool

各种测试没问题后,使用UEFITool把ffs加到自己的BIOS里,我是加”Setup”的后面,并把”Setup”这个DXE的”dependency section”导出来,然后替换自己编译出来的模块的”dependency section”这一步其实就是修改inf的[depex],这样做基本可以保证这个模块在Setup执行后执行。把改好的BIOS烧进主板里,进windows确认Codec的状态,如果出现UEFI_APPLICATION可以用,但是用DXE_DRIVER却不行的情况,很大可能是[depex]没改好,运行时机不对,运行时控制器还没有初始化,可以换其他DXE模块的”dependency section”试试,注意一定要选择运行靠后且有GUID的。哪些是运行靠后的?只能靠猜或者去试了。

好了,测试OK之后,好好享受吧~

转载请注明出处 https://racede.me/uefi-get-start-codec-alc888-replace-vt1708s.html

带ALC888的P8Q77-M

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注