You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EDK2编写的UEFI应用仅打印读取文件最后一个字符问题排查

问题分析与修复方案

你的UEFI应用仅输出文件最后一个字符,核心问题出在字符类型不匹配和打印格式错误,具体问题及修复如下:

1. 缓冲区类型与打印格式不兼容

UEFI环境中Print函数的%s格式符要求传入CHAR16*(宽字符指针),但你的代码中:

  • 定义的Buffer是UINT8数组,存储单字节数据
  • 直接用%s打印UINT8数组时,会被解析为宽字符序列。单字节内容会被当作宽字符的低字节,高字节默认补0,形成的宽字符大多无效,直到最后一个字节后添加的单字节'\0',才会让最后一个字符被正确识别为宽字符,导致只输出最后一个内容。

2. 文件路径打印格式错误

代码中两处打印文件路径时误用了%c格式符:

Print(L"Failed to open %c in read mode.\n", FilePath);
Print(L"Failed to get file size of %c.\n", FilePath);

%c用于打印单个字符,而FilePath是CHAR16*字符串,应该改为%s,否则只会打印路径的第一个字符。


修复后的完整代码

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

#define BufferSize 1024

EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE* SystemTable) {
    EFI_STATUS Status = EFI_SUCCESS;
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* SimpleFileSystem;
    EFI_FILE_PROTOCOL* RootDir;
    EFI_FILE_PROTOCOL* File = NULL;
    CHAR16 FilePath[] = L"\\HelloWorld.txt";
    UINTN FileSize;
    // 改为CHAR16缓冲区,适配UEFI宽字符打印要求
    CHAR16 Buffer[BufferSize / sizeof(CHAR16)];

    // 定位文件系统协议
    Status = gBS->LocateProtocol(&gEfiSimpleFileSystemProtocolGuid, NULL, (VOID **)&SimpleFileSystem);
    if (EFI_ERROR(Status)) {
        Print(L"Failed to locate simple file system protocol.\n");
        return Status;
    }

    // 打开根目录
    Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &RootDir);
    if (EFI_ERROR(Status)) {
        Print(L"Failed to open root directory of file system.\n");
        return Status;
    }

    // 打开目标文件
    Status = RootDir->Open(RootDir, &File, FilePath, EFI_FILE_MODE_READ, 0);
    if (EFI_ERROR(Status)) {
        Print(L"Failed to open %s in read mode.\n", FilePath);
        RootDir->Close(RootDir);
        return Status;
    }

    // 获取文件大小
    Status = File->SetPosition(File, 0xFFFFFFFFFFFFFFFF);
    if (!EFI_ERROR(Status)) {
        Status = File->GetPosition(File, &FileSize);
    }
    if(EFI_ERROR(Status)) {
        Print(L"Failed to get file size of %s.\n", FilePath);
        File->Close(File);
        RootDir->Close(RootDir);
        return Status;
    }

    // 检查文件大小是否超出缓冲区容量
    if (FileSize > sizeof(Buffer)) {
        Print(L"File size exceeds buffer capacity.\n");
        File->Close(File);
        RootDir->Close(RootDir);
        return EFI_BUFFER_TOO_SMALL;
    }

    // 读取文件内容到缓冲区
    Status = File->SetPosition(File, 0);
    if (!EFI_ERROR(Status)) {
        Status = File->Read(File, &FileSize, Buffer);
    }
    if (EFI_ERROR(Status)) {
        Print(L"Failed to read file content.\n");
        File->Close(File);
        RootDir->Close(RootDir);
        return Status;
    } else {
        // 用宽字符终止符确保字符串正确结束
        UINTN CharCount = FileSize / sizeof(CHAR16);
        if (CharCount < ARRAY_SIZE(Buffer)) {
            Buffer[CharCount] = L'\0';
        } else {
            Buffer[ARRAY_SIZE(Buffer)-1] = L'\0';
        }
    }

    // 关闭文件和目录
    File->Close(File);
    RootDir->Close(RootDir);

    // 打印文件内容
    Print(L"File content: %s\n", Buffer);

    return Status;
}

关键修复说明

  • 将Buffer类型改为CHAR16,匹配UEFIPrint函数的宽字符要求
  • 修正文件路径打印的格式符,把%c改为%s
  • 使用宽字符终止符L'\0'替代单字节'\0',保证字符串正确终止
  • 增加缓冲区容量检查,避免越界访问

内容的提问来源于stack exchange,提问作者Shmurkio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:37:41