windows-nt/Source/XPSP1/NT/base/efiutil/efinvram/savrstor.c
2020-09-26 16:20:57 +08:00

497 lines
9.8 KiB
C

/*++
Module Name:
savrstor.c
Abstract:
Save/Restore boot options to/from disk
Author:
Raj Kuramkote (v-rajk) 07-12-00
Revision History:
--*/
#include <precomp.h>
//
// externs
//
VOID
UtoA(
OUT CHAR8* c,
IN CHAR16* u
);
#define EFINVRAM_DEBUG 0
//
// Writes boot options data to file
//
EFI_STATUS
PopulateNvrFile (
EFI_FILE_HANDLE NvrFile,
CHAR8* bootoptions,
UINT32 buffersize
)
{
UINTN size;
size= buffersize;
NvrFile->Write (NvrFile,&size,bootoptions);
NvrFile->Close(NvrFile);
return EFI_SUCCESS;
}
INTN
ParseNvrFile (
EFI_FILE_HANDLE NvrFile
)
{
EFI_STATUS Status;
CHAR8 *buffer;
UINTN i,j,k,size;
UINT64 BootNumber;
UINT64 BootSize;
UINT16 FreeBootNumber;
VOID *BootOption;
UINTN blockBegin;
EFI_DEVICE_PATH *FilePath;
EFI_FILE_INFO *fileInfo;
EFI_STATUS status;
size= SIZE_OF_EFI_FILE_INFO+255*sizeof (CHAR16);
fileInfo = AllocatePool (size);
if (fileInfo == NULL) {
Print(L"\n");
Print (L"Failed to allocate memory for File Info buffer!\n");
return -1;
}
Status = NvrFile->GetInfo(NvrFile,&GenericFileInfo,&size,fileInfo);
size=(UINTN) fileInfo->FileSize;
FreePool (fileInfo);
buffer = AllocatePool ((size+1));
if (buffer == NULL) {
Print(L"\n");
Print (L"Failed to allocate memory for File buffer!\n");
return -1;
}
Status = NvrFile->Read(NvrFile,&size,buffer);
NvrFile->Close (NvrFile);
if (EFI_ERROR (Status)) {
Print(L"\n");
Print (L"Failed to read nvr file!\n");
FreePool (buffer);
return -1;
}
#if EFINVRAM_DEBUG
Print (L"\nRestoring NVRAM. Filesize = %x\n",
size
);
#endif
//
// One ugly hack! Needs to be cleaned up..
//
k=0;
while(k < size ) {
blockBegin = k;
CopyMem( &BootNumber, &buffer[k], sizeof(BootNumber));
k += sizeof(UINT64);
CopyMem( &BootSize, &buffer[k], sizeof(BootSize));
k += sizeof(UINT64);
BootOption = (VOID *)((CHAR8*)buffer + k);
k += BootSize;
#if EFINVRAM_DEBUG
Print (L"Boot%04x: start = %x, end = %x, options size %x, ptr = %x\n",
BootNumber,
blockBegin,
k-1,
BootSize,
BootOption
);
#endif
//
// We don't use the incoming BootNumber because that number
// is relative to the boot options that were present when
// it was saved. Hence, we need to find a new boot entry #
// relative to the current boot option table
//
FreeBootNumber = FindFreeBootOption();
//
// write the current boot entry into the table at the
// free boot entry location
//
status = WritePackedDataToNvr(
FreeBootNumber,
BootOption,
(UINT32)BootSize
);
if (status != EFI_SUCCESS) {
Print (L"Failed to write to NVRAM\n");
return -1;
}
}
FreePool (buffer);
return 0;
}
EFI_STATUS
OpenCreateFile (
UINT64 OCFlags,
EFI_FILE_HANDLE* StartHdl,
CHAR16* Name
)
{
EFI_FILE_IO_INTERFACE *Vol;
EFI_FILE_HANDLE RootFs;
EFI_FILE_HANDLE CurDir;
EFI_FILE_HANDLE FileHandle;
CHAR16 FileName[100],*DevicePathAsString;
UINTN i;
EFI_STATUS Status;
//
// Open the volume for the device where the nvrutil was started.
//
Status = BS->HandleProtocol (ExeImage->DeviceHandle,
&FileSystemProtocol,
&Vol
);
if (EFI_ERROR(Status)) {
Print(L"\n");
Print(L"Can not get a FileSystem handle for %s DeviceHandle\n",ExeImage->FilePath);
return Status;
}
Status = Vol->OpenVolume (Vol, &RootFs);
if (EFI_ERROR(Status)) {
Print(L"\n");
Print(L"Can not open the volume for the file system\n");
return Status;
}
CurDir = RootFs;
//
// Open saved boot options file
//
FileName[0] = 0;
DevicePathAsString = DevicePathToStr(ExeImage->FilePath);
if (DevicePathAsString!=NULL) {
StrCpy(FileName,DevicePathAsString);
FreePool(DevicePathAsString);
}
// for(i=StrLen(FileName);i>0 && FileName[i]!='\\';i--);
// FileName[i+1] = 0;
StrCpy(FileName, L".\\");
StrCat(FileName,Name);
Status = CurDir->Open (CurDir,
&FileHandle,
FileName,
OCFlags,
0
);
*StartHdl=FileHandle;
return Status;
}
EFI_STATUS
DeleteFile (
CHAR16 *FileName
)
{
EFI_FILE_HANDLE FileHandle;
EFI_STATUS Status;
//
// Get the file handle
//
Status = OpenCreateFile (
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
&FileHandle,
FileName
);
if (EFI_ERROR(Status)) {
return Status;
}
//
// do the delete
//
Status = FileHandle->Delete(FileHandle);
if (EFI_ERROR(Status)) {
Print(L"\n");
Print(L"Can not delete the file %s\n",FileName);
return Status;
}
return Status;
}
EFI_STATUS
InitializeNvrSaveFile(
CHAR16* fileName,
EFI_FILE_HANDLE* nvrFile
)
{
EFI_STATUS status;
//
// we need to delete the existing NVRFILE so that we avoid
// the problem of the new data buffer being smaller than the
// existing file length. If this happens, the remains of the
// previous osbootdata exist after the new buffer and before the
// EOF.
//
status = DeleteFile (fileName);
if (EFI_ERROR(status) && status != EFI_NOT_FOUND) {
return status;
}
status = OpenCreateFile (EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE,nvrFile,fileName);
if (EFI_ERROR (status)) {
return status;
}
return status;
}
INTN
SaveBootOption (
CHAR16* fileName,
UINT64 bootEntryNumber
)
{
EFI_STATUS status;
EFI_FILE_HANDLE nvrFile;
UINT32 k;
CHAR8* buffer;
UINT64 BootNumber;
UINT64 BootSize;
INTN val;
UINT64 bufferSize;
if(bootEntryNumber > (UINT32)GetBootOrderCount()) {
return -1;
}
//
// open the save file
//
status = InitializeNvrSaveFile(fileName, &nvrFile);
if (EFI_ERROR (status)) {
Print(L"\nCan not open the file %s\n",fileName);
return status;
}
BootNumber = ((CHAR16*)BootOrder)[bootEntryNumber];
BootSize = LoadOptionsSize[bootEntryNumber];
ASSERT(LoadOptions[bootEntryNumber] != NULL);
ASSERT(LoadOptionsSize[bootEntryNumber] > 0);
//
// Sanity checking for the the load options
//
bufferSize = BootSize + sizeof(BootNumber) + sizeof(BootSize);
ASSERT(bufferSize <= MAXBOOTVARSIZE);
buffer = AllocatePool(bufferSize);
k = 0;
CopyMem( &buffer[k], &BootNumber, sizeof(BootNumber));
k += sizeof(BootNumber);
CopyMem( &buffer[k], &BootSize, sizeof(BootSize));
k += sizeof(BootSize);
CopyMem( &buffer[k], LoadOptions[bootEntryNumber], LoadOptionsSize[bootEntryNumber] );
k += (UINT32)LoadOptionsSize[bootEntryNumber];
#if EFINVRAM_DEBUG
Print(L"Boot%04x: options size = %x, total size = %x\n",
BootNumber,
BootSize,
k
);
#endif
ASSERT(k == bufferSize);
val = PopulateNvrFile (nvrFile, buffer, (UINT32)bufferSize );
FreePool(buffer);
return val;
}
INTN
SaveAllBootOptions (
CHAR16* fileName
)
{
EFI_STATUS status;
EFI_FILE_HANDLE nvrFile;
UINT32 i, j, k;
INTN val;
CHAR8* buffer;
UINT32 beginBlock;
j = (UINT32)GetBootOrderCount();
if(j == 0) {
return -1;
}
buffer = AllocatePool( j * MAXBOOTVARSIZE );
if(buffer == NULL) {
return -1;
}
//
// open the save file
//
status = InitializeNvrSaveFile(fileName, &nvrFile);
if (EFI_ERROR (status)) {
Print(L"\nCan not open the file %s\n",fileName);
return status;
}
k = 0;
//
// get boot option env variables
//
for ( i = 0; i < j; i++ ) {
UINT64 BootNumber;
UINT64 BootSize;
beginBlock = k;
BootNumber = ((CHAR16*)BootOrder)[i];
CopyMem( &buffer[k], &BootNumber, sizeof(BootNumber));
k += sizeof(BootNumber);
BootSize = LoadOptionsSize[i];
CopyMem( &buffer[k], &BootSize, sizeof(BootSize));
k += sizeof(BootSize);
CopyMem( &buffer[k], LoadOptions[i], LoadOptionsSize[i] );
k += (UINT32)LoadOptionsSize[i];
#if EFINVRAM_DEBUG
Print(L"Boot%04x: begin = %x, end = %x, options size = %x\n",
BootNumber,
beginBlock,
k-1,
BootSize
);
#endif
}
#if EFINVRAM_DEBUG
Print(L"Total size = %x\n", k);
#endif
ASSERT(k <= j*MAXBOOTVARSIZE);
val = PopulateNvrFile (nvrFile, buffer, k );
FreePool(buffer);
return val;
}
BOOLEAN
RestoreFileExists(
CHAR16* fileName
)
{
EFI_STATUS Status;
EFI_FILE_HANDLE nvrFile;
//
// Read from saved boot options file
//
Status = OpenCreateFile (EFI_FILE_MODE_READ,&nvrFile,fileName);
if (EFI_ERROR (Status)) {
return FALSE;
}
nvrFile->Close(nvrFile);
return TRUE;
}
INTN
RestoreNvr (
CHAR16* fileName
)
{
EFI_STATUS Status;
EFI_FILE_HANDLE nvrFile;
//
// Read from saved boot options file
//
Status = OpenCreateFile (EFI_FILE_MODE_READ,&nvrFile,fileName);
if (EFI_ERROR (Status)) {
Print(L"\nCan not open the file %s\n",fileName);
return Status;
}
//
// This updates nvram with saved boot options
//
return (ParseNvrFile (nvrFile));
}