OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
VariableNonVolatile.c
Go to the documentation of this file.
1
10#include "VariableParsing.h"
11
13
20UINTN
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
44EFI_STATUS
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);
119
120 return EFI_SUCCESS;
121}
122
133EFI_STATUS
135 OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase
136 )
137{
138 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
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 FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
146 UINT32 BackUpOffset;
147 UINT32 BackUpSize;
148 UINT32 HwErrStorageSize;
149 UINT32 MaxUserNvVariableSpaceSize;
150 UINT32 BoottimeReservedNvVariableSpaceSize;
151 EFI_STATUS Status;
152 VOID *FtwProtocol;
153
155
156 //
157 // Allocate runtime memory used for a memory copy of the FLASH region.
158 // Keep the memory and the FLASH in sync as updates occur.
159 //
160 NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
161 NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
162 if (NvStorageData == NULL) {
163 return EFI_OUT_OF_RESOURCES;
164 }
165
166 NvStorageBase = NV_STORAGE_VARIABLE_BASE;
167 ASSERT (NvStorageBase != 0);
168
169 //
170 // Copy NV storage data to the memory buffer.
171 //
172 CopyMem (NvStorageData, (UINT8 *)(UINTN)NvStorageBase, NvStorageSize);
173
174 Status = GetFtwProtocol ((VOID **)&FtwProtocol);
175 //
176 // If FTW protocol has been installed, no need to check FTW last write data hob.
177 //
178 if (EFI_ERROR (Status)) {
179 //
180 // Check the FTW last write data hob.
181 //
182 GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
183 if (GuidHob != NULL) {
184 FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *)GET_GUID_HOB_DATA (GuidHob);
185 if (FtwLastWriteData->TargetAddress == NvStorageBase) {
186 DEBUG ((DEBUG_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN)FtwLastWriteData->SpareAddress));
187 //
188 // Copy the backed up NV storage data to the memory buffer from spare block.
189 //
190 CopyMem (NvStorageData, (UINT8 *)(UINTN)(FtwLastWriteData->SpareAddress), NvStorageSize);
191 } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&
192 (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize)))
193 {
194 //
195 // Flash NV storage from the Offset is backed up in spare block.
196 //
197 BackUpOffset = (UINT32)(FtwLastWriteData->TargetAddress - NvStorageBase);
198 BackUpSize = NvStorageSize - BackUpOffset;
199 DEBUG ((DEBUG_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN)FtwLastWriteData->SpareAddress));
200 //
201 // Copy the partial backed up NV storage data to the memory buffer from spare block.
202 //
203 CopyMem (NvStorageData + BackUpOffset, (UINT8 *)(UINTN)FtwLastWriteData->SpareAddress, BackUpSize);
204 }
205 }
206 }
207
208 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NvStorageData;
209
210 //
211 // Check if the Firmware Volume is not corrupted
212 //
213 if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
214 FreePool (NvStorageData);
215 DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
216 return EFI_VOLUME_CORRUPTED;
217 }
218
219 VariableStore = (VARIABLE_STORE_HEADER *)((UINTN)FvHeader + FvHeader->HeaderLength);
220 VariableStoreLength = NvStorageSize - FvHeader->HeaderLength;
221 ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);
222 ASSERT (VariableStore->Size == VariableStoreLength);
223
224 //
225 // Check if the Variable Store header is not corrupted
226 //
227 if (GetVariableStoreStatus (VariableStore) != EfiValid) {
228 FreePool (NvStorageData);
229 DEBUG ((DEBUG_ERROR, "Variable Store header is corrupted\n"));
230 return EFI_VOLUME_CORRUPTED;
231 }
232
233 mNvFvHeaderCache = FvHeader;
234
235 *VariableStoreBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore;
236
237 HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);
238 MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize);
239 BoottimeReservedNvVariableSpaceSize = PcdGet32 (PcdBoottimeReservedNvVariableSpaceSize);
240
241 //
242 // Note that in EdkII variable driver implementation, Hardware Error Record type variable
243 // is stored with common variable in the same NV region. So the platform integrator should
244 // ensure that the value of PcdHwErrStorageSize is less than the value of
245 // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
246 //
247 ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
248 //
249 // Ensure that the value of PcdMaxUserNvVariableSpaceSize is less than the value of
250 // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
251 //
252 ASSERT (MaxUserNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
253 //
254 // Ensure that the value of PcdBoottimeReservedNvVariableSpaceSize is less than the value of
255 // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
256 //
257 ASSERT (BoottimeReservedNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
258
259 mVariableModuleGlobal->CommonVariableSpace = ((UINTN)VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize);
260 mVariableModuleGlobal->CommonMaxUserVariableSpace = ((MaxUserNvVariableSpaceSize != 0) ? MaxUserNvVariableSpaceSize : mVariableModuleGlobal->CommonVariableSpace);
262
263 DEBUG ((
264 DEBUG_INFO,
265 "Variable driver common space: 0x%x 0x%x 0x%x\n",
269 ));
270
271 //
272 // The max NV variable size should be < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
273 //
274 ASSERT (GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
275
276 return EFI_SUCCESS;
277}
278
287EFI_STATUS
289 VOID
290 )
291{
292 VARIABLE_HEADER *Variable;
293 VARIABLE_HEADER *NextVariable;
294 EFI_PHYSICAL_ADDRESS VariableStoreBase;
295 UINTN VariableSize;
296 EFI_STATUS Status;
297
298 if (PcdGetBool (PcdEmuVariableNvModeEnable)) {
299 Status = InitEmuNonVolatileVariableStore (&VariableStoreBase);
300 if (EFI_ERROR (Status)) {
301 return Status;
302 }
303
305 DEBUG ((DEBUG_INFO, "Variable driver will work at emulated non-volatile variable mode!\n"));
306 } else {
307 Status = InitRealNonVolatileVariableStore (&VariableStoreBase);
308 if (EFI_ERROR (Status)) {
309 return Status;
310 }
311
313 }
314
316 mNvVariableCache = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
317 mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));
318
319 mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize);
320 mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize);
321
322 //
323 // Parse non-volatile variable data and get last variable offset.
324 //
328 VariableSize = (UINTN)NextVariable - (UINTN)Variable;
329 if ((Variable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
331 } else {
333 }
334
335 Variable = NextVariable;
336 }
337
339
340 return EFI_SUCCESS;
341}
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)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition UserMisc.c:671
EFI_FIRMWARE_VOLUME_HEADER * mNvFvHeaderCache
Definition Variable.c:46
VARIABLE_STORE_HEADER * mNvVariableCache
Definition Variable.c:41
EFI_STATUS GetFtwProtocol(OUT VOID **FtwProtocol)
#define NV_STORAGE_VARIABLE_BASE
Definition Variable.h:43
EFI_STATUS InitRealNonVolatileVariableStore(OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase)
EFI_STATUS InitNonVolatileVariableStore(VOID)
EFI_STATUS InitEmuNonVolatileVariableStore(OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase)
UINTN GetNonVolatileMaxVariableSize(VOID)
VARIABLE_MODULE_GLOBAL * mVariableModuleGlobal
Definition Variable.c:35
VARIABLE_HEADER * GetNextVariablePtr(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFormat)
VARIABLE_HEADER * GetStartPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
VARIABLE_STORE_STATUS GetVariableStoreStatus(IN VARIABLE_STORE_HEADER *VarStoreHeader)
BOOLEAN IsValidVariableHeader(IN VARIABLE_HEADER *Variable, IN VARIABLE_HEADER *VariableStoreEnd)
VARIABLE_HEADER * GetEndPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
#define ASSERT(x)
Definition coder.h:55
#define MAX(a, b)
Definition coder.h:59
BOOLEAN AuthFormat
Definition Variable.h:103
BOOLEAN EmuNvMode
Definition Variable.h:105
EFI_PHYSICAL_ADDRESS NonVolatileVariableBase
Definition Variable.h:99
VARIABLE_GLOBAL VariableGlobal
Definition Variable.h:109
UINTN NonVolatileLastVariableOffset
Definition Variable.h:111
UINTN CommonMaxUserVariableSpace
Definition Variable.h:113
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL * FvbInstance
Definition Variable.h:126
UINTN CommonRuntimeVariableSpace
Definition Variable.h:114