Step to UEFI (139)关于Image DevicePath 的小实验

最近做了一个关于 Image 的 Device Path 的实验,比较简单,分享一下。
首先是根据当前 Application 的 ImageHandle 取得对应的 Handle。使用 HandleProtcol 直接打开加载在Application 上面的 EFI_Loaded_Image_Protocol。在这个 Protocol上有 FilePath,就是当前 Image 的 Device Path Protocol ,具体分析可以在【参考1】看到。
接下来,要把取得的 FilePath转化为人类易读的字符串。使用 Device_Path_To_Text_Protocol,具体用法可以在【参考2】找到。
最后,我们看一下这个 Device Path 的Raw Data,先是输出 Type、SubType和Length。从结果中看到属于 File Path Media Path,对照 Specification进一步分析,就是说在 Length 后面跟着一个CHAT16 字符串。
dp2
完整代码如下:

/** @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>
#include <Protocol/LoadedImage.h>
#include <Protocol/DevicePath.h> //EFI_DEVICE_PATH_PROTOCOL
#include <Protocol/DevicePathToText.h> //EFI_DEVICE_PATH_TO_TEXT_PROTOCOL

extern EFI_BOOT_SERVICES         *gBS;

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
        EFI_STATUS               Status;
        EFI_LOADED_IMAGE_PROTOCOL *ImageInfo = NULL;
        EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *Device2TextProtocol;
        CHAR16  *TextDevicePath;
        UINTN           Index;
        CHAR8  *p;
        
        Status = gBS -> HandleProtocol(
                        ImageHandle,
                        &gEfiLoadedImageProtocolGuid,
                        &ImageInfo);
        if (EFI_ERROR(Status)) {
                Print(L"Error!\n");
        }

        //get a converter.
        Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid,
                                     NULL,
                                     (VOID**)&Device2TextProtocol
                                    );

        //convert device path to text.
        if (!EFI_ERROR (Status))
        {
                TextDevicePath= Device2TextProtocol->ConvertDevicePathToText(ImageInfo->FilePath, TRUE, FALSE);
                Print(L"%s\n",TextDevicePath);
                gBS->FreePool(TextDevicePath);
        }
        
        Print(L"Type:[%d] SubType:[%d] Length:[%d] \n",
                    ImageInfo->FilePath->Type,            
                    ImageInfo->FilePath->SubType,
                    ImageInfo->FilePath->Length[0]+
                    (ImageInfo->FilePath->Length[1]<<8));
        
        Print(L"%x\n",ImageInfo->FilePath);  
        p=(CHAR8 *)ImageInfo->FilePath;
        p=p+4;
        Print(L"%s\n",p);          
        for (Index=0;Index<ImageInfo->FilePath->Length[0]+(ImageInfo->FilePath->Length[1]<<8)-4;Index++) {
              Print(L"%2X ",*p);  
              p++;
        }
        Print(L"\n");  

        return 0;
}

 

运行结果:

dp1

结果中第一行是Device_Path_To_Text_Protocol转化的结果;第二行是这个DevciePath 的基本信息;第三行是DevicePath的内存地址,实验表明当运行完 Application后,这里面的内容会被释放掉,无法使用MEM之类的指令查看到;第四行是直接输出字符串的结果,可以看到和前面的使用 Protocol 的结果一致;最后一行直接输出DevicePath 的内容,就是 “\idp.EFI”的 Unicode值。
完整的 源代码和 X64 EFI 下载:
ImageDevicePath

参考:
1. https://www.lab-z.com/efiloadedimageprotocol/ EFILOADEDIMAGEPROTOCOL的使用
2. https://www.lab-z.com/dpdemo/解析 DevicePath 的例子

发表回复

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