【问题标题】:How to read LBA (UEFI)如何阅读 LBA (UEFI)
【发布时间】:2021-03-25 02:47:40
【问题描述】:

我想在 UEFI 中列出根目录的内容,但我没有找到任何协议可以做到这一点;因此我想打印目录文件的内容,但EFI_FILE_PROTOCOL 无法读取目录文件。我唯一能做的就是读取包含该信息的磁盘扇区,但EFI_BLOCK_IO_PROTOCOL 返回0x02

代码如下:

#include <efi.h>
#include <efilib.h>

EFI_STATUS
efi_main(EFI_HANDLE Image, EFI_SYSTEM_TABLE* Systab)
{
    EFI_LOADED_IMAGE_PROTOCOL* LoadedImage;
    EFI_BLOCK_IO_PROTOCOL* BlockIO;
    UINT16* Buffer;
    EFI_STATUS Status;

    InitializeLib(Image, Systab);
    Status = uefi_call_wrapper(BS->HandleProtocol, 3,
                                Image,
                                &gEfiLoadedImageProtocolGuid,
                                &LoadedImage);
    if(Status != EFI_SUCCESS) {
        Print(L"HandleProtocol() failed [0]\n");
    }
    Status = uefi_call_wrapper(BS->HandleProtocol, 3,
                                LoadedImage->DeviceHandle,
                                &gEfiBlockIoProtocolGuid,
                                &BlockIO);
    if(Status != EFI_SUCCESS) {
        Print(L"HandleProtocol() failed [1]\n");
    }

    Status = uefi_call_wrapper(BlockIO->ReadBlocks, 5,
                                BlockIO,
                                BlockIO->Media->MediaId,
                                (EFI_LBA)1,
                                BlockIO->Media->BlockSize,
                                Buffer);
    if(Status != EFI_SUCCESS) {
        Print(L"Failed to read disk with code 0x%x\n", Status);
    }
    else for(int i = 0; i < 512; i++) {
        Print(L"%c", (CHAR8)Buffer[i]);
    }

    return EFI_SUCCESS; 
}

你能看出我做错了什么吗?

【问题讨论】:

  • EFI 规范说“EFI_FILE_PROTOCOL 提供对文件或目录内容的访问,...”
  • 问题是 EFI_FILE_PROTOCOL.Open() 读取文件当前位置的目录条目,而不是我想要的整个目录文件。至少这是我能用那个协议做的最好的事情;如果你知道怎么做,我很乐意听。

标签: c uefi gnu-efi


【解决方案1】:
UINT16* Buffer;

这是什么?一个未初始化的指针!你把它传递给ReadBlocks(),然后你得到一个错误。你的Buffer 应该这样定义:

UINT8 Buffer[512];

顺便说一下,列出目录中文件的正确方法是使用EFI_FILE_PROTOCOL.Read()。 UEFI 规范说:

如果这是一个目录,该函数读取文件当前位置的目录条目并返回Buffer中的条目。如果Buffer 不足以容纳当前目录条目,则返回EFI_BUFFER_TOO_SMALL 并且不更新当前文件位置。 BufferSize 设置为读取条目所需的缓冲区大小。成功后,当前位置将更新为下一个目录条目。如果没有更多目录条目,则读取返回零长度缓冲区。 EFI_FILE_INFO 是作为目录条目返回的结构。

这里是代码示例(错误处理被忽略)

#include <efi.h>
#include <efilib.h>

#define FILE_BUFFER_SIZE 4096

EFI_STATUS efi_main(EFI_HANDLE *ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
    InitializeLib(ImageHandle, SystemTable);

    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
    EFI_FILE_PROTOCOL *RootDir;
    UINT8 Buffer[FILE_BUFFER_SIZE];
    UINTN BufferSize;
    EFI_FILE_INFO *FileInfo;

    // clear screen
    uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);

    // open the filesystem
    uefi_call_wrapper(BS->LocateProtocol, 3, &FileSystemProtocol, NULL, &FileSystem);

    // open the root directory
    uefi_call_wrapper(FileSystem->OpenVolume, 2, FileSystem, &RootDir);

    while (TRUE) {
        BufferSize = sizeof(Buffer);

        // read one directory entry
        uefi_call_wrapper(RootDir->Read, 3, RootDir, &BufferSize, Buffer);

        // stop reading when there are no more entries
        if (BufferSize == 0) {
            break;
        }

        // cast and print the filename
        FileInfo = (EFI_FILE_INFO *)Buffer;
        Print(L"%s\n", FileInfo->FileName);
    }

    // close the root directory
    uefi_call_wrapper(RootDir->Close, 1, RootDir);

    Pause();

    return EFI_SUCCESS; 
}

【讨论】:

  • 该缓冲区包含什么类型的数据?
  • @GiovanniZaccaria 如果你指的是ReadBlocks() 的结果,那只是一些原始数据。
猜你喜欢
  • 2016-01-11
  • 2019-04-25
  • 2012-07-06
  • 2020-06-29
  • 2018-03-18
  • 2011-08-12
  • 2011-09-08
  • 2011-01-19
  • 2012-01-16
相关资源
最近更新 更多