5

UEFI开发探索70- YIE001PCIe开发板(06 UEFI驱动)

 4 years ago
source link: http://yiiyee.cn/blog/2021/01/17/uefi%e5%bc%80%e5%8f%91%e6%8e%a2%e7%b4%a270-yie001%e5%bc%80%e5%8f%91%e6%9d%bf%ef%bc%8806-uefi%e9%a9%b1%e5%8a%a8%ef%bc%89/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

UEFI开发探索70- YIE001PCIe开发板(06 UEFI驱动)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

前两篇中,我们了解了UEFI驱动模型的基本架构。 在此基础上,本篇将以一个有趣的UEFI驱动GopRotate,配合自己编写的测试用UEFI应用TestGopRotate,演示UEFI驱动的运行和测试过程。

1 UEFI驱动GopRotate

此示例由apop2提供,源码仓库为https://github.com/apop2/GopRotate。工程GopRotate包含5个源文件:ComponentName.c、GopRotate.c、GopRotate.h、GopRotateBlt.c和GopRotate.inf。这几个文件的作用分别如下:

1) ComponentName.c。实现了EFI_COMPONENT_NAME_PROTOCOL的接口函数,提供UEFI驱动的名称;
2)GopRotate.c。实现EFI_DRIVER_BINDING_PROTOCOL及其接口函数,安装EFI_DRIVER_BINDING_PROTOCOL和EFI_COMPONENT_NAME_PROTOCOL,以及实现UEFI Shell界面旋转功能的Protocol;
3) GopRotate.h。定义了驱动所需数据结构以及Protocol接口函数原型;
4) GopRotateBlt.c。实现UEFI Shell界面旋转的函数,以及提供此功能的Protocol接口函数的实现;
5) GopRotate.inf,编译UEFI驱动的INF文件。

为实现UEFI Shell界面的旋转,示例工程GopRotate主要做了以下工作:

  • 找到安装了EFI_GRAPHICS_OUTPUT_PROTOCOL的控制器,并且不能是虚拟设备;
  • 对EFI_GRAPHICS_OUTPUT_PROTOCOL的Blt()接口函数进行替换,更换为GopRotate中实现旋转显示的函数BltRotate();
  • Shell界面旋转多少度,由内部私有结构体的成员变量Rotation决定。实现控制此变量的GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL,此Protocol提供了两个接口函数,用来获取Rotation值和设置Rotation的值。

示例工程GopRotate的私有结构体如示例1所示。

【示例1】GopRotate的私有结构体

typedef struct
{
  UINTN                                       Signature;  //私有数据结构体签名
  EFI_HANDLE                                  Handle;     //管理设备的句柄
  EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT            Blt;    //原始的Blt()接口函数   
  EFI_GRAPHICS_OUTPUT_PROTOCOL                *Gop;   //Gop实例     
  GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL GopRotate;//用户使用的Protocol
  ROTATE_SCREEN                               Rotation;    //控制屏幕旋转角度
} GRAPHICS_OUTPUT_ROTATE_PRIVATE;
typedef enum
{
    Rotate0 = 0,     //不旋转
    Rotate90 = 1,    //旋转90度
    Rotate180 = 2,   //旋转180度
    Rotate270 = 3,   //旋转270度
    RotateMax = 4
} ROTATE_SCREEN;

GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL用来设置和获取屏幕旋转的角度,它提供了两个接口函数,如示例2所示。

【示例2GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL函数接口

typedef struct _GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL \
GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL;
struct _GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL
{
  GRAPHICS_OUTPUT_PROTOCOL_ROTATE_GET_ROTATION GetRotation; //获取旋转角度
  GRAPHICS_OUTPUT_PROTOCOL_ROTATE_SET_ROTATION SetRotation; //设置旋转角度
};
typedef EFI_STATUS (EFIAPI *GRAPHICS_OUTPUT_PROTOCOL_ROTATE_GET_ROTATION)(
  IN  GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL  *This, //Protocol实例
  IN  ROTATE_SCREEN                             *Rotation   //旋转的角度
  );
typedef EFI_STATUS (EFIAPI *GRAPHICS_OUTPUT_PROTOCOL_ROTATE_SET_ROTATION)(
  IN  GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL  *This, //Protocol实例
  IN  ROTATE_SCREEN                             Rotation    //旋转的角度
  );

