1 | /* $Id: EmuVariable.c 43212 2012-09-06 05:49:10Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * EmuVariable.c
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2012 Oracle Corporation
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
10 | * available from http://www.virtualbox.org. This file is free software;
|
---|
11 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
12 | * General Public License (GPL) as published by the Free Software
|
---|
13 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
16 | */
|
---|
17 |
|
---|
18 | /** @file
|
---|
19 | Sample ACPI Platform Driver
|
---|
20 |
|
---|
21 | Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
|
---|
22 | This program and the accompanying materials
|
---|
23 | are licensed and made available under the terms and conditions of the BSD License
|
---|
24 | which accompanies this distribution. The full text of the license may be found at
|
---|
25 | http://opensource.org/licenses/bsd-license.php
|
---|
26 |
|
---|
27 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
---|
28 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
---|
29 |
|
---|
30 | **/
|
---|
31 | /** @file
|
---|
32 |
|
---|
33 | Emulation Variable services operate on the runtime volatile memory.
|
---|
34 | The nonvolatile variable space doesn't exist.
|
---|
35 |
|
---|
36 | Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
---|
37 | This program and the accompanying materials
|
---|
38 | are licensed and made available under the terms and conditions of the BSD License
|
---|
39 | which accompanies this distribution. The full text of the license may be found at
|
---|
40 | http://opensource.org/licenses/bsd-license.php
|
---|
41 |
|
---|
42 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
---|
43 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
---|
44 |
|
---|
45 | **/
|
---|
46 |
|
---|
47 | #include "Variable.h"
|
---|
48 |
|
---|
49 | ///
|
---|
50 | /// Don't use module globals after the SetVirtualAddress map is signaled
|
---|
51 | ///
|
---|
52 | ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
|
---|
53 |
|
---|
54 | VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
|
---|
55 |
|
---|
56 | ///
|
---|
57 | /// The size of a 3 character ISO639 language code.
|
---|
58 | ///
|
---|
59 | #define ISO_639_2_ENTRY_SIZE 3
|
---|
60 |
|
---|
61 | /**
|
---|
62 | Update the variable region with Variable information. These are the same
|
---|
63 | arguments as the EFI Variable services.
|
---|
64 |
|
---|
65 | @param[in] VariableName Name of variable
|
---|
66 |
|
---|
67 | @param[in] VendorGuid Guid of variable
|
---|
68 |
|
---|
69 | @param[in] Data Variable data
|
---|
70 |
|
---|
71 | @param[in] DataSize Size of data. 0 means delete
|
---|
72 |
|
---|
73 | @param[in] Attributes Attribues of the variable
|
---|
74 |
|
---|
75 | @param[in] Variable The variable information which is used to keep track of variable usage.
|
---|
76 |
|
---|
77 | @retval EFI_SUCCESS The update operation is success.
|
---|
78 |
|
---|
79 | @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.
|
---|
80 |
|
---|
81 | **/
|
---|
82 | EFI_STATUS
|
---|
83 | EFIAPI
|
---|
84 | UpdateVariable (
|
---|
85 | IN CHAR16 *VariableName,
|
---|
86 | IN EFI_GUID *VendorGuid,
|
---|
87 | IN VOID *Data,
|
---|
88 | IN UINTN DataSize,
|
---|
89 | IN UINT32 Attributes OPTIONAL,
|
---|
90 | IN VARIABLE_POINTER_TRACK *Variable
|
---|
91 | );
|
---|
92 |
|
---|
93 | /**
|
---|
94 | Finds variable in storage blocks of volatile and non-volatile storage areas.
|
---|
95 |
|
---|
96 | This code finds variable in storage blocks of volatile and non-volatile storage areas.
|
---|
97 | If VariableName is an empty string, then we just return the first
|
---|
98 | qualified variable without comparing VariableName and VendorGuid.
|
---|
99 | Otherwise, VariableName and VendorGuid are compared.
|
---|
100 |
|
---|
101 | @param VariableName Name of the variable to be found.
|
---|
102 | @param VendorGuid Vendor GUID to be found.
|
---|
103 | @param PtrTrack VARIABLE_POINTER_TRACK structure for output,
|
---|
104 | including the range searched and the target position.
|
---|
105 | @param Global Pointer to VARIABLE_GLOBAL structure, including
|
---|
106 | base of volatile variable storage area, base of
|
---|
107 | NV variable storage area, and a lock.
|
---|
108 |
|
---|
109 | @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
|
---|
110 | VendorGuid is NULL.
|
---|
111 | @retval EFI_SUCCESS Variable successfully found.
|
---|
112 | @retval EFI_NOT_FOUND Variable not found.
|
---|
113 |
|
---|
114 | **/
|
---|
115 | EFI_STATUS
|
---|
116 | FindVariable (
|
---|
117 | IN CHAR16 *VariableName,
|
---|
118 | IN EFI_GUID *VendorGuid,
|
---|
119 | OUT VARIABLE_POINTER_TRACK *PtrTrack,
|
---|
120 | IN VARIABLE_GLOBAL *Global
|
---|
121 | );
|
---|
122 |
|
---|
123 | /**
|
---|
124 | Acquires lock only at boot time. Simply returns at runtime.
|
---|
125 |
|
---|
126 | This is a temperary function which will be removed when
|
---|
127 | EfiAcquireLock() in UefiLib can handle the call in UEFI
|
---|
128 | Runtimer driver in RT phase.
|
---|
129 | It calls EfiAcquireLock() at boot time, and simply returns
|
---|
130 | at runtime
|
---|
131 |
|
---|
132 | @param Lock A pointer to the lock to acquire
|
---|
133 |
|
---|
134 | **/
|
---|
135 | VOID
|
---|
136 | AcquireLockOnlyAtBootTime (
|
---|
137 | IN EFI_LOCK *Lock
|
---|
138 | )
|
---|
139 | {
|
---|
140 | if (!EfiAtRuntime ()) {
|
---|
141 | EfiAcquireLock (Lock);
|
---|
142 | }
|
---|
143 | }
|
---|
144 |
|
---|
145 | /**
|
---|
146 | Releases lock only at boot time. Simply returns at runtime.
|
---|
147 |
|
---|
148 | This is a temperary function which will be removed when
|
---|
149 | EfiReleaseLock() in UefiLib can handle the call in UEFI
|
---|
150 | Runtimer driver in RT phase.
|
---|
151 | It calls EfiReleaseLock() at boot time, and simply returns
|
---|
152 | at runtime
|
---|
153 |
|
---|
154 | @param Lock A pointer to the lock to release
|
---|
155 |
|
---|
156 | **/
|
---|
157 | VOID
|
---|
158 | ReleaseLockOnlyAtBootTime (
|
---|
159 | IN EFI_LOCK *Lock
|
---|
160 | )
|
---|
161 | {
|
---|
162 | if (!EfiAtRuntime ()) {
|
---|
163 | EfiReleaseLock (Lock);
|
---|
164 | }
|
---|
165 | }
|
---|
166 |
|
---|
167 | /**
|
---|
168 | Gets pointer to the variable data.
|
---|
169 |
|
---|
170 | This function gets the pointer to the variable data according
|
---|
171 | to the input pointer to the variable header.
|
---|
172 |
|
---|
173 | @param Variable Pointer to the variable header.
|
---|
174 |
|
---|
175 | @return Pointer to variable data
|
---|
176 |
|
---|
177 | **/
|
---|
178 | UINT8 *
|
---|
179 | GetVariableDataPtr (
|
---|
180 | IN VARIABLE_HEADER *Variable
|
---|
181 | )
|
---|
182 | {
|
---|
183 | if (Variable->StartId != VARIABLE_DATA) {
|
---|
184 | return NULL;
|
---|
185 | }
|
---|
186 | //
|
---|
187 | // Be careful about pad size for alignment
|
---|
188 | //
|
---|
189 | return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
|
---|
190 | }
|
---|
191 |
|
---|
192 | /**
|
---|
193 | Gets pointer to header of the next potential variable.
|
---|
194 |
|
---|
195 | This function gets the pointer to the next potential variable header
|
---|
196 | according to the input point to the variable header. The return value
|
---|
197 | is not a valid variable if the input variable was the last variable
|
---|
198 | in the variabl store.
|
---|
199 |
|
---|
200 | @param Variable Pointer to header of the next variable
|
---|
201 |
|
---|
202 | @return Pointer to next variable header.
|
---|
203 | @retval NULL Input was not a valid variable header.
|
---|
204 |
|
---|
205 | **/
|
---|
206 | VARIABLE_HEADER *
|
---|
207 | GetNextPotentialVariablePtr (
|
---|
208 | IN VARIABLE_HEADER *Variable
|
---|
209 | )
|
---|
210 | {
|
---|
211 | VARIABLE_HEADER *VarHeader;
|
---|
212 |
|
---|
213 | if (Variable->StartId != VARIABLE_DATA) {
|
---|
214 | return NULL;
|
---|
215 | }
|
---|
216 | //
|
---|
217 | // Be careful about pad size for alignment
|
---|
218 | //
|
---|
219 | VarHeader = (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
|
---|
220 |
|
---|
221 | return VarHeader;
|
---|
222 | }
|
---|
223 |
|
---|
224 | /**
|
---|
225 | Gets pointer to header of the next variable.
|
---|
226 |
|
---|
227 | This function gets the pointer to the next variable header according
|
---|
228 | to the input point to the variable header.
|
---|
229 |
|
---|
230 | @param Variable Pointer to header of the next variable
|
---|
231 |
|
---|
232 | @return Pointer to next variable header.
|
---|
233 |
|
---|
234 | **/
|
---|
235 | VARIABLE_HEADER *
|
---|
236 | GetNextVariablePtr (
|
---|
237 | IN VARIABLE_HEADER *Variable
|
---|
238 | )
|
---|
239 | {
|
---|
240 | VARIABLE_HEADER *VarHeader;
|
---|
241 |
|
---|
242 | VarHeader = GetNextPotentialVariablePtr (Variable);
|
---|
243 |
|
---|
244 | if ((VarHeader == NULL) || (VarHeader->StartId != VARIABLE_DATA)) {
|
---|
245 | return NULL;
|
---|
246 | }
|
---|
247 |
|
---|
248 | return VarHeader;
|
---|
249 | }
|
---|
250 |
|
---|
251 | /**
|
---|
252 | Updates LastVariableOffset variable for the given variable store.
|
---|
253 |
|
---|
254 | LastVariableOffset points to the offset to use for the next variable
|
---|
255 | when updating the variable store.
|
---|
256 |
|
---|
257 | @param[in] VariableStore Pointer to the start of the variable store
|
---|
258 | @param[out] LastVariableOffset Offset to put the next new variable in
|
---|
259 |
|
---|
260 | **/
|
---|
261 | VOID
|
---|
262 | InitializeLocationForLastVariableOffset (
|
---|
263 | IN VARIABLE_STORE_HEADER *VariableStore,
|
---|
264 | OUT UINTN *LastVariableOffset
|
---|
265 | )
|
---|
266 | {
|
---|
267 | VARIABLE_HEADER *VarHeader;
|
---|
268 |
|
---|
269 | *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);
|
---|
270 | VarHeader = (VARIABLE_HEADER*) ((UINT8*)VariableStore + *LastVariableOffset);
|
---|
271 | while (VarHeader->StartId == VARIABLE_DATA) {
|
---|
272 | VarHeader = GetNextPotentialVariablePtr (VarHeader);
|
---|
273 |
|
---|
274 | if (VarHeader != NULL) {
|
---|
275 | *LastVariableOffset = (UINTN) VarHeader - (UINTN) VariableStore;
|
---|
276 | } else {
|
---|
277 | return;
|
---|
278 | }
|
---|
279 | }
|
---|
280 | }
|
---|
281 |
|
---|
282 | /**
|
---|
283 | Gets pointer to the end of the variable storage area.
|
---|
284 |
|
---|
285 | This function gets pointer to the end of the variable storage
|
---|
286 | area, according to the input variable store header.
|
---|
287 |
|
---|
288 | @param VolHeader Pointer to the variale store header
|
---|
289 |
|
---|
290 | @return Pointer to the end of the variable storage area.
|
---|
291 |
|
---|
292 | **/
|
---|
293 | VARIABLE_HEADER *
|
---|
294 | GetEndPointer (
|
---|
295 | IN VARIABLE_STORE_HEADER *VolHeader
|
---|
296 | )
|
---|
297 | {
|
---|
298 | //
|
---|
299 | // The end of variable store
|
---|
300 | //
|
---|
301 | return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VolHeader + VolHeader->Size);
|
---|
302 | }
|
---|
303 |
|
---|
304 | /**
|
---|
305 | Routine used to track statistical information about variable usage.
|
---|
306 | The data is stored in the EFI system table so it can be accessed later.
|
---|
307 | VariableInfo.efi can dump out the table. Only Boot Services variable
|
---|
308 | accesses are tracked by this code. The PcdVariableCollectStatistics
|
---|
309 | build flag controls if this feature is enabled.
|
---|
310 |
|
---|
311 | A read that hits in the cache will have Read and Cache true for
|
---|
312 | the transaction. Data is allocated by this routine, but never
|
---|
313 | freed.
|
---|
314 |
|
---|
315 | @param[in] VariableName Name of the Variable to track
|
---|
316 | @param[in] VendorGuid Guid of the Variable to track
|
---|
317 | @param[in] Volatile TRUE if volatile FALSE if non-volatile
|
---|
318 | @param[in] Read TRUE if GetVariable() was called
|
---|
319 | @param[in] Write TRUE if SetVariable() was called
|
---|
320 | @param[in] Delete TRUE if deleted via SetVariable()
|
---|
321 | @param[in] Cache TRUE for a cache hit.
|
---|
322 |
|
---|
323 | **/
|
---|
324 | VOID
|
---|
325 | UpdateVariableInfo (
|
---|
326 | IN CHAR16 *VariableName,
|
---|
327 | IN EFI_GUID *VendorGuid,
|
---|
328 | IN BOOLEAN Volatile,
|
---|
329 | IN BOOLEAN Read,
|
---|
330 | IN BOOLEAN Write,
|
---|
331 | IN BOOLEAN Delete,
|
---|
332 | IN BOOLEAN Cache
|
---|
333 | )
|
---|
334 | {
|
---|
335 | VARIABLE_INFO_ENTRY *Entry;
|
---|
336 |
|
---|
337 | if (FeaturePcdGet (PcdVariableCollectStatistics)) {
|
---|
338 |
|
---|
339 | if (EfiAtRuntime ()) {
|
---|
340 | // Don't collect statistics at runtime
|
---|
341 | return;
|
---|
342 | }
|
---|
343 |
|
---|
344 | if (gVariableInfo == NULL) {
|
---|
345 | //
|
---|
346 | // on the first call allocate a entry and place a pointer to it in
|
---|
347 | // the EFI System Table
|
---|
348 | //
|
---|
349 | gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
|
---|
350 | ASSERT (gVariableInfo != NULL);
|
---|
351 |
|
---|
352 | CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);
|
---|
353 | gVariableInfo->Name = AllocatePool (StrSize (VariableName));
|
---|
354 | ASSERT (gVariableInfo->Name != NULL);
|
---|
355 | StrCpy (gVariableInfo->Name, VariableName);
|
---|
356 | gVariableInfo->Volatile = Volatile;
|
---|
357 |
|
---|
358 | gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
|
---|
359 | }
|
---|
360 |
|
---|
361 |
|
---|
362 | for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) {
|
---|
363 | if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {
|
---|
364 | if (StrCmp (VariableName, Entry->Name) == 0) {
|
---|
365 | if (Read) {
|
---|
366 | Entry->ReadCount++;
|
---|
367 | }
|
---|
368 | if (Write) {
|
---|
369 | Entry->WriteCount++;
|
---|
370 | }
|
---|
371 | if (Delete) {
|
---|
372 | Entry->DeleteCount++;
|
---|
373 | }
|
---|
374 | if (Cache) {
|
---|
375 | Entry->CacheCount++;
|
---|
376 | }
|
---|
377 |
|
---|
378 | return;
|
---|
379 | }
|
---|
380 | }
|
---|
381 |
|
---|
382 | if (Entry->Next == NULL) {
|
---|
383 | //
|
---|
384 | // If the entry is not in the table add it.
|
---|
385 | // Next iteration of the loop will fill in the data
|
---|
386 | //
|
---|
387 | Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
|
---|
388 | ASSERT (Entry->Next != NULL);
|
---|
389 |
|
---|
390 | CopyGuid (&Entry->Next->VendorGuid, VendorGuid);
|
---|
391 | Entry->Next->Name = AllocatePool (StrSize (VariableName));
|
---|
392 | ASSERT (Entry->Next->Name != NULL);
|
---|
393 | StrCpy (Entry->Next->Name, VariableName);
|
---|
394 | Entry->Next->Volatile = Volatile;
|
---|
395 | }
|
---|
396 |
|
---|
397 | }
|
---|
398 | }
|
---|
399 | }
|
---|
400 |
|
---|
401 | /**
|
---|
402 | Get index from supported language codes according to language string.
|
---|
403 |
|
---|
404 | This code is used to get corresponding index in supported language codes. It can handle
|
---|
405 | RFC4646 and ISO639 language tags.
|
---|
406 | In ISO639 language tags, take 3-characters as a delimitation to find matched string and calculate the index.
|
---|
407 | In RFC4646 language tags, take semicolon as a delimitation to find matched string and calculate the index.
|
---|
408 |
|
---|
409 | For example:
|
---|
410 | SupportedLang = "engfraengfra"
|
---|
411 | Lang = "eng"
|
---|
412 | Iso639Language = TRUE
|
---|
413 | The return value is "0".
|
---|
414 | Another example:
|
---|
415 | SupportedLang = "en;fr;en-US;fr-FR"
|
---|
416 | Lang = "fr-FR"
|
---|
417 | Iso639Language = FALSE
|
---|
418 | The return value is "3".
|
---|
419 |
|
---|
420 | @param SupportedLang Platform supported language codes.
|
---|
421 | @param Lang Configured language.
|
---|
422 | @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
|
---|
423 |
|
---|
424 | @retval the index of language in the language codes.
|
---|
425 |
|
---|
426 | **/
|
---|
427 | UINTN
|
---|
428 | GetIndexFromSupportedLangCodes(
|
---|
429 | IN CHAR8 *SupportedLang,
|
---|
430 | IN CHAR8 *Lang,
|
---|
431 | IN BOOLEAN Iso639Language
|
---|
432 | )
|
---|
433 | {
|
---|
434 | UINTN Index;
|
---|
435 | UINTN CompareLength;
|
---|
436 | UINTN LanguageLength;
|
---|
437 |
|
---|
438 | if (Iso639Language) {
|
---|
439 | CompareLength = ISO_639_2_ENTRY_SIZE;
|
---|
440 | for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {
|
---|
441 | if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {
|
---|
442 | //
|
---|
443 | // Successfully find the index of Lang string in SupportedLang string.
|
---|
444 | //
|
---|
445 | Index = Index / CompareLength;
|
---|
446 | return Index;
|
---|
447 | }
|
---|
448 | }
|
---|
449 | ASSERT (FALSE);
|
---|
450 | return 0;
|
---|
451 | } else {
|
---|
452 | //
|
---|
453 | // Compare RFC4646 language code
|
---|
454 | //
|
---|
455 | Index = 0;
|
---|
456 | for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++);
|
---|
457 |
|
---|
458 | for (Index = 0; *SupportedLang != '\0'; Index++, SupportedLang += CompareLength) {
|
---|
459 | //
|
---|
460 | // Skip ';' characters in SupportedLang
|
---|
461 | //
|
---|
462 | for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++);
|
---|
463 | //
|
---|
464 | // Determine the length of the next language code in SupportedLang
|
---|
465 | //
|
---|
466 | for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);
|
---|
467 |
|
---|
468 | if ((CompareLength == LanguageLength) &&
|
---|
469 | (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {
|
---|
470 | //
|
---|
471 | // Successfully find the index of Lang string in SupportedLang string.
|
---|
472 | //
|
---|
473 | return Index;
|
---|
474 | }
|
---|
475 | }
|
---|
476 | ASSERT (FALSE);
|
---|
477 | return 0;
|
---|
478 | }
|
---|
479 | }
|
---|
480 |
|
---|
481 | /**
|
---|
482 | Get language string from supported language codes according to index.
|
---|
483 |
|
---|
484 | This code is used to get corresponding language string in supported language codes. It can handle
|
---|
485 | RFC4646 and ISO639 language tags.
|
---|
486 | In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.
|
---|
487 | In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.
|
---|
488 |
|
---|
489 | For example:
|
---|
490 | SupportedLang = "engfraengfra"
|
---|
491 | Index = "1"
|
---|
492 | Iso639Language = TRUE
|
---|
493 | The return value is "fra".
|
---|
494 | Another example:
|
---|
495 | SupportedLang = "en;fr;en-US;fr-FR"
|
---|
496 | Index = "1"
|
---|
497 | Iso639Language = FALSE
|
---|
498 | The return value is "fr".
|
---|
499 |
|
---|
500 | @param SupportedLang Platform supported language codes.
|
---|
501 | @param Index the index in supported language codes.
|
---|
502 | @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
|
---|
503 |
|
---|
504 | @retval the language string in the language codes.
|
---|
505 |
|
---|
506 | **/
|
---|
507 | CHAR8 *
|
---|
508 | GetLangFromSupportedLangCodes (
|
---|
509 | IN CHAR8 *SupportedLang,
|
---|
510 | IN UINTN Index,
|
---|
511 | IN BOOLEAN Iso639Language
|
---|
512 | )
|
---|
513 | {
|
---|
514 | UINTN SubIndex;
|
---|
515 | UINTN CompareLength;
|
---|
516 | CHAR8 *Supported;
|
---|
517 |
|
---|
518 | SubIndex = 0;
|
---|
519 | Supported = SupportedLang;
|
---|
520 | if (Iso639Language) {
|
---|
521 | //
|
---|
522 | // according to the index of Lang string in SupportedLang string to get the language.
|
---|
523 | // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
|
---|
524 | // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
|
---|
525 | //
|
---|
526 | CompareLength = ISO_639_2_ENTRY_SIZE;
|
---|
527 | mVariableModuleGlobal->Lang[CompareLength] = '\0';
|
---|
528 | return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);
|
---|
529 |
|
---|
530 | } else {
|
---|
531 | while (TRUE) {
|
---|
532 | //
|
---|
533 | // take semicolon as delimitation, sequentially traverse supported language codes.
|
---|
534 | //
|
---|
535 | for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {
|
---|
536 | Supported++;
|
---|
537 | }
|
---|
538 | if ((*Supported == '\0') && (SubIndex != Index)) {
|
---|
539 | //
|
---|
540 | // Have completed the traverse, but not find corrsponding string.
|
---|
541 | // This case is not allowed to happen.
|
---|
542 | //
|
---|
543 | ASSERT(FALSE);
|
---|
544 | return NULL;
|
---|
545 | }
|
---|
546 | if (SubIndex == Index) {
|
---|
547 | //
|
---|
548 | // according to the index of Lang string in SupportedLang string to get the language.
|
---|
549 | // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
|
---|
550 | // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
|
---|
551 | //
|
---|
552 | mVariableModuleGlobal->PlatformLang[CompareLength] = '\0';
|
---|
553 | return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);
|
---|
554 | }
|
---|
555 | SubIndex++;
|
---|
556 |
|
---|
557 | //
|
---|
558 | // Skip ';' characters in Supported
|
---|
559 | //
|
---|
560 | for (; *Supported != '\0' && *Supported == ';'; Supported++);
|
---|
561 | }
|
---|
562 | }
|
---|
563 | }
|
---|
564 |
|
---|
565 | /**
|
---|
566 | Returns a pointer to an allocated buffer that contains the best matching language
|
---|
567 | from a set of supported languages.
|
---|
568 |
|
---|
569 | This function supports both ISO 639-2 and RFC 4646 language codes, but language
|
---|
570 | code types may not be mixed in a single call to this function. This function
|
---|
571 | supports a variable argument list that allows the caller to pass in a prioritized
|
---|
572 | list of language codes to test against all the language codes in SupportedLanguages.
|
---|
573 |
|
---|
574 | If SupportedLanguages is NULL, then ASSERT().
|
---|
575 |
|
---|
576 | @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that
|
---|
577 | contains a set of language codes in the format
|
---|
578 | specified by Iso639Language.
|
---|
579 | @param[in] Iso639Language If TRUE, then all language codes are assumed to be
|
---|
580 | in ISO 639-2 format. If FALSE, then all language
|
---|
581 | codes are assumed to be in RFC 4646 language format
|
---|
582 | @param[in] ... A variable argument list that contains pointers to
|
---|
583 | Null-terminated ASCII strings that contain one or more
|
---|
584 | language codes in the format specified by Iso639Language.
|
---|
585 | The first language code from each of these language
|
---|
586 | code lists is used to determine if it is an exact or
|
---|
587 | close match to any of the language codes in
|
---|
588 | SupportedLanguages. Close matches only apply to RFC 4646
|
---|
589 | language codes, and the matching algorithm from RFC 4647
|
---|
590 | is used to determine if a close match is present. If
|
---|
591 | an exact or close match is found, then the matching
|
---|
592 | language code from SupportedLanguages is returned. If
|
---|
593 | no matches are found, then the next variable argument
|
---|
594 | parameter is evaluated. The variable argument list
|
---|
595 | is terminated by a NULL.
|
---|
596 |
|
---|
597 | @retval NULL The best matching language could not be found in SupportedLanguages.
|
---|
598 | @retval NULL There are not enough resources available to return the best matching
|
---|
599 | language.
|
---|
600 | @retval Other A pointer to a Null-terminated ASCII string that is the best matching
|
---|
601 | language in SupportedLanguages.
|
---|
602 |
|
---|
603 | **/
|
---|
604 | CHAR8 *
|
---|
605 | EFIAPI
|
---|
606 | VariableGetBestLanguage (
|
---|
607 | IN CONST CHAR8 *SupportedLanguages,
|
---|
608 | IN BOOLEAN Iso639Language,
|
---|
609 | ...
|
---|
610 | )
|
---|
611 | {
|
---|
612 | VA_LIST Args;
|
---|
613 | CHAR8 *Language;
|
---|
614 | UINTN CompareLength;
|
---|
615 | UINTN LanguageLength;
|
---|
616 | CONST CHAR8 *Supported;
|
---|
617 | CHAR8 *Buffer;
|
---|
618 |
|
---|
619 | ASSERT (SupportedLanguages != NULL);
|
---|
620 |
|
---|
621 | VA_START (Args, Iso639Language);
|
---|
622 | while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {
|
---|
623 | //
|
---|
624 | // Default to ISO 639-2 mode
|
---|
625 | //
|
---|
626 | CompareLength = 3;
|
---|
627 | LanguageLength = MIN (3, AsciiStrLen (Language));
|
---|
628 |
|
---|
629 | //
|
---|
630 | // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language
|
---|
631 | //
|
---|
632 | if (!Iso639Language) {
|
---|
633 | for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
|
---|
634 | }
|
---|
635 |
|
---|
636 | //
|
---|
637 | // Trim back the length of Language used until it is empty
|
---|
638 | //
|
---|
639 | while (LanguageLength > 0) {
|
---|
640 | //
|
---|
641 | // Loop through all language codes in SupportedLanguages
|
---|
642 | //
|
---|
643 | for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
|
---|
644 | //
|
---|
645 | // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages
|
---|
646 | //
|
---|
647 | if (!Iso639Language) {
|
---|
648 | //
|
---|
649 | // Skip ';' characters in Supported
|
---|
650 | //
|
---|
651 | for (; *Supported != '\0' && *Supported == ';'; Supported++);
|
---|
652 | //
|
---|
653 | // Determine the length of the next language code in Supported
|
---|
654 | //
|
---|
655 | for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
|
---|
656 | //
|
---|
657 | // If Language is longer than the Supported, then skip to the next language
|
---|
658 | //
|
---|
659 | if (LanguageLength > CompareLength) {
|
---|
660 | continue;
|
---|
661 | }
|
---|
662 | }
|
---|
663 | //
|
---|
664 | // See if the first LanguageLength characters in Supported match Language
|
---|
665 | //
|
---|
666 | if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {
|
---|
667 | VA_END (Args);
|
---|
668 |
|
---|
669 | Buffer = Iso639Language ? mVariableModuleGlobal->Lang : mVariableModuleGlobal->PlatformLang;
|
---|
670 | Buffer[CompareLength] = '\0';
|
---|
671 | return CopyMem (Buffer, Supported, CompareLength);
|
---|
672 | }
|
---|
673 | }
|
---|
674 |
|
---|
675 | if (Iso639Language) {
|
---|
676 | //
|
---|
677 | // If ISO 639 mode, then each language can only be tested once
|
---|
678 | //
|
---|
679 | LanguageLength = 0;
|
---|
680 | } else {
|
---|
681 | //
|
---|
682 | // If RFC 4646 mode, then trim Language from the right to the next '-' character
|
---|
683 | //
|
---|
684 | for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
|
---|
685 | }
|
---|
686 | }
|
---|
687 | }
|
---|
688 | VA_END (Args);
|
---|
689 |
|
---|
690 | //
|
---|
691 | // No matches were found
|
---|
692 | //
|
---|
693 | return NULL;
|
---|
694 | }
|
---|
695 |
|
---|
696 | /**
|
---|
697 | Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.
|
---|
698 |
|
---|
699 | When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.
|
---|
700 |
|
---|
701 | According to UEFI spec, PlatformLangCodes/LangCodes are only set once in firmware initialization,
|
---|
702 | and are read-only. Therefore, in variable driver, only store the original value for other use.
|
---|
703 |
|
---|
704 | @param[in] VariableName Name of variable
|
---|
705 |
|
---|
706 | @param[in] Data Variable data
|
---|
707 |
|
---|
708 | @param[in] DataSize Size of data. 0 means delete
|
---|
709 |
|
---|
710 | **/
|
---|
711 | VOID
|
---|
712 | AutoUpdateLangVariable(
|
---|
713 | IN CHAR16 *VariableName,
|
---|
714 | IN VOID *Data,
|
---|
715 | IN UINTN DataSize
|
---|
716 | )
|
---|
717 | {
|
---|
718 | EFI_STATUS Status;
|
---|
719 | CHAR8 *BestPlatformLang;
|
---|
720 | CHAR8 *BestLang;
|
---|
721 | UINTN Index;
|
---|
722 | UINT32 Attributes;
|
---|
723 | VARIABLE_POINTER_TRACK Variable;
|
---|
724 | BOOLEAN SetLanguageCodes;
|
---|
725 |
|
---|
726 | //
|
---|
727 | // Don't do updates for delete operation
|
---|
728 | //
|
---|
729 | if (DataSize == 0) {
|
---|
730 | return;
|
---|
731 | }
|
---|
732 |
|
---|
733 | SetLanguageCodes = FALSE;
|
---|
734 |
|
---|
735 | if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {
|
---|
736 | //
|
---|
737 | // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
|
---|
738 | //
|
---|
739 | if (EfiAtRuntime ()) {
|
---|
740 | return;
|
---|
741 | }
|
---|
742 |
|
---|
743 | SetLanguageCodes = TRUE;
|
---|
744 |
|
---|
745 | //
|
---|
746 | // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only
|
---|
747 | // Therefore, in variable driver, only store the original value for other use.
|
---|
748 | //
|
---|
749 | if (mVariableModuleGlobal->PlatformLangCodes != NULL) {
|
---|
750 | FreePool (mVariableModuleGlobal->PlatformLangCodes);
|
---|
751 | }
|
---|
752 | mVariableModuleGlobal->PlatformLangCodes = AllocateRuntimeCopyPool (DataSize, Data);
|
---|
753 | ASSERT (mVariableModuleGlobal->PlatformLangCodes != NULL);
|
---|
754 |
|
---|
755 | //
|
---|
756 | // PlatformLang holds a single language from PlatformLangCodes,
|
---|
757 | // so the size of PlatformLangCodes is enough for the PlatformLang.
|
---|
758 | //
|
---|
759 | if (mVariableModuleGlobal->PlatformLang != NULL) {
|
---|
760 | FreePool (mVariableModuleGlobal->PlatformLang);
|
---|
761 | }
|
---|
762 | mVariableModuleGlobal->PlatformLang = AllocateRuntimePool (DataSize);
|
---|
763 | ASSERT (mVariableModuleGlobal->PlatformLang != NULL);
|
---|
764 |
|
---|
765 | } else if (StrCmp (VariableName, L"LangCodes") == 0) {
|
---|
766 | //
|
---|
767 | // LangCodes is a volatile variable, so it can not be updated at runtime.
|
---|
768 | //
|
---|
769 | if (EfiAtRuntime ()) {
|
---|
770 | return;
|
---|
771 | }
|
---|
772 |
|
---|
773 | SetLanguageCodes = TRUE;
|
---|
774 |
|
---|
775 | //
|
---|
776 | // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only
|
---|
777 | // Therefore, in variable driver, only store the original value for other use.
|
---|
778 | //
|
---|
779 | if (mVariableModuleGlobal->LangCodes != NULL) {
|
---|
780 | FreePool (mVariableModuleGlobal->LangCodes);
|
---|
781 | }
|
---|
782 | mVariableModuleGlobal->LangCodes = AllocateRuntimeCopyPool (DataSize, Data);
|
---|
783 | ASSERT (mVariableModuleGlobal->LangCodes != NULL);
|
---|
784 | }
|
---|
785 |
|
---|
786 | if (SetLanguageCodes
|
---|
787 | && (mVariableModuleGlobal->PlatformLangCodes != NULL)
|
---|
788 | && (mVariableModuleGlobal->LangCodes != NULL)) {
|
---|
789 | //
|
---|
790 | // Update Lang if PlatformLang is already set
|
---|
791 | // Update PlatformLang if Lang is already set
|
---|
792 | //
|
---|
793 | Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);
|
---|
794 | if (!EFI_ERROR (Status)) {
|
---|
795 | //
|
---|
796 | // Update Lang
|
---|
797 | //
|
---|
798 | VariableName = L"PlatformLang";
|
---|
799 | Data = GetVariableDataPtr (Variable.CurrPtr);
|
---|
800 | DataSize = Variable.CurrPtr->DataSize;
|
---|
801 | } else {
|
---|
802 | Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);
|
---|
803 | if (!EFI_ERROR (Status)) {
|
---|
804 | //
|
---|
805 | // Update PlatformLang
|
---|
806 | //
|
---|
807 | VariableName = L"Lang";
|
---|
808 | Data = GetVariableDataPtr (Variable.CurrPtr);
|
---|
809 | DataSize = Variable.CurrPtr->DataSize;
|
---|
810 | } else {
|
---|
811 | //
|
---|
812 | // Neither PlatformLang nor Lang is set, directly return
|
---|
813 | //
|
---|
814 | return;
|
---|
815 | }
|
---|
816 | }
|
---|
817 | }
|
---|
818 |
|
---|
819 | //
|
---|
820 | // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.
|
---|
821 | //
|
---|
822 | Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
|
---|
823 |
|
---|
824 | if (StrCmp (VariableName, L"PlatformLang") == 0) {
|
---|
825 | //
|
---|
826 | // Update Lang when PlatformLangCodes/LangCodes were set.
|
---|
827 | //
|
---|
828 | if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {
|
---|
829 | //
|
---|
830 | // When setting PlatformLang, firstly get most matched language string from supported language codes.
|
---|
831 | //
|
---|
832 | BestPlatformLang = VariableGetBestLanguage (mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);
|
---|
833 | if (BestPlatformLang != NULL) {
|
---|
834 | //
|
---|
835 | // Get the corresponding index in language codes.
|
---|
836 | //
|
---|
837 | Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);
|
---|
838 |
|
---|
839 | //
|
---|
840 | // Get the corresponding ISO639 language tag according to RFC4646 language tag.
|
---|
841 | //
|
---|
842 | BestLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, Index, TRUE);
|
---|
843 |
|
---|
844 | //
|
---|
845 | // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
|
---|
846 | //
|
---|
847 | FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);
|
---|
848 |
|
---|
849 | Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
|
---|
850 |
|
---|
851 | DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));
|
---|
852 |
|
---|
853 | ASSERT_EFI_ERROR(Status);
|
---|
854 | }
|
---|
855 | }
|
---|
856 |
|
---|
857 | } else if (StrCmp (VariableName, L"Lang") == 0) {
|
---|
858 | //
|
---|
859 | // Update PlatformLang when PlatformLangCodes/LangCodes were set.
|
---|
860 | //
|
---|
861 | if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {
|
---|
862 | //
|
---|
863 | // When setting Lang, firstly get most matched language string from supported language codes.
|
---|
864 | //
|
---|
865 | BestLang = VariableGetBestLanguage (mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);
|
---|
866 | if (BestLang != NULL) {
|
---|
867 | //
|
---|
868 | // Get the corresponding index in language codes.
|
---|
869 | //
|
---|
870 | Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, BestLang, TRUE);
|
---|
871 |
|
---|
872 | //
|
---|
873 | // Get the corresponding RFC4646 language tag according to ISO639 language tag.
|
---|
874 | //
|
---|
875 | BestPlatformLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);
|
---|
876 |
|
---|
877 | //
|
---|
878 | // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
|
---|
879 | //
|
---|
880 | FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);
|
---|
881 |
|
---|
882 | Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,
|
---|
883 | AsciiStrSize (BestPlatformLang), Attributes, &Variable);
|
---|
884 |
|
---|
885 | DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));
|
---|
886 | ASSERT_EFI_ERROR (Status);
|
---|
887 | }
|
---|
888 | }
|
---|
889 | }
|
---|
890 | }
|
---|
891 |
|
---|
892 | /**
|
---|
893 | Update the variable region with Variable information. These are the same
|
---|
894 | arguments as the EFI Variable services.
|
---|
895 |
|
---|
896 | @param[in] VariableName Name of variable
|
---|
897 |
|
---|
898 | @param[in] VendorGuid Guid of variable
|
---|
899 |
|
---|
900 | @param[in] Data Variable data
|
---|
901 |
|
---|
902 | @param[in] DataSize Size of data. 0 means delete
|
---|
903 |
|
---|
904 | @param[in] Attributes Attribues of the variable
|
---|
905 |
|
---|
906 | @param[in] Variable The variable information which is used to keep track of variable usage.
|
---|
907 |
|
---|
908 | @retval EFI_SUCCESS The update operation is success.
|
---|
909 |
|
---|
910 | @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.
|
---|
911 |
|
---|
912 | **/
|
---|
913 | EFI_STATUS
|
---|
914 | EFIAPI
|
---|
915 | UpdateVariable (
|
---|
916 | IN CHAR16 *VariableName,
|
---|
917 | IN EFI_GUID *VendorGuid,
|
---|
918 | IN VOID *Data,
|
---|
919 | IN UINTN DataSize,
|
---|
920 | IN UINT32 Attributes OPTIONAL,
|
---|
921 | IN VARIABLE_POINTER_TRACK *Variable
|
---|
922 | )
|
---|
923 | {
|
---|
924 | EFI_STATUS Status;
|
---|
925 | VARIABLE_HEADER *NextVariable;
|
---|
926 | UINTN VarNameSize;
|
---|
927 | UINTN VarNameOffset;
|
---|
928 | UINTN VarDataOffset;
|
---|
929 | UINTN VarSize;
|
---|
930 | VARIABLE_GLOBAL *Global;
|
---|
931 | UINTN NonVolatileVarableStoreSize;
|
---|
932 |
|
---|
933 | Global = &mVariableModuleGlobal->VariableGlobal[Physical];
|
---|
934 |
|
---|
935 | if (Variable->CurrPtr != NULL) {
|
---|
936 | //
|
---|
937 | // Update/Delete existing variable
|
---|
938 | //
|
---|
939 |
|
---|
940 | if (EfiAtRuntime ()) {
|
---|
941 | //
|
---|
942 | // If EfiAtRuntime and the variable is Volatile and Runtime Access,
|
---|
943 | // the volatile is ReadOnly, and SetVariable should be aborted and
|
---|
944 | // return EFI_WRITE_PROTECTED.
|
---|
945 | //
|
---|
946 | if (Variable->Volatile) {
|
---|
947 | Status = EFI_WRITE_PROTECTED;
|
---|
948 | goto Done;
|
---|
949 | }
|
---|
950 | //
|
---|
951 | // Only variable have NV attribute can be updated/deleted in Runtime
|
---|
952 | //
|
---|
953 | if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
|
---|
954 | Status = EFI_INVALID_PARAMETER;
|
---|
955 | goto Done;
|
---|
956 | }
|
---|
957 | }
|
---|
958 |
|
---|
959 | //
|
---|
960 | // Setting a data variable with no access, or zero DataSize attributes
|
---|
961 | // specified causes it to be deleted.
|
---|
962 | //
|
---|
963 | if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
|
---|
964 | Variable->CurrPtr->State &= VAR_DELETED;
|
---|
965 | UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
|
---|
966 | Status = EFI_SUCCESS;
|
---|
967 | goto Done;
|
---|
968 | }
|
---|
969 |
|
---|
970 | //
|
---|
971 | // If the variable is marked valid and the same data has been passed in
|
---|
972 | // then return to the caller immediately.
|
---|
973 | //
|
---|
974 | if (Variable->CurrPtr->DataSize == DataSize &&
|
---|
975 | CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0
|
---|
976 | ) {
|
---|
977 | Status = EFI_SUCCESS;
|
---|
978 | goto Done;
|
---|
979 | } else if (Variable->CurrPtr->State == VAR_ADDED) {
|
---|
980 | //
|
---|
981 | // Mark the old variable as in delete transition
|
---|
982 | //
|
---|
983 | Variable->CurrPtr->State &= VAR_IN_DELETED_TRANSITION;
|
---|
984 | }
|
---|
985 |
|
---|
986 | } else {
|
---|
987 | //
|
---|
988 | // No found existing variable, Create a new variable
|
---|
989 | //
|
---|
990 |
|
---|
991 | //
|
---|
992 | // Make sure we are trying to create a new variable.
|
---|
993 | // Setting a data variable with no access, or zero DataSize attributes means to delete it.
|
---|
994 | //
|
---|
995 | if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
|
---|
996 | Status = EFI_NOT_FOUND;
|
---|
997 | goto Done;
|
---|
998 | }
|
---|
999 |
|
---|
1000 | //
|
---|
1001 | // Only variable have NV|RT attribute can be created in Runtime
|
---|
1002 | //
|
---|
1003 | if (EfiAtRuntime () &&
|
---|
1004 | (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {
|
---|
1005 | Status = EFI_INVALID_PARAMETER;
|
---|
1006 | goto Done;
|
---|
1007 | }
|
---|
1008 | }
|
---|
1009 |
|
---|
1010 | //
|
---|
1011 | // Function part - create a new variable and copy the data.
|
---|
1012 | // Both update a variable and create a variable will come here.
|
---|
1013 | //
|
---|
1014 |
|
---|
1015 | VarNameOffset = sizeof (VARIABLE_HEADER);
|
---|
1016 | VarNameSize = StrSize (VariableName);
|
---|
1017 | VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
|
---|
1018 | VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
|
---|
1019 |
|
---|
1020 | if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
|
---|
1021 | NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(Global->NonVolatileVariableBase))->Size;
|
---|
1022 | if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
|
---|
1023 | && ((HEADER_ALIGN (VarSize) + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
|
---|
1024 | || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)
|
---|
1025 | && ((HEADER_ALIGN (VarSize) + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {
|
---|
1026 | Status = EFI_OUT_OF_RESOURCES;
|
---|
1027 | goto Done;
|
---|
1028 | }
|
---|
1029 |
|
---|
1030 | NextVariable = (VARIABLE_HEADER *) (UINT8 *) (mVariableModuleGlobal->NonVolatileLastVariableOffset
|
---|
1031 | + (UINTN) Global->NonVolatileVariableBase);
|
---|
1032 | mVariableModuleGlobal->NonVolatileLastVariableOffset += HEADER_ALIGN (VarSize);
|
---|
1033 |
|
---|
1034 | if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
|
---|
1035 | mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VarSize);
|
---|
1036 | } else {
|
---|
1037 | mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VarSize);
|
---|
1038 | }
|
---|
1039 | } else {
|
---|
1040 | if ((UINT32) (HEADER_ALIGN (VarSize) + mVariableModuleGlobal->VolatileLastVariableOffset) >
|
---|
1041 | ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
|
---|
1042 | ) {
|
---|
1043 | Status = EFI_OUT_OF_RESOURCES;
|
---|
1044 | goto Done;
|
---|
1045 | }
|
---|
1046 |
|
---|
1047 | NextVariable = (VARIABLE_HEADER *) (UINT8 *) (mVariableModuleGlobal->VolatileLastVariableOffset
|
---|
1048 | + (UINTN) Global->VolatileVariableBase);
|
---|
1049 | mVariableModuleGlobal->VolatileLastVariableOffset += HEADER_ALIGN (VarSize);
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | NextVariable->StartId = VARIABLE_DATA;
|
---|
1053 | NextVariable->Attributes = Attributes;
|
---|
1054 | NextVariable->State = VAR_ADDED;
|
---|
1055 | NextVariable->Reserved = 0;
|
---|
1056 |
|
---|
1057 | //
|
---|
1058 | // There will be pad bytes after Data, the NextVariable->NameSize and
|
---|
1059 | // NextVariable->NameSize should not include pad size so that variable
|
---|
1060 | // service can get actual size in GetVariable
|
---|
1061 | //
|
---|
1062 | NextVariable->NameSize = (UINT32)VarNameSize;
|
---|
1063 | NextVariable->DataSize = (UINT32)DataSize;
|
---|
1064 |
|
---|
1065 | CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));
|
---|
1066 | CopyMem (
|
---|
1067 | (UINT8 *) ((UINTN) NextVariable + VarNameOffset),
|
---|
1068 | VariableName,
|
---|
1069 | VarNameSize
|
---|
1070 | );
|
---|
1071 | CopyMem (
|
---|
1072 | (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
|
---|
1073 | Data,
|
---|
1074 | DataSize
|
---|
1075 | );
|
---|
1076 |
|
---|
1077 | //
|
---|
1078 | // Mark the old variable as deleted
|
---|
1079 | //
|
---|
1080 | if (Variable->CurrPtr != NULL) {
|
---|
1081 | Variable->CurrPtr->State &= VAR_DELETED;
|
---|
1082 | }
|
---|
1083 |
|
---|
1084 | UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
|
---|
1085 |
|
---|
1086 | Status = EFI_SUCCESS;
|
---|
1087 |
|
---|
1088 | Done:
|
---|
1089 | return Status;
|
---|
1090 | }
|
---|
1091 |
|
---|
1092 | /**
|
---|
1093 | Finds variable in storage blocks of volatile and non-volatile storage areas.
|
---|
1094 |
|
---|
1095 | This code finds variable in storage blocks of volatile and non-volatile storage areas.
|
---|
1096 | If VariableName is an empty string, then we just return the first
|
---|
1097 | qualified variable without comparing VariableName and VendorGuid.
|
---|
1098 | Otherwise, VariableName and VendorGuid are compared.
|
---|
1099 |
|
---|
1100 | @param VariableName Name of the variable to be found.
|
---|
1101 | @param VendorGuid Vendor GUID to be found.
|
---|
1102 | @param PtrTrack VARIABLE_POINTER_TRACK structure for output,
|
---|
1103 | including the range searched and the target position.
|
---|
1104 | @param Global Pointer to VARIABLE_GLOBAL structure, including
|
---|
1105 | base of volatile variable storage area, base of
|
---|
1106 | NV variable storage area, and a lock.
|
---|
1107 |
|
---|
1108 | @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
|
---|
1109 | VendorGuid is NULL.
|
---|
1110 | @retval EFI_SUCCESS Variable successfully found.
|
---|
1111 | @retval EFI_NOT_FOUND Variable not found.
|
---|
1112 |
|
---|
1113 | **/
|
---|
1114 | EFI_STATUS
|
---|
1115 | FindVariable (
|
---|
1116 | IN CHAR16 *VariableName,
|
---|
1117 | IN EFI_GUID *VendorGuid,
|
---|
1118 | OUT VARIABLE_POINTER_TRACK *PtrTrack,
|
---|
1119 | IN VARIABLE_GLOBAL *Global
|
---|
1120 | )
|
---|
1121 | {
|
---|
1122 | VARIABLE_HEADER *Variable[2];
|
---|
1123 | VARIABLE_STORE_HEADER *VariableStoreHeader[2];
|
---|
1124 | UINTN Index;
|
---|
1125 |
|
---|
1126 | //
|
---|
1127 | // 0: Non-Volatile, 1: Volatile
|
---|
1128 | //
|
---|
1129 | VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
|
---|
1130 | VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
|
---|
1131 |
|
---|
1132 | //
|
---|
1133 | // Start Pointers for the variable.
|
---|
1134 | // Actual Data Pointer where data can be written.
|
---|
1135 | //
|
---|
1136 | Variable[0] = (VARIABLE_HEADER *) HEADER_ALIGN (VariableStoreHeader[0] + 1);
|
---|
1137 | Variable[1] = (VARIABLE_HEADER *) HEADER_ALIGN (VariableStoreHeader[1] + 1);
|
---|
1138 |
|
---|
1139 | if (VariableName[0] != 0 && VendorGuid == NULL) {
|
---|
1140 | return EFI_INVALID_PARAMETER;
|
---|
1141 | }
|
---|
1142 | //
|
---|
1143 | // Find the variable by walk through non-volatile and volatile variable store
|
---|
1144 | //
|
---|
1145 | for (Index = 0; Index < 2; Index++) {
|
---|
1146 | PtrTrack->StartPtr = (VARIABLE_HEADER *) HEADER_ALIGN (VariableStoreHeader[Index] + 1);
|
---|
1147 | PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
|
---|
1148 |
|
---|
1149 | while ((Variable[Index] < GetEndPointer (VariableStoreHeader[Index])) && (Variable[Index] != NULL)) {
|
---|
1150 | if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) {
|
---|
1151 | if (!(EfiAtRuntime () && ((Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0))) {
|
---|
1152 | if (VariableName[0] == 0) {
|
---|
1153 | PtrTrack->CurrPtr = Variable[Index];
|
---|
1154 | PtrTrack->Volatile = (BOOLEAN) Index;
|
---|
1155 | return EFI_SUCCESS;
|
---|
1156 | } else {
|
---|
1157 | if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {
|
---|
1158 | if (CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize) == 0) {
|
---|
1159 | PtrTrack->CurrPtr = Variable[Index];
|
---|
1160 | PtrTrack->Volatile = (BOOLEAN) Index;
|
---|
1161 | return EFI_SUCCESS;
|
---|
1162 | }
|
---|
1163 | }
|
---|
1164 | }
|
---|
1165 | }
|
---|
1166 | }
|
---|
1167 |
|
---|
1168 | Variable[Index] = GetNextVariablePtr (Variable[Index]);
|
---|
1169 | }
|
---|
1170 | }
|
---|
1171 | PtrTrack->CurrPtr = NULL;
|
---|
1172 | return EFI_NOT_FOUND;
|
---|
1173 | }
|
---|
1174 |
|
---|
1175 | /**
|
---|
1176 | This code finds variable in storage blocks (Volatile or Non-Volatile).
|
---|
1177 |
|
---|
1178 | @param VariableName A Null-terminated Unicode string that is the name of
|
---|
1179 | the vendor's variable.
|
---|
1180 | @param VendorGuid A unique identifier for the vendor.
|
---|
1181 | @param Attributes If not NULL, a pointer to the memory location to return the
|
---|
1182 | attributes bitmask for the variable.
|
---|
1183 | @param DataSize Size of Data found. If size is less than the
|
---|
1184 | data, this value contains the required size.
|
---|
1185 | @param Data On input, the size in bytes of the return Data buffer.
|
---|
1186 | On output, the size of data returned in Data.
|
---|
1187 | @param Global Pointer to VARIABLE_GLOBAL structure
|
---|
1188 |
|
---|
1189 | @retval EFI_SUCCESS The function completed successfully.
|
---|
1190 | @retval EFI_NOT_FOUND The variable was not found.
|
---|
1191 | @retval EFI_BUFFER_TOO_SMALL DataSize is too small for the result. DataSize has
|
---|
1192 | been updated with the size needed to complete the request.
|
---|
1193 | @retval EFI_INVALID_PARAMETER VariableName or VendorGuid or DataSize is NULL.
|
---|
1194 |
|
---|
1195 | **/
|
---|
1196 | EFI_STATUS
|
---|
1197 | EFIAPI
|
---|
1198 | EmuGetVariable (
|
---|
1199 | IN CHAR16 *VariableName,
|
---|
1200 | IN EFI_GUID *VendorGuid,
|
---|
1201 | OUT UINT32 *Attributes OPTIONAL,
|
---|
1202 | IN OUT UINTN *DataSize,
|
---|
1203 | OUT VOID *Data,
|
---|
1204 | IN VARIABLE_GLOBAL *Global
|
---|
1205 | )
|
---|
1206 | {
|
---|
1207 | VARIABLE_POINTER_TRACK Variable;
|
---|
1208 | UINTN VarDataSize;
|
---|
1209 | EFI_STATUS Status;
|
---|
1210 | UINT8 *VariableDataPtr;
|
---|
1211 |
|
---|
1212 | if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
|
---|
1213 | return EFI_INVALID_PARAMETER;
|
---|
1214 | }
|
---|
1215 |
|
---|
1216 | AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
|
---|
1217 |
|
---|
1218 | //
|
---|
1219 | // Find existing variable
|
---|
1220 | //
|
---|
1221 | Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
|
---|
1222 |
|
---|
1223 | if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
|
---|
1224 | goto Done;
|
---|
1225 | }
|
---|
1226 | //
|
---|
1227 | // Get data size
|
---|
1228 | //
|
---|
1229 | VarDataSize = Variable.CurrPtr->DataSize;
|
---|
1230 | if (*DataSize >= VarDataSize) {
|
---|
1231 | if (Data == NULL) {
|
---|
1232 | Status = EFI_INVALID_PARAMETER;
|
---|
1233 | goto Done;
|
---|
1234 | }
|
---|
1235 | VariableDataPtr = GetVariableDataPtr (Variable.CurrPtr);
|
---|
1236 | ASSERT (VariableDataPtr != NULL);
|
---|
1237 |
|
---|
1238 | CopyMem (Data, VariableDataPtr, VarDataSize);
|
---|
1239 | if (Attributes != NULL) {
|
---|
1240 | *Attributes = Variable.CurrPtr->Attributes;
|
---|
1241 | }
|
---|
1242 |
|
---|
1243 | *DataSize = VarDataSize;
|
---|
1244 | UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);
|
---|
1245 | Status = EFI_SUCCESS;
|
---|
1246 | goto Done;
|
---|
1247 | } else {
|
---|
1248 | *DataSize = VarDataSize;
|
---|
1249 | Status = EFI_BUFFER_TOO_SMALL;
|
---|
1250 | goto Done;
|
---|
1251 | }
|
---|
1252 |
|
---|
1253 | Done:
|
---|
1254 | ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
|
---|
1255 | return Status;
|
---|
1256 | }
|
---|
1257 |
|
---|
1258 | /**
|
---|
1259 |
|
---|
1260 | This code Finds the Next available variable.
|
---|
1261 |
|
---|
1262 | @param VariableNameSize Size of the variable.
|
---|
1263 | @param VariableName On input, supplies the last VariableName that was returned by GetNextVariableName().
|
---|
1264 | On output, returns the Null-terminated Unicode string of the current variable.
|
---|
1265 | @param VendorGuid On input, supplies the last VendorGuid that was returned by GetNextVariableName().
|
---|
1266 | On output, returns the VendorGuid of the current variable.
|
---|
1267 | @param Global Pointer to VARIABLE_GLOBAL structure.
|
---|
1268 |
|
---|
1269 | @retval EFI_SUCCESS The function completed successfully.
|
---|
1270 | @retval EFI_NOT_FOUND The next variable was not found.
|
---|
1271 | @retval EFI_BUFFER_TOO_SMALL VariableNameSize is too small for the result.
|
---|
1272 | VariableNameSize has been updated with the size needed to complete the request.
|
---|
1273 | @retval EFI_INVALID_PARAMETER VariableNameSize or VariableName or VendorGuid is NULL.
|
---|
1274 |
|
---|
1275 | **/
|
---|
1276 | EFI_STATUS
|
---|
1277 | EFIAPI
|
---|
1278 | EmuGetNextVariableName (
|
---|
1279 | IN OUT UINTN *VariableNameSize,
|
---|
1280 | IN OUT CHAR16 *VariableName,
|
---|
1281 | IN OUT EFI_GUID *VendorGuid,
|
---|
1282 | IN VARIABLE_GLOBAL *Global
|
---|
1283 | )
|
---|
1284 | {
|
---|
1285 | VARIABLE_POINTER_TRACK Variable;
|
---|
1286 | UINTN VarNameSize;
|
---|
1287 | EFI_STATUS Status;
|
---|
1288 |
|
---|
1289 | if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
|
---|
1290 | return EFI_INVALID_PARAMETER;
|
---|
1291 | }
|
---|
1292 |
|
---|
1293 | AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
|
---|
1294 |
|
---|
1295 | Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
|
---|
1296 |
|
---|
1297 | if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
|
---|
1298 | goto Done;
|
---|
1299 | }
|
---|
1300 |
|
---|
1301 | while (TRUE) {
|
---|
1302 | if (VariableName[0] != 0) {
|
---|
1303 | //
|
---|
1304 | // If variable name is not NULL, get next variable
|
---|
1305 | //
|
---|
1306 | Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
|
---|
1307 | }
|
---|
1308 | //
|
---|
1309 | // If both volatile and non-volatile variable store are parsed,
|
---|
1310 | // return not found
|
---|
1311 | //
|
---|
1312 | if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {
|
---|
1313 | Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));
|
---|
1314 | if (Variable.Volatile) {
|
---|
1315 | Variable.StartPtr = (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));
|
---|
1316 | Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));
|
---|
1317 | } else {
|
---|
1318 | Status = EFI_NOT_FOUND;
|
---|
1319 | goto Done;
|
---|
1320 | }
|
---|
1321 |
|
---|
1322 | Variable.CurrPtr = Variable.StartPtr;
|
---|
1323 | if (Variable.CurrPtr->StartId != VARIABLE_DATA) {
|
---|
1324 | continue;
|
---|
1325 | }
|
---|
1326 | }
|
---|
1327 | //
|
---|
1328 | // Variable is found
|
---|
1329 | //
|
---|
1330 | if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) {
|
---|
1331 | if (!(EfiAtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0))) {
|
---|
1332 | VarNameSize = Variable.CurrPtr->NameSize;
|
---|
1333 | if (VarNameSize <= *VariableNameSize) {
|
---|
1334 | CopyMem (
|
---|
1335 | VariableName,
|
---|
1336 | GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
|
---|
1337 | VarNameSize
|
---|
1338 | );
|
---|
1339 | CopyMem (
|
---|
1340 | VendorGuid,
|
---|
1341 | &Variable.CurrPtr->VendorGuid,
|
---|
1342 | sizeof (EFI_GUID)
|
---|
1343 | );
|
---|
1344 | Status = EFI_SUCCESS;
|
---|
1345 | } else {
|
---|
1346 | Status = EFI_BUFFER_TOO_SMALL;
|
---|
1347 | }
|
---|
1348 |
|
---|
1349 | *VariableNameSize = VarNameSize;
|
---|
1350 | goto Done;
|
---|
1351 | }
|
---|
1352 | }
|
---|
1353 | }
|
---|
1354 |
|
---|
1355 | Done:
|
---|
1356 | ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
|
---|
1357 | return Status;
|
---|
1358 |
|
---|
1359 | }
|
---|
1360 |
|
---|
1361 | /**
|
---|
1362 |
|
---|
1363 | This code sets variable in storage blocks (Volatile or Non-Volatile).
|
---|
1364 |
|
---|
1365 | @param VariableName A Null-terminated Unicode string that is the name of the vendor's
|
---|
1366 | variable. Each VariableName is unique for each
|
---|
1367 | VendorGuid. VariableName must contain 1 or more
|
---|
1368 | Unicode characters. If VariableName is an empty Unicode
|
---|
1369 | string, then EFI_INVALID_PARAMETER is returned.
|
---|
1370 | @param VendorGuid A unique identifier for the vendor
|
---|
1371 | @param Attributes Attributes bitmask to set for the variable
|
---|
1372 | @param DataSize The size in bytes of the Data buffer. A size of zero causes the
|
---|
1373 | variable to be deleted.
|
---|
1374 | @param Data The contents for the variable
|
---|
1375 | @param Global Pointer to VARIABLE_GLOBAL structure
|
---|
1376 | @param VolatileOffset The offset of last volatile variable
|
---|
1377 | @param NonVolatileOffset The offset of last non-volatile variable
|
---|
1378 |
|
---|
1379 | @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
|
---|
1380 | defined by the Attributes.
|
---|
1381 | @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied, or the
|
---|
1382 | DataSize exceeds the maximum allowed, or VariableName is an empty
|
---|
1383 | Unicode string, or VendorGuid is NULL.
|
---|
1384 | @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
---|
1385 | @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure.
|
---|
1386 | @retval EFI_WRITE_PROTECTED The variable in question is read-only or cannot be deleted.
|
---|
1387 | @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
|
---|
1388 |
|
---|
1389 | **/
|
---|
1390 | EFI_STATUS
|
---|
1391 | EFIAPI
|
---|
1392 | EmuSetVariable (
|
---|
1393 | IN CHAR16 *VariableName,
|
---|
1394 | IN EFI_GUID *VendorGuid,
|
---|
1395 | IN UINT32 Attributes,
|
---|
1396 | IN UINTN DataSize,
|
---|
1397 | IN VOID *Data,
|
---|
1398 | IN VARIABLE_GLOBAL *Global,
|
---|
1399 | IN UINTN *VolatileOffset,
|
---|
1400 | IN UINTN *NonVolatileOffset
|
---|
1401 | )
|
---|
1402 | {
|
---|
1403 | VARIABLE_POINTER_TRACK Variable;
|
---|
1404 | EFI_STATUS Status;
|
---|
1405 |
|
---|
1406 | //
|
---|
1407 | // Check input parameters
|
---|
1408 | //
|
---|
1409 | if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
|
---|
1410 | return EFI_INVALID_PARAMETER;
|
---|
1411 | }
|
---|
1412 |
|
---|
1413 | if (DataSize != 0 && Data == NULL) {
|
---|
1414 | return EFI_INVALID_PARAMETER;
|
---|
1415 | }
|
---|
1416 |
|
---|
1417 | //
|
---|
1418 | // Not support authenticated variable write yet.
|
---|
1419 | //
|
---|
1420 | if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
---|
1421 | return EFI_INVALID_PARAMETER;
|
---|
1422 | }
|
---|
1423 |
|
---|
1424 | //
|
---|
1425 | // Make sure if runtime bit is set, boot service bit is set also
|
---|
1426 | //
|
---|
1427 | if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
|
---|
1428 | return EFI_INVALID_PARAMETER;
|
---|
1429 | }
|
---|
1430 | //
|
---|
1431 | // The size of the VariableName, including the Unicode Null in bytes plus
|
---|
1432 | // the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)
|
---|
1433 | // bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.
|
---|
1434 | //
|
---|
1435 | if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
|
---|
1436 | if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||
|
---|
1437 | (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {
|
---|
1438 | return EFI_INVALID_PARAMETER;
|
---|
1439 | }
|
---|
1440 | //
|
---|
1441 | // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX"
|
---|
1442 | //
|
---|
1443 | if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {
|
---|
1444 | return EFI_INVALID_PARAMETER;
|
---|
1445 | }
|
---|
1446 | } else {
|
---|
1447 | //
|
---|
1448 | // The size of the VariableName, including the Unicode Null in bytes plus
|
---|
1449 | // the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
|
---|
1450 | //
|
---|
1451 | if ((DataSize > PcdGet32 (PcdMaxVariableSize)) ||
|
---|
1452 | (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) {
|
---|
1453 | return EFI_INVALID_PARAMETER;
|
---|
1454 | }
|
---|
1455 | }
|
---|
1456 |
|
---|
1457 | AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
|
---|
1458 |
|
---|
1459 | //
|
---|
1460 | // Check whether the input variable is already existed
|
---|
1461 | //
|
---|
1462 |
|
---|
1463 | Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
|
---|
1464 |
|
---|
1465 | //
|
---|
1466 | // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang
|
---|
1467 | //
|
---|
1468 | AutoUpdateLangVariable (VariableName, Data, DataSize);
|
---|
1469 |
|
---|
1470 | Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);
|
---|
1471 |
|
---|
1472 | ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
|
---|
1473 | return Status;
|
---|
1474 | }
|
---|
1475 |
|
---|
1476 | /**
|
---|
1477 |
|
---|
1478 | This code returns information about the EFI variables.
|
---|
1479 |
|
---|
1480 | @param Attributes Attributes bitmask to specify the type of variables
|
---|
1481 | on which to return information.
|
---|
1482 | @param MaximumVariableStorageSize On output the maximum size of the storage space available for
|
---|
1483 | the EFI variables associated with the attributes specified.
|
---|
1484 | @param RemainingVariableStorageSize Returns the remaining size of the storage space available for EFI
|
---|
1485 | variables associated with the attributes specified.
|
---|
1486 | @param MaximumVariableSize Returns the maximum size of an individual EFI variable
|
---|
1487 | associated with the attributes specified.
|
---|
1488 | @param Global Pointer to VARIABLE_GLOBAL structure.
|
---|
1489 |
|
---|
1490 | @retval EFI_SUCCESS Valid answer returned.
|
---|
1491 | @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied
|
---|
1492 | @retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the
|
---|
1493 | MaximumVariableStorageSize, RemainingVariableStorageSize,
|
---|
1494 | MaximumVariableSize are undefined.
|
---|
1495 |
|
---|
1496 | **/
|
---|
1497 | EFI_STATUS
|
---|
1498 | EFIAPI
|
---|
1499 | EmuQueryVariableInfo (
|
---|
1500 | IN UINT32 Attributes,
|
---|
1501 | OUT UINT64 *MaximumVariableStorageSize,
|
---|
1502 | OUT UINT64 *RemainingVariableStorageSize,
|
---|
1503 | OUT UINT64 *MaximumVariableSize,
|
---|
1504 | IN VARIABLE_GLOBAL *Global
|
---|
1505 | )
|
---|
1506 | {
|
---|
1507 | VARIABLE_HEADER *Variable;
|
---|
1508 | VARIABLE_HEADER *NextVariable;
|
---|
1509 | UINT64 VariableSize;
|
---|
1510 | VARIABLE_STORE_HEADER *VariableStoreHeader;
|
---|
1511 | UINT64 CommonVariableTotalSize;
|
---|
1512 | UINT64 HwErrVariableTotalSize;
|
---|
1513 |
|
---|
1514 | CommonVariableTotalSize = 0;
|
---|
1515 | HwErrVariableTotalSize = 0;
|
---|
1516 |
|
---|
1517 | if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
|
---|
1518 | return EFI_INVALID_PARAMETER;
|
---|
1519 | }
|
---|
1520 |
|
---|
1521 | if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
|
---|
1522 | //
|
---|
1523 | // Make sure the Attributes combination is supported by the platform.
|
---|
1524 | //
|
---|
1525 | return EFI_UNSUPPORTED;
|
---|
1526 | } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
|
---|
1527 | //
|
---|
1528 | // Make sure if runtime bit is set, boot service bit is set also.
|
---|
1529 | //
|
---|
1530 | return EFI_INVALID_PARAMETER;
|
---|
1531 | } else if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
|
---|
1532 | //
|
---|
1533 | // Make sure RT Attribute is set if we are in Runtime phase.
|
---|
1534 | //
|
---|
1535 | return EFI_INVALID_PARAMETER;
|
---|
1536 | } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
|
---|
1537 | //
|
---|
1538 | // Make sure Hw Attribute is set with NV.
|
---|
1539 | //
|
---|
1540 | return EFI_INVALID_PARAMETER;
|
---|
1541 | } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
---|
1542 | //
|
---|
1543 | // Not support authentiated variable write yet.
|
---|
1544 | //
|
---|
1545 | return EFI_UNSUPPORTED;
|
---|
1546 | }
|
---|
1547 |
|
---|
1548 | AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
|
---|
1549 |
|
---|
1550 | if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
|
---|
1551 | //
|
---|
1552 | // Query is Volatile related.
|
---|
1553 | //
|
---|
1554 | VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
|
---|
1555 | } else {
|
---|
1556 | //
|
---|
1557 | // Query is Non-Volatile related.
|
---|
1558 | //
|
---|
1559 | VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
|
---|
1560 | }
|
---|
1561 |
|
---|
1562 | //
|
---|
1563 | // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
|
---|
1564 | // with the storage size (excluding the storage header size)
|
---|
1565 | //
|
---|
1566 | *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
|
---|
1567 |
|
---|
1568 | //
|
---|
1569 | // Harware error record variable needs larger size.
|
---|
1570 | //
|
---|
1571 | if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
|
---|
1572 | *MaximumVariableStorageSize = PcdGet32 (PcdHwErrStorageSize);
|
---|
1573 | *MaximumVariableSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);
|
---|
1574 | } else {
|
---|
1575 | if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
|
---|
1576 | ASSERT (PcdGet32 (PcdHwErrStorageSize) < VariableStoreHeader->Size);
|
---|
1577 | *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize);
|
---|
1578 | }
|
---|
1579 |
|
---|
1580 | //
|
---|
1581 | // Let *MaximumVariableSize be PcdGet32 (PcdMaxVariableSize) with the exception of the variable header size.
|
---|
1582 | //
|
---|
1583 | *MaximumVariableSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);
|
---|
1584 | }
|
---|
1585 |
|
---|
1586 | //
|
---|
1587 | // Point to the starting address of the variables.
|
---|
1588 | //
|
---|
1589 | Variable = (VARIABLE_HEADER *) HEADER_ALIGN (VariableStoreHeader + 1);
|
---|
1590 |
|
---|
1591 | //
|
---|
1592 | // Now walk through the related variable store.
|
---|
1593 | //
|
---|
1594 | while (Variable < GetEndPointer (VariableStoreHeader)) {
|
---|
1595 | NextVariable = GetNextVariablePtr(Variable);
|
---|
1596 | if (NextVariable == NULL) {
|
---|
1597 | break;
|
---|
1598 | }
|
---|
1599 | VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
|
---|
1600 |
|
---|
1601 | if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
|
---|
1602 | HwErrVariableTotalSize += VariableSize;
|
---|
1603 | } else {
|
---|
1604 | CommonVariableTotalSize += VariableSize;
|
---|
1605 | }
|
---|
1606 |
|
---|
1607 | //
|
---|
1608 | // Go to the next one.
|
---|
1609 | //
|
---|
1610 | Variable = NextVariable;
|
---|
1611 | }
|
---|
1612 |
|
---|
1613 | if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD){
|
---|
1614 | *RemainingVariableStorageSize = *MaximumVariableStorageSize - HwErrVariableTotalSize;
|
---|
1615 | } else {
|
---|
1616 | *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;
|
---|
1617 | }
|
---|
1618 |
|
---|
1619 | if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {
|
---|
1620 | *MaximumVariableSize = 0;
|
---|
1621 | } else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {
|
---|
1622 | *MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);
|
---|
1623 | }
|
---|
1624 |
|
---|
1625 | ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
|
---|
1626 | return EFI_SUCCESS;
|
---|
1627 | }
|
---|
1628 |
|
---|
1629 | /**
|
---|
1630 | Initializes variable store area.
|
---|
1631 |
|
---|
1632 | This function allocates memory space for variable store area and initializes its attributes.
|
---|
1633 |
|
---|
1634 | @param VolatileStore Indicates if the variable store is volatile.
|
---|
1635 |
|
---|
1636 | **/
|
---|
1637 | EFI_STATUS
|
---|
1638 | InitializeVariableStore (
|
---|
1639 | IN BOOLEAN VolatileStore
|
---|
1640 | )
|
---|
1641 | {
|
---|
1642 | EFI_STATUS Status;
|
---|
1643 | VARIABLE_STORE_HEADER *VariableStore;
|
---|
1644 | BOOLEAN FullyInitializeStore;
|
---|
1645 | EFI_PHYSICAL_ADDRESS *VariableBase;
|
---|
1646 | UINTN *LastVariableOffset;
|
---|
1647 | VARIABLE_STORE_HEADER *VariableStoreHeader;
|
---|
1648 | VARIABLE_HEADER *Variable;
|
---|
1649 | VOID *VariableData;
|
---|
1650 | EFI_HOB_GUID_TYPE *GuidHob;
|
---|
1651 |
|
---|
1652 | FullyInitializeStore = TRUE;
|
---|
1653 |
|
---|
1654 | if (VolatileStore) {
|
---|
1655 | VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase;
|
---|
1656 | LastVariableOffset = &mVariableModuleGlobal->VolatileLastVariableOffset;
|
---|
1657 | } else {
|
---|
1658 | VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase;
|
---|
1659 | LastVariableOffset = &mVariableModuleGlobal->NonVolatileLastVariableOffset;
|
---|
1660 | }
|
---|
1661 |
|
---|
1662 | //
|
---|
1663 | // Note that in EdkII variable driver implementation, Hardware Error Record type variable
|
---|
1664 | // is stored with common variable in the same NV region. So the platform integrator should
|
---|
1665 | // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
|
---|
1666 | // PcdVariableStoreSize.
|
---|
1667 | //
|
---|
1668 | ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdVariableStoreSize));
|
---|
1669 |
|
---|
1670 | //
|
---|
1671 | // Allocate memory for variable store.
|
---|
1672 | //
|
---|
1673 | if (VolatileStore || (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0)) {
|
---|
1674 | VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize));
|
---|
1675 | } else {
|
---|
1676 | //
|
---|
1677 | // A memory location has been reserved for the NV variable store. Certain
|
---|
1678 | // platforms may be able to preserve a memory range across system resets,
|
---|
1679 | // thereby providing better NV variable emulation.
|
---|
1680 | //
|
---|
1681 | VariableStore =
|
---|
1682 | (VARIABLE_STORE_HEADER *)(VOID*)(UINTN)
|
---|
1683 | PcdGet64 (PcdEmuVariableNvStoreReserved);
|
---|
1684 | if (
|
---|
1685 | (VariableStore->Size == PcdGet32 (PcdVariableStoreSize)) &&
|
---|
1686 | (VariableStore->Format == VARIABLE_STORE_FORMATTED) &&
|
---|
1687 | (VariableStore->State == VARIABLE_STORE_HEALTHY)
|
---|
1688 | ) {
|
---|
1689 | DEBUG((
|
---|
1690 | EFI_D_INFO,
|
---|
1691 | "Variable Store reserved at %p appears to be valid\n",
|
---|
1692 | VariableStore
|
---|
1693 | ));
|
---|
1694 | FullyInitializeStore = FALSE;
|
---|
1695 | }
|
---|
1696 | }
|
---|
1697 |
|
---|
1698 | if (NULL == VariableStore) {
|
---|
1699 | return EFI_OUT_OF_RESOURCES;
|
---|
1700 | }
|
---|
1701 |
|
---|
1702 | if (FullyInitializeStore) {
|
---|
1703 | SetMem (VariableStore, PcdGet32 (PcdVariableStoreSize), 0xff);
|
---|
1704 | }
|
---|
1705 |
|
---|
1706 | //
|
---|
1707 | // Variable Specific Data
|
---|
1708 | //
|
---|
1709 | *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;
|
---|
1710 | InitializeLocationForLastVariableOffset (VariableStore, LastVariableOffset);
|
---|
1711 |
|
---|
1712 | CopyGuid (&VariableStore->Signature, &gEfiVariableGuid);
|
---|
1713 | VariableStore->Size = PcdGet32 (PcdVariableStoreSize);
|
---|
1714 | VariableStore->Format = VARIABLE_STORE_FORMATTED;
|
---|
1715 | VariableStore->State = VARIABLE_STORE_HEALTHY;
|
---|
1716 | VariableStore->Reserved = 0;
|
---|
1717 | VariableStore->Reserved1 = 0;
|
---|
1718 |
|
---|
1719 | if (!VolatileStore) {
|
---|
1720 | //
|
---|
1721 | // Get HOB variable store.
|
---|
1722 | //
|
---|
1723 | GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
|
---|
1724 | if (GuidHob != NULL) {
|
---|
1725 | VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
|
---|
1726 | if (CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
|
---|
1727 | (VariableStoreHeader->Format == VARIABLE_STORE_FORMATTED) &&
|
---|
1728 | (VariableStoreHeader->State == VARIABLE_STORE_HEALTHY)
|
---|
1729 | ) {
|
---|
1730 | DEBUG ((EFI_D_INFO, "HOB Variable Store appears to be valid.\n"));
|
---|
1731 | //
|
---|
1732 | // Flush the HOB variable to Emulation Variable storage.
|
---|
1733 | //
|
---|
1734 | for ( Variable = (VARIABLE_HEADER *) HEADER_ALIGN (VariableStoreHeader + 1)
|
---|
1735 | ; (Variable < GetEndPointer (VariableStoreHeader) && (Variable != NULL))
|
---|
1736 | ; Variable = GetNextVariablePtr (Variable)
|
---|
1737 | ) {
|
---|
1738 | ASSERT (Variable->State == VAR_ADDED);
|
---|
1739 | ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
|
---|
1740 | VariableData = GetVariableDataPtr (Variable);
|
---|
1741 | Status = EmuSetVariable (
|
---|
1742 | GET_VARIABLE_NAME_PTR (Variable),
|
---|
1743 | &Variable->VendorGuid,
|
---|
1744 | Variable->Attributes,
|
---|
1745 | Variable->DataSize,
|
---|
1746 | VariableData,
|
---|
1747 | &mVariableModuleGlobal->VariableGlobal[Physical],
|
---|
1748 | &mVariableModuleGlobal->VolatileLastVariableOffset,
|
---|
1749 | &mVariableModuleGlobal->NonVolatileLastVariableOffset
|
---|
1750 | );
|
---|
1751 | ASSERT_EFI_ERROR (Status);
|
---|
1752 | }
|
---|
1753 | }
|
---|
1754 | }
|
---|
1755 | }
|
---|
1756 |
|
---|
1757 | return EFI_SUCCESS;
|
---|
1758 | }
|
---|
1759 |
|
---|
1760 | /**
|
---|
1761 | Initializes variable store area for non-volatile and volatile variable.
|
---|
1762 |
|
---|
1763 | This function allocates and initializes memory space for global context of ESAL
|
---|
1764 | variable service and variable store area for non-volatile and volatile variable.
|
---|
1765 |
|
---|
1766 | @param ImageHandle The Image handle of this driver.
|
---|
1767 | @param SystemTable The pointer of EFI_SYSTEM_TABLE.
|
---|
1768 |
|
---|
1769 | @retval EFI_SUCCESS Function successfully executed.
|
---|
1770 | @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
|
---|
1771 |
|
---|
1772 | **/
|
---|
1773 | EFI_STATUS
|
---|
1774 | EFIAPI
|
---|
1775 | VariableCommonInitialize (
|
---|
1776 | IN EFI_HANDLE ImageHandle,
|
---|
1777 | IN EFI_SYSTEM_TABLE *SystemTable
|
---|
1778 | )
|
---|
1779 | {
|
---|
1780 | EFI_STATUS Status;
|
---|
1781 |
|
---|
1782 | //
|
---|
1783 | // Allocate memory for mVariableModuleGlobal
|
---|
1784 | //
|
---|
1785 | mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimeZeroPool (
|
---|
1786 | sizeof (ESAL_VARIABLE_GLOBAL)
|
---|
1787 | );
|
---|
1788 | if (NULL == mVariableModuleGlobal) {
|
---|
1789 | return EFI_OUT_OF_RESOURCES;
|
---|
1790 | }
|
---|
1791 |
|
---|
1792 | EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, TPL_NOTIFY);
|
---|
1793 |
|
---|
1794 | //
|
---|
1795 | // Intialize volatile variable store
|
---|
1796 | //
|
---|
1797 | Status = InitializeVariableStore (TRUE);
|
---|
1798 | if (EFI_ERROR (Status)) {
|
---|
1799 | FreePool(mVariableModuleGlobal);
|
---|
1800 | return Status;
|
---|
1801 | }
|
---|
1802 | //
|
---|
1803 | // Intialize non volatile variable store
|
---|
1804 | //
|
---|
1805 | Status = InitializeVariableStore (FALSE);
|
---|
1806 |
|
---|
1807 | return Status;
|
---|
1808 | }
|
---|