Step to UEFI (140)ProtocolsPerHandle 的例子

Boot Services 提供了 ProtocolsPerHandle 函数,用它可以取得一个 Handle上面的 Protocols。这里编写程序用来验证一下。
函数原型在 UEFI Specification 中可以看到:

pph

编写程序,取得当前 Application 上面的 Protocol:

/** @file
    A simple, basic, application showing how the Hello application could be
    built using the "Standard C Libraries" from StdLib.

    Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
    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.

    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 <Library/BaseLib.h>
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>

extern EFI_BOOT_SERVICES         *gBS;

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
        EFI_GUID     **ProtocolBuffer;
        UINTN        ProtocolCount;
        EFI_STATUS   Status;
        UINTN        i;
        
        Status = gBS->ProtocolsPerHandle(ImageHandle, &ProtocolBuffer, &ProtocolCount);
        if (EFI_ERROR (Status)) {
                //
                // TheHandle is not valid, so do not add to handle list
                //
                Print(L"Can't get Protcols on ImageHandle\n");
                return 0;
        }

        Print(L"Protocol list\n");        
        for (i=0;i<ProtocolCount;i++)   {
                Print(L"%g \n",ProtocolBuffer[i]);
        }
        FreePool (ProtocolBuffer);
        

        return 0;
}

 

运行结果如下(NT32虚拟机中运行结果):

pph2

在 DEC 文件中查找这些 GUID对应的 Protocol,如下:

752F3136-4E16-4FDC-A22A-E5F46812F4CA gEfiShellParametersProtocolGuid
BC62157E-3E33-4FEC-9920-2D3B36D750DF gEfiLoadedImageDevicePathProtocolGuid
5B1B31A1-9562-11D2-8E3F-00A0C969723B gEfiLoadedImageProtocolGuid

源代码和EFI下载:
sd

=============================================================
2018年2月24日 krishnaLee(sssky307)做了一番深入的研究,他发现一个可以将 UUID 转化为对应名称的简单方法。例程如下:

#include <Uefi.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h> //global gST gBS gImageHandle

#include <Protocol/LoadedImage.h>      //EFI_LOADED_IMAGE_PROTOCOL
#include <Protocol/DevicePath.h>       //EFI_DEVICE_PATH_PROTOCOL

#include <Library/DevicePathLib.h>     //link
#include <Library/ShellLib.h>
#include <Library/ShellCommandLib.h> 
#include <Library/HandleParsingLib.h> 

EFI_STATUS
EFIAPI
UefiMain(
    IN EFI_HANDLE ImageHandle,
    IN EFI_SYSTEM_TABLE *SystemTable)
{

  EFI_GUID **ProtocolGuidArray;
  UINTN ArrayCount;
  CHAR16 *str;

  Print(L"1\n");
  EFI_STATUS status = gBS->ProtocolsPerHandle(gImageHandle,&ProtocolGuidArray,&ArrayCount);

  if (status == EFI_SUCCESS)
  {
    for (UINTN i = 0; i < ArrayCount; i++)
    {
      str = GetStringNameFromGuid(ProtocolGuidArray[i], 0);
      Print(L"%s,%g\n", str,ProtocolGuidArray[i]);
      if (str)
      {
        gBS->FreePool(str);
        str=0;
      }
    }

    if (ProtocolGuidArray)
    {
      gBS->FreePool(ProtocolGuidArray);
      ProtocolGuidArray=0;
    }
  }

  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
    //open the Loaded image protocol,which is binded on the imageHandle,to get the device handle.
    status = gBS->OpenProtocol(
      gImageHandle,
      &gEfiLoadedImageProtocolGuid,
      (VOID **)&LoadedImage,
      gImageHandle,
      NULL,
      EFI_OPEN_PROTOCOL_GET_PROTOCOL);

  if(status == EFI_SUCCESS)
  {
    Print(L"2\n");
   status = gBS->ProtocolsPerHandle(LoadedImage->DeviceHandle,&ProtocolGuidArray,&ArrayCount);
    
      if (status == EFI_SUCCESS)
      {
        for (UINTN i = 0; i < ArrayCount; i++)
        {
          str = GetStringNameFromGuid(ProtocolGuidArray[i], 0);
          Print(L"%s,%g\n", str,ProtocolGuidArray[i]);
          if (str)
          {
            gBS->FreePool(str);
            str=0;
          }
        }
    
        if (ProtocolGuidArray)
        {
          gBS->FreePool(ProtocolGuidArray);
          ProtocolGuidArray=0;
        }
      }

      gBS->CloseProtocol(
        gImageHandle,
        &gEfiLoadedImageProtocolGuid,
        gImageHandle,
        NULL);
  }


  return EFI_SUCCESS;
}

 

在 NT32 下运行的结果如下:

dpe

完整的代码下载:

mytesthandle

特别提醒,如果在 AppPkg 中编译,需要在AppPkg.dsc的 [LibraryClasses] 中加入下面的语句:

HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf

再次感谢 krishnaLee(sssky307)

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注