UEFI Driver编写

来源:互联网 发布:万方数据库要钱吗 编辑:程序博客网 时间:2024/06/11 03:29

最近有想在UEFI SHELL下实现所有设备的测试和访问,而且要做的平台通用性,UEFI的protocol很好支持,但是很多硬件的驱动是在PEI阶段或者没有加入规范,于是按照driver的形式写这些驱动,需要调用的时候去找这些driver的GUID来调用,这样整个调用框架不变,只要每次加载不同平台的driver就可以。有点类似linux的思路,下面代码均载录EDK SHELL。


1、首先,定义一个GUID,这个GUID是唯一的,并且不能重复,以后就是通过GUID来找这个Driver。

#define EFI_CPU_ARCH_PROTOCOL_GUID \  { 0x26baccb1, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } }

2、然后定义一个方法的集合,比如EnableInterrupt、DisableInterrupt。这里的EnableInterrupt、DisableInterrupt是函数指针,具体的实现后面会讲到

typedef struct _EFI_CPU_ARCH_PROTOCOL   EFI_CPU_ARCH_PROTOCOL;////// The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE/// Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt/// vectors and exception vectors, reading internal processor timers, resetting the processor, and/// determining the processor frequency.///struct _EFI_CPU_ARCH_PROTOCOL {  EFI_CPU_FLUSH_DATA_CACHE            FlushDataCache;  EFI_CPU_ENABLE_INTERRUPT            EnableInterrupt;  EFI_CPU_DISABLE_INTERRUPT           DisableInterrupt;  EFI_CPU_GET_INTERRUPT_STATE         GetInterruptState;  EFI_CPU_INIT                        Init;  EFI_CPU_REGISTER_INTERRUPT_HANDLER  RegisterInterruptHandler;  EFI_CPU_GET_TIMER_VALUE             GetTimerValue;  EFI_CPU_SET_MEMORY_ATTRIBUTES       SetMemoryAttributes;  ///  /// The number of timers that are available in a processor. The value in this   /// field is a constant that must not be modified after the CPU Architectural   /// Protocol is installed. All consumers must treat this as a read-only field.  ///  UINT32                              NumberOfTimers;  ///  /// The size, in bytes, of the alignment required for DMA buffer allocations.   /// This is typically the size of the largest data cache line in the platform.   /// The value in this field is a constant that must not be modified after the   /// CPU Architectural Protocol is installed. All consumers must treat this as   /// a read-only field.    ///  UINT32                              DmaBufferAlignment;};

3、定义好方法后,可以用InstallProtocolInterface,把driver具体实现挂接上去。

  //  // Install CPU Architectural Protocol  //  Status = gBS->InstallProtocolInterface (                  &mHandle,                  &gEfiCpuArchProtocolGuid,                  EFI_NATIVE_INTERFACE,                  &mCpuArchProtocol                  );


其中

mHandle :如果为NULL,则系统会自动生成一个Handle,加入到系统Handle链表里

gEfiCpuArchProtocolGuid:即是开始定义的GUID

EFI_NATIVE_INTERFACE:系统参数,只有这一种类型

mCpuArchProtocol:driver的具体实现,具体定义如下

//// The Cpu Architectural Protocol that this Driver produces//EFI_CPU_ARCH_PROTOCOL       mCpuArchProtocol = {  FlushCpuDataCache,  EnableInterrupt,  DisableInterrupt,  GetInterruptStateInstance,  Init,  RegisterInterruptHandler,  GetTimerValue,  SetMemoryAttributes,  1,  4,};

然后EnableInterrupt,DisableInterrupt都是函数名,定义了具体的方法如下:

/**  This function enables interrupt processing by the processor.  This function implements EnableInterrupt() service of CPU Architecture Protocol.  This function enables interrupt processing by the processor. This function is  used to implement the Boot Services RaiseTPL() and RestoreTPL().  @param  This              The EFI_CPU_ARCH_PROTOCOL instance.  @retval EFI_SUCCESS       Interrupts are enabled on the processor.  @retval EFI_DEVICE_ERROR  Interrupts could not be enabled on the processor.**/EFI_STATUSEFIAPIEnableInterrupt (  IN EFI_CPU_ARCH_PROTOCOL          *This  ){  EnableInterrupts ();  return EFI_SUCCESS;}

挂接后,每次Load这个Driver就可以,通过标准方法HandleProtocol来调用了。这样就实现了一个Driver的编写。


4、总结

1、Driver先要定义一个GUID,和方法的集合,然后再用InstallProtocolInterface挂接,之后Load到内存后就可以被系统调用了

2、这样定义的Driver都可以用标准接口调用,而且BIOS中已经包含大部分的驱动,这样在测试时,只要调用定义好的GUID,而Driver根据不同的

      平台适配。

3、还有问题就是UEFI还有很多总线类的驱动没有定义的很详细,比如SVID,LPC等?


0 0
原创粉丝点击