如何读取 LBA (UEFI)

How to read LBA (UEFI)

我想列出 UEFI 中根目录的内容,但我没有找到任何协议可以做到这一点;因此我想打印目录文件的内容,但是 EFI_FILE_PROTOCOL 无法读取目录文件。我唯一能做的就是读取包含该信息的磁盘扇区,但是 EFI_BLOCK_IO_PROTOCOL returns 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; 
}

你能看出我哪里做错了吗?

UINT16* Buffer;

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

UINT8 Buffer[512];

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

If This is a directory, the function reads the directory entry at the file’s current position and returns the entry in Buffer. If the Buffer is not large enough to hold the current directory entry, then EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. BufferSize is set to be the size of the buffer needed to read the entry. On success, the current position is updated to the next directory entry. If there are no more directory entries, the read returns a zero-length buffer. EFI_FILE_INFO is the structure returned as the directory entry.

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

#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; 
}