uefi读取文件

本文深入探讨了EFI_SIMPLE_FILE_SYSTEM_PROTOCOL在UEFI系统中的作用,包括如何在myworkspace目录下查找相关协议,理解其内部定义及在inf文件中的引用方式。详细解释了如何使用此协议来实现基本的文件操作,如读取文件和控制文件系统。通过实例代码展示了如何在UEFI环境中加载并使用此协议,以实现对文件系统的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

读取文件会需要一个协议     EFI_SIMPLE_FILE_SYSTEM_PROTOCOL

在myworkspace目录下搜索 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL ;(在搜索选项中选择 "文件内容")

可以发现很多文件中有此协议,但是根据命名规范,可以推测文件命中有 simple file system三个单词

然后找到simplefilesystem.h文件,发现其中果然定义了EFI_SIMPLE_FILE_SYSTEM_PROTOCOL ,(经常会有几次 typedef用来取别名)

最后有一个extern EFI_GUID gEfiSimpleFileSystemProtocolGuid;

其中 gEfiSimpleFileSystemProtocolGuid是该协议的id

这个id在  MyWorkSpace\MdePkg\MdePkg.dec 中有定义

所以在inf文件要加上:
[Protocols]
  gEfiSimpleFileSystemProtocolGuid

用以识别

#include <uefi.h>
#include <library/uefilib.h>
#include <library/uefiapplicationentrypoint.h>
#include <protocol/simplefilesystem.h>

//extern EFI_GUID gEfiSimpleFileSystemProtocolGuid;
//gEfiSimpleFileSystemProtocolGuid就是协议的GUID

EFI_STATUS EFIAPI GetString(IN EFI_SYSTEM_TABLE *gST,CHAR16* Str)
{
    UINTN                   Index1,Index2=0;
    EFI_STATUS              Status;
    EFI_INPUT_KEY           key;

    while(EFI_SUCCESS == (Status = gST->BootServices->WaitForEvent(1, &(gST->ConIn->WaitForKey), &Index1)))
    {
        gST->ConIn->ReadKeyStroke(gST->ConIn,&key);

        if(key.UnicodeChar == 13)
        {
            Str[Index2]=0;
            break;
        }

        if(key.UnicodeChar!=8)
        {
            Str[Index2]=key.UnicodeChar;
            ++Index2;
            Print(L"%c",key.UnicodeChar);
        }
        else
        {
            if(Index2>0)
            {
                Str[Index2]=0;
                --Index2;
                Print(L"\b");
            }
        }
    }

    Print(L"\n");

    return Status;
}

EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_STATUS                              Status; //用来接收函数返回值,判断函数执行情况
    INTN                                    HandleCount,HandleIndex=0; //HandleCount表示个数
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL         *Sfs; //将协议加载到Sfs上
    EFI_HANDLE                              *Files=NULL; //Files用来接收容器
    EFI_FILE_PROTOCOL                       *Root; //Root是用来打开卷的
    EFI_FILE_PROTOCOL                       *file; //file是用来读取文件的
    UINTN                                   FileSize=512,i; //FileSize用来表示前后读取大小
    UINT8                                   FileBuffer[512]; //存放读取到的文件数据
    CHAR16                                  FileName[100]; //获取文件名

    GetString(SystemTable,FileName);

    //找到所有提供 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 的控制器    
    //将控制器s 以数组形式存放在Files中,Files用来接收,HandleCount表示个数
    Status=SystemTable->BootServices->LocateHandleBuffer(
            ByProtocol,
            &gEfiSimpleFileSystemProtocolGuid,
            NULL,
            &HandleCount,
            &Files);

    if(!EFI_ERROR(Status))
    {
        Print(L"==successed to find %d controllers==\n",HandleCount);

        for(HandleIndex=HandleCount-1; HandleIndex > -1; --HandleIndex)
        {
                // 打开EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
                //将协议加载到Sfs上,这样Sfs才能打开卷
//                Status = SystemTable->BootServices->HandleProtocol(
//                    Files[HandleIndex],
//                    &gEfiSimpleFileSystemProtocolGuid,
//                    (VOID**)&Sfs);

                Status = SystemTable->BootServices->OpenProtocol(
                    Files[HandleIndex],
                    &gEfiSimpleFileSystemProtocolGuid,
                    (VOID**)&Sfs,
                    ImageHandle,
                    NULL,
                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);

                if(Status == EFI_SUCCESS)
                {
                    //uefi说明文档中有说明:要先OpenVolume打开卷,然后读取文件
                    //Sfs是用来打开卷的,Root是用来打开文件的
                    Status = Sfs->OpenVolume(Sfs, &Root);

                    if(Status == EFI_SUCCESS)
                    {
                        Print(L"==controller %d successed to open the volume==\n",HandleIndex);

                        //打开文件,Root是用来打开文件的,file是用来读取文件的
                        Status = Root->Open(Root, &file, FileName, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY);

                        if(Status == EFI_SUCCESS)
                        {
                            Print(L"==controller %d successed to open the file : %s==\n",HandleIndex,FileName);

                            //读取文件,file是用来读取文件的,FileSize用来表示前后读取大小
                            Status = file->Read(file,&FileSize,(VOID*)FileBuffer);

                            if(!EFI_ERROR(Status))
                            {
                                Print(L"==successed     to read the file==\n");
                                for(i=0;i<FileSize;++i)
                                {
                                    Print(L"%c",FileBuffer[i]);
                                }
                                Print(L"\n==read over==\n");

                                //return EFI_SUCCESS;
                            }
                            else
                            {
                                Print(L"!!failed to read the file!!\n");
                            }
                            
                        }
                        else
                        {
                            Print(L"!!controller %d failed to open the file : %s!!\n",HandleIndex,FileName);                            
                        }
                    }
                }

                Status = SystemTable->BootServices->CloseProtocol(
                    Files[HandleIndex],
                    &gEfiSimpleFileSystemProtocolGuid,
                    ImageHandle,
                    NULL);

                if(Status == EFI_SUCCESS)
                {
                    Print(L"==Successed to close the protocol==\n");
                }
                else
                {
                    Print(L"!!Failed to close the protocol!!\n");
                }
                
                Print(L"== %d traverse over==\n",HandleCount-HandleIndex);
        }

    }        
    Print(L"==program over==\n");
    return EFI_SUCCESS;
}


 


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值