UEFI原理与编程(八):UEFI中的Protocol基础结构及其在内核中的表示

UEFI中的Protocol基础结构及其在内核中的表示

前言

  在编写UEFI程序的过程中我们会经常使用Protocol。Protocol类似于服务器与客户端的之间的一种约定,双方根据这种约定信息互通信息。这里的服务器和客户端是一种广义的称呼,提供服务的叫服务器,使用服务的成为客户端。比如常见的TCP、COM等都是Protocol。在使用Protocol之前,还是要仔细了解一下,它到底是什么样子的。

一、Protocol的结构

  Protocol引入了面向对象的思想来设计管理。它用struct来模拟class;用函数指针(Protolcol的成员变量)模拟成员函数,此函数的第一参数必须指向Protocol的指针,用来模拟this指针。

/// /EDK2/MdePkg/Include/Protocol/BlockIo.h
struct _EFI_BLOCK_IO_PROTOCOL {
  ///
  /// The revision to which the block IO interface adheres. All future
  /// revisions must be backwards compatible. If a future version is not
  /// back wards compatible, it is not the same GUID.
  ///
  UINT64              Revision;
  ///
  /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
  ///
  EFI_BLOCK_IO_MEDIA  *Media;

  EFI_BLOCK_RESET     Reset;
  EFI_BLOCK_READ      ReadBlocks;
  EFI_BLOCK_WRITE     WriteBlocks;
  EFI_BLOCK_FLUSH     FlushBlocks;

};

注意,Protocol的版本号必须向后兼容,如果不能兼容就需要对外来版本定义不同的GUID。每个Protocol必须有一个为一的GUID。如下:

/// /EDK2/MdePkg/Include/Protocol/BlockIo.h
#define EFI_BLOCK_IO_PROTOCOL_GUID \
  { \
    0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
  }

typedef struct _EFI_BLOCK_IO_PROTOCOL  EFI_BLOCK_IO_PROTOCOL;

结构体EFI_BLOCK_IO_PROTOCOL有两个成员变量和四个成员函数(其实本质是成员变量,这个变量是函数指针)。
下面是 EFI_BLOCK_IO_PROTOCOL的ReadBlocks服务的函数原型:

/**
  Read BufferSize bytes from Lba into Buffer.

  @param  This       Indicates a pointer to the calling context.
  @param  MediaId    Id of the media, changes every time the media is replaced.
  @param  Lba        The starting Logical Block Address to read from
  @param  BufferSize Size of Buffer, must be a multiple of device block size.
  @param  Buffer     A pointer to the destination buffer for the data. The caller is
                     responsible for either having implicit or explicit ownership of the buffer.

  @retval EFI_SUCCESS           The data was read correctly from the device.
  @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
  @retval EFI_NO_MEDIA          There is no media in the device.
  @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, 
                                or the buffer is not on proper alignment.

**/
typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_READ)(
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN UINT32                         MediaId,
  IN EFI_LBA                        Lba,
  IN UINTN                          BufferSize,
  OUT VOID                          *Buffer
  );

它的第一个参数 *This指向的是EFI_BLOCK_TOPROTOCOL对象自己的This指针,就是指向它的一个实例。这方面它已经具备了class的一些特征了。与C++不同的是成员函数This指针是自动加入,而Protocol成员函数
的This指针需要手动加入。

二、Protocol在UEFI内核中的表示

  在使用Protocol之前,需要先了解Protocol在UEFI内核中的表示。

  EFI_HANDLE

typedef VOID *EFI_HANDLE;

  EFI_HANDLE是指向某种对象的指针,UEFI用它来表示某个对象。UEFI扫描总线后,会为每个设备建立一个 Controller,用于控制设备,所有设备的驱动以Protocol的形式安装到Controller,这个Controller就是EFI_HANDLE对象。当我们将一个.efi文件加载到内存中时,UEFI会为该文件建立一个Image对象,这个Image对象也是一个EFI_HANDLE对象。在UEFI内部,EFI_HANDLE被理解为IHANDLE,IHANDLE的数据结构如下:

