ACPI.sys,从Windows到Bios的桥梁(2):Windows应用程序响应GPIO(SCI)设备中断 Bios篇

2024-01-18 22:10

本文主要是介绍ACPI.sys,从Windows到Bios的桥梁(2):Windows应用程序响应GPIO(SCI)设备中断 Bios篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    2010年毕业那会,我首次接触到51单片机,当时发现51单片机如此简单却功能完备:尽管它没有搭载OS,却能接收GPIO Port上的设备事件并反过来控制Port上的设备。反观基于x86体系的PC,虽然功能强大,但终端用户却因为下列限制,很难控制主板上的设备(小到自己往主板上的装一个按键):

a.主板厂商本着能省则省的原则,未必会在主板上保留空闲的GPIO Port;退一步,即使厂商出于某种原因,保留了空闲的GPIO Port,终端用户没有主板回路图,也无法找到这些GPIO Port;

b.即使用户侥幸找到了GPIO Port,但是GPIO Port是由主板厂商在Bios中设定的,普通用户无法修改这些设定;另外,Intel仅向IBV/OEM等它的合作厂商提供PCH spec,除非发生了类似2020年7月Intel泄露了30G相关资料,否则终端用户无法对外设进行准确的设定;

c.OS足够强大,以至于抽象了底层硬件实现(OS的透明性),这是积极的一面。但是反过来,正是因为OS的透明性,位于Ring3层的用户或者App很难访问硬件。

以上种种,无不是PC行业整体给初学者添加的重重壁垒。而我,由于机缘巧合,有机会在这些壁垒上自底向上的(Bios--Acpi.sys/OS--驱动--App)打了一串小孔,从而能在Ring3层接受来自硬件层的GPIO中断。本文基于Intel Whiskey Lake平台,总结了这种自上而下的(非标准)访问方式,也算是我对毕业这么多年的一个回顾~

 

0.神秘的P2SB接口

PCH EDS Vol2中规定,Intel PCH通过P2SB(Primary to Sideband Bridge)接口,以下列公式访问GPIO Pad:

图1.

 

图2

而P2SB接口是PCH上的PCIe设备,在Whisky Lake平台上,它位于B:0/D:31/F:1。看到这,你的第一反应一定是计算P2SB的配置空间地址,然后通过MMIO方式获得SBREG_BAR。但是P2SB和PMC Controller(B:0/D:31/F:2)一样神秘:即使已知Bus\Device\Function Number,也无法访问该PCIe设备的配置空间:

图3.MMIO方式读取3种PCIe设备的配置空间的结果(Address值0xE0000000,0xE00F9000,0xE00FA000分别对应PCIe设备B:0/D:0/F:0 B:0/D:31/F:1和B:0/D:31/F:2 )。无法获得P2SB的配置空间,进而无法获得P2SB Base Address(B:0/D:31/F:1/Reg 0x10),所以本文结束!

当然不会结束,我开玩笑的。可以从Intel提供给IBV\OEM的Intel\WhiskLakeSiliconPkg目录下找到(读者可以在Intel泄露的30G资料里找到KabyLakeSiliconePkg~ )SBREG_BAR和通过P2SB接口访问各类寄存器的宏定义:

/**Definition for PCR addressThe PCR address is used to the PCR MMIO programming
**/
#define PCH_PCR_ADDRESS(Pid, Offset)    (PCH_PCR_BASE_ADDRESS | ((UINT8)(Pid) << 16) | (UINT16)(Offset))#define PCH_PCR_BASE_ADDRESS              0xFD000000     ///< SBREG MMIO base address

这个宏定义可以视为对图1中红线部分的补充说明。

PortID

不同于51单片机访问GPIO Port,Intel PCH视GPIO为GPIO Pad(可以将GPIO Pad理解为主板上的焊点,当然Pad本身也有焊盘的意思。焊点GPIO Pad到真正的GPIO Port之间还有不为人知的回路)。同时,Intel PCH将若干物理内存上相近的GPIO Pad划到同一个GPIO Community(GPIO组),以便于访问,并赋予各个GPIO Community平台唯一的Port ID。各个平台定义的Port ID不同,需要查询EDS Vol1,下图为Whisky Lake定义的Port ID:

