简要说明

Protocol是UEFI中的一个重要概念(事实上《UEFI SPEC》中有超过70%的内容都是在讲Protocol),下面简单说明下:

1. 首先,非常重要的一点,Protocol不是什么特殊的东西,它就是一个结构体,比如说下面是一个用于存储设备访问的Protocol:

  1. ///
  2. /// This protocol provides control over block devices.
  3. ///
  4. struct _EFI_BLOCK_IO_PROTOCOL {
  5. ///
  6. /// The revision to which the block IO interface adheres. All future
  7. /// revisions must be backwards compatible. If a future version is not
  8. /// back wards compatible, it is not the same GUID.
  9. ///
  10. UINT64 Revision;
  11. ///
  12. /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
  13. ///
  14. EFI_BLOCK_IO_MEDIA *Media;
  15. EFI_BLOCK_RESET Reset;
  16. EFI_BLOCK_READ ReadBlocks;
  17. EFI_BLOCK_WRITE WriteBlocks;
  18. EFI_BLOCK_FLUSH FlushBlocks;
  19. };

2. 其次,Protocol不是UEFI BIOS一开始就可以用的。我们知道UEFI BIOS启动时分为不同的阶段,SEC-PEI-DXE-BDS等等。而Protocol需要等到DXE阶段才可以使用(不需要特别在意DXE阶段的哪个点开始,基本上我们开发时写的DXE模块都可以使用)。

3. UEFI框架下提供了函数来存取Protocol。

4. Protocol的作用跟普通的结构体没有区别,如果存放的是数据就作为存储用,如果存放的是函数指针就用作特定代码执行。

5. UEFI下将大部分的设备初始化和其它功能代码都包装成了一个个的Protocol,所以要学习UEFI,Protocol是必经之路。

Protocol的实现说明

首先一张图说明:

这里需要关注的图中红框部分的内容。

这里实际上是两种链表,一种是Handle的链表,一种是Protocol的链表。Handle其实就是一个不会重复的整型数字,而Protocol在之前已经说过就是一个结构体。各个Handle连接在一起构成一个链表,每个Handle上可以附着若干个不会重复的Protocol。

上述的两种链表交织成了一张网,这张网被称为“Handle Database”。

这个Handle Database会在DXE最开始的地方初始化起来,之后通过接口可以扩展,搜寻等等操作。

关于具体的代码实现这里不再介绍,可以参考DXE阶段开始的代码(DxeMain.c)。

Protocol的使用

在UEFI Boot Service中提供了如下的函数用来操作Protocol:

  1. //
  2. // Protocol Handler Services
  3. //
  4. EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface;
  5. EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface;
  6. EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface;
  7. EFI_HANDLE_PROTOCOL HandleProtocol;
  8. VOID *Reserved;
  9. EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify;
  10. EFI_LOCATE_HANDLE LocateHandle;
  11. EFI_LOCATE_DEVICE_PATH LocateDevicePath;
  12. EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable;
  13. //
  14. // Open and Close Protocol Services
  15. //
  16. EFI_OPEN_PROTOCOL OpenProtocol;
  17. EFI_CLOSE_PROTOCOL CloseProtocol;
  18. EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation;
  19. //
  20. // Library Services
  21. //
  22. EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle;
  23. EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer;
  24. EFI_LOCATE_PROTOCOL LocateProtocol;
  25. EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces;
  26. EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces;

它们可以分为几种不同的类型:

1. 安装和卸载接口,就是这里的IntallXXX,ReinstallXXX,UninstallXXX,IntallMultipleXXX,UninstallMultipleXXX等。

2. 获取和关闭接口,比如HandleProtocol,LocateHandle等等。

3. 其它辅助接口,比如OpenProtocolInformation,RegisterProtocolNotify等,其中RegisterProtocolNotify注册了一个回调函数,当指定的Protocol被安装时,这个回调函数就会被执行。

之后会有实际的代码来介绍如何使用这些接口。

几种特殊的Protocol

UEFI中的Protocol有一些比较特殊的类型,本节将介绍这些Protocol。

Architectural Protocol

