uefi读硬盘和分区数据

inf文件:

[Defines]
  INF_VERSION             = 0x00010006
  BASE_NAME               = efidiskx
  #BASE_NAME               = efidisk
  FILE_GUID               = 6987936E-ED34-44db-AE97-1FA5E4ED2117
  MODULE_TYPE             = UEFI_APPLICATION
  VERSION_STRING          = 1.01
  ENTRY_POINT             = UefiMain

[Sources]
  efidisk.c

[Packages]
  MdePkg/MdePkg.dec
  efidisk/efidisk.dec

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib

[Protocols]
  gEfiDiskIoProtocolGuid
  gEfiBlockIoProtocolGuid
  gEfiDevicePathProtocolGuid
  gEfiDevicePathToTextProtocolGuid
  gEfiSimpleFileSystemProtocolGuid

读取文件

FileIo.c

#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_FILE_PROTOCOL* EFIAPI GetFile(IN EFI_SYSTEM_TABLE *gST)
{    
    EFI_STATUS                              Status; //用来接收函数返回值,判断函数执行情况
    INTN                                    HandleFileCount,HandleFileIndex=0; //HandleFileCount表示个数
    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用来表示前后读取大小
    CHAR16                                  FileName[100]; //获取文件名

    Print(L"     please input the file name : \n     ");
    GetString(gST,FileName);

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

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

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


                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",HandleFileIndex);

                        //打开文件,Root是用来打开文件的,file是用来读取文件的,属性要是读写
                        Status = Root->Open(Root, &file, FileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);

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

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

        }

    }


    return NULL;
}

main文件,只读了一个扇区而已,每个分区的512字节

#include <uefi.h>
#include <library/uefilib.h>
#include <library/uefiapplicationentrypoint.h>
#include <protocol/diskio.h>
#include <protocol/blockio.h>
#include <protocol/devicepath.h>
#include <protocol/devicepathtotext.h>
//#include <C:\myworkspace\MdeModulePkg\Universal\Disk\DiskIoDxe\diskio.h>
#include <uefi/uefigpt.h>
#include <protocol/simplefilesystem.h>
#include <library/printlib.h>
#include <library/baselib.h>
#include "FileOp.h"

#define BYTES         512         //预备读取BYTES字节
#define EXBYTE         4     //一个字节拓展为EXBYTE个字节用来显示16进制和空格或者换行

VOID EFIAPI ShowHex(UINT8* Buffer,UINTN len)
{
    UINTN                                                         i=0;
    for(i = 0; i < 52; ++i)
    {
        if(i%26 == 0)
            Print(L"\r\n");

        Print(L"%02x ",Buffer[i]);
    }
}

//将一个字节拆分有两个字节的16进制字符
VOID EFIAPI DecToChar(UINT8* CharBuff,UINT8 I)
{
    CharBuff[0]=((I/16) > 9)?('A'+(I/16)-10):('0'+(I/16));
    CharBuff[1]=((I%16) > 9)?('A'+(I%16)-10):('0'+(I%16));
}

//将所有字节拆分有两个字节的16进制字符,在拓展两个字节的空格或者换行
VOID EFIAPI DecToCharBuffer(UINT8* Buffin,UINTN len,UINT8* Buffout)
{
    UINTN i=0;

    for(i=0;i<len;++i)
    {
        DecToChar(Buffout+i*4,Buffin[i]);
        if((i+1)%16==0)//判断是不是该换行了,不换行看起来不好
        {
            *(Buffout+ i*4 +2)='\r';
            *(Buffout+ i*4 +3)='\n';
        }
        else//不空格看起来也不好,windown换行是\r\n,为了操作方便,就空了两个
        {
            *(Buffout+ i*4 +2)=' ';
            *(Buffout+ i*4 +3)=' ';
        }
    }
}

EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_STATUS                            Status; //函数返回值
    INTN                                  HandleCount,HandleIndex; //控制器数目,当前控制器好
    EFI_HANDLE                            *Controllers=NULL; //存放相应控制器
    EFI_DISK_IO_PROTOCOL                  *DiskIo; //硬盘读取的协议
    EFI_BLOCK_IO_PROTOCOL                 *BlockIo; //块设备读取的协议
    EFI_DEVICE_PATH_PROTOCOL              *DevicePath; //获取设备路径所需的协议
    EFI_DEVICE_PATH_TO_TEXT_PROTOCOL      *DevicePathToText; //将设备路径转化为文本的协议
    EFI_BLOCK_IO_MEDIA                    *Media; //设备
    CHAR16                                *TextOfDevicePath; //设备路径的可视化文本

    EFI_BOOT_SERVICES                     *gBS=SystemTable->BootServices; //为了少些几个单词
    UINT8                                 Buffer[BYTES]; //存放读取数据
    UINT8                                 Bufferout[BYTES*EXBYTE]; //存放读取后转为16进制字符的数据
    UINTN                                 WriteSize; //读写大小
