一些情况下,我们需要在 Shell 下面使用文件进行测试,这次编写一个工具,生成使用随机数填充的文件。为了校验方便,文件的末尾有一个 checksum,按照 32Bits 的 UINTN ,整个文件的和应该是 0 .
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/SimpleFileSystem.h>
#include <Library/MemoryAllocationLib.h>
extern EFI_BOOT_SERVICES *gBS;
extern EFI_SYSTEM_TABLE *gST;
extern EFI_RUNTIME_SERVICES *gRT;
//copied from \StdLib\Include\stdlib.h
/** Expands to an integer constant expression that is the maximum value
returned by the rand function.
The value of the RAND_MAX macro shall be at least 32767.
**/
#define RAND_MAX 0x7fffffff
//Copied from \StdLib\LibC\StdLib\Rand.c
static UINT32 next = 1;
/** Compute a pseudo-random number.
*
* Compute x = (7^5 * x) mod (2^31 - 1)
* without overflowing 31 bits:
* (2^31 - 1) = 127773 * (7^5) + 2836
* From "Random number generators: good ones are hard to find",
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
**/
UINT32
rand()
{
INT32 hi, lo, x;
/* Can't be initialized with 0, so use another value. */
if (next == 0)
next = 123459876;
hi = next / 127773;
lo = next % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
return ((next = x) % ((UINT32)RAND_MAX + 1));
}
int
EFIAPI
main (
IN int Argc,
IN CHAR16 **Argv
)
{
UINTN FileSize=0;
EFI_STATUS Status;
EFI_FILE_PROTOCOL *Root;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
EFI_FILE_PROTOCOL *FileHandle=0;
UINTN *HandleBuffer;
UINT32 i,t,sum=0;
if (Argc>1) {
FileSize=StrDecimalToUintn(Argv[1])*1024;
//Print(L"%d",FileSize);
}
else
{
FileSize=1024*1024*10;
}
Status = gBS->LocateProtocol(
&gEfiSimpleFileSystemProtocolGuid,
NULL,
(VOID **)&SimpleFileSystem);
if (EFI_ERROR(Status)) {
Print(L"Cannot find EFI_SIMPLE_FILE_SYSTEM_PROTOCOL \r\n");
return Status;
}
Status = SimpleFileSystem->OpenVolume(SimpleFileSystem,&Root);
if (EFI_ERROR(Status)) {
Print(L"OpenVolume error \r\n");
return Status;
}
Status = Root -> Open(Root,
&FileHandle,
(CHAR16 *) L"ztest.bin",
EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
0);
if (EFI_ERROR(Status) || (FileHandle==0)) {
Print(L"Open error \r\n");
return Status;
}
HandleBuffer = AllocateZeroPool(FileSize);
if (HandleBuffer == NULL) {
Print(L"Not enough memory!\n");
return Status;
}
for (i=0;i<(FileSize-4)/4;i++)
{
t=rand();
*(HandleBuffer+i)=t;
sum=sum+t;
}
*(HandleBuffer+(FileSize-4)/4)=(UINT32)(0-sum);
Status = FileHandle -> Write(FileHandle, &FileSize, HandleBuffer);
Print(L"Write Done \r\n");
FreePool(HandleBuffer);
Status = FileHandle -> Close (FileHandle);
return EFI_SUCCESS;
}
除了生成文件的工具,还有一个用来校验文件的工具,他的作用是将文件全部内容相加,查看结果是否为0.
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <Protocol/EfiShell.h>
#include <Library/ShellLib.h>
#include <Library/MemoryAllocationLib.h>
int
EFIAPI
main (
IN int Argc,
IN CHAR16 **Argv
)
{
EFI_FILE_HANDLE FileHandle;
RETURN_STATUS Status;
EFI_FILE_INFO *FileInfo = NULL;
UINT32 *HandleBuffer=NULL;
UINTN ReadSize;
UINT32 i,sum=0;
//Check if there is a parameter
if (Argc == 1) {
Print(L"Usage: crctest [filename]\n");
return 0;
}
//Open the file given by the parameter
Status = ShellOpenFileByName(Argv[1], (SHELL_FILE_HANDLE *)&FileHandle,
EFI_FILE_MODE_READ , 0);
if(Status != RETURN_SUCCESS) {
Print(L"OpenFile failed!\n");
return EFI_SUCCESS;
}
//Get file size
FileInfo = ShellGetFileInfo( (SHELL_FILE_HANDLE)FileHandle);
//if the file size is not the multiple of 4, we don't check it!
if ((UINTN) FileInfo-> FileSize % 4 !=0 ) {
Print(L"We can't check this file as the filesize is wrong!\n");
}
//Allocate a memory buffer
HandleBuffer = AllocateZeroPool((UINTN) FileInfo-> FileSize);
if (HandleBuffer == NULL) {
return (SHELL_OUT_OF_RESOURCES); }
ReadSize=(UINTN) FileInfo-> FileSize;
//Load the whole file to the buffer
Status = ShellReadFile(FileHandle,&ReadSize,HandleBuffer);
for (i=0;i< FileInfo-> FileSize / 4;i++)
{
sum=sum+*(HandleBuffer+i);
}
if (sum==0) {
Print(L"Pass!\n");
}
else
{
Print(L"Fail!\n");
}
FreePool(HandleBuffer);
FileHandle -> Close (FileHandle);
return EFI_SUCCESS;
}
完整的代码和 EFI 文件下载:
TestFileGen
Chker