/*++ Module Name: savrstor.c Abstract: Save/Restore boot options to/from disk Author: Raj Kuramkote (v-rajk) 07-12-00 Revision History: --*/ #include // // 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)); }