简体   繁体   English

如何阅读 LBA (UEFI)

[英]How to read LBA (UEFI)

I wanted to list the content of the root directory in UEFI, but I didn't find any protocol to do that;我想在 UEFI 中列出根目录的内容,但我没有找到任何协议可以做到这一点; therefore I wanted to print the content of the directory file, but the EFI_FILE_PROTOCOL can't read direcory files.因此我想打印目录文件的内容,但EFI_FILE_PROTOCOL无法读取目录文件。 The only other thing that I can do is to read the disk sector which contains that information, but the EFI_BLOCK_IO_PROTOCOL returns 0x02 .我唯一能做的另一件事是读取包含该信息的磁盘扇区,但EFI_BLOCK_IO_PROTOCOL返回0x02

Here is the code:这是代码:

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

Can you spot what I did wrong?你能看出我做错了什么吗?

UINT16* Buffer;

What's this?这是什么? An uninitialized pointer!一个未初始化的指针! You pass this to ReadBlocks() , then you got an error.你把它传递给ReadBlocks() ,然后你得到一个错误。 Your Buffer should be defined like this:你的Buffer应该这样定义:

UINT8 Buffer[512];

By the way, the correct way to list files in a directory is to use EFI_FILE_PROTOCOL.Read() .顺便说一句,列出目录中文件的正确方法是使用EFI_FILE_PROTOCOL.Read() The UEFI Specification says: UEFI 规范说:

If This is a directory, the function reads the directory entry at the file's current position and returns the entry in Buffer .如果 This 是一个目录,则 function 读取文件当前 position 处的目录条目并返回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.如果Buffer不足以容纳当前目录条目,则返回EFI_BUFFER_TOO_SMALL并且不更新当前文件 position。 BufferSize is set to be the size of the buffer needed to read the entry. BufferSize设置为读取条目所需的缓冲区大小。 On success, the current position is updated to the next directory entry.成功后,当前 position 将更新为下一个目录条目。 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. EFI_FILE_INFO是作为目录条目返回的结构。

Here is the code example (error handling is ignored)这是代码示例(忽略错误处理)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM