一些情况下,我们需要在 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