497 lines
9.8 KiB
C
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));
|
|
|
|
}
|