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 调用均正确执行。