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

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>