UEFI 基础教程 (五) - PPI 初探

一、 编写源代码

  1. 编写C:\edkii\OvmfPkg\MyHelloWorldInstallPPI\MyHelloWorldInstallPPI.c,

    #include <uefi.h>
    #include <Library/UefiLib.h>
    #include <Library/BaseLib.h>
    #include <Library/DebugLib.h>
    #include <Library/BaseMemoryLib.h>
    #include <Library/UefiDriverEntryPoint.h>
    #include <Library/PeimEntryPoint.h>
    #include <Library/PeiServicesLib.h>
    #include <Library/PeiServicesTablePointerLib.h>
    #include <Pi/PiHob.h>
    #include <Pi/PiPeiCis.h>
    
    EFI_GUID gMyHelloWorldPEIGUID = { 0xbdb38129, 0x4d65, 0x39f4, { 0x72, 0x12, 0x68, 0xcf, 0x5a, 0x19, 0xa, 0xf8 }};
    
    EFI_STATUS
    EFIAPI
    PrintHelloMsg (
      IN CHAR16 * Msg
      )
    {
      DEBUG ((EFI_D_ERROR, "[MyHelloWorldPPI] PrintHelloMsg : %s \n",Msg));
      return EFI_SUCCESS;
    }
    
    typedef EFI_STATUS (EFIAPI * PRINTMSG)(CHAR16 *Msg);
    typedef struct _EFI_HELLOWORLD_PROTOCOL  {
        PRINTMSG PrintMsg;
    }EFI_HELLOWORLD_PROTOCOL;
    
    EFI_HELLOWORLD_PROTOCOL mHelloWorldPpi = {
        PrintHelloMsg
    };
    
    EFI_PEI_PPI_DESCRIPTOR     mPpiListCodePpi = {
      (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
      &gMyHelloWorldPEIGUID,
      &mHelloWorldPpi
    };
    
    EFI_STATUS
    EFIAPI
    MyHelloWorldInstallPPIEntry(
      IN       EFI_PEI_FILE_HANDLE  FileHandle,
      IN CONST EFI_PEI_SERVICES     **PeiServices
    )
    {
      EFI_STATUS                              Status = EFI_SUCCESS;
      DEBUG ((EFI_D_ERROR, "[MyHelloWorldPPI] MyHelloWorldInstallPPIEntry Start..\n"));
      PeiServicesInstallPpi  (&mPpiListCodePpi);
      DEBUG ((EFI_D_ERROR, "[MyHelloWorldPPI] MyHelloWorldInstallPPIEntry End..\n"));
    
      return Status;
    }
    
  2. 编写C:\edkii\OvmfPkg\MyHelloWorldInstallPPI\MyHelloWorldInstallPPI.inf,

    [Defines] 
      INF_VERSION = 0x00010006 
      BASE_NAME = MyHelloWorldInstallPPI 
      FILE_GUID = 69E6DE5D-F09E-485E-9936-EB70FDCFC82A
      MODULE_TYPE = PEIM
      VERSION_STRING = 1.0
      ENTRY_POINT = MyHelloWorldInstallPPIEntry 
      
    [Sources] 
      MyHelloWorldInstallPPI.c 
      
    [Packages]
      MdePkg/MdePkg.dec
      ShellPkg/ShellPkg.dec 
      MdeModulePkg/MdeModulePkg.dec
      
    [LibraryClasses]
      BaseLib
      PeimEntryPoint
      BaseMemoryLib
      DebugLib
      PeiServicesLib
      PrintLib
      #PeiLib
      #EfiCommonLib
    
    [depex]
      TRUE
    
    
    
  3. 编写 C:\edkii\OvmfPkg\MyHelloWorldLocatePPI\MyHelloWorldLocatePPI.c

    #include <uefi.h>
    #include <Library/UefiLib.h>
    #include <Library/BaseLib.h>
    #include <Library/DebugLib.h>
    #include <Library/BaseMemoryLib.h>
    #include <Library/UefiDriverEntryPoint.h>
    #include <Library/PeimEntryPoint.h>
    #include <Library/PeiServicesLib.h>
    #include <Library/PeiServicesTablePointerLib.h>
    #include <Pi/PiHob.h>
    
    EFI_GUID gMyHelloWorldPEIGUID = { 0xbdb38129, 0x4d65, 0x39f4, { 0x72, 0x12, 0x68, 0xcf, 0x5a, 0x19, 0xa, 0xf8 }};
    
    
    typedef EFI_STATUS (EFIAPI * PRINTMSG)(CHAR16 *Msg);
    typedef struct _EFI_HELLOWORLD_PROTOCOL  {
        PRINTMSG PrintMsg;
    }EFI_HELLOWORLD_PROTOCOL;
    
    //ShellCEntryLib call user interface ShellAppMain
    EFI_STATUS
    EFIAPI
    MyHelloWorldLocatePPIEntry(
      IN       EFI_PEI_FILE_HANDLE  FileHandle,
      IN CONST EFI_PEI_SERVICES     **PeiServices
    )
    {
      EFI_STATUS  Status = EFI_SUCCESS;
      EFI_HELLOWORLD_PROTOCOL *mHelloWorldPpi = NULL;
      DEBUG ((EFI_D_ERROR, "[MyHelloWorldPPI] MyHelloWorldLocatePPIEntry Locate PPI Start..\n"));
      Status = PeiServicesLocatePpi (
               &gMyHelloWorldPEIGUID,
               0,
               NULL,
               (VOID **)&mHelloWorldPpi
               );
      if (EFI_ERROR(Status)){
          DEBUG ((EFI_D_ERROR, "[MyHelloWorldPPI] MyHelloWorldLocatePPIEntry Locate PPI Fail..%r\n",Status));
          return Status;
      }
      mHelloWorldPpi->PrintMsg(L"2019 CSDN Locate PPI Hello World ...\n");
      DEBUG ((EFI_D_ERROR, "[MyHelloWorldPPI] MyHelloWorldLocatePPIEntry Locate PPI End..\n"));
      return Status;
    }
    
  4. 编写 C:\edkii\OvmfPkg\MyHelloWorldLocatePPI\MyHelloWorldLocatePPI.inf

    [Defines] 
      INF_VERSION = 0x00010006 
      BASE_NAME = MyHelloWorldLocatePPI 
      FILE_GUID = 69E6DE6D-F39F-485f-9037-EB70FDCFC82B
      MODULE_TYPE = PEIM
      VERSION_STRING = 1.0
      ENTRY_POINT = MyHelloWorldLocatePPIEntry 
      
    [Sources] 
      MyHelloWorldLocatePPI.c 
      
    [Packages]
      MdePkg/MdePkg.dec
      ShellPkg/ShellPkg.dec 
      MdeModulePkg/MdeModulePkg.dec
      
    [LibraryClasses]
      BaseLib
      PeimEntryPoint
      BaseMemoryLib
      DebugLib
      PeiServicesLib
      PrintLib
      #PeiLib
      #EfiCommonLib
    
    [depex]
      TRUE
    
  5. 修改C:\edkii\OvmfPkg\OvmfPkgX64.dsc

    [Components]
    ...    
    #
    # PEI Phase modules
    #
    INF  OvmfPkg/MyHelloWorldInstallPPI/MyHelloWorldInstallPPI.inf
    INF  OvmfPkg/MyHelloWorldLocatePPI/MyHelloWorldLocatePPI.inf
    ...
    
    1. 修改C:\edkii\OvmfPkg\OvmfPkgX64.fdf
    [FV.PEIFV]
    ...
    #
    # PEI Phase modules
    #
    INF  OvmfPkg/MyHelloWorldInstallPPI/MyHelloWorldInstallPPI.inf
    INF  OvmfPkg/MyHelloWorldLocatePPI/MyHelloWorldLocatePPI.inf
    ...
    

二、 编译生成EFI文件

运行edksetup.bat编译整个OvmfPkg Package

三、 运行HelloWorld PPI Driver

  1. 拷贝 C:\edkii\Build\OvmfX64\DEBUG_VS2013x86\FV\OVMF.fd 到C:\qemu
  2. 执行setup-qemu-x64.bat | findstr MyHelloWorldPPI 的输出如下,
    UEFI 基础教程 (五) - PPI 初探

四、 小结

PPI(PEIM-to-PEIM Interface) 是一种PEIM驱动之间的通信方式,本文中MyHelloWorldInstallPPI模块通过PeiServicesInstallPpi提供了mPpiListCodePpi 服务,而MyHelloWorldLocatePPI模块通过PeiServicesLocatePpi获取了mPpiListCodePpi对象,通过访问对象的成员函数即可完成对驱动MyHelloWorldInstallPPI资源的访问。

上一篇:uefi中Sec阶段和Pei阶段的启动分析


下一篇:黑苹果 更换引导文件到硬盘