Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

496 lines
9.8 KiB

  1. /*++
  2. Module Name:
  3. savrstor.c
  4. Abstract:
  5. Save/Restore boot options to/from disk
  6. Author:
  7. Raj Kuramkote (v-rajk) 07-12-00
  8. Revision History:
  9. --*/
  10. #include <precomp.h>
  11. //
  12. // externs
  13. //
  14. VOID
  15. UtoA(
  16. OUT CHAR8* c,
  17. IN CHAR16* u
  18. );
  19. #define EFINVRAM_DEBUG 0
  20. //
  21. // Writes boot options data to file
  22. //
  23. EFI_STATUS
  24. PopulateNvrFile (
  25. EFI_FILE_HANDLE NvrFile,
  26. CHAR8* bootoptions,
  27. UINT32 buffersize
  28. )
  29. {
  30. UINTN size;
  31. size= buffersize;
  32. NvrFile->Write (NvrFile,&size,bootoptions);
  33. NvrFile->Close(NvrFile);
  34. return EFI_SUCCESS;
  35. }
  36. INTN
  37. ParseNvrFile (
  38. EFI_FILE_HANDLE NvrFile
  39. )
  40. {
  41. EFI_STATUS Status;
  42. CHAR8 *buffer;
  43. UINTN i,j,k,size;
  44. UINT64 BootNumber;
  45. UINT64 BootSize;
  46. UINT16 FreeBootNumber;
  47. VOID *BootOption;
  48. UINTN blockBegin;
  49. EFI_DEVICE_PATH *FilePath;
  50. EFI_FILE_INFO *fileInfo;
  51. EFI_STATUS status;
  52. size= SIZE_OF_EFI_FILE_INFO+255*sizeof (CHAR16);
  53. fileInfo = AllocatePool (size);
  54. if (fileInfo == NULL) {
  55. Print(L"\n");
  56. Print (L"Failed to allocate memory for File Info buffer!\n");
  57. return -1;
  58. }
  59. Status = NvrFile->GetInfo(NvrFile,&GenericFileInfo,&size,fileInfo);
  60. size=(UINTN) fileInfo->FileSize;
  61. FreePool (fileInfo);
  62. buffer = AllocatePool ((size+1));
  63. if (buffer == NULL) {
  64. Print(L"\n");
  65. Print (L"Failed to allocate memory for File buffer!\n");
  66. return -1;
  67. }
  68. Status = NvrFile->Read(NvrFile,&size,buffer);
  69. NvrFile->Close (NvrFile);
  70. if (EFI_ERROR (Status)) {
  71. Print(L"\n");
  72. Print (L"Failed to read nvr file!\n");
  73. FreePool (buffer);
  74. return -1;
  75. }
  76. #if EFINVRAM_DEBUG
  77. Print (L"\nRestoring NVRAM. Filesize = %x\n",
  78. size
  79. );
  80. #endif
  81. //
  82. // One ugly hack! Needs to be cleaned up..
  83. //
  84. k=0;
  85. while(k < size ) {
  86. blockBegin = k;
  87. CopyMem( &BootNumber, &buffer[k], sizeof(BootNumber));
  88. k += sizeof(UINT64);
  89. CopyMem( &BootSize, &buffer[k], sizeof(BootSize));
  90. k += sizeof(UINT64);
  91. BootOption = (VOID *)((CHAR8*)buffer + k);
  92. k += BootSize;
  93. #if EFINVRAM_DEBUG
  94. Print (L"Boot%04x: start = %x, end = %x, options size %x, ptr = %x\n",
  95. BootNumber,
  96. blockBegin,
  97. k-1,
  98. BootSize,
  99. BootOption
  100. );
  101. #endif
  102. //
  103. // We don't use the incoming BootNumber because that number
  104. // is relative to the boot options that were present when
  105. // it was saved. Hence, we need to find a new boot entry #
  106. // relative to the current boot option table
  107. //
  108. FreeBootNumber = FindFreeBootOption();
  109. //
  110. // write the current boot entry into the table at the
  111. // free boot entry location
  112. //
  113. status = WritePackedDataToNvr(
  114. FreeBootNumber,
  115. BootOption,
  116. (UINT32)BootSize
  117. );
  118. if (status != EFI_SUCCESS) {
  119. Print (L"Failed to write to NVRAM\n");
  120. return -1;
  121. }
  122. }
  123. FreePool (buffer);
  124. return 0;
  125. }
  126. EFI_STATUS
  127. OpenCreateFile (
  128. UINT64 OCFlags,
  129. EFI_FILE_HANDLE* StartHdl,
  130. CHAR16* Name
  131. )
  132. {
  133. EFI_FILE_IO_INTERFACE *Vol;
  134. EFI_FILE_HANDLE RootFs;
  135. EFI_FILE_HANDLE CurDir;
  136. EFI_FILE_HANDLE FileHandle;
  137. CHAR16 FileName[100],*DevicePathAsString;
  138. UINTN i;
  139. EFI_STATUS Status;
  140. //
  141. // Open the volume for the device where the nvrutil was started.
  142. //
  143. Status = BS->HandleProtocol (ExeImage->DeviceHandle,
  144. &FileSystemProtocol,
  145. &Vol
  146. );
  147. if (EFI_ERROR(Status)) {
  148. Print(L"\n");
  149. Print(L"Can not get a FileSystem handle for %s DeviceHandle\n",ExeImage->FilePath);
  150. return Status;
  151. }
  152. Status = Vol->OpenVolume (Vol, &RootFs);
  153. if (EFI_ERROR(Status)) {
  154. Print(L"\n");
  155. Print(L"Can not open the volume for the file system\n");
  156. return Status;
  157. }
  158. CurDir = RootFs;
  159. //
  160. // Open saved boot options file
  161. //
  162. FileName[0] = 0;
  163. DevicePathAsString = DevicePathToStr(ExeImage->FilePath);
  164. if (DevicePathAsString!=NULL) {
  165. StrCpy(FileName,DevicePathAsString);
  166. FreePool(DevicePathAsString);
  167. }
  168. // for(i=StrLen(FileName);i>0 && FileName[i]!='\\';i--);
  169. // FileName[i+1] = 0;
  170. StrCpy(FileName, L".\\");
  171. StrCat(FileName,Name);
  172. Status = CurDir->Open (CurDir,
  173. &FileHandle,
  174. FileName,
  175. OCFlags,
  176. 0
  177. );
  178. *StartHdl=FileHandle;
  179. return Status;
  180. }
  181. EFI_STATUS
  182. DeleteFile (
  183. CHAR16 *FileName
  184. )
  185. {
  186. EFI_FILE_HANDLE FileHandle;
  187. EFI_STATUS Status;
  188. //
  189. // Get the file handle
  190. //
  191. Status = OpenCreateFile (
  192. EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
  193. &FileHandle,
  194. FileName
  195. );
  196. if (EFI_ERROR(Status)) {
  197. return Status;
  198. }
  199. //
  200. // do the delete
  201. //
  202. Status = FileHandle->Delete(FileHandle);
  203. if (EFI_ERROR(Status)) {
  204. Print(L"\n");
  205. Print(L"Can not delete the file %s\n",FileName);
  206. return Status;
  207. }
  208. return Status;
  209. }
  210. EFI_STATUS
  211. InitializeNvrSaveFile(
  212. CHAR16* fileName,
  213. EFI_FILE_HANDLE* nvrFile
  214. )
  215. {
  216. EFI_STATUS status;
  217. //
  218. // we need to delete the existing NVRFILE so that we avoid
  219. // the problem of the new data buffer being smaller than the
  220. // existing file length. If this happens, the remains of the
  221. // previous osbootdata exist after the new buffer and before the
  222. // EOF.
  223. //
  224. status = DeleteFile (fileName);
  225. if (EFI_ERROR(status) && status != EFI_NOT_FOUND) {
  226. return status;
  227. }
  228. status = OpenCreateFile (EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE,nvrFile,fileName);
  229. if (EFI_ERROR (status)) {
  230. return status;
  231. }
  232. return status;
  233. }
  234. INTN
  235. SaveBootOption (
  236. CHAR16* fileName,
  237. UINT64 bootEntryNumber
  238. )
  239. {
  240. EFI_STATUS status;
  241. EFI_FILE_HANDLE nvrFile;
  242. UINT32 k;
  243. CHAR8* buffer;
  244. UINT64 BootNumber;
  245. UINT64 BootSize;
  246. INTN val;
  247. UINT64 bufferSize;
  248. if(bootEntryNumber > (UINT32)GetBootOrderCount()) {
  249. return -1;
  250. }
  251. //
  252. // open the save file
  253. //
  254. status = InitializeNvrSaveFile(fileName, &nvrFile);
  255. if (EFI_ERROR (status)) {
  256. Print(L"\nCan not open the file %s\n",fileName);
  257. return status;
  258. }
  259. BootNumber = ((CHAR16*)BootOrder)[bootEntryNumber];
  260. BootSize = LoadOptionsSize[bootEntryNumber];
  261. ASSERT(LoadOptions[bootEntryNumber] != NULL);
  262. ASSERT(LoadOptionsSize[bootEntryNumber] > 0);
  263. //
  264. // Sanity checking for the the load options
  265. //
  266. bufferSize = BootSize + sizeof(BootNumber) + sizeof(BootSize);
  267. ASSERT(bufferSize <= MAXBOOTVARSIZE);
  268. buffer = AllocatePool(bufferSize);
  269. k = 0;
  270. CopyMem( &buffer[k], &BootNumber, sizeof(BootNumber));
  271. k += sizeof(BootNumber);
  272. CopyMem( &buffer[k], &BootSize, sizeof(BootSize));
  273. k += sizeof(BootSize);
  274. CopyMem( &buffer[k], LoadOptions[bootEntryNumber], LoadOptionsSize[bootEntryNumber] );
  275. k += (UINT32)LoadOptionsSize[bootEntryNumber];
  276. #if EFINVRAM_DEBUG
  277. Print(L"Boot%04x: options size = %x, total size = %x\n",
  278. BootNumber,
  279. BootSize,
  280. k
  281. );
  282. #endif
  283. ASSERT(k == bufferSize);
  284. val = PopulateNvrFile (nvrFile, buffer, (UINT32)bufferSize );
  285. FreePool(buffer);
  286. return val;
  287. }
  288. INTN
  289. SaveAllBootOptions (
  290. CHAR16* fileName
  291. )
  292. {
  293. EFI_STATUS status;
  294. EFI_FILE_HANDLE nvrFile;
  295. UINT32 i, j, k;
  296. INTN val;
  297. CHAR8* buffer;
  298. UINT32 beginBlock;
  299. j = (UINT32)GetBootOrderCount();
  300. if(j == 0) {
  301. return -1;
  302. }
  303. buffer = AllocatePool( j * MAXBOOTVARSIZE );
  304. if(buffer == NULL) {
  305. return -1;
  306. }
  307. //
  308. // open the save file
  309. //
  310. status = InitializeNvrSaveFile(fileName, &nvrFile);
  311. if (EFI_ERROR (status)) {
  312. Print(L"\nCan not open the file %s\n",fileName);
  313. return status;
  314. }
  315. k = 0;
  316. //
  317. // get boot option env variables
  318. //
  319. for ( i = 0; i < j; i++ ) {
  320. UINT64 BootNumber;
  321. UINT64 BootSize;
  322. beginBlock = k;
  323. BootNumber = ((CHAR16*)BootOrder)[i];
  324. CopyMem( &buffer[k], &BootNumber, sizeof(BootNumber));
  325. k += sizeof(BootNumber);
  326. BootSize = LoadOptionsSize[i];
  327. CopyMem( &buffer[k], &BootSize, sizeof(BootSize));
  328. k += sizeof(BootSize);
  329. CopyMem( &buffer[k], LoadOptions[i], LoadOptionsSize[i] );
  330. k += (UINT32)LoadOptionsSize[i];
  331. #if EFINVRAM_DEBUG
  332. Print(L"Boot%04x: begin = %x, end = %x, options size = %x\n",
  333. BootNumber,
  334. beginBlock,
  335. k-1,
  336. BootSize
  337. );
  338. #endif
  339. }
  340. #if EFINVRAM_DEBUG
  341. Print(L"Total size = %x\n", k);
  342. #endif
  343. ASSERT(k <= j*MAXBOOTVARSIZE);
  344. val = PopulateNvrFile (nvrFile, buffer, k );
  345. FreePool(buffer);
  346. return val;
  347. }
  348. BOOLEAN
  349. RestoreFileExists(
  350. CHAR16* fileName
  351. )
  352. {
  353. EFI_STATUS Status;
  354. EFI_FILE_HANDLE nvrFile;
  355. //
  356. // Read from saved boot options file
  357. //
  358. Status = OpenCreateFile (EFI_FILE_MODE_READ,&nvrFile,fileName);
  359. if (EFI_ERROR (Status)) {
  360. return FALSE;
  361. }
  362. nvrFile->Close(nvrFile);
  363. return TRUE;
  364. }
  365. INTN
  366. RestoreNvr (
  367. CHAR16* fileName
  368. )
  369. {
  370. EFI_STATUS Status;
  371. EFI_FILE_HANDLE nvrFile;
  372. //
  373. // Read from saved boot options file
  374. //
  375. Status = OpenCreateFile (EFI_FILE_MODE_READ,&nvrFile,fileName);
  376. if (EFI_ERROR (Status)) {
  377. Print(L"\nCan not open the file %s\n",fileName);
  378. return Status;
  379. }
  380. //
  381. // This updates nvram with saved boot options
  382. //
  383. return (ParseNvrFile (nvrFile));
  384. }