为了实现旋转UEFI Shell界面的功能,示例工程GopRotate中实现了大量的代码,这些代码主要是围绕私有结构体GRAPHICS_OUTPUT_ROTATE_PRIVATE来构建逻辑的。核心逻辑有两处:一是替换原有Blt()函数,使得其他UEFI应用或驱动在调用Blt()接口时,实际上是调用了我们准备的函数BltRotate();二是根据用户指定的旋转角度,实现UEFI Shell界面的转换显示,此功能主要由BltRotate()函数实现。

替换接口函数Blt()的操作,在驱动的Start()函数中实现,代码就不贴出来了。

经过Start()函数的操作后,当用户调用Blt()接口函数时,实际上调用的是BltRotate()函数。在BltRotate()函数中,调用了PerformTranslations()函数,它针对不同的旋转角度,对显示进行了处理。

在GopRotate的代码中,能够清楚地看出处理逻辑,函数根据用户设定的旋转角度,对显示进行了变换处理。完成了上述两个核心逻辑后,实现设置旋转角度和获取旋转角度两个接口函数,以及其他管理驱动的代码就可以了。这些编写过程,与框架驱动BlankDrv的编写过程很类似,并不难理解,直接查看代码很容易明白。

2 UEFI应用TestGopRotate

GopRotate提供了GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL,以及此Protocol的两个接口函数,供用户设定UEFI Shell界面旋转的角度,以及获取旋转的角度。为了测试GopRotate,我编写了应用程序TestGopRotate,可通过命令行指定旋转的角度,源代码地址在文末提供。

TestGopRotate可以读取当前设定的旋转角度,设定旋转角度是通过不同的命令行参数来实现的,其用法如示例3所示。

【示例3】TestGopRotate的用法

FS0:\> TestGopRotate   //不带参数,获取当前旋转角度
Rotate90                 //旋转90度
FS0:\> TestGopRotate 3//可选择参数0,1,2,3,分别表示旋转0度,90度,180度和270度

代码的编写方法,与67篇示例工程TestServiceDrv的编写方法类似。将需要访问的Protocol的头文件GopRotate.h拷贝到TestGopRotate的文件夹下,编写访问Protocol及接口函数的代码就可以了。代码的核心部分如示例4所示。

【示例4】设置旋转的角度

EFI_STATUS      Status; 
GRAPHICS_OUTPUT_PROTOCOL_ROTATE_PROTOCOL *GopRotate = NULL;
  …… //代码略
Status=gBS->LocateProtocol(&gGraphicsOutputProtocolRotateProtocolGuid,
NULL, (VOID **)&GopRotate);//获取Protocol实例
  …… //代码略
if(Argc == 2) 
{
    switch(Argv[1][0])
    {
      case ‘0’:    
        GopRotate->SetRotation(GopRotate, Rotate0); //不旋转
        break;
      case ‘1’:
        GopRotate->SetRotation(GopRotate, Rotate90); //旋转90度
        break;
      case ‘2’:
        GopRotate->SetRotation(GopRotate, Rotate180); //旋转180度
        break;
      case ‘3’:
        GopRotate->SetRotation(GopRotate, Rotate270); //旋转270度
        break;
      default:
        break;
   }
}
return EFI_SUCCESS;

3 测试

编译这两个示例的方法,和前几篇中的方法是一样的。

编译驱动:

C:\UEFIWorkspace>build -t VS2015x86 -p RobinPkg\RobinPkg.dsc \
-m RobinPkg\Drivers\GopRotate\GopRotate.inf -a IA32

编译UEFI应用:

C:\UEFIWorkspace>build -t VS2015x86 -p RobinPkg\RobinPkg.dsc \
-m RobinPkg\Applications\TestGopRotate\TestGopRotate.inf -a IA32

运行效果:

图1 测试GopRotate

Gitee地址:https://gitee.com/luobing4365/uefi-exolorer
项目代码位于:/FF RobinPkg/ RobinPkg /Applications/TestGopRotate
              /FF RobinPkg/ RobinPkg /Drivers/GopRotate

63 total views, 2 views today

210c9a4d410d265665667a36fbe0f529?s=49&d=identicon&r=g作者 罗冰(Robin)发布于 2021年1月17日2021年1月21日分类 BIOS/UEFI


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK