一、 编写源代码
- 编写UEFI Application
代码C:\edkii\OvmfPkg\MyHelloWorldFileIO\MyHelloWorldFileIO.c,
EFI_STATUS OpenShellProtocol( EFI_SHELL_PROTOCOL **gEfiShellProtocol )
{
EFI_STATUS Status;
Status = gBS->OpenProtocol(
gImageHandle,
&gEfiShellProtocolGuid,
(VOID **)gEfiShellProtocol,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR(Status)) {
//
// Search for the shell protocol
//
Status = gBS->LocateProtocol(
&gEfiShellProtocolGuid,
NULL,
(VOID **)gEfiShellProtocol
);
if (EFI_ERROR(Status)) {
gEfiShellProtocol = NULL;
}
}
return Status;
}
INTN
EFIAPI
ShellAppMain( UINTN Argc, CHAR16 **Argv)
{
CHAR16 * OldLogFileName = NULL;
CHAR16 *LineBuff = NULL;
CHAR16 NewFileName[128] = {0};
CHAR16 * ArrayBuffer = NULL;
EFI_STATUS Status ;
SHELL_FILE_HANDLE FileHandle;
UINTN Index = 0;
UINTN WbufSize = 0;
UINTN FileSize = 0;
UINTN i = 0;
UINTN StartIndex = 0;
CHAR8 *Ptr = NULL;
if (Argc <= 1){
Print(L"Please input file name!\n");
return (-1);
}
OldLogFileName = Argv[1];
Print(L"The Old file name is %s!\n",OldLogFileName);
EFI_SHELL_PROTOCOL *gEfiShellProtocol;
Status = OpenShellProtocol(&gEfiShellProtocol);
Status = gEfiShellProtocol->OpenFileByName((CONST CHAR16*)OldLogFileName, &FileHandle, EFI_FILE_MODE_READ);
if (EFI_ERROR(Status)){
Print(L"Please Input Valid Filename!\n");
return (-1);
}
StrnCpyS(NewFileName,128,OldLogFileName,StrLen(OldLogFileName)-4);
StrCatS(NewFileName,128,L"_New.txt");
Print(L"New FileName is %s\n",NewFileName);
//删除同名的文件
gEfiShellProtocol->DeleteFileByName(NewFileName);
//获取文件实际大小
Status = gEfiShellProtocol->GetFileSize(FileHandle,&FileSize);
if (EFI_ERROR (Status)) {
gEfiShellProtocol->CloseFile (FileHandle);
return Status;
}
Print (L"File FileSize is %d!\n",FileSize);
if (FileSize < 0){
Print (L"File cotent is empty!\n");
return (-1);
}
FileSize += 1;
//根据文件大小申请对应大小的内存
Status = gBS -> AllocatePool (EfiReservedMemoryType, FileSize , &ArrayBuffer);
Status = gBS -> AllocatePool (EfiReservedMemoryType, FileSize , &LineBuff);
BZero(ArrayBuffer,FileSize);
BZero(LineBuff,FileSize);
Status = gEfiShellProtocol->ReadFile(FileHandle, &FileSize ,ArrayBuffer);
if (EFI_ERROR(Status)){
Print(L"Read Filename Error!\n");
return (-1);
}
//创建新的文件句柄
Status = gEfiShellProtocol->CreateFile((CONST CHAR16*)NewFileName,0 ,&FileHandle);
if (EFI_ERROR(Status)){
Print(L"Create Filename %s Fail!\n",NewFileName);
return (-1);
}
//读取的文件内容写入新建文件
WbufSize = FileSize;
Status = gEfiShellProtocol->WriteFile(FileHandle,&WbufSize,ArrayBuffer);
//关闭文件句柄
Status = gEfiShellProtocol->CloseFile(FileHandle);
Ptr = (CHAR8 * )ArrayBuffer;
for (i = 0 ; i < FileSize ; i ++ ){
if (Ptr[i] == '\n'){
Ptr[i] = '\0';
Ascii2UnicodeString(Ptr + StartIndex, LineBuff);
StartIndex = i + 1;
Index += 1;
//按行输出
Print(L"Line %d: %S!\n",Index,LineBuff);
BZero(LineBuff,FileSize);
}
}
return (0);
}
二、 编译生成EFI文件
运行edksetup.bat
编译整个OvmfPkg Package
三、 运行 UEFI APP MyHelloWorldFileIO.efi
- 拷贝
C:\edkii\Build\OvmfX64\DEBUG_VS2013x86\FV\OVMF.fd
到C:\qemu
;拷贝C:\edkii\Build\OvmfX64\DEBUG_VS2013x86\X64\OvmfPkg\MyHelloWorldFileIO\MyHelloWorldFileIO\OUTPUT\MyHelloWorldFileIO.efi
到 虚拟盘HDD_BOOT.img
- 执行
etup-qemu-x64.bat
, 然后在UEFI SHELL
中执行MyHelloWorldFileIO.efi
,结果如下,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
四、 小结
文件操作是UEFI中一个比较重要的功能,本文利用EFI_SHELL_PROTOCOL实现对文件的读取,并写入新建文件,然后按行输出到Console.这里需要注意的是,若是读取ASCII文件输出终端需要今日能够ASCII与Unicode转换工作。