protocol_protocols - CSDN
  • 在oc 语言中的protocol相当于Java中的interface(接口),是经常用到的知识点。 基本用途 • 可以用来声明一大堆方法(不能声明成员变量) • 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明 • ...

          在oc 语言中的protocol相当于Java中的interface(接口),是经常用到的知识点。

    基本用途

    • 可以用来声明一大堆方法(不能声明成员变量)
    • 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明
    • 只要父类遵守了某个协议,就相当于子类也遵守了。

    协议的编写格式

    @protocol 协议名称
    // 方法声明列表
    @end

    某个类遵守协议

    @interface 类名 : 父类 <协议名称>
    @end

    关键字

    协议中有2个关键字可以控制方法是否要实现(默认是@required),在大多数情况下,用途在于程序员之间的交流
    • @required:这个方法必须要实现(若不实现,编译器会发出警告)
    • @optional:这个方法不一定要实现

    协议遵守协议
    • 一个协议可以遵守其他多个协议,多个协议之间用逗号 , 隔开
    • 一个协议遵守了其他协议,就相当于拥有了其他协议中的方法声明
    @protocol 协议名称 <协议1, 协议2>
    @end

    基协议
    • NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它
    • 其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议
    • NSObject协议中声明很多最基本的方法,比如description、retain、release等
    • 建议每个新的协议都要遵守NSObject协议

    定义变量时指定协议

    // NSObject类型的对象,并且要遵守NSCopying协议
    NSObject<NSCopying> *obj;
    // 任何OC对象,并且要遵守NSCoding协议
    id<NSCoding> obj2;

      代理设计模式
    • 设计原理
    • 有些麻烦的事情不想自己亲自做,就可以找个人帮忙做,即交给代理对象去做
    • 设计原则
    • 首先得拥有某个代理对象属性
    • 其次要很清楚代理有哪些方法
    • 最后要保证能解耦

    • 实现方案
    • 定义一个protocol,在其中声明一些和代理沟通的方法
    • 拥有一个代理属性id<protocol> delegate
    • 让代理遵守protocol

    下面是一个实例。

    MyProtocol.h文件

    #import <Foundation/Foundation.h>
    
    @protocol MyProtocol <NSObject>
    @optional
    //可选
    -(void)print:(int)value;
    @required
    //必须实现的
    -(int)printValue:(int)value1 andValue:(int)value2;
    
    @end
    

    MyTest.文件

    #import <Foundation/Foundation.h>
    #import "MyProtocol.h"
    
    @interface MyTest : NSObject<MyProtocol>
    -(void)showInfo;
    
    @end


    MyTest.m文件

    #import "MyTest.h"
    
    @implementation MyTest
    
    -(void)showInfo
    {
        NSLog(@"show info is calling");
        
    }
    -(int)printValue:(int)value1 andValue:(int)value2
    {
        NSLog(@"print info that value1 is %d and value2 is %d",value1,value2);
        return 0;
    }
    
    
    //下面的方法可以实现也可以不实现
    -(void)print:(int)value
    {
        NSLog(@"print is value is %d",value);
        
    }
    
    @end


    main.m文件

    #import "MyTest.h"
    #import "MyProtocol.h"
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            //普通类的调用方法
            MyTest *myTest=[[MyTest alloc]init];
            [myTest showInfo];
            
            SEL sel=@selector(print:); //这个print转换成方法
            //确定这个print方法是否实现
            if([myTest respondsToSelector:sel]){
                [myTest print:20];
            }
            
            [myTest printValue:20 andValue:15];
    
            //下面的方法使用协议的方式来调用
            id<MyProtocol> myprotocol=[[MyTest alloc]init];
            if([myprotocol respondsToSelector:@selector(print:)]){
                [myprotocol print:210];
            }
    
            
        }
        return 0;
    }

    控制台输出为:

    2016-04-25 13:39:51.960 protocal[1988:143688] show info is calling
    2016-04-25 13:39:51.960 protocal[1988:143688] print is value is 20
    2016-04-25 13:39:51.961 protocal[1988:143688] print info that value1 is 20 and value2 is 15
    2016-04-25 13:39:51.961 protocal[1988:143688] print is value is 210
    Program ended with exit code: 0



    不妥之处,欢迎提出,相互学习,共同进步!














    展开全文
  • BIOS/UEFI基础——Protocol介绍

    千次阅读 2019-11-03 21:27:55
    BIOS/UEFI基础——Protocol介绍。

    简要说明

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

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

    ///
    ///  This protocol provides control over block devices.
    ///
    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;
    
    };

    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:

      //
      // Protocol Handler Services
      //
      EFI_INSTALL_PROTOCOL_INTERFACE    InstallProtocolInterface;
      EFI_REINSTALL_PROTOCOL_INTERFACE  ReinstallProtocolInterface;
      EFI_UNINSTALL_PROTOCOL_INTERFACE  UninstallProtocolInterface;
      EFI_HANDLE_PROTOCOL               HandleProtocol;
      VOID                              *Reserved;
      EFI_REGISTER_PROTOCOL_NOTIFY      RegisterProtocolNotify;
      EFI_LOCATE_HANDLE                 LocateHandle;
      EFI_LOCATE_DEVICE_PATH            LocateDevicePath;
      EFI_INSTALL_CONFIGURATION_TABLE   InstallConfigurationTable;
    
      //
      // Open and Close Protocol Services
      //
      EFI_OPEN_PROTOCOL                 OpenProtocol;
      EFI_CLOSE_PROTOCOL                CloseProtocol;
      EFI_OPEN_PROTOCOL_INFORMATION     OpenProtocolInformation;
    
      //
      // Library Services
      //
      EFI_PROTOCOLS_PER_HANDLE          ProtocolsPerHandle;
      EFI_LOCATE_HANDLE_BUFFER          LocateHandleBuffer;
      EFI_LOCATE_PROTOCOL               LocateProtocol;
      EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES    InstallMultipleProtocolInterfaces;
      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如下所示:

    //
    // DXE Core Global Variables for all of the Architectural Protocols.
    // If a protocol is installed mArchProtocols[].Present will be TRUE.
    //
    // CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
    // and mArchProtocols[].Registration as it creates events for every array
    // entry.
    //
    EFI_CORE_PROTOCOL_NOTIFY_ENTRY  mArchProtocols[] = {
      { &gEfiSecurityArchProtocolGuid,         (VOID **)&gSecurity,      NULL, NULL, FALSE },
      { &gEfiCpuArchProtocolGuid,              (VOID **)&gCpu,           NULL, NULL, FALSE },
      { &gEfiMetronomeArchProtocolGuid,        (VOID **)&gMetronome,     NULL, NULL, FALSE },
      { &gEfiTimerArchProtocolGuid,            (VOID **)&gTimer,         NULL, NULL, FALSE },
      { &gEfiBdsArchProtocolGuid,              (VOID **)&gBds,           NULL, NULL, FALSE },
      { &gEfiWatchdogTimerArchProtocolGuid,    (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
      { &gEfiRuntimeArchProtocolGuid,          (VOID **)&gRuntime,       NULL, NULL, FALSE },
      { &gEfiVariableArchProtocolGuid,         (VOID **)NULL,            NULL, NULL, FALSE },
      { &gEfiVariableWriteArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
      { &gEfiCapsuleArchProtocolGuid,          (VOID **)NULL,            NULL, NULL, FALSE },
      { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL,            NULL, NULL, FALSE },
      { &gEfiResetArchProtocolGuid,            (VOID **)NULL,            NULL, NULL, FALSE },
      { &gEfiRealTimeClockArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
      { NULL,                                  (VOID **)NULL,            NULL, NULL, FALSE }
    };

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

      //
      // Transfer control to the BDS Architectural Protocol
      //
      gBds->Entry (gBds);

    使DXE阶段过渡到BDS阶段。

     

    Device Path Protocol

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

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

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

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

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

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

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

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

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

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

    ///
    /// Controller Device Path.
    ///
    typedef struct {
      EFI_DEVICE_PATH_PROTOCOL        Header;
      ///
      /// Controller number.
      ///
      UINT32                          ControllerNumber;
    } 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的结构如下:

    ///
    /// This protocol provides the services required to determine if a driver supports a given controller. 
    /// If a controller is supported, then it also provides routines to start and stop the controller.
    ///
    struct _EFI_DRIVER_BINDING_PROTOCOL {
      EFI_DRIVER_BINDING_SUPPORTED  Supported;
      EFI_DRIVER_BINDING_START      Start;
      EFI_DRIVER_BINDING_STOP       Stop;
      
      ///
      /// The version number of the UEFI driver that produced the
      /// EFI_DRIVER_BINDING_PROTOCOL. This field is used by
      /// the EFI boot service ConnectController() to determine
      /// the order that driver's Supported() service will be used when
      /// a controller needs to be started. EFI Driver Binding Protocol
      /// instances with higher Version values will be used before ones
      /// with lower Version values. The Version values of 0x0-
      /// 0x0f and 0xfffffff0-0xffffffff are reserved for
      /// platform/OEM specific drivers. The Version values of 0x10-
      /// 0xffffffef are reserved for IHV-developed drivers.
      ///
      UINT32                        Version;
      
      ///
      /// The image handle of the UEFI driver that produced this instance
      /// of the EFI_DRIVER_BINDING_PROTOCOL.
      ///
      EFI_HANDLE                    ImageHandle;
      
      ///
      /// The handle on which this instance of the
      /// EFI_DRIVER_BINDING_PROTOCOL is installed. In most
      /// cases, this is the same handle as ImageHandle. However, for
      /// UEFI drivers that produce more than one instance of the
      /// EFI_DRIVER_BINDING_PROTOCOL, this value may not be
      /// the same as ImageHandle.  
      ///
      EFI_HANDLE                    DriverBindingHandle;
    };

    下面是一个例子:

    1. 声明:

    //
    // Simple Network Protocol Driver Global Variables
    //
    EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {
      SimpleNetworkDriverSupported,
      SimpleNetworkDriverStart,
      SimpleNetworkDriverStop,
      0xa,
      NULL,
      NULL
    };

    2. 安装:

    EFI_STATUS
    EFIAPI
    InitializeSnpNiiDriver (
      IN EFI_HANDLE       ImageHandle,
      IN EFI_SYSTEM_TABLE *SystemTable
      )
    {
      return EfiLibInstallDriverBindingComponentName2 (
               ImageHandle,
               SystemTable,
               &gSimpleNetworkDriverBinding,
               ImageHandle,
               &gSimpleNetworkComponentName,
               &gSimpleNetworkComponentName2
               );
    }

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

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

      //
      // DriverSupport Services
      //
      EFI_CONNECT_CONTROLLER            ConnectController;
      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:

    /**
    *  @Package     : BeniPkg
    *  @FileName    : HelloWorldProtocol.h
    *  @Date        : 20190211
    *  @Author      : Wei Jiang
    *  @Version     : 0.1
    *  @Description :
    *    This file describes a protocol for test.
    *
    *  @History:
    *    20190211: Initialize.
    *
    *  This program and the accompanying materials
    *  are licensed and made available under the terms and conditions of the BSD License
    *  which accompanies this distribution. The full text of the license may be found at
    *  http://opensource.org/licenses/bsd-license.php
    *
    *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
    *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
    **/
    
    #ifndef __BENI_HELLO_WORLD_PROTOCOL_H__
    #define __BENI_HELLO_WORLD_PROTOCOL_H__
    
    #include <Uefi.h>
    
    #define EFI_HELLO_WORLD_PROTOCOL_GUID \
      {0x038f1af5, 0x1c8d, 0x408f, { 0xab, 0x25, 0x30, 0xae, 0xb5, 0x96, 0x5d, 0x6e }}
    
    typedef struct _EFI_HELLO_WORLD_PROTOCOL EFI_HELLO_WORLD_PROTOCOL;
    
    /**
      Print "Hello Wrold".
    
      @param[in]  This                  A pointer to the EFI_HELLO_WORLD_PROTOCOL instance.
    
      @retval  EFI_SUCCESS              Always return EFI_SUCCESS after print.
    
    **/
    typedef
    EFI_STATUS
    (EFIAPI *HELLO) (
      IN  EFI_HELLO_WORLD_PROTOCOL      *This
      );
    
    struct _EFI_HELLO_WORLD_PROTOCOL {
      UINTN                   Version;
      HELLO                   Hello;
    };
    
    extern EFI_GUID gEfiHelloWorldProtocolGuid;
    
    #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:

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

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

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

    /**
    *  @Package     : BeniPkg
    *  @FileName    : ProtocolServer.c
    *  @Date        : 20190211
    *  @Author      : Wei Jiang
    *  @Version     : 0.1
    *  @Description :
    *    Install EFI_HELLO_WORLD_PROTOCOL.
    *
    *  @History:
    *    20190211: Initialize.
    *
    *  This program and the accompanying materials
    *  are licensed and made available under the terms and conditions of the BSD License
    *  which accompanies this distribution. The full text of the license may be found at
    *  http://opensource.org/licenses/bsd-license.php
    *
    *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
    *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
    **/
    
    #include <Uefi.h>
    
    #include <Library/UefiDriverEntryPoint.h>
    #include <Library/UefiBootServicesTableLib.h>
    #include <Library/MemoryAllocationLib.h>
    #include <Library/DebugLib.h>
    
    #include <Protocol/HelloWorldProtocol.h>
    
    /**
      Print "Hello Wrold".
    
      @param[in]  This                  A pointer to the EFI_HELLO_WORLD_PROTOCOL instance.
    
      @retval  EFI_SUCCESS              Always return EFI_SUCCESS after print.
    
    **/
    EFI_STATUS
    EFIAPI
    Hello (
      IN  EFI_HELLO_WORLD_PROTOCOL      *This
      )
    {
      DEBUG ((EFI_D_ERROR, "Hello World\n"));
    
      return EFI_SUCCESS;
    }
    
    /**
      Main entry of the driver.
    
      @param[in]  ImageHandle           Image handle for this driver.
      @param[in]   SystemTable          Pointer to the System Table.
    
      @retval  EFI_SUCCESS              Driver executed successfully.
      @retval  Others                   Error happened.
    
    **/
    EFI_STATUS
    EFIAPI
    ProtocolServerEntry (
      IN  EFI_HANDLE                    ImageHandle,
      IN  EFI_SYSTEM_TABLE              *SystemTable
      )
    {
      EFI_STATUS                   Status;
      EFI_HELLO_WORLD_PROTOCOL     *Protocol;
    
      Protocol = AllocatePool (sizeof (EFI_HELLO_WORLD_PROTOCOL));
      if (NULL == Protocol) {
        DEBUG ((EFI_D_ERROR, "[BENI][%a][%d]: Out of resource.", __FUNCTION__, __LINE__));
        return EFI_OUT_OF_RESOURCES;
      }
    
      Protocol->Version = 0x01;
      Protocol->Hello   = Hello;
    
      Status = gBS->InstallProtocolInterface (
                        &ImageHandle,
                        &gEfiHelloWorldProtocolGuid,
                        EFI_NATIVE_INTERFACE,
                        Protocol
                        );
      if (EFI_ERROR (Status)) {
        DEBUG ((EFI_D_ERROR, "[BENI]Install EFI_HELLO_WORLD_PROTOCOL failed. - %r\n", Status));
        FreePool (Protocol);
        return Status;
      }
    
      return EFI_SUCCESS;
    }

    观察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的使用:

    /**
    *  @Package     : BeniPkg
    *  @FileName    : ProtocolConsumer.c
    *  @Date        : 20190211
    *  @Author      : Wei Jiang
    *  @Version     : 0.1
    *  @Description :
    *    Use EFI_HELLO_WORLD_PROTOCOL.
    *
    *  @History:
    *    20190211: Initialize.
    *
    *  This program and the accompanying materials
    *  are licensed and made available under the terms and conditions of the BSD License
    *  which accompanies this distribution. The full text of the license may be found at
    *  http://opensource.org/licenses/bsd-license.php
    *
    *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
    *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
    **/
    
    #include <Uefi.h>
    
    #include <Library/UefiDriverEntryPoint.h>
    #include <Library/UefiBootServicesTableLib.h>
    #include <Library/DebugLib.h>
    
    #include <Protocol/HelloWorldProtocol.h>
    
    /**
      Main entry of the driver.
    
      @param[in]  ImageHandle           Image handle for this driver.
      @param[in]   SystemTable          Pointer to the System Table.
    
      @retval  EFI_SUCCESS              Driver executed successfully.
      @retval  Others                   Error happened.
    
    **/
    EFI_STATUS
    EFIAPI
    ProtocolConsumerEntry (
      IN  EFI_HANDLE                    ImageHandle,
      IN  EFI_SYSTEM_TABLE              *SystemTable
      )
    {
      EFI_STATUS                   Status;
      EFI_HELLO_WORLD_PROTOCOL     *Protocol;
    
      Status = gBS->LocateProtocol (&gEfiHelloWorldProtocolGuid, NULL, (VOID **)&Protocol);
      if (EFI_ERROR (Status)) {
        DEBUG ((EFI_D_ERROR, "[BENI]Locate EFI_HELLO_WORLD_PROTOCOL failed. - %r\n", Status));
        return Status;
      }
    
      DEBUG ((EFI_D_ERROR, "Protocol Version: 0x%08x\n", Protocol->Version));
      Status = Protocol->Hello (Protocol);
      if (EFI_ERROR (Status)) {
        DEBUG ((EFI_D_ERROR, "[BENI]Protocol->Hello failed. - %r\n", Status));
        return Status;
      }
    
      return EFI_SUCCESS;
    }

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

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

     

    展开全文
  • Protocol(协议)

    千次阅读 2017-04-05 09:15:09
    Protocol(协议)的声明看起来类似一个类的接口,不同的是Protocol没有父类也不能定义实例变量。Protocol是一种特殊的程序设计结构,用于声明专门被别的类实现的方法。因为OC是单继承的,由于不支持多继承,所以很多...

    一、概述

    Protocol(协议)的声明看起来类似一个类的接口,不同的是Protocol没有父类也不能定义实例变量。Protocol是一种特殊的程序设计结构,用于声明专门被别的类实现的方法。因为OC是单继承的,由于不支持多继承,所以很多时候都是用Protocol和Category来代替实现多继承。Protocol只能定义公用的一套接口,但不能提供具体的实现方法。也就是说,它只告诉你要做什么,但具体怎么做,它不关心。

    Protocol的基本用途:

    (1)可以用来声明一大堆方法(不能声明成员变量)

    (2)只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明

    (3)只要父类遵守了某个协议,就相当于子类也遵守了

    (4)和java中的接口很相似,但比接口功能更丰富

     

    二、创建与遵守Protocol

    1、创建Protocol

    创建Protocol很简单,如下图:

    snip20170109_1

    snip20170109_2

    比如我们填写的文件名为MyProtocol,之后会生成一个MyPotocol.h文件,文件内容如下:

     

    之后我们就在其中声明需要的方法,但要注意的是这里只做声明,不做实现。并且不能声明变。具体的实现要在遵守这个协议的类中实现,综上,protocol就是用来声明方法的。

     

    协议可用定义在单独.h文件中,也可用定义在某个类中:

    (1) 如果这个协议只用在某个类中,应该把协议定义在该类中

    (2) 如果这个协议用在很多类中,就应该定义在单独文件中

     

    2、基协议

    (1)NSObject是一个基类,是最根本最基本的类,任何其他类最终都要继承它

    (2)其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议

    (3)NSObject协议中声明了很多最基本的方法,比如description、retain、release等

    (4)建议每个新协议都要遵守NSObject协议

     

    3、协议中方法声明的关键字

    (1) @required (默认)

    要求实现,如果没有实现,会发出警告,但不报错

    (2) @optional

    不要求实现,不实现也不会有警告

    例如:

    @require

    – (void)test;

     

    @optional

    – (void)test2;

     

    4、遵守协议

    首先要#import “协议文件名.h”或者@protocol 协议名称,但是使用@protocol 协议名称时只是告诉下面代码这是一个协议,但不知道协议里面有什么东西,一般只在用到协议内容的时候在#import”协议文件名.h”。在实际开发中常用@protocol 协议名称

    (1) 类遵守协议

    @interface 类名 : 父类名 <协议名称1, 协议名称2>

    @end

    (2) 协议遵守协议

    @protocol 协议名称 <其他协议名称1, 其他协议名称2>

    @end

     

    5、定义一个变量的时候,限制这个变量保存的对象遵守某个协议

    类名<协议名称> *变量名;

    id<协议名称> 变量名;

    如果obj和obj2没有遵守MyProtocol的协议,编译器会警告。

     

    6、@property中声明的属性也可用做一个遵守协议的限制

    @property (nonatomic, strong) 类名<协议名称> *属性名;

    @property (nonatomic, strong) id<协议名称> 属性名;

     

    三、Protocol的一个简单示例

    例如:

    我们新建一个Protocol,命名为HelloProtocol,然后就只会生成一个HelloProtocol.h文件,注意肯定没有.m文件,协议只是用来声明方法,并不是来实现的。

     

    新建Person类,在Person.h中引入协议,如下:

     

    Person.m如下:

     

    之后在main.m中创建Person的对象去调用这些方法:

    例子很简单,这里不做过多讲解~

    展开全文
  • protocol

    2020-06-29 17:18:45
    protocol 官网 protocol 下载 protocol 安装说明
    展开全文
  • OC语言之Protocol基本使用

    千次阅读 2016-07-17 21:15:40
    # Protocol基本概念 ##1.protocol 基本概念 - Protocol翻译过来, 叫做”协议”  +在写java的时候都会有接口interface这个概念,接口就是一堆方法的声明没有实现,而在OC里面Interface是一个类的头文件的声明,并不是...
  • Protocol概述

    2016-03-26 21:23:51
    Protocol概述在*OO的世界,可能会希望某对象在特定条件下会有特定的行为。* As an example, a table view expects to be able to communicate with a data source object in order to find out what it is required...
  • @protocol的一个小细节

    千次阅读 2015-12-09 21:29:57
    @protocol的一个小细节前不久重构一个类, 用protocol做了一些特别的事情, 结果被坑了. 先不说怎么被坑, 我们来一段代码, 大伙猜猜结果是啥?@protocol ProtocolA <NSObject> @end @protocol ProtocolB <NSObject> @...
  • Protocol完整的

    2020-04-13 18:47:49
    文章目录1.HTTP协议1.1.HTTP的特性1.2.HTTP报文1.2.1.请求报文1.请求行1.GET请求方式1.功能:信息的获取【安全且幂等】2.功能:数据提交3.注意2.POST请求方式1.POST数据提交方式:application/x-...
  • 一、导致ERR_SSL_PROTOCOL_ERROR错误主要有以下几个原因: Invalid System Time 系统时间与网络时间不同步 Firewall blocking the website or IP address Website could be blacklisted in the Hosts ...
  • Protocol Buffer 简介

    万次阅读 2019-04-04 09:25:15
    一、Protocol Buffer 与 XML、JSON 的区别 Protocol Buffer 和 XML、JSON一样都是结构数据序列化的工具,但它们的数据格式有比较大的区别: 首先,Protocol Buffer 序列化之后得到的数据不是可读的字符...
  • 习惯用 Json、XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式,性能比 Json、XML 真的强!太!多! 由于 Google出品,我相信...
  • 通信协议之Protocol buffer(Java篇)

    万次阅读 多人点赞 2016-12-30 23:31:53
    来到新公司后发现同事们用的更多的的协议都不是json,而是Protocol buffer。这个东西之前没有听说过,不明白同事们为什么放弃好好的json不用,用这个。后来了解到经常是设备与设备之间进行通信,而不是设备与服务器...
  • java.net.MalformedURLException: no protocol 此异常,为:no protocol,没有指定通信协议异常。3 解决方法既然咱们已经知道了是因为没有指定通信协议,从而导致异常的发生。那么,咱们再回过头来,看看上面的
  • 这个方法主要思路是利用自定义URL Protocol来调用应用程序。浏览器在解析到自定义URL Protocol之后,会寻找注册表,然后通过注册表启动相应的程序,然后启动改程序,传入参数。对于我这个项目而言,主要思路是利用这...
  • Protocol Buffer3整理

    千次阅读 2019-09-17 19:43:32
    Protocol Buffer概述 Protocol Buffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及...
  • 在Python中使用protocol buffers参考指南

    万次阅读 2013-11-30 15:36:56
    Protocol Buffer 入门: Python 本教程提供了一个Python程序员使用protocol buffers的基本的入门教程。通过创建一个简单的示例应用程序,它向您展示了如何 *在一个.proto文件中定义消息的格式。 *使用protocol buffer...
  • Protocol Buffer的使用

    千次阅读 2018-04-17 16:12:25
    大家对于json xml这两个数据传输协议都比较熟悉,但是说起谷歌的protocol buffer,可能大家很多人没有接触过。在此之前,先介绍下数据传输协议中经常会听到的两个名词。序列化:将数据结构或对象转化为二进制字符串...
  • 如何理解UEFI中handle和protocol的概念

    千次阅读 2017-12-13 21:22:27
    UEFI中到处都会出现Handle和Protocol这两个概念,这个对于理解UEFI的设计思路还是很重要的,但是翻遍了UEFI spec,并没有给出很清晰的概念。后来干脆去翻源码的定义,立马有种拨云见日的感觉。   基本上,...
  • Protocol Buffer简介02. Protocol Buffer优缺点03. Protocol Buffer安装04. Protocol Buffer测试05. 参考 01. Protocol Buffer简介 protobuf也叫protocol buffer是google 的一种数据交换的格式,它独立于语言,...
  • 今天安装了navicat 和 mysql,...Client does not support authentication protocol requested by server; consider upgrading MySQL client 网上找了如下方法: 其一: mysql&amp;gt; SET PASS...
1 2 3 4 5 ... 20
收藏数 619,119
精华内容 247,647
关键字:

protocol