图4.本文用到的是GPIO community 4 GPP_E,Port ID:6A

至此,铺垫已经完成,开始正题:配置Bios使GPIO在OS下触发SCI Event需要3步(把大象关进冰箱要几步?也需要三步。):

1.配置GPIO,使其能触发GPIO SCI event;

2.配置PMC;

3.ACPI响应SCI event;

1.配置GPIO,使其能触发GPIO SCI event

这一步分3小步:

1.1.选择GPIO pin

如果读者能获得主板的GPIO table(其实读者几乎没可能获得OEM厂商的GPIO table这类内部资料,这就是我在文章开头说的障碍之一),那么从中挑选一个空闲的GPIO pin并不是难事。这篇文章使用的主板,OEM厂商设置GPP_E22是一个弱上拉信号,辅助Bios判断主板上喇叭类型(品牌喇叭/杂牌喇叭),我琢磨着这类引脚应该能随意折腾,于是外接了一根引线作为GPP_E22的输入线,另外又引出一根地线:

图5.

1.2.将GPIO Pin配置为Edge/Level触发&Enable GPIO SCI

Bios通过Pad Configuration DW0 寄存器设置来控制GPIO pin的触发方式以及中断触发类型(SCI/SMI/NMI/IOxACPI)等属性,如果将中断触发类型设置为SCI,还需要配置GPI General Purpose Events Enable寄存器:

图6.

图7.

我已经提前在主板上按如下方式配置这2个寄存器,

{GPIO_CNL_LP_GPP_E22, {GpioPadModeGpio,     GpioHostOwnAcpi,   GpioDirIn,       GpioOutDefault,       GpioIntSci | GpioIntLevel,             GpioPlatformReset,  GpioTermNone,     GpioPadConfigUnlock                           }},   

为了验证配置结果,可以将GPI_GPE_EN_GPP_E_22的偏移(Offset:0x164)和PAD_CFG_DW0_GPPC_E_22的偏移(Offset:0x8E0)作为宏PCH_PCR_ADDRESS的参数分别计算出它们的地址,然后用RW查看配置结果:

图8. GPI_GPE_EN_GPP_E_22的配置

图9. PAD_CFG_DW0_GPPC_E_22的配置

这种验证方式并不是很直观,如果读者有"Intel GPIO Configuration"工具,可以以报表的形式,获得更直观的结果:

 

图10.Intel GPIO Configuration输出结果

1.3.将GPIO Community映射到PMC GPE event

根据PCH spec可知,GPE顶层中断源共有128个,PCH外部中断将中断信号映射到GPE顶层中断源后,才有机会触发中断。仅仅完成上面的配置还不足以触发GPE SCI中断,还需要建立从GPIO到GPE的映射。建立这种映射依赖GPIO Community的Miscellaneous Configuration寄存器(MISCCFG:Offset 10):

图11.

对于Whisky Lake平台,默认的映射关系是GPP_E-->GPE_DW2/None-->GPE_DW1/GPP_B-->GPE_DW0(这种映射关系不能随意改变,改变映射关系可能不会生效)

图12.MISCCFG配置

2.配置PMC

理论上应该配置被GPPC_E22映射的用于触发PMC GPE_EN的寄存器:GPE_EN_95_64,但实际测试过程中发现不去置位GPE_EN_95_64:22也能触发SCI中断。

图12. 

 前面也说过我们无法通过MMIO获得PMC Controller PCIe配置空间的值,更无法获得ACPI Power managerment IO register的地址,所以最终还是要到Intel代码中获得:

TOKENName  = "ACPI_BASE_ADDRESS"Value  = "0x1800"Help  = "ACPI Base Address(ABASE), D31F2, Offset 40h"TokenType = IntegerTargetH = Yes
End

 由此可知,ACPI Power managerment IO register(ABASE)的偏移地址为0x1800:

图13.ACPI Power managerment IO register物理地址输出.

