【问题标题】:How to open a file by it's full path in UEFI如何通过 UEFI 中的完整路径打开文件
【发布时间】:2017-02-04 19:07:20
【问题描述】:

我是 UEFI 的初学者。我正在尝试从我的 UEFI 应用程序中打开一个文件。文件路径是

fs1:/myfolder/myfile.txt

代码(在this answer的帮助下)

efiStatus = bs->LocateHandleBuffer(ByProtocol, 
                                   &sfspGuid, 
                                   NULL, 
                                   &handleCount, 
                                   &handles);

for (index = 0; index < (int)handleCount; ++ index)
{
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs = NULL;

    efiStatus = bs->HandleProtocol(
        handles[index],
        &sfspGuid,
        (void**)&fs);

    EFI_FILE_PROTOCOL* root = NULL;
    ...
    efiStatus = fs->OpenVolume(fs, &root);

    EFI_FILE_PROTOCOL* token = NULL;

    efiStatus = root->Open(
        root, 
        &token,
        L"myfolder\\myfile.txt",
        EFI_FILE_MODE_READ,
        EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
}

但是使用这种方法,我只能遍历所有文件系统句柄并打开每个卷并尝试打开我的文件。

但我想给出我的文件的完整路径并在它的卷中打开它。

我怎样才能做到这一点?


编辑:

我尝试按照 @Alex 在 cmets 中的建议使用 Shell API 打开文件。 下面是代码。但它挂在函数 OpenFileByName 中。

这段代码有什么错误? (argv[1] 将是我的文件路径fs1:\myfile.txt

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

    EFI_STATUS      status;
    UINTN           argc;
    CHAR16          **argv;
    SHELL_FILE_HANDLE Handle;

    status = get_args(&argc, &argv);
    if (EFI_ERROR(status)) {
       Print(L"ERROR: Parsing command line arguments: %d\n", status);
       return status;
    }

    if (argc <= 1){
        Print(L"No file name to open\n");
        return (EFI_UNSUPPORTED);  //need to have at least one parameter
    }

    Print(L"File to open is: %s\n", argv[1]);

    status = gEfiShellProtocol->OpenFileByName (argv[1], &Handle, 
        EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE);

    if (EFI_ERROR(status)) {
        Print(L"\nFile Open did not work %s\n", argv[1]);
        return (status);
    }else{
        Print(L"\nFile Open worked %s\n", argv[1]);
        gEfiShellProtocol->CloseFile(Handle);
    }

    return EFI_SUCCESS;
}

即使我尝试GetCurDir 函数,代码也会挂起。

Print(L"Dir: %s \n",gEfiShellProtocol->GetCurDir(NULL));

任何指针都会有所帮助。

【问题讨论】:

  • 我可以看到另一种方法。因此,在 UEFI 中,一切都是句柄,因此文件没有什么不同。您可以尝试为该特定文件创建/构造设备路径,然后使用该设备路径打开句柄。基本上,您可以克隆控制器的现有设备路径,然后为您的文件添加特定节点。我认为这可能行得通。
  • 作为参考,我会研究 EDK Shell 的实现!
  • 查看 EFI_SHELL_PROTOCOL 的 EFI_SHELL_OPEN_FILE_BY_NAME
  • 谢谢@Alex。将对此进行调查。
  • @Alex ,你能看看我对这个问题的编辑吗?我按照您的建议尝试了 Shell API,但遇到了上述问题。请查看编辑。谢谢

标签: file filesystems uefi


【解决方案1】:

回复评论如何获取EFI_SHELL_PROTOCOL: 该过程与任何 Efi 协议基本相同。首先,获取接口的句柄:

UINTN BufferSize;
EFI_HANDLE* Buffer;
Status = bs->LocateHandle(ByProtocol, &gEfiShellProtocolGuid, NULL, &BufferSize, Buffer);

然后,使用正确大小的缓冲区分配和调用:

    Status = bs->AllocatePool(EfiBootServicesData, BufferSize, &Buffer);

    Status = bs->LocateHandle(ByProtocol, &gEfiShellProtocolGuid, NULL, &BufferSize, Buffer);

现在,您可以获取协议的句柄。请记住,它是 EFI,可能安装了多个协议!这就是为什么我们必须遍历所有这些。但在这种情况下,很可能只有一个 SHELL 协议实例:

 UINTN HandleCounter;
 for (HandleCounter = 0 ; HandleCounter < (BufferSize/sizeof(EFI_HANDLE)) ; HandleCounter++)
 {
    Status = bs->OpenProtocol(Buffer[HandleCounter],
                              &gEfiShellProtocolGuid,
                              (VOID**)&gEfiShellProtocol,
                              imageHandle, 
                              NULL,
                              EFI_OPEN_PROTOCOL_GET_PROTOCOL);

别忘了检查每一步的状态!

当然不要忘记:

bs->FreePool(buffer);

至于协议本身,您不必关闭它。从 2.31 开始的 EFI 不再需要它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 2010-10-24
    • 2014-06-08
    • 1970-01-01
    • 2014-05-18
    • 2012-04-19
    相关资源
    最近更新 更多