S3NvramSave.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /** @file
  2. Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include "S3NvramSave.h"
  6. #include <Protocol/Decompress.h>
  7. #include <Library/CompressLib.h>
  8. #include <Protocol/VariableLock.h>
  9. /**
  10. This function will retrieve the S3 data from HOBs produced by MRC
  11. and will save it to NVRAM if the data is absent or different from
  12. the previously saved data.
  13. @param VOID
  14. @retval VOID
  15. **/
  16. VOID
  17. SaveS3StructToNvram (
  18. VOID
  19. )
  20. {
  21. EFI_STATUS Status;
  22. UINTN BufferSize;
  23. UINTN CurrentHobSize;
  24. UINTN S3ChunkSize;
  25. CHAR16 EfiMemoryConfigVariable[] = L"MemoryConfig0";
  26. EFI_HOB_GUID_TYPE *GuidHob = NULL;
  27. VOID *HobData = NULL;
  28. VOID *VariableData = NULL;
  29. UINTN CompressedDataSize;
  30. UINT32 ScratchSize;
  31. VOID *CompressedData = NULL;
  32. VOID *Scratch = NULL;
  33. EFI_DECOMPRESS_PROTOCOL *Decompress = NULL;
  34. VOID *CompressedVariableData = NULL;
  35. UINTN CompressedBufferSize;
  36. EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock = NULL;
  37. //
  38. // Get first S3 data HOB
  39. //
  40. GuidHob = GetFirstGuidHob (&gEfiMemoryConfigDataHobGuid);
  41. Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
  42. DEBUG((DEBUG_INFO, "[SaveMemoryConfigEntryPoint] Locate Decompress protocol - %r\n", Status));
  43. if(EFI_ERROR (Status)) {
  44. ASSERT_EFI_ERROR (Status);
  45. return;
  46. }
  47. Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
  48. DEBUG((DEBUG_INFO, "[SaveMemoryConfigEntryPoint] Locate Variable Lock protocol - %r\n", Status));
  49. ASSERT_EFI_ERROR(Status);
  50. while (TRUE) {
  51. if (GuidHob == NULL) {
  52. break;
  53. }
  54. HobData = GET_GUID_HOB_DATA(GuidHob);
  55. CurrentHobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
  56. DEBUG((EFI_D_INFO, " Current Hob Size(bytes) is: %d\n", CurrentHobSize));
  57. //
  58. // Use the HOB data to save Memory Configuration Data
  59. //
  60. BufferSize = CurrentHobSize;
  61. Status = gBS->AllocatePool (
  62. EfiBootServicesData,
  63. BufferSize,
  64. (VOID**)&VariableData
  65. );
  66. ASSERT (VariableData != NULL);
  67. S3ChunkSize = MAX_HOB_ENTRY_SIZE / 8;
  68. DEBUG((EFI_D_INFO, " S3ChunkSize Hob Size(bytes): %d\n", S3ChunkSize));
  69. while (CurrentHobSize) {
  70. if (S3ChunkSize > CurrentHobSize) {
  71. S3ChunkSize = CurrentHobSize;
  72. }
  73. BufferSize = S3ChunkSize;
  74. CompressedDataSize = 0;
  75. ScratchSize = 0;
  76. Status = gRT->GetVariable (
  77. EfiMemoryConfigVariable,
  78. &gEfiMemoryConfigDataGuid,
  79. NULL,
  80. &CompressedDataSize,
  81. NULL
  82. );
  83. if(Status == EFI_BUFFER_TOO_SMALL) {
  84. Status = gBS->AllocatePool (
  85. EfiBootServicesData,
  86. CompressedDataSize,
  87. (VOID**)&CompressedData
  88. );
  89. ASSERT (Status == EFI_SUCCESS);
  90. }
  91. if(!EFI_ERROR (Status))
  92. {
  93. Status = gRT->GetVariable (
  94. EfiMemoryConfigVariable,
  95. &gEfiMemoryConfigDataGuid,
  96. NULL,
  97. &CompressedDataSize,
  98. CompressedData
  99. );
  100. if (!EFI_ERROR (Status)) {
  101. Status = Decompress->GetInfo (
  102. Decompress,
  103. CompressedData,
  104. (UINT32)CompressedDataSize,
  105. (UINT32*)&BufferSize,
  106. &ScratchSize
  107. );
  108. }
  109. if (!EFI_ERROR (Status)) {
  110. Status = gBS->AllocatePool (
  111. EfiBootServicesData,
  112. ScratchSize,
  113. (VOID**)&Scratch
  114. );
  115. }
  116. if (!EFI_ERROR (Status)) {
  117. Status = Decompress->Decompress (
  118. Decompress,
  119. CompressedData,
  120. (UINT32)CompressedDataSize,
  121. VariableData,
  122. (UINT32)BufferSize,
  123. Scratch,
  124. ScratchSize
  125. );
  126. }
  127. if (EFI_ERROR (Status)) {
  128. DEBUG((EFI_D_ERROR, "Getting variables error: 0x%x\n", Status));
  129. ASSERT (Status == EFI_SUCCESS);
  130. }
  131. if(Scratch != NULL) {
  132. gBS->FreePool (Scratch);
  133. Scratch = NULL;
  134. }
  135. }
  136. if(CompressedData != NULL) {
  137. gBS->FreePool (CompressedData);
  138. CompressedData = NULL;
  139. }
  140. if ( (EFI_ERROR(Status)) || (CompareMem (HobData, VariableData, S3ChunkSize) != 0) ) {
  141. Status = gBS->AllocatePool (
  142. EfiBootServicesData,
  143. BufferSize,
  144. (VOID**)&CompressedVariableData
  145. );
  146. ASSERT (CompressedVariableData != NULL);
  147. if (Status == EFI_SUCCESS) {
  148. CompressedBufferSize = BufferSize;
  149. Status = Compress(HobData, S3ChunkSize, CompressedVariableData, &CompressedBufferSize);
  150. if (Status == EFI_BUFFER_TOO_SMALL){
  151. gBS->FreePool(CompressedVariableData);
  152. Status = gBS->AllocatePool(
  153. EfiBootServicesData,
  154. CompressedBufferSize,
  155. (VOID**)&CompressedVariableData
  156. );
  157. ASSERT (CompressedVariableData != NULL);
  158. Status = Compress(HobData, S3ChunkSize, CompressedVariableData, &CompressedBufferSize);
  159. }
  160. if(Status == EFI_SUCCESS) {
  161. Status = gRT->SetVariable (
  162. EfiMemoryConfigVariable,
  163. &gEfiMemoryConfigDataGuid,
  164. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
  165. CompressedBufferSize,
  166. CompressedVariableData
  167. );
  168. }
  169. if(CompressedVariableData != NULL) {
  170. gBS->FreePool(CompressedVariableData);
  171. CompressedVariableData = NULL;
  172. }
  173. }
  174. if (EFI_ERROR (Status)) {
  175. DEBUG((EFI_D_ERROR, "Set variable error. Status: 0x%x\n", Status));
  176. ASSERT_EFI_ERROR (Status);
  177. }
  178. }
  179. //
  180. // Lock the Memory Config Variable
  181. //
  182. Status = VariableLock->RequestToLock(VariableLock, EfiMemoryConfigVariable, &gEfiMemoryConfigDataGuid);
  183. ASSERT_EFI_ERROR(Status);
  184. HobData = (UINT8 *) (HobData) + S3ChunkSize;
  185. CurrentHobSize -= S3ChunkSize;
  186. EfiMemoryConfigVariable[12]++; // Increment number in the string
  187. }
  188. //
  189. // Get next S3 Config data hob, if none left, results NULL
  190. //
  191. GuidHob = GET_NEXT_HOB (GuidHob); // Increment to next HOB
  192. GuidHob = GetNextGuidHob (&gEfiMemoryConfigDataHobGuid, GuidHob); // Now search for next MemConfig HOB
  193. if(VariableData != NULL) {
  194. gBS->FreePool(VariableData);
  195. VariableData = NULL;
  196. }
  197. }
  198. return;
  199. }
  200. EFI_STATUS
  201. EFIAPI
  202. S3NvramSaveEntry (
  203. IN EFI_HANDLE ImageHandle,
  204. IN EFI_SYSTEM_TABLE *SystemTable
  205. )
  206. /**
  207. This is the main entry point of the S3 NVRAM Save module.
  208. @param ImageHandle - Handle for the image of this driver.
  209. @param SystemTable - Pointer to the EFI System Table.
  210. @retval EFI_SUCCESS - Module launched successfully.
  211. **/
  212. {
  213. EFI_STATUS Status = EFI_SUCCESS;
  214. //
  215. // Save the s3 strututre from MRC into NVRAM if needed
  216. //
  217. SaveS3StructToNvram();
  218. return Status;
  219. }