///IHANDLE - 包含了 Protocols 链表
typedef struct{
    UINTN        Signature;
    LIST_ENTRY   AllHandles;
    LIST_ENTRY   Protocols;
    UINTN        LocateRequest;
    UINT64       Key;
}IHANDLE

  每个IHANDLE中都有一个Protocol链表,存放属于自己的Protocol。所有的IAHDNLE通过AllHandles链接起来。IHANDLE的Protocols是一个双向链表,链表中的每一个元素是PROTOCOL_INTERFACE,通过PROTOCOL_INTERFACE的Protocol指针可以得到这个Protocol的GUID,通过interface指针就可以找到这个Protocol的实例。
这里写图片描述
注:图片来源与《UEFI原理与编程》

三、总结

  这部分简单介绍了Protocol的结构和在UEFI内核中的表示,算是使用protocol之前对它简单的认识。后面将会讲到,Protocol如何使用。

参考资料

  1. 《UEFI原理与编程》
  2.  UEFI Spec 2_6
  3.  EDK2 GitHub
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: UEFI(Unified Extensible Firmware Interface)是一种固件接口标准,用于用于替换传统的BIOS(Basic Input/Output System)固件,旨在提高系统启动速度、安全性和可靠性。 UEFI原理编程完整版PDF是一份详细的技术指南,提供了UEFI开发所需的全部信息,包括如何设计UEFI驱动程序、应用程序和固件,以及如何使用UEFI的各种功能。 这份PDF文件将UEFI划分为四个主要模块:启动服务、管理服务、硬件抽象层和UEFI Shell。每个模块都有详细的描述和示例代码,此外还包含了UEFI的系统架构、数据结构、驱动程序与应用程序的开发方法等内容。 此外,UEFI原理编程完整版PDF还介绍了UEFI与安全性、多核技术、嵌入式系统等方面的关系,并为读者提供了关键的UefiSpec和UefiDebugTools库文档。 总之,UEFI原理编程完整版PDF是一份权威的技术指南,涵盖了UEFI方方面面的内容,非常适合开发人员和工程师学习和参考。 ### 回答2: UEFI(Unified Extensible Firmware Interface)是一种新型的启动编程接口,它替代了旧版的BIOS(基本输入输出系统)。UEFI原理编程可以帮助开发人员理解UEFI的工作原理编程技巧。 UEFI拥有完善的安全性和可靠性,其编程方式也十分灵活。与BIOS相比,UEFI可以支持更多的硬件平台和更大的硬盘容量,同时也可以优化启动速度和程序的执行效率。 UEFI原理编程pdf完整版可以帮助开发人员更好地了解UEFI的概念和架构,并提供丰富的代码示例,帮助开发人员快速掌握UEFI编程技能。除此之外,该书还介绍了UEFI的启动流程、安全策略、UEFI应用的开发和调试等内容,对于想要深入学习UEFI编程的开发人员来说是一本很有价值的参考书。 总之,UEFI原理编程pdf完整版是一本优秀的技术参考书,其内容涵盖了UEFI的方方面面,对于想要深入了解和运用UEFI的开发人员来说具有很高的参考价值。 ### 回答3: UEFI(Unified Extensible Firmware Interface)是一种新型的系统固件接口,它为操作系统与硬件之间提供了一种标准的接口。相比传统的BIOS,UEFI可以支持更多的硬件功能,同时也更加安全和灵活。 UEFI原理主要包括以下几个方面:1、UEFI接口包括了启动管理器,硬件抽象层,运行环境和应用层等模块;2、UEFI支持模块化设计和驱动加载,可以动态地加载和卸载硬件驱动,提高了系统灵活性和安全性;3、UEFI使用GUID Partition Table(GPT)替代MBR分区表,支持更大的硬盘容量和更稳定的系统启动;4、UEFI还支持Secure Boot功能,可以防止恶意程序篡改启动软件和系统文件,提高了系统安全性。 关于UEFI编程,需要掌握以下几个核心内容:1、UEFI开发环境的搭建,需要熟悉UEFI规范以及系统固件接口的程序编写;2、UEFI应用程序的设计和开发,可以利用UEFI提供的应用程序接口(API)或者开发自定义的应用程序;3、UEFI驱动程序的编写,需要掌握UEFI驱动程序的架构和编程模型;4、UEFI启动管理器的开发,需要熟悉UEFI启动管理器的设计和实现。 总之,UEFI是一种新型的系统固件接口,可以为操作系统和硬件提供一个标准的接口,提高系统的安全性和灵活性。对于UEFI编程的学习和掌握,则需要对UEFI规范和程序设计有深入的了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值