UEFI实战之读取键盘信息(1)

注:完整代码及其配置文件信息见最后

一、确定读取方式

正常情况下有两种读取方式,一种是通过IO端口直接读取配置空间,另一种是通过内存映射MMIO来读取设备信息。

也可以直接通过UEFI Spec提供的Protocol来直接定位拿到键盘设备,这个方法比较简单,后面有时间再介绍。

二、遍历设备类型,找出键盘设备

我们需要判定一个设备是不是键盘,可以根据上图中的08H中的Class Code来判断设备类型,其中Class Code分为三部分:

(1)Base Class:位于Class Code的高8位

(2)Sub-Class:位于Class Code的中8位

(3)Prog. I/F:位于Class Code的低8位

下表中表示出了Class Code具体的设备类型码:

从上述我们得知,键盘属于输入设备,因此ClassCode中的Base Class应该属于0x09

根据Base Class,接着读取Sub-Class,可以得知键盘设备的Sub-Class位0x00

因此可以通过0x09 0x00拿到键盘控制器Keyboard controller

三、读取键盘设备信息

【尚未完成】拿到键盘控制器之后,可以扫描该键盘控制器下的设备,查看是否存在键盘设备,拿到键盘设备的Handle。

下图中显示了PCI的配置空间,通过配置空间可以读取键盘信息:

四、代码

Get-USB-Keyboard-Info.h

#ifndef GET_USB_KEYBOARD_INFO_H
#define GET_USB_KEYBOARD_INFO_H

#include<Uefi.h>
#include<Library/IoLib.h>
#include<Library/UefiLib.h>

#define PCI_CONFIGURATION_ADDRESS_PORT  0xCF8
#define PCI_CONFIGURATION_DATA_PORT     0xCFC
#define PCIADDR_IO(B,D,F,OFF) ( 0x80000000 + ((B)<<16) +((D)<<11) + ((F)<<8) +((OFF)&0xFC) )
#define PCIADDR_MMIO(B,D,F,OFF) ( 0x80000000+ ((B)<<20) + ((D)<<15)+ ((F)<<12) + OFF )

UINT8 PCIRead8( UINT32 Bus, UINT32 Device, UINT32 Func, UINT8 OFF );

UINT8 PCIRead16( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF );

#endif

Get-USB-Keyboard-Info.c

#include "Get-USB-Keyboard-Info.h"

UINT8 PCIRead8_Byte0 ( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF ) {
  IoWrite32 ( PCI_CONFIGURATION_ADDRESS_PORT, PCIADDR_IO(B,D,F,OFF) );
  return IoRead8 ( PCI_CONFIGURATION_DATA_PORT );
}

UINT8 PCIRead8_Byte1 ( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF ) {
  IoWrite32 ( PCI_CONFIGURATION_ADDRESS_PORT, PCIADDR_IO(B,D,F,OFF) );
  return IoRead8 ( PCI_CONFIGURATION_DATA_PORT + 1 );
}

UINT8 PCIRead8_Byte2 ( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF ) {
  IoWrite32 ( PCI_CONFIGURATION_ADDRESS_PORT, PCIADDR_IO(B,D,F,OFF) );
  return IoRead8 ( PCI_CONFIGURATION_DATA_PORT + 2 );
}

UINT8 PCIRead8_Byte3 ( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF ) {
  IoWrite32 ( PCI_CONFIGURATION_ADDRESS_PORT, PCIADDR_IO(B,D,F,OFF) );
  return IoRead8 ( PCI_CONFIGURATION_DATA_PORT + 3 );
}

UINT16 PCIRead16_Word0 ( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF ) {
  IoWrite32 ( PCI_CONFIGURATION_ADDRESS_PORT, PCIADDR_IO(B,D,F,OFF) );
  return IoRead16 (PCI_CONFIGURATION_DATA_PORT);
}

UINT16 PCIRead16_Word1 ( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF ) {
  IoWrite32 ( PCI_CONFIGURATION_ADDRESS_PORT, PCIADDR_IO(B,D,F,OFF) );
  return IoRead16 (PCI_CONFIGURATION_DATA_PORT +1 );
}

UINT32 PCIRead32 ( UINT32 B, UINT32 D, UINT32 F, UINT8 OFF ) {
  IoWrite32 ( PCI_CONFIGURATION_ADDRESS_PORT, PCIADDR_IO(B,D,F,OFF) );
  return IoRead32 ( PCI_CONFIGURATION_DATA_PORT );
}

