3. 创建新文件

任务目标

在UEFI环境下的FAT文件系统中,于根目录创建一个名为test.txt的新文件,并通过再次打开该文件来验证其创建成功。

核心实现

本案例使用UEFI Shell下的标准应用程序框架,通过ShellOpenFileByName()配合EFI_FILE_MODE_CREATE标志实现文件创建。核心逻辑包含三个步骤:定位根文件系统、创建文件、重新打开验证。

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

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

  // 1. 定位第一个支持SimpleFileSystem协议的设备
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiSimpleFileSystemProtocolGuid,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (EFI_ERROR (Status) || HandleCount == 0) {
    Print (L"未找到文件系统设备: %r\n", Status);
    return Status;
  }

  DeviceHandle = HandleBuffer[0];
  Status = gBS->HandleProtocol (
                  DeviceHandle,
                  &gEfiSimpleFileSystemProtocolGuid,
                  (VOID **)&FileSystem
                  );
  if (EFI_ERROR (Status)) {
    Print (L"打开文件系统协议失败: %r\n", Status);
    goto Done;
  }

  // 2. 打开根目录
  Status = FileSystem->OpenVolume (FileSystem, &RootDir);
  if (EFI_ERROR (Status)) {
    Print (L"打开根目录失败: %r\n", Status);
    goto Done;
  }

  // 3. 创建新文件(CREATE | READ | WRITE)
  Status = RootDir->Open (
                     RootDir,
                     &NewFile,
                     L"test.txt",
                     EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
                     0
                     );
  if (EFI_ERROR (Status)) {
    Print (L"创建文件失败: %r\n", Status);
    goto Done;
  }
  Print (L"文件 test.txt 创建成功\n");

  // 4. 关闭创建的文件,然后重新打开验证
  NewFile->Close (NewFile);
  NewFile = NULL;

  Status = RootDir->Open (
                     RootDir,
                     &NewFile,
                     L"test.txt",
                     EFI_FILE_MODE_READ,
                     0
                     );
  if (!EFI_ERROR (Status) && NewFile != NULL) {
    Print (L"验证成功:文件 test.txt 已存在\n");
    NewFile->Close (NewFile);
  } else {
    Print (L"验证失败:无法重新打开 test.txt\n");
    Status = EFI_NOT_FOUND;
  }

Done:
  if (RootDir != NULL) {
    RootDir->Close (RootDir);
  }
  if (HandleBuffer != NULL) {
    FreePool (HandleBuffer);
  }
  return Status;
}

编译与运行

在EDK2环境中,将上述代码保存为CreateFile.c,并在.inf文件中声明ShellLib和UefiLib依赖。编译命令如下:

build -p YourPackage.dsc -m YourPackage/CreateFile.inf

将生成的CreateFile.efi拷贝至UEFI Shell可访问的FAT分区,在Shell中执行:

fs0:
CreateFile.efi

验证方法

程序执行后观察输出:

  • 若显示文件 test.txt 创建成功且随后显示验证成功:文件 test.txt 已存在,则说明创建与验证均通过。
  • 在Shell中执行ls test.txt,若列出该文件则进一步确认文件已存在于根目录。

判定标准:两次Open调用均返回EFI_SUCCESS,且第二次以只读方式重新打开成功,即证明文件创建并持久化于文件系统中。