//    EFI_PARTITION_TABLE_HEADER            *gptHeader; //gpt头,如果读取gpt头的话,读取偏移量要移512字节的mbr

    EFI_FILE_PROTOCOL                      *file=GetFile(SystemTable); //将读取到的二进制数据转化为人类看得懂的16进制字符后存放到文件中

    if(file)
    {
        Print(L"==successed to Get a File==\n");
    }
    else
    {
        Print(L"!!failed to get a file!!\n");
        return EFI_NOT_FOUND;
    }

    //看哪些控制器支持硬盘io
    Status = gBS->LocateHandleBuffer(
        ByProtocol,
        &gEfiDiskIoProtocolGuid,
        NULL,
        &HandleCount,
        &Controllers);

    if(EFI_SUCCESS == Status)
    {
        Print(L"HandleCount : %d\n", HandleCount);

        for(HandleIndex = 0; HandleIndex < HandleCount; ++HandleIndex)
        {
            Print(L"\nHandleIndex : %d\n", HandleIndex);

            //打开硬盘io服务,因为是要操作硬盘
            Status = gBS->HandleProtocol(
                Controllers[HandleIndex],
                &gEfiDiskIoProtocolGuid,
                (VOID**)&DiskIo);

            if(Status == EFI_SUCCESS)
            {
                //打开设备路径服务,读取数据就是读取块设备硬盘设备里的二进制,这些设备要用路径来操作
                Status = gBS->HandleProtocol(
                    Controllers[HandleIndex],
                    &gEfiDevicePathProtocolGuid,
                    (VOID**)&DevicePath);

                if(EFI_SUCCESS == Status)
                {
                    //打开设备路径转化为字符串的服务,不然不容易看懂
                    Status = gBS->LocateProtocol(
                        &gEfiDevicePathToTextProtocolGuid,
                        NULL,
                        (VOID**)&DevicePathToText);

                    if(EFI_SUCCESS == Status)
                    {
                        //将设备路径转化为字符串
                        TextOfDevicePath = DevicePathToText->ConvertDevicePathToText(DevicePath,TRUE,TRUE);

                        Print(L"== %d path== \n%s \n", HandleIndex, TextOfDevicePath);
                        //将设备路径的字符串写入文件
                        WriteSize=StrLen(TextOfDevicePath)*2;
                        file->Write(file,&WriteSize,TextOfDevicePath);
                        WriteSize=2;
                        file->Write(file,&WriteSize,"\r\n");

                        //BlockIo = *((EFI_BLOCK_IO_PROTOCOL**)(DiskIo + 2));
                        //Io = DISK_IO_PRIVATE_DATA_FROM_DISK_IO(DiskIo);
                        //BlockIo = Io->BlockIo;
                        //打开块设备服务
                        Status = gBS->HandleProtocol(
                            Controllers[HandleIndex],
                            &gEfiBlockIoProtocolGuid,
                            (VOID**)&BlockIo);
                        //设备就是该块的设备
                        Media = BlockIo->Media;

                        if(EFI_SUCCESS == Status)
                        {
                            Print(L"==read something==\n");

                            //用硬盘读取功能读取相应设备id的数据,这是硬盘数据读取,不是文件数据读取,
                            //如果要读的是gpt,偏移量不是0,而是512,这512是mbr
                            Status = DiskIo->ReadDisk(DiskIo,Media->MediaId,0,BYTES,Buffer);

                            //gptHeader = (EFI_PARTITION_TABLE_HEADER*)Buffer;//偏移量不是512的话,就没必要了

                            //将枯燥的二进制转化为看得懂的16进制文本
                            DecToCharBuffer(Buffer,BYTES,Bufferout);
                            //那些文本的大小就是读取的字节数乘以一个字节转化后的大小
                            WriteSize=BYTES*EXBYTE;

                            //将看得懂的16进制文本写入文件
                            Status = file->Write(file,&WriteSize,Bufferout);

                            if(EFI_SUCCESS == Status)
                            {
                                Print(L"==successed to write %d BYTES==\n",WriteSize);
                            }
                            else
                            {
                                Print(L"!!failed to write %d BYTES!!\n",WriteSize);
                            }
                            

                            ShowHex(Buffer,52);
                        }
                        else
                        {
                            Print(L"!!failed to read disk!!\n");
                        }
                    }//关闭各种服务
                }
            }
        }
    }

    file->Close(file);//关闭文件,不然写了也白写

    return EFI_SUCCESS;
}


 


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值