Step to UEFI (219)Windows 下的 IoApic

前面介绍了 Shell 下的 IoApic 的读写,这次研究一下 Windows 下面的。在 Windows 下面,我们可以直接使用 RW_Everything 来进行读取,设定如下:

RW_Everything 读取 IoApic

读取结果如下:

RW_Everything 读取 IoApic 结果

我们特别关注 0x12 偏移处的值为 0x980 (这台机器和之前的 WinDBG 调试的不是同一个机器,IoApic 不同)。我猜测这里是PS/2 keyboard 的 IRQ0。参照资料修改 Bit16 (Interrupt Mask),设置为1会 Disable 这个中断。于是 x012 会被写为 0x0001 0980,这时候我发现键盘无法工作了。

IoApic Interrupt Mask

测试的这个机器是笔记本,键盘是挂在EC 下面的,EC汇报给系统的是PS/2键盘。

Device Manager PS/2 Keyboard

于是,通过这样的方式我阻止了 IRQ1 的产生,因此按键会无效。接下来,再将这个恢复为之前的 0x980,但是笔记本键盘是不工作的。我猜测应该有可能是按键堵住了 Buffer,所以再使用 RW 读取 0x60 IO port(就是打开 0x60 IO Port 页面看一下),键盘即恢复了工作。有兴趣的朋友可以自行尝试,记得需要连接一个 USB 键盘。

结论:我们现在谈论的IRQ 只的是针对 IOAPIC的Number, 比如,IRQ1 位于 I/O Redirection Table Register 1 的位置,同时这个 Register 会给出对应的 Vector。当中断发生时,CPU 会根据 Vector 找到 IDT 中给出来的ISR (Interrupt Service Routine)。

额外的实验,我们可以编写一个 Python Script 来配合 Dbc实现 IoApic 的读取,代码如下:

def Test():
    def get_APIC_DAT(index):
        _base.mem(0xfec00000 , 1, index)
        return _base.mem(0xfec00010, 4)
    import common.baseaccess as _baseaccess
    _base = _baseaccess.getglobalbase()    
    print("Script from www.lab-z.com")
    for i in range(0,0x77):
        print("%02x:%08X %08X" %(i,get_APIC_DAT(0x10+i*2),get_APIC_DAT(0x10+i*2+1)))        

上述代码命名为 myscript.py, 运行结果如下:

PythonSv 读取 IoApic

发表评论

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