1. 初始化EFI_SIMPLE_FILE_SYSTEM_PROTOCOL

任务目标

在UEFI应用中,通过系统表定位卷设备上的 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL,并调用其 OpenVolume() 方法获取根目录句柄,以验证协议可用性。本案例聚焦于协议定位与打开的标准流程,不涉及文件读写操作。

核心实现

#include <Uefi.h>
#include <Protocol/SimpleFileSystem.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                       Status;
  EFI_HANDLE                      *HandleBuffer = NULL;
  UINTN                            HandleCount   = 0;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem    = NULL;
  EFI_FILE_PROTOCOL               *RootDir       = NULL;
  UINTN                            Index;

  // 1. 查找系统中所有支持 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 的句柄
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiSimpleFileSystemProtocolGuid,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (EFI_ERROR (Status) || HandleCount == 0) {
    Print (L"未找到支持文件系统协议的设备。Status: %r\n", Status);
    return Status;
  }

  // 2. 遍历句柄,尝试打开协议并获取根目录
  for (Index = 0; Index < HandleCount; Index++) {
    Status = gBS->HandleProtocol (
                    HandleBuffer[Index],
                    &gEfiSimpleFileSystemProtocolGuid,
                    (VOID **)&FileSystem
                    );
    if (EFI_ERROR (Status)) {
      continue;
    }

    // 3. 调用 OpenVolume 验证协议可用性
    Status = FileSystem->OpenVolume (FileSystem, &RootDir);
    if (EFI_ERROR (Status)) {
      Print (L"句柄 %d: OpenVolume 失败,Status: %r\n", Index, Status);
      continue;
    }

    // 4. 验证成功:关闭根目录句柄并退出
    Print (L"成功打开文件系统协议,句柄索引: %d\n", Index);
    RootDir->Close (RootDir);
    break;
  }

  if (Index == HandleCount) {
    Print (L"所有句柄均无法打开文件系统卷。\n");
    Status = EFI_NOT_FOUND;
  }

  if (HandleBuffer != NULL) {
    FreePool (HandleBuffer);
  }

  return Status;
}

编译与运行

本案例基于EDK2环境,需在包的 .inf 文件中声明依赖:

[Protocols]
  gEfiSimpleFileSystemProtocolGuid

[Depex]
  gEfiSimpleFileSystemProtocolGuid

编译命令(在EDK2构建环境中):

build -p YourPackage/YourPackage.dsc -m YourPackage/InitFileSystem.inf -a X64

将生成的 .efi 文件放入UEFI shell可访问的FAT分区,在shell中执行:

fs0:\> InitFileSystem.efi

验证方法

程序执行后观察输出:

  • 若输出 成功打开文件系统协议,句柄索引: N,说明协议定位与打开成功,OpenVolume 返回的根目录句柄有效。
  • 若输出 未找到支持文件系统协议的设备,说明当前执行环境无可用FAT卷(如在启动管理器shell中),需切换到实际文件系统映射(如 fs0:)后重试。
  • 若输出 所有句柄均无法打开文件系统卷,表明协议存在但卷不可用,需检查设备状态。

判定通过条件:程序返回 EFI_SUCCESS(shell无错误提示),且打印成功信息。该结果直接证明 LocateHandleBuffer 定位、HandleProtocol 打开以及 OpenVolume 调用均正确执行。