UEFI规定了一些Protocol,这些Protocol在UEFI BIOS运行的过程中会安装,且一定需要被安装,如果没有被安装的话,系统就会报错。

这些Protocol如下所示:

  1. //
  2. // DXE Core Global Variables for all of the Architectural Protocols.
  3. // If a protocol is installed mArchProtocols[].Present will be TRUE.
  4. //
  5. // CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
  6. // and mArchProtocols[].Registration as it creates events for every array
  7. // entry.
  8. //
  9. EFI_CORE_PROTOCOL_NOTIFY_ENTRY mArchProtocols[] = {
  10. { &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE },
  11. { &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE },
  12. { &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE },
  13. { &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE },
  14. { &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE },
  15. { &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
  16. { &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE },
  17. { &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
  18. { &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
  19. { &gEfiCapsuleArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
  20. { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
  21. { &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
  22. { &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
  23. { NULL, (VOID **)NULL, NULL, NULL, FALSE }
  24. };

这些Protocol都是UEFI或者系统必须的最基础的Protocol,比如说这里的gEfiBdsArchProtocolGuid对应的Protocol,它是BDS阶段的如果,在DXEMain.c中有如下的代码:

  1. //
  2. // Transfer control to the BDS Architectural Protocol
  3. //
  4. gBds->Entry (gBds);

使DXE阶段过渡到BDS阶段。

Device Path Protocol

Device Path Protocol是一种纯数据的结构体,它表示的是一个设备的可编程路径,可以简称就是Device Path(后面就直接省略掉Protocol)。

这种说法比较抽象,而且这里说的“设备”也并不一定需要是真实的设备,它可以是虚拟设备,甚至可以是一个文件。

Device Path的具体说明有在其它的文章中介绍,这里不做具体的说明。

这里简单介绍一下它的结构体:

  1. /**
  2. This protocol can be used on any device handle to obtain generic path/location
  3. information concerning the physical device or logical device. If the handle does
  4. not logically map to a physical device, the handle may not necessarily support
  5. the device path protocol. The device path describes the location of the device
  6. the handle is for. The size of the Device Path can be determined from the structures
  7. that make up the Device Path.
  8. **/
  9. typedef struct {
  10. UINT8 Type; ///< 0x01 Hardware Device Path.
  11. ///< 0x02 ACPI Device Path.
  12. ///< 0x03 Messaging Device Path.
  13. ///< 0x04 Media Device Path.
  14. ///< 0x05 BIOS Boot Specification Device Path.
  15. ///< 0x7F End of Hardware Device Path.
  16. UINT8 SubType; ///< Varies by Type
  17. ///< 0xFF End Entire Device Path, or
  18. ///< 0x01 End This Instance of a Device Path and start a new
  19. ///< Device Path.
  20. UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define
  21. ///< type of data. Size of data is included in Length.
  22. } EFI_DEVICE_PATH_PROTOCOL;

它的结构非常的简单,是一个可变长的结构体。

成员包括了一个基本的头部(分为类型,子类型和长度三部分),以及之后的具体类型所需要包含的成员。

Device Path有一个非常重要的作用就是标记对应Handle的属性。

举一个简单的例子,现在有两个硬盘,那么它们都有一个_EFI_BLOCK_IO_PROTOCOL(见开头),然而我们想访问其中一个特定的硬盘,如何找到这个硬件,就可以依赖于Device Path。

以硬盘的Device Path举例,它的类型是HARDWARE_DEVICE_PATH,子类型是HW_CONTROLLER_DP,因此它的Device Path中包含如下的部分:

  1. ///
  2. /// Controller Device Path.
  3. ///
  4. typedef struct {
  5. EFI_DEVICE_PATH_PROTOCOL Header;
  6. ///
  7. /// Controller number.
  8. ///
  9. UINT32 ControllerNumber;
  10. } CONTROLLER_DEVICE_PATH;

而两个不同的硬盘,其中的ControllerNumber可能是不同的(根据不同的硬件配置),因此就可以确定到底使用哪个Device Path,最终获取到正确的_EFI_BLOCK_IO_PROTOCOL,大致流程如下:

1. 调用LocateHandleBuffer获取到所有安装了_EFI_BLOCK_IO_PROTOCOL的Handle;

2. 遍历所有的Handle;

3. 根据上述Handle获取到Device Path Protocol,根据这个Device  Path Protocol就能够确定该Handle是否是我们要找的那个Handle;

4. 通过找到的Handle,调用HandleProtocol来到对应的_EFI_BLOCK_IO_PROTOCOL,然后就可以使用这个Protocol来访问硬盘。

以上是使用Device Path Protocol的一个示例。

当然Device Path Protocol的用法还有很多,这个就需要自己摸索了。

EFI_DRIVER_BINDING_PROTOCOL

该类Protocol用在一种叫做UEFI Driver Model类型的驱动中。

这种驱动在DXE阶段安装,但实际使用是在BDS阶段。

这种Protocol的结构如下:

  1. ///
  2. /// This protocol provides the services required to determine if a driver supports a given controller.
  3. /// If a controller is supported, then it also provides routines to start and stop the controller.
  4. ///
  5. struct _EFI_DRIVER_BINDING_PROTOCOL {
  6. EFI_DRIVER_BINDING_SUPPORTED Supported;
  7. EFI_DRIVER_BINDING_START Start;
  8. EFI_DRIVER_BINDING_STOP Stop;
  9. ///
  10. /// The version number of the UEFI driver that produced the
  11. /// EFI_DRIVER_BINDING_PROTOCOL. This field is used by
  12. /// the EFI boot service ConnectController() to determine
  13. /// the order that driver's Supported() service will be used when
  14. /// a controller needs to be started. EFI Driver Binding Protocol
  15. /// instances with higher Version values will be used before ones
  16. /// with lower Version values. The Version values of 0x0-
  17. /// 0x0f and 0xfffffff0-0xffffffff are reserved for
  18. /// platform/OEM specific drivers. The Version values of 0x10-
  19. /// 0xffffffef are reserved for IHV-developed drivers.
  20. ///
  21. UINT32 Version;
  22. ///
  23. /// The image handle of the UEFI driver that produced this instance
  24. /// of the EFI_DRIVER_BINDING_PROTOCOL.
  25. ///
  26. EFI_HANDLE ImageHandle;
  27. ///
  28. /// The handle on which this instance of the
  29. /// EFI_DRIVER_BINDING_PROTOCOL is installed. In most
  30. /// cases, this is the same handle as ImageHandle. However, for
  31. /// UEFI drivers that produce more than one instance of the
  32. /// EFI_DRIVER_BINDING_PROTOCOL, this value may not be
  33. /// the same as ImageHandle.
  34. ///
  35. EFI_HANDLE DriverBindingHandle;
  36. };

下面是一个例子:

1. 声明:

  1. //
  2. // Simple Network Protocol Driver Global Variables
  3. //
  4. EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {
  5. SimpleNetworkDriverSupported,
  6. SimpleNetworkDriverStart,
  7. SimpleNetworkDriverStop,
  8. 0xa,
  9. NULL,
  10. NULL
  11. };

2. 安装:

  1. EFI_STATUS
  2. EFIAPI
  3. InitializeSnpNiiDriver (
  4. IN EFI_HANDLE ImageHandle,
  5. IN EFI_SYSTEM_TABLE *SystemTable
  6. )
  7. {
  8. return EfiLibInstallDriverBindingComponentName2 (
  9. ImageHandle,
  10. SystemTable,
  11. &gSimpleNetworkDriverBinding,
  12. ImageHandle,
  13. &gSimpleNetworkComponentName,
  14. &gSimpleNetworkComponentName2
  15. );
  16. }

上述代码在Snp.c中,整个模块就是在DXE阶段安装了若干个Protocol(其它的不是很重要)。

这里的EFI_DRIVER_BINDING_PROTOCOL通常是不会通过HandleProtocol等函数去获取的,而是使用下面的接口(也在UEFI Boot Service中):

  1. //
  2. // DriverSupport Services
  3. //
  4. EFI_CONNECT_CONTROLLER ConnectController;
  5. EFI_DISCONNECT_CONTROLLER DisconnectController;

当调用ConnectController的时候,代码首先会去执行EFI_DRIVER_BINDING_PROTOCOL中的XXXSupported函数,判断传入的Handle是否符合该Protocol执行的要求,如果符合就执行XXXStart函数,否则就直接退出;而DisconnectController会去执行Protocol中的XXXStop函数。

EFI_DRIVER_BINDING_PROTOCOL或者说UEFI Driver Model实现了一种动态的方式来执行代码以完成初始化。

所以EFI_DRIVER_BINDING_PROTOCOL也是比较特殊的一种Protocol。

自己编写Protocol

下面简单的编写一个自己的Protocol,并使用该Protocol。

具体的代码可以在https://gitee.com/jiangwei0512/vUDK2017找到。

编写Protocol并安装

1. 首先需要定义一个Protocol,通常会在独立Package的Include/Protocol目录下创建一个头文件,这里是HelloWorldProtocol.h:

  1. /**
  2. * @Package : BeniPkg
  3. * @FileName : HelloWorldProtocol.h
  4. * @Date : 20190211
  5. * @Author : Wei Jiang
  6. * @Version : 0.1
  7. * @Description :
  8. * This file describes a protocol for test.
  9. *
  10. * @History:
  11. * 20190211: Initialize.
  12. *
  13. * This program and the accompanying materials
  14. * are licensed and made available under the terms and conditions of the BSD License
  15. * which accompanies this distribution. The full text of the license may be found at
  16. * http://opensource.org/licenses/bsd-license.php
  17. *
  18. * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  20. **/
  21. #ifndef __BENI_HELLO_WORLD_PROTOCOL_H__
  22. #define __BENI_HELLO_WORLD_PROTOCOL_H__
  23. #include <Uefi.h>
  24. #define EFI_HELLO_WORLD_PROTOCOL_GUID \
  25. {0x038f1af5, 0x1c8d, 0x408f, { 0xab, 0x25, 0x30, 0xae, 0xb5, 0x96, 0x5d, 0x6e }}
  26. typedef struct _EFI_HELLO_WORLD_PROTOCOL EFI_HELLO_WORLD_PROTOCOL;
  27. /**
  28. Print "Hello Wrold".
  29. @param[in] This A pointer to the EFI_HELLO_WORLD_PROTOCOL instance.
  30. @retval EFI_SUCCESS Always return EFI_SUCCESS after print.
  31. **/
  32. typedef
  33. EFI_STATUS
  34. (EFIAPI *HELLO) (
  35. IN EFI_HELLO_WORLD_PROTOCOL *This
  36. );
  37. struct _EFI_HELLO_WORLD_PROTOCOL {
  38. UINTN Version;
  39. HELLO Hello;
  40. };
  41. extern EFI_GUID gEfiHelloWorldProtocolGuid;
  42. #endif // __BENI_HELLO_WORLD_PROTOCOL_H__

实际上上述代码中重要的有两个部分,一个就是Protocol,这里定义了一个包含一个整型和一个函数指针的Protocol;另一个是一个EFI_GUID,之前的说明中一直没有提到,它其实是对应Protocol的标记,前面提到的UEFI Boot Service中的Protocol处理接口需要通过这个EFI_GUID来操作Protocol。因为EFI_GUID是唯一的,所以能够对应特定的Protocol。

不仅在头文件中需要声明EFI_GUID,这里就是gEfiHelloWorldProtocolGuid,还需要在dec文件中定义该EFI_GUID:

  1. [Protocols]
  2. # // Include/Protocol/HelloWorldProtocol.h
  3. # // {038F1AF5-1C8D-408F-AB25-03AEB5965D6E}
  4. gEfiHelloWorldProtocolGuid = { 0x038f1af5, 0x1c8d, 0x408f, { 0xab, 0x25, 0x30, 0xae, 0xb5, 0x96, 0x5d, 0x6e } }

否则在其它代码中就无法使用gEfiHelloWorldProtocolGuid。

2. 之后就是EFI_HELLO_WORLD_PROTOCOL的实现和安装:

  1. /**
  2. * @Package : BeniPkg
  3. * @FileName : ProtocolServer.c
  4. * @Date : 20190211
  5. * @Author : Wei Jiang
  6. * @Version : 0.1
  7. * @Description :
  8. * Install EFI_HELLO_WORLD_PROTOCOL.
  9. *
  10. * @History:
  11. * 20190211: Initialize.
  12. *
  13. * This program and the accompanying materials
  14. * are licensed and made available under the terms and conditions of the BSD License
  15. * which accompanies this distribution. The full text of the license may be found at
  16. * http://opensource.org/licenses/bsd-license.php
  17. *
  18. * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  20. **/
  21. #include <Uefi.h>
  22. #include <Library/UefiDriverEntryPoint.h>
  23. #include <Library/UefiBootServicesTableLib.h>
  24. #include <Library/MemoryAllocationLib.h>
  25. #include <Library/DebugLib.h>
  26. #include <Protocol/HelloWorldProtocol.h>
  27. /**
  28. Print "Hello Wrold".
  29. @param[in] This A pointer to the EFI_HELLO_WORLD_PROTOCOL instance.
  30. @retval EFI_SUCCESS Always return EFI_SUCCESS after print.
  31. **/
  32. EFI_STATUS
  33. EFIAPI
  34. Hello (
  35. IN EFI_HELLO_WORLD_PROTOCOL *This
  36. )
  37. {
  38. DEBUG ((EFI_D_ERROR, "Hello World\n"));
  39. return EFI_SUCCESS;
  40. }
  41. /**
  42. Main entry of the driver.
  43. @param[in] ImageHandle Image handle for this driver.
  44. @param[in] SystemTable Pointer to the System Table.
  45. @retval EFI_SUCCESS Driver executed successfully.
  46. @retval Others Error happened.
  47. **/
  48. EFI_STATUS
  49. EFIAPI
  50. ProtocolServerEntry (
  51. IN EFI_HANDLE ImageHandle,
  52. IN EFI_SYSTEM_TABLE *SystemTable
  53. )
  54. {
  55. EFI_STATUS Status;
  56. EFI_HELLO_WORLD_PROTOCOL *Protocol;
  57. Protocol = AllocatePool (sizeof (EFI_HELLO_WORLD_PROTOCOL));
  58. if (NULL == Protocol) {
  59. DEBUG ((EFI_D_ERROR, "[BENI][%a][%d]: Out of resource.", __FUNCTION__, __LINE__));
  60. return EFI_OUT_OF_RESOURCES;
  61. }
  62. Protocol->Version = 0x01;
  63. Protocol->Hello = Hello;
  64. Status = gBS->InstallProtocolInterface (
  65. &ImageHandle,
  66. &gEfiHelloWorldProtocolGuid,
  67. EFI_NATIVE_INTERFACE,
  68. Protocol
  69. );
  70. if (EFI_ERROR (Status)) {
  71. DEBUG ((EFI_D_ERROR, "[BENI]Install EFI_HELLO_WORLD_PROTOCOL failed. - %r\n", Status));
  72. FreePool (Protocol);
  73. return Status;
  74. }
  75. return EFI_SUCCESS;
  76. }

观察Protocol的安装,可以看到这里使用的参数:

ImageHandle:这个就是用来存放Protocol的EFI_HANDLE,当然也可以使用初始值为NULL的新的Handle,不过方便起见就使用了原有的;

gEfiHelloWorldProtocolGuid:这个就是用来标记EFI_HELLO_WORLD_PROTOCOL的EFI_GUID;

EFI_NATIVE_INTERFACE:这是Protocol的属性,类型是EFI_INTERFACE_TYPE,目前只有这一个值;

Protocol:就是本模块实现的Protocol实例,这里需要注意它的类型是XXX_PROTOCOL指针,有时候可能一时疏忽写成了&Protocol,就会导致使用该Protocol的时候异常挂死;

3. 最后就是对Protocol的使用:

  1. /**
  2. * @Package : BeniPkg
  3. * @FileName : ProtocolConsumer.c
  4. * @Date : 20190211
  5. * @Author : Wei Jiang
  6. * @Version : 0.1
  7. * @Description :
  8. * Use EFI_HELLO_WORLD_PROTOCOL.
  9. *
  10. * @History:
  11. * 20190211: Initialize.
  12. *
  13. * This program and the accompanying materials
  14. * are licensed and made available under the terms and conditions of the BSD License
  15. * which accompanies this distribution. The full text of the license may be found at
  16. * http://opensource.org/licenses/bsd-license.php
  17. *
  18. * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  20. **/
  21. #include <Uefi.h>
  22. #include <Library/UefiDriverEntryPoint.h>
  23. #include <Library/UefiBootServicesTableLib.h>
  24. #include <Library/DebugLib.h>
  25. #include <Protocol/HelloWorldProtocol.h>
  26. /**
  27. Main entry of the driver.
  28. @param[in] ImageHandle Image handle for this driver.
  29. @param[in] SystemTable Pointer to the System Table.
  30. @retval EFI_SUCCESS Driver executed successfully.
  31. @retval Others Error happened.
  32. **/
  33. EFI_STATUS
  34. EFIAPI
  35. ProtocolConsumerEntry (
  36. IN EFI_HANDLE ImageHandle,
  37. IN EFI_SYSTEM_TABLE *SystemTable
  38. )
  39. {
  40. EFI_STATUS Status;
  41. EFI_HELLO_WORLD_PROTOCOL *Protocol;
  42. Status = gBS->LocateProtocol (&gEfiHelloWorldProtocolGuid, NULL, (VOID **)&Protocol);
  43. if (EFI_ERROR (Status)) {
  44. DEBUG ((EFI_D_ERROR, "[BENI]Locate EFI_HELLO_WORLD_PROTOCOL failed. - %r\n", Status));
  45. return Status;
  46. }
  47. DEBUG ((EFI_D_ERROR, "Protocol Version: 0x%08x\n", Protocol->Version));
  48. Status = Protocol->Hello (Protocol);
  49. if (EFI_ERROR (Status)) {
  50. DEBUG ((EFI_D_ERROR, "[BENI]Protocol->Hello failed. - %r\n", Status));
  51. return Status;
  52. }
  53. return EFI_SUCCESS;
  54. }

关于实现就比较简单了,只是调用LocateProtocol来获取Protocol,然后使用即可。

以上就是对Protocol的一个实现以及简单的使用,对应的模块是ProtocolServer.inf和ProtocolConsumer.inf。


http://www.taodudu.cc/news/show-2786716.html

相关文章:

  • HA高可用搭建
  • UEFI----EFI_DRIVER_BINDING_PROTOCOL
  • 【UEFI基础】Protocol介绍
  • Jscex没有xxxAsync().stop()怎么办?
  • LInux 实训二记录
  • Windows下使用Jconsole远程监控Linux系统中java服务器资源占用情况
  • net_device详解
  • Darknet官方文档(含Yolo-V2和V3在win和Linux训练测试步骤、计算mAP、调参优化等)
  • Linux下service xxx start/stop/restart启动服务、关闭服务、重启服务深入理解@
  • UDS 服务 Service 0x31 - RoutineControl
  • 【RPC】序列化与反序列化
  • Java 序列化详解
  • oracle 查找所有序列,Oracle查询所有序列
  • 序列比对
  • 序列的相关性
  • 时间序列分析教程(一):基本性质
  • 什么是序列化 怎么序列化 为什么序列化
  • Json序列化技术
  • 【生信MOOC】生物序列比对工具——多序列比对
  • 时间序列预测
  • postgres查询序列_PostgreSQL之序列(Sequence)
  • SpringBoot的序列化和反序列化
  • python创建时间序列_python 时间序列
  • 序列化和反序列化
  • postgres查询序列_PostgreSQL 序列使用
  • 序列比对算法
  • 序列化和反序列化的详解
  • Python序列(包括序列类型和常用操作)
  • 序列(sequence)(Python入门十二)
  • 【python】什么是序列,Python序列详解

BIOS/UEFI基础——Protocol介绍相关推荐

  1. BIOS/UEFI基础——FDF文件

    综述 FDF的全称是Flash Description File. 它是构成BIOS二进制的描述符,即FDF文件描述了BIOS二进制的组成结构. 本文的目的就是介绍FDF文件内部的组成以及它们是如何完 ...

  2. 【UEFI基础】Protocol介绍

    简要说明 Protocol是UEFI中的一个重要概念(事实上<UEFI SPEC>中有超过70%的内容都是在讲Protocol),下面简单说明下: 1. 首先,非常重要的一点,Protoc ...

  3. 【UEFI基础】UEFI事件介绍

    简述 在[UEFI基础]System Table和Architecture Protocols介绍Boot Service时提到有一部分与事件相关的接口,它们创建.触发.等待和关闭事件,来完成某些功能 ...

  4. 【UEFI基础】Device Path

    什么是Device Path 没有在UEFI SPEC中找到一个非常清晰的Device Path的定义. 关于Device Path,UEFI SPEC中有如下的描述: A Device Path i ...

  5. 【UEFI基础】UEFI变量基础2

    说明 之前已经写过一篇变量相关的文章[UEFI基础]UEFI变量基础,该文章使用的是模拟的变量,而本文更接近于实际的变量模块. 环境设置 为了测试BIOS的变量功能,需要修改QEMU的启动选项,如下所 ...

  6. 【UEFI基础】ACPI基础

    什么是ACPI 高级配置和电源管理接口(Advanced Configuration and Power Management Interface). ACPI是一套协议标准,软硬件都需实现以配合使用 ...

  7. UEFI——UEFI 基础服务

    文章目录 前言 BootService Table gBS EFI_BOOT_SERVICES SystemTable EFI_SYSTEM_TABLE SystemTable mBootServic ...

  8. uefi多linux系统启动盘,DIY制作无需格BIOS+UEFI双启动U盘工具|支持syslinux+grub+boomgr+grub2多启动...

    如果你想让你的U盘可启动的话,要怎么做呢,可能很多人都知道借助软件能自动实现,但那些方式都需要把U盘格式化一遍,而这个工具完全不需要,只需要把下载的文件解压到U盘根目录就能实现多启动了,支持bios和 ...

  9. linux route 刷新_linux基础命令介绍十五:推陈出新

    本文介绍ip.ss.journalctl和firewall-cmd,它们旨在代替linux中原有的一些命令或服务. 1.ip ip [OPTIONS] OBJECT COMMAND ip是iprout ...

最新文章

  1. 字符串-验证回文串(双指针法)
  2. linux查看当前的工作目录,Linux-查看当前工作目录(pwd)
  3. 把iPhone充电口改成Type-C,卖了56万!
  4. PAT甲级1074 Reversing Linked List :[C++题解]反转链表,借用vector
  5. 零基础学Python(第十七章 模块import)
  6. php获取flash上传视频文件大小,如何获取flash文件(.swf文件)的长度和宽度
  7. numpy 矩阵求逆_numpy 矩阵运算
  8. 华为18级工程师三年心血终成趣谈网络协议文档(附大牛讲解)
  9. linux java 错误日志_求大神解决啊啊 啊,看看这个怎么了,在LINUX运行完的错误日志...
  10. 2020最新教师资格证《中学综合素质》必考知识点大全
  11. from functools import reduce——从典型实例做抓手看reduce函数使用
  12. echarts 北京公交线路-线路效应
  13. 听说ES6中新增了能够与众不同的Symbol数据类型
  14. 独立分包中包含app.wxss的问题
  15. 数据挖掘与数据分析的主要区别是什么?
  16. echart地图隐藏南海诸岛
  17. 计算机显示字体怎么设置,电脑字体太小怎么调,教您怎样更改电脑界面的字体大小...
  18. Ipopt输出的含义
  19. iptables四表五链
  20. SLAM本质剖析-Boost之Geometry函数大全(二)

热门文章

  1. 扫福得福背后,支付宝 AR 红包的技术创新与故事
  2. 【热血足球联盟】补丁记录
  3. 大庭广众、朗朗乾坤之下,老师竟然带十男两女拉上窗帘、关上门做出这种不可描述之事...
  4. 微信小程序流量主广告怎么加圆角
  5. 三维动画渲染用什么软件好?
  6. ABB机器人的几种停止指令详解
  7. YOLOv3 论文精读
  8. java期末李鹤_Willike
  9. CSDN文章转PDF
  10. java中单例和多例