3.ACPI响应SCI event

ACPI命名空间\_GPE下_Lxx\_Exx Control Method用于接收和处理SCI event,_L/_E分别指电平触发和边缘触发,而xx(16 进制)是128个GPE中断源中的编号。本文中GPPC_E Port映射到GPE_96_64(GPPC_E22映射到了GPE_86),因此我们需要在\_GPE下添加_L56 Control Method:

Intel\CometLakePlatSamplePkg\Acpi\AcpiTables\Dsdt\Gpe.aslScope(\_GPE){Method (_L56, 0, Serialized){DSTR("l-event _L56"); //打印日志}}

重新编译和烧录Bios,看下Bios输出结果

当GPIO pin处于高电平时(pin在上拉状态下),有大量的"l-event _L56"输出;当GPIO pin搭上Gnd引脚,不会有这条语句输出:

图14.GPP_E22处于高电平时,Bios输出

图15.GPP_E22拉低电后,Bios输出 

总结:

Tiger Lake Platform Controller Hub (PCH) BIOS Specification概括了GPIO SCI的步骤:

参考:

声明:虽然我基于Whiskey Lake平台实现了对硬件的访问,但是该平台的PCH spec以及Bios writer guide不能公开,读者只能用已流落在民间的Skylake Lake平台相关文档替代。尽管Sky Lake和Whiskey Lake两个平台存在差异,但并不影响整体思路。

a.<Intel® 100 Series Chipset Family PCH Datasheet, Vol. 1 > (简称PCH EDS Vol1)/<Intel® 100 Series Chipset Family PCH Datasheet, Vol. 2> (简称PCH EDS Vol2), 这两份是Intel Skylake PCH spec,规定了PCH的寄存器偏移/默认值等;

b.<Tiger Lake Platform Controller Hub (PCH) BIOS Specification>, 这一份是Intel Tiger Lake bios writer guide,规定了如何在Bios中配置GPIO;

 

 

 

 

 

这篇关于ACPI.sys,从Windows到Bios的桥梁(2):Windows应用程序响应GPIO(SCI)设备中断 Bios篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/620414

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

log4j2相关配置说明以及${sys:catalina.home}应用

${sys:catalina.home} 等价于 System.getProperty("catalina.home") 就是Tomcat的根目录:  C:\apache-tomcat-7.0.77 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" /> 2017-08-10

在 Windows 上部署 gitblit

在 Windows 上部署 gitblit 在 Windows 上部署 gitblit 缘起gitblit 是什么安装JDK部署 gitblit 下载 gitblit 并解压配置登录注册为 windows 服务 修改 installService.cmd 文件运行 installService.cmd运行 gitblitw.exe查看 services.msc 缘起

Windows如何添加右键新建菜单

Windows如何添加右键新建菜单 文章目录 Windows如何添加右键新建菜单实验环境缘起以新建`.md`文件为例第一步第二步第三步 总结 实验环境 Windows7 缘起 因为我习惯用 Markdown 格式写文本,每次新建一个.txt后都要手动修改为.md,真的麻烦。如何在右键新建菜单中添加.md选项呢? 网上有很多方法,这些方法我都尝试了,要么太麻烦,要么不凑效

Windows下Nginx的安装及开机启动

1、将nginx-1.16.1.zip解压拷贝至D:\web\nginx目录下。 2、启动Nginx,两种方法: (1)直接双击nginx.exe,双击后一个黑色的弹窗一闪而过。 (2)打开cmd命令窗口,切换到nginx目录下,输入命令 nginx.exe 或者 start nginx ,回车即可。 3、检查nginx是否启动成功。 直接在浏览器地址栏输入网址 http://lo

简单的角色响应鼠标而移动

actor类 //处理移动距离,核心是找到角色坐标在世界坐标的向量的投影(x,y,z),然后在世界坐标中合成,此CC是在地面行走,所以Y轴投影始终置为0; using UnityEngine; using System.Collections; public class actor : MonoBehaviour { public float speed=0.1f; CharacterCo

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码