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