3

我想在 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; 
}

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

4

1 回答 1

2
UINT16* Buffer;

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

UINT8 Buffer[512];

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

如果 This 是一个目录,则该函数读取文件当前位置的目录条目并返回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; 
}
于 2020-12-14T18:02:05.623 回答