TianoCore EDK2 master
Loading...
Searching...
No Matches
VariableNonVolatile.c
Go to the documentation of this file.
1
10#include "VariableParsing.h"
11
12extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
13
22 VOID
23 )
24{
25 if (PcdGet32 (PcdHwErrStorageSize) != 0) {
26 return MAX (
27 MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)),
28 PcdGet32 (PcdMaxHardwareErrorVariableSize)
29 );
30 } else {
31 return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize));
32 }
33}
34
46 OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase
47 )
48{
49 VARIABLE_STORE_HEADER *VariableStore;
50 UINT32 VariableStoreLength;
51 BOOLEAN FullyInitializeStore;
52 UINT32 HwErrStorageSize;
53
54 FullyInitializeStore = TRUE;
55
56 VariableStoreLength = PcdGet32 (PcdVariableStoreSize);
57 ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);
58
59 //
60 // Allocate memory for variable store.
61 //
62 if (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0) {
63 VariableStore = (VARIABLE_STORE_HEADER *)AllocateRuntimePool (VariableStoreLength);
64 if (VariableStore == NULL) {
65 return EFI_OUT_OF_RESOURCES;
66 }
67 } else {
68 //
69 // A memory location has been reserved for the NV variable store. Certain
70 // platforms may be able to preserve a memory range across system resets,
71 // thereby providing better NV variable emulation.
72 //
73 VariableStore =
74 (VARIABLE_STORE_HEADER *)(VOID *)(UINTN)
75 PcdGet64 (PcdEmuVariableNvStoreReserved);
76 if ((VariableStore->Size == VariableStoreLength) &&
77 (CompareGuid (&VariableStore->Signature, &gEfiAuthenticatedVariableGuid) ||
78 CompareGuid (&VariableStore->Signature, &gEfiVariableGuid)) &&
79 (VariableStore->Format == VARIABLE_STORE_FORMATTED) &&
80 (VariableStore->State == VARIABLE_STORE_HEALTHY))
81 {
82 DEBUG ((
83 DEBUG_INFO,
84 "Variable Store reserved at %p appears to be valid\n",
85 VariableStore
86 ));
87 FullyInitializeStore = FALSE;
88 }
89 }
90
91 if (FullyInitializeStore) {
92 SetMem (VariableStore, VariableStoreLength, 0xff);
93 //
94 // Use gEfiAuthenticatedVariableGuid for potential auth variable support.
95 //
96 CopyGuid (&VariableStore->Signature, &gEfiAuthenticatedVariableGuid);
97 VariableStore->Size = VariableStoreLength;
98 VariableStore->Format = VARIABLE_STORE_FORMATTED;
99 VariableStore->State = VARIABLE_STORE_HEALTHY;
100 VariableStore->Reserved = 0;
101 VariableStore->Reserved1 = 0;
102 }
103
104 *VariableStoreBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore;
105
106 HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);
107
108 //
109 // Note that in EdkII variable driver implementation, Hardware Error Record type variable
110 // is stored with common variable in the same NV region. So the platform integrator should
111 // ensure that the value of PcdHwErrStorageSize is less than the value of
112 // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
113 //
114 ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
115
116 mVariableModuleGlobal->CommonVariableSpace = ((UINTN)VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize);
117 mVariableModuleGlobal->CommonMaxUserVariableSpace = mVariableModuleGlobal->CommonVariableSpace;
118 mVariableModuleGlobal->CommonRuntimeVariableSpace = mVariableModuleGlobal->CommonVariableSpace;
119
120 return EFI_SUCCESS;
121}
122
135 OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase
136 )
137{
139 VARIABLE_STORE_HEADER *VariableStore;
140 UINT32 VariableStoreLength;
141 EFI_HOB_GUID_TYPE *GuidHob;
142 EFI_PHYSICAL_ADDRESS NvStorageBase;
143 UINT8 *NvStorageData;
144 UINT32 NvStorageSize;
145 UINT64 NvStorageSize64;
146 FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
147 UINT32 BackUpOffset;
148 UINT32 BackUpSize;
149 UINT32 HwErrStorageSize;
150 UINT32 MaxUserNvVariableSpaceSize;
151 UINT32 BoottimeReservedNvVariableSpaceSize;
152 EFI_STATUS Status;
153 VOID *FtwProtocol;
154
155 mVariableModuleGlobal->FvbInstance = NULL;
156
157 Status = GetVariableFlashNvStorageInfo (&NvStorageBase, &NvStorageSize64);
158 ASSERT_EFI_ERROR (Status);
159
160 Status = SafeUint64ToUint32 (NvStorageSize64, &NvStorageSize);
161 // This driver currently assumes the size will be UINT32 so assert the value is safe for now.
162 ASSERT_EFI_ERROR (Status);
163
164 ASSERT (NvStorageBase != 0);
165
166 //
167 // Allocate runtime memory used for a memory copy of the FLASH region.
168 // Keep the memory and the FLASH in sync as updates occur.
169 //
170 NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
171 if (NvStorageData == NULL) {
172 return EFI_OUT_OF_RESOURCES;
173 }
174
175 //
176 // Copy NV storage data to the memory buffer.
177 //
178 CopyMem (NvStorageData, (UINT8 *)(UINTN)NvStorageBase, NvStorageSize);
179
180 Status = GetFtwProtocol ((VOID **)&FtwProtocol);
181 //
182 // If FTW protocol has been installed, no need to check FTW last write data hob.
183 //
184 if (EFI_ERROR (Status)) {
185 //
186 // Check the FTW last write data hob.
187 //
188 GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
189 if (GuidHob != NULL) {
190 FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *)GET_GUID_HOB_DATA (GuidHob);
191 if (FtwLastWriteData->TargetAddress == NvStorageBase) {
192 DEBUG ((DEBUG_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN)FtwLastWriteData->SpareAddress));
193 //
194 // Copy the backed up NV storage data to the memory buffer from spare block.
195 //
196 CopyMem (NvStorageData, (UINT8 *)(UINTN)(FtwLastWriteData->SpareAddress), NvStorageSize);
197 } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&
198 (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize)))
199 {
200 //
201 // Flash NV storage from the Offset is backed up in spare block.
202 //
203 BackUpOffset = (UINT32)(FtwLastWriteData->TargetAddress - NvStorageBase);
204 BackUpSize = NvStorageSize - BackUpOffset;
205 DEBUG ((DEBUG_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN)FtwLastWriteData->SpareAddress));
206 //
207 // Copy the partial backed up NV storage data to the memory buffer from spare block.
208 //
209 CopyMem (NvStorageData + BackUpOffset, (UINT8 *)(UINTN)FtwLastWriteData->SpareAddress, BackUpSize);
210 }
211 }
212 }
213
214 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NvStorageData;
215
216 //
217 // Check if the Firmware Volume is not corrupted
218 //
219 if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
220 FreePool (NvStorageData);
221 DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
222 return EFI_VOLUME_CORRUPTED;
223 }
224
225 VariableStore = (VARIABLE_STORE_HEADER *)((UINTN)FvHeader + FvHeader->HeaderLength);
226 VariableStoreLength = NvStorageSize - FvHeader->HeaderLength;
227 ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);
228 ASSERT (VariableStore->Size == VariableStoreLength);
229
230 //
231 // Check if the Variable Store header is not corrupted
232 //
233 if (GetVariableStoreStatus (VariableStore) != EfiValid) {
234 FreePool (NvStorageData);
235 DEBUG ((DEBUG_ERROR, "Variable Store header is corrupted\n"));
236 return EFI_VOLUME_CORRUPTED;
237 }
238
239 mNvFvHeaderCache = FvHeader;
240
241 *VariableStoreBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore;
242
243 HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);
244 MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize);
245 BoottimeReservedNvVariableSpaceSize = PcdGet32 (PcdBoottimeReservedNvVariableSpaceSize);
246
247 //
248 // Note that in EdkII variable driver implementation, Hardware Error Record type variable
249 // is stored with common variable in the same NV region. So the platform integrator should
250 // ensure that the value of PcdHwErrStorageSize is less than the value of
251 // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
252 //
253 ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
254 //
255 // Ensure that the value of PcdMaxUserNvVariableSpaceSize is less than the value of
256 // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
257 //
258 ASSERT (MaxUserNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
259 //
260 // Ensure that the value of PcdBoottimeReservedNvVariableSpaceSize is less than the value of
261 // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
262 //
263 ASSERT (BoottimeReservedNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
264
265 mVariableModuleGlobal->CommonVariableSpace = ((UINTN)VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize);
266 mVariableModuleGlobal->CommonMaxUserVariableSpace = ((MaxUserNvVariableSpaceSize != 0) ? MaxUserNvVariableSpaceSize : mVariableModuleGlobal->CommonVariableSpace);
267 mVariableModuleGlobal->CommonRuntimeVariableSpace = mVariableModuleGlobal->CommonVariableSpace - BoottimeReservedNvVariableSpaceSize;
268
269 DEBUG ((
270 DEBUG_INFO,
271 "Variable driver common space: 0x%x 0x%x 0x%x\n",
272 mVariableModuleGlobal->CommonVariableSpace,
273 mVariableModuleGlobal->CommonMaxUserVariableSpace,
274 mVariableModuleGlobal->CommonRuntimeVariableSpace
275 ));
276
277 //
278 // The max NV variable size should be < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
279 //
280 ASSERT (GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
281
282 return EFI_SUCCESS;
283}
284
295 VOID
296 )
297{
298 VARIABLE_HEADER *Variable;
299 VARIABLE_HEADER *NextVariable;
300 EFI_PHYSICAL_ADDRESS VariableStoreBase;
301 UINTN VariableSize;
302 EFI_STATUS Status;
303
304 if (PcdGetBool (PcdEmuVariableNvModeEnable)) {
305 Status = InitEmuNonVolatileVariableStore (&VariableStoreBase);
306 if (EFI_ERROR (Status)) {
307 return Status;
308 }
309
310 mVariableModuleGlobal->VariableGlobal.EmuNvMode = TRUE;
311 DEBUG ((DEBUG_INFO, "Variable driver will work at emulated non-volatile variable mode!\n"));
312 } else {
313 Status = InitRealNonVolatileVariableStore (&VariableStoreBase);
314 if (EFI_ERROR (Status)) {
315 return Status;
316 }
317
318 mVariableModuleGlobal->VariableGlobal.EmuNvMode = FALSE;
319 }
320
321 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
322 mNvVariableCache = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
323 mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));
324
325 mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize);
326 mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize);
327
328 //
329 // Parse non-volatile variable data and get last variable offset.
330 //
333 NextVariable = GetNextVariablePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat);
334 VariableSize = (UINTN)NextVariable - (UINTN)Variable;
336 mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
337 } else {
338 mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
339 }
340
341 Variable = NextVariable;
342 }
343
344 mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN)Variable - (UINTN)mNvVariableCache;
345
346 return EFI_SUCCESS;
347}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateRuntimePool(IN UINTN AllocationSize)
VOID *EFIAPI AllocateRuntimeZeroPool(IN UINTN AllocationSize)
EFI_STATUS GetFtwProtocol(OUT VOID **FtwProtocol)
Definition: VariableDxe.c:150
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
RETURN_STATUS EFIAPI SafeUint64ToUint32(IN UINT64 Operand, OUT UINT32 *Result)
Definition: SafeIntLib.c:2698
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD
#define EFI_VARIABLE_NON_VOLATILE
VARIABLE_HEADER * GetStartPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:86
VARIABLE_STORE_STATUS GetVariableStoreStatus(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:372
VARIABLE_HEADER * GetEndPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:109
BOOLEAN IsValidVariableHeader(IN VARIABLE_HEADER *Variable)
Definition: Variable.c:129
VARIABLE_HEADER * GetNextVariablePtr(IN VARIABLE_STORE_INFO *StoreInfo, IN VARIABLE_HEADER *Variable, IN VARIABLE_HEADER *VariableHeader)
Definition: Variable.c:329
EFI_FIRMWARE_VOLUME_HEADER * mNvFvHeaderCache
Definition: Variable.c:44
VARIABLE_STORE_HEADER * mNvVariableCache
Definition: Variable.c:39
EFI_STATUS EFIAPI GetVariableFlashNvStorageInfo(OUT EFI_PHYSICAL_ADDRESS *BaseAddress, OUT UINT64 *Length)
#define VARIABLE_STORE_FORMATTED
EFI_STATUS InitRealNonVolatileVariableStore(OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase)
EFI_STATUS InitNonVolatileVariableStore(VOID)
EFI_STATUS InitEmuNonVolatileVariableStore(OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase)
UINTN GetNonVolatileMaxVariableSize(VOID)