创建设备路径

上一节中我们介绍了用来把设备路径转换为字符串的函数ConvertDevicePathToText()。与之相对应地,UEFI标准中还有用来把字符串转换为设备路径的函数,它就是EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL中的ConvertTextToDevicePath()函数,图4.10展示了它的定义。

本节示例代码的目录为create-path (日文版为031_create_devpath_1)。

struct EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL {
    unsigned long long _buf;
    struct EFI_DEVICE_PATH_PROTOCOL *(*ConvertTextToDevicePath) (
        const unsigned short *TextDevicePath);
};

图4.10: EFI_DEVICE_PATH_TO_TEXT_PROTOCOL的定义

同样,我们需要用到LocateProtocol()函数来获取EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL的地址,如图4.11所示。

struct EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *DPFTP;  /* 需要在efi.h中声明 */

void efi_init(struct EFI_SYSTEM_TABLE *SystemTable)
{
    /* ... */
    struct EFI_GUID dpftp_guid = {0x5c99a21, 0xc70f, 0x4ad2,
                      {0x8a, 0x5f, 0x35, 0xdf,
                       0x33, 0x43, 0xf5, 0x1e}};
    /* ... */
    ST->BootServices->LocateProtocol(&dpftp_guid, NULL, (void **)&DPFTP);
}

图4.11: 获取EFI_DEVICE_PATH_TO_TEXT_PROTOCOL的接口(位于efi.c中)

接下来,我们就可以调用ConvertTextToDevicePath()函数来创建设备路径了。在上一节中,启动时执行的UEFI应用程序的设备路径的字符串表示是\EFI\BOOT\BOOTX64.EFI。这里,我们把字符串\test.efi转换为设备路径,如图4.12所示。这个字符串表示“根目录下名为test.efi的UEFI应用程序”。

#include "efi.h"
#include "common.h"

void efi_main(void *ImageHandle __attribute__ ((unused)), struct EFI_SYSTEM_TABLE *SystemTable)
{
    struct EFI_DEVICE_PATH_PROTOCOL *dev_path;

    efi_init(SystemTable);
    ST->ConOut->ClearScreen(ST->ConOut);

    dev_path = DPFTP->ConvertTextToDevicePath(L"\\test.efi");
    puts(L"dev_path: ");
    puts(DPTTP->ConvertDevicePathToText(dev_path, FALSE, FALSE));
    puts(L"\r\n");

    while (TRUE);
}

图4.12: 使用ConvertTextToDevicePath()的例子

为了确认是否创建成功,这里我们对刚才创建的设备路径调用ConvertDevicePathToText()来把它转换成字符串再输出到屏幕上,如图4.13所示。

图4.12程序输出的设备路径

图4.13: 图4.12程序输出的设备路径

可以看到,我们成功地创建了我们想要的设备路径。