VOID
PrintDeviceInfo ( UINT32 B, UINT32 D, UINT32 F ) {
  //define 
  UINT16       DeviceID                         = PCIRead16_Word1( B, D, F, 0 );
  Print(L"DeviceID:%04x\n",DeviceID);
  UINT16       VendorID                         = PCIRead16_Word0( B, D, F, 0 );
  Print(L"VendorID:%04x\n",VendorID);
  UINT16       Status                           = PCIRead16_Word1( B, D, F, 0x04 );
  Print(L"Status:%04x\n",Status);
  UINT16       Command                          = PCIRead16_Word0( B, D, F, 0x04 );
  Print(L"Command:%04x\n",Command);
  UINT32       ClassCode                        = ( ( PCIRead32( B, D, F, 0x08 ) ) >>8 );
  Print(L"ClassCode:%06x\n",ClassCode);
  UINT8        RevisionID                       = PCIRead8_Byte0( B, D, F, 0x08 );
  Print(L"RevisionID:%02x\n",RevisionID);
  UINT8        BIST                             = PCIRead8_Byte3( B, D, F, 0x0C );
  Print(L"BIST:%02x\n",BIST);
  UINT8        HeaderType                       = PCIRead8_Byte2( B, D, F, 0x0C );
  Print(L"HeaderType:%02x\n",HeaderType);
  UINT8        LatencyTimer                     = PCIRead8_Byte1( B, D, F, 0x0C );
  Print(L"LatencyTimer:%02x\n",LatencyTimer);
  UINT8        CachelineSize                    = PCIRead8_Byte0( B, D, F, 0x0C );
  Print(L"CachelineSize:%02x\n",CachelineSize);
  UINT8        BaseAddressRegisters;
  Print(L"BaseAddressRegisters:\n");
  for(UINT8 i = 0x10; i < 0x28; i+=4 )
  {
    BaseAddressRegisters                        = PCIRead8_Byte0( B, D, F, i );
    Print(L"%02x ",BaseAddressRegisters);
    BaseAddressRegisters                        = PCIRead8_Byte1( B, D, F, i );
    Print(L"%02x ",BaseAddressRegisters);
    BaseAddressRegisters                        = PCIRead8_Byte2( B, D, F, i );
    Print(L"%02x ",BaseAddressRegisters);
    BaseAddressRegisters                        = PCIRead8_Byte3( B, D, F, i );
    Print(L"%02x",BaseAddressRegisters);
    Print(L"\n");
  }
  UINT32       CardbusCISPointer                = PCIRead32( B, D, F, 0x28 );
  Print(L"CardbusCISPointer:%08x\n",CardbusCISPointer);
  UINT16       SubsystemID                      = PCIRead16_Word1( B, D, F, 0x2C );
  Print(L"SubsystemID:%04x\n",SubsystemID);
  UINT16       SubsystemVendorID                = PCIRead16_Word0( B, D, F, 0x2C );
  Print(L"SubsystemVendorID:%04x\n",SubsystemVendorID );
  UINT32       ExpansionROMBaseAddress          = PCIRead32( B, D, F, 0x30 );
  Print(L"ExpansionROMBaseAddress:%08x\n",ExpansionROMBaseAddress);
  UINT8        CapabilitiesPointer              = PCIRead8_Byte0( B, D, F, 0x34 );
  Print(L"CapabilitiesPointer:%02x\n",CapabilitiesPointer);
  UINT8        Max_Lat                          = PCIRead8_Byte3( B, D, F, 0x3C );
  Print(L"Max_Lat:%02x\n",Max_Lat);
  UINT8        Min_Gnt                          = PCIRead8_Byte2( B, D, F, 0x3C );
  Print(L"Min_Gnt:%02x\n",Min_Gnt);
  UINT8        InterruptPin                     = PCIRead8_Byte1( B, D, F, 0x3C );
  Print(L"InterruptPin:%02x\n",InterruptPin);
  UINT8        InterruptLine                    = PCIRead8_Byte0( B, D, F, 0x3C );
  Print(L"InterruptLine:%02x\n",InterruptLine);
}

EFI_STATUS IsUSBKeyBoardDevice(UINT32 B, UINT32 D, UINT32 F) {
  UINT8 Class    = PCIRead8_Byte3( B, D, F, 0x08 );
  UINT8 SubClass = PCIRead8_Byte2( B, D, F, 0x08 ); 
  if ( (Class == 0x09) && (SubClass == 0x00) )
  {
    Print(L"Check USB Device success \n");
    return EFI_SUCCESS;
  }
  return EFI_LOAD_ERROR;
}

EFI_STATUS EFIAPI
EntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
) 
{
  EFI_STATUS           Status;
  //Bus
  for (UINT32 B = 0; B <= 255; B++) 
  {
    //Device
    for ( UINT32 D = 0; D <= 31; D++ ) 
    {
      //Function
      for ( UINT32 F = 0; F <= 7; F++ ) 
      {
        
        // F == 0
      	if ( F == 0 ) 
        {
            //No device
            if ( PCIRead32(B, D, F, 0x00) == 0xFFFFFFFF ) 
            {
              break;
            }// end if 

            if ( ( PCIRead8_Byte2 (B, D, F, 0x0C) & 0x80 ) == 0)
            {//0 signal-function  1 multi-function
              Status = IsUSBKeyBoardDevice( B, D, F );
              if ( !EFI_ERROR (Status) ) 
              {
                PrintDeviceInfo(B, D, F);
              }
            break;
            }
      	}

        if ( PCIRead32 (B, D, F, 0x00) != 0xFFFFFFFF ) 
        {
          //Judge device type
          Status = IsUSBKeyBoardDevice( B, D, F );
          if ( !EFI_ERROR (Status) ) 
          {
            PrintDeviceInfo(B, D, F);
          }
        }

      }//Function
    }//Device
  }//Bus

  return               Status;
}

Get-USB-Keyboard-Info.inf

[Defines]
  INF_VERSION        =  0x00010005
  BASE_NAME          =  Get-USB-Keyboard-Info
  FILE_GUID          =  dbe25720-dfb7-45c2-8574-2d3f340483f2
  VERSION_STRING     =  1.0
  MODULE_TYPE        =  UEFI_APPLICATION
  ENTRY_POINT        =  EntryPoint

[Sources]
  Get-USB-Keyboard-Info.c

[Packages]
  MdePkg/MdePkg.dec
  Pkg/Pkg.dec

[LibraryClasses]
  UefiApplicationEntryPoint
  IoLib
  UefiLib

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值