2

UEFI开发探索71- YIE001PCIe开发板(07 OptionROM框架)

 3 years ago
source link: http://yiiyee.cn/blog/2021/01/17/uefi%e5%bc%80%e5%8f%91%e6%8e%a2%e7%b4%a271-yie001%e5%bc%80%e5%8f%91%e6%9d%bf%ef%bc%8807-optionrom%e6%a1%86%e6%9e%b6%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.

UEFI开发探索71- YIE001PCIe开发板(07 OptionROM框架)

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

正在编辑新书《UEFI编程实践》(暂定名),现在介绍的内容,都整理到了第8章中了。

写书还是比较费神的,博客中可以随意行文,书稿则完全不能这么做。为了做到准确,有时为了确定一个数据,需要花费整个上午查找资料。期待今年上半年能够出版吧。

关于Option ROM,在第34、35和36篇中,已经描述过其历史和原理了。现在有了开发板,就可以在上面直接进行开发了。

1 开发Option ROM

代码是基于BlankDrv中的架构进行开发的,主要修改Supported()函数和Start()函数。Supported()函数中,判断是否为目标PCIE设备(也即是否为YIE001开发板);Start()函数中,添加界面代码以及访问硬件设备的代码。

示例1中给出了修改后的Supported()代码。

【示例1】Supported()函数

EFI_STATUS EFIAPI BlankDrvDriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath   OPTIONAL)
{
  EFI_STATUS Status;
  UINT16 MyVendorID, MyDeviceID;
EFI_PCI_IO_PROTOCOL  *PciIo;
  Status = gBS->OpenProtocol (Controller, &gEfiPciIoProtocolGuid,
                  (VOID **) &PciIo,This->DriverBindingHandle,
                  Controller,EFI_OPEN_PROTOCOL_BY_DRIVER);
  if (EFI_ERROR (Status)) return Status;
  Status = PciIo->Pci.Read(PciIo,EfiPciIoWidthUint16,0,1,&MyVendorID);
  if (EFI_ERROR (Status)) goto Done; //获取厂商ID
  Status = PciIo->Pci.Read(PciIo,EfiPciIoWidthUint16,2,1,&MyDeviceID);
  if (EFI_ERROR (Status)) goto Done; //获取设备ID
  Status = EFI_SUCCESS;
  //通过厂商ID和设备ID,判断是否为目标设备
  if (MyVendorID != CH366_VENDOR_ID || MyDeviceID != CH366_DEVICE_ID)
    Status = EFI_UNSUPPORTED;
  Done:  //关闭所用的Protocol
  gBS->CloseProtocol(Controller,&gEfiPciIoProtocolGuid,
         This->DriverBindingHandle,Controller);
  return Status;
}

在Supported()函数中,首先使用OpenProtocol()打开PCI I/O Protocol,如果打开失败,则返回EFI_UNSUPPORTED。然后使用得到的PCI I/O Protocol实例,从PCI设备的配置空间,获得厂商ID和设备ID。如果所得到的厂商ID及设备ID,与目标设备的一致,则返回EFI_SUCCESS,否则返回EFI_UNSUPPORTED。

示例2中给出了修改后的Start()函数。

【示例2】Start()函数

EFI_STATUS EFIAPI BlankDrvDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath   OPTIONAL  )
{
  ……  //代码略
  Status = PciIo->Pci.Read(PciIo,EfiPciIoWidthUint16,16,1,&MyIoBaseAddr);     
  if (EFI_ERROR (Status)) goto Done;
  MyIoBaseAddr=(MyIoBaseAddr&0x0fffe);  //得到I/O基地址
HelloUEFI();                              //Oprom的演示函数
  Status = EFI_SUCCESS;
Done: ……  //代码略
return Status;
}

Start()函数在函数起始,通过PCI I/O Protocol的实例,在设备的PCI空间中将此基地址取到。其后调用HelloUEFI()函数,实现需要的功能。

也就是说,完成这些框架后,可以把精力集中在HelloUEFI()函数的编写上。UEFI开发探索的系列博客中,使用各种Protocol,实现了各种功能的示例程序。这些程序略作修改,都可以移植到这个地方。

本篇中,直接在HelloUEFI()中,添加打印字符串,并等待用户输入,实现简单的演示功能就可以了。如下所示:

VOID HelloUEFI(VOID)
{
  gST->ConOut->OutputString(gST->ConOut,L”Hello, I am YIE001!\n\r”)
  WaitKey();  //等待用户按键
}

2 编译及测试Option ROM

所编写的UEFI驱动,需要按照一定的方法编译,才能生成Option ROM。在第36篇中,已经比较详细地介绍过如何编译了。

本篇采用修改INF文件的方式,对UEFI驱动进行编译。示例3中给出了INF文件的修改样本。

【示例3】INF文件

[Defines]
  ……                        //其他变量,略去
  PCI_VENDOR_ID = 0x1C00     //厂商ID
  PCI_DEVICE_ID = 0x4349     //设备ID
  PCI_CLASS_CODE = 0x020000 //设备分类号
  PCI_REVISION = 0x0003      //代码版本
  PCI_COMPRESS = TRUE        //是否压缩,TRUE为压缩

假设自己编写的示例工程为MyOprom,则编译命令如下:

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

注意使用X64目标架构进行编译,大部分的机器基本上都是64位的UEFI BIOS了。

编译完成之后,将在输出目录中生成MyOprom.efi和MyOprom.rom两个文件。使用EfiRom工具,运行“-d”命令,可以查看MyOprom.rom的信息。可以看到MyOprom.rom已经是个有效的UEFI Option ROM文件,其厂商ID、设备ID等信息,与INF文件中设定的一致。

测试的方法有两种,一是在UEFI Shell下,使用load命令或者loadpcirom命令,直接将驱动挂载在设备控制器的句柄上,显示MyOprom中实现的功能;二是将二进制ROM文件,按照CH366的要求,以二进制的形式写入YIE001上的Flash ROM中,进行测试。

这两种测试方法,都要求YIE001开发板插在实际机器上运行。

这里先介绍下前一种测试方法,后一种方法,在YIE001的下一篇博客中再讨论。

将编译好的64位efi程序和rom文件,即MyOprom.efi和MyOprom.rom复制到UEFI启动U盘中。

把开发板YIE001插在主板的PCIe槽上,然后启动测试的计算机,进入UEFI Shell环境。在

UEFI Shell环境下,可以使用Shell命令“pci”列举出所有PCI设备,查看开发板YIE001是否被系统识别出来。YIE001开发板上设定的厂商ID是0x1C00,设备ID是0x4349,可在列举出的PCI设备中寻找是否存在。

使用如下命令进行测试:

load MyOprom.efi

loadpcirom MyOprom.rom

加载驱动(或者Option ROM)后,屏幕上会显示示例工程中HelloUEFI()函数打印的字符串。

78 total views, 1 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