]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.c
Remove DiskIoPartition module
[mirror_edk2.git] / EdkModulePkg / Universal / Variable / RuntimeDxe / Emu / EmuVariable.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 EmuVariable.c
15
16 Abstract:
17
18 Revision History
19
20 --*/
21
22 #include "Variable.h"
23
24 //
25 // Don't use module globals after the SetVirtualAddress map is signaled
26 //
27 ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
28
29 UINT32
30 EFIAPI
31 ArrayLength (
32 IN CHAR16 *String
33 )
34 /*++
35
36 Routine Description:
37
38 Determine the length of null terminated char16 array.
39
40 Arguments:
41
42 String Null-terminated CHAR16 array pointer.
43
44 Returns:
45
46 UINT32 Number of bytes in the string, including the double NULL at the end;
47
48 --*/
49 {
50 UINT32 Count;
51
52 if (NULL == String) {
53 return 0;
54 }
55
56 Count = 0;
57
58 while (0 != String[Count]) {
59 Count++;
60 }
61
62 return (Count * 2) + 2;
63 }
64
65 UINTN
66 EFIAPI
67 GetPadSize (
68 IN UINTN Value
69 )
70 /*++
71
72 Routine Description:
73
74 This function return the pad size for alignment
75
76 Arguments:
77
78 Value The value need to align
79
80 Returns:
81
82 Pad size for value
83
84 --*/
85 {
86 //
87 // If alignment is 0 or 1, means no alignment required
88 //
89 if (ALIGNMENT == 0 || ALIGNMENT == 1) {
90 return 0;
91 }
92
93 return ALIGNMENT - (Value % ALIGNMENT);
94 }
95
96 VARIABLE_STORE_STATUS
97 EFIAPI
98 GetVariableStoreStatus (
99 IN VARIABLE_STORE_HEADER *VarStoreHeader
100 )
101 /*++
102
103 Routine Description:
104
105 This code gets the pointer to the variable name.
106
107 Arguments:
108
109 VarStoreHeader Pointer to the Variable Store Header.
110
111 Returns:
112
113 EfiHealthy Variable store is healthy
114 EfiRaw Variable store is raw
115 EfiInvalid Variable store is invalid
116
117 --*/
118 {
119 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&
120 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
121 VarStoreHeader->State == VARIABLE_STORE_HEALTHY
122 ) {
123
124 return EfiValid;
125 } else if (VarStoreHeader->Signature == 0xffffffff &&
126 VarStoreHeader->Size == 0xffffffff &&
127 VarStoreHeader->Format == 0xff &&
128 VarStoreHeader->State == 0xff
129 ) {
130
131 return EfiRaw;
132 } else {
133 return EfiInvalid;
134 }
135 }
136
137 UINT8 *
138 EFIAPI
139 GetVariableDataPtr (
140 IN VARIABLE_HEADER *Variable
141 )
142 /*++
143
144 Routine Description:
145
146 This code gets the pointer to the variable data.
147
148 Arguments:
149
150 Variable Pointer to the Variable Header.
151
152 Returns:
153
154 UINT8* Pointer to Variable Data
155
156 --*/
157 {
158 if (Variable->StartId != VARIABLE_DATA) {
159 return NULL;
160 }
161 //
162 // Be careful about pad size for alignment
163 //
164 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GetPadSize (Variable->NameSize));
165 }
166
167 VARIABLE_HEADER *
168 EFIAPI
169 GetNextVariablePtr (
170 IN VARIABLE_HEADER *Variable
171 )
172 /*++
173
174 Routine Description:
175
176 This code gets the pointer to the next variable header.
177
178 Arguments:
179
180 Variable Pointer to the Variable Header.
181
182 Returns:
183
184 VARIABLE_HEADER* Pointer to next variable header.
185
186 --*/
187 {
188 VARIABLE_HEADER *VarHeader;
189
190 if (Variable->StartId != VARIABLE_DATA) {
191 return NULL;
192 }
193 //
194 // Be careful about pad size for alignment
195 //
196 VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
197
198 if (VarHeader->StartId != VARIABLE_DATA ||
199 (sizeof (VARIABLE_HEADER) + VarHeader->DataSize + VarHeader->NameSize) > MAX_VARIABLE_SIZE
200 ) {
201 return NULL;
202 }
203
204 return VarHeader;
205 }
206
207 VARIABLE_HEADER *
208 EFIAPI
209 GetEndPointer (
210 IN VARIABLE_STORE_HEADER *VolHeader
211 )
212 /*++
213
214 Routine Description:
215
216 This code gets the pointer to the last variable memory pointer byte
217
218 Arguments:
219
220 Variable Pointer to the Variable Header.
221
222 Returns:
223
224 VARIABLE_HEADER* Pointer to last unavailable Variable Header
225
226 --*/
227 {
228 //
229 // The end of variable store
230 //
231 return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size);
232 }
233
234 EFI_STATUS
235 EFIAPI
236 FindVariable (
237 IN CHAR16 *VariableName,
238 IN EFI_GUID *VendorGuid,
239 OUT VARIABLE_POINTER_TRACK *PtrTrack,
240 IN VARIABLE_GLOBAL *Global
241 )
242 /*++
243
244 Routine Description:
245
246 This code finds variable in storage blocks (Volatile or Non-Volatile)
247
248 Arguments:
249
250 VariableName Name of the variable to be found
251 VendorGuid Vendor GUID to be found.
252 PtrTrack Variable Track Pointer structure that contains
253 Variable Information.
254 Contains the pointer of Variable header.
255 Global VARIABLE_GLOBAL pointer
256
257 Returns:
258
259 EFI STATUS
260
261 --*/
262 {
263 VARIABLE_HEADER *Variable[2];
264 VARIABLE_STORE_HEADER *VariableStoreHeader[2];
265 UINTN Index;
266
267 //
268 // 0: Non-Volatile, 1: Volatile
269 //
270 VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
271 VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
272
273 //
274 // Start Pointers for the variable.
275 // Actual Data Pointer where data can be written.
276 //
277 Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);
278 Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);
279
280 if (VariableName[0] != 0 && VendorGuid == NULL) {
281 return EFI_INVALID_PARAMETER;
282 }
283 //
284 // Find the variable by walk through non-volatile and volatile variable store
285 //
286 for (Index = 0; Index < 2; Index++) {
287 PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);
288 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
289
290 while ((Variable[Index] != NULL) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {
291 if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) {
292 if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
293 if (VariableName[0] == 0) {
294 PtrTrack->CurrPtr = Variable[Index];
295 PtrTrack->Volatile = (BOOLEAN) Index;
296 return EFI_SUCCESS;
297 } else {
298 if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {
299 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) {
300 PtrTrack->CurrPtr = Variable[Index];
301 PtrTrack->Volatile = (BOOLEAN) Index;
302 return EFI_SUCCESS;
303 }
304 }
305 }
306 }
307 }
308
309 Variable[Index] = GetNextVariablePtr (Variable[Index]);
310 }
311 }
312 PtrTrack->CurrPtr = NULL;
313 return EFI_NOT_FOUND;
314 }
315
316 EFI_STATUS
317 EFIAPI
318 GetVariable (
319 IN CHAR16 *VariableName,
320 IN EFI_GUID * VendorGuid,
321 OUT UINT32 *Attributes OPTIONAL,
322 IN OUT UINTN *DataSize,
323 OUT VOID *Data,
324 IN VARIABLE_GLOBAL * Global,
325 IN UINT32 Instance
326 )
327 /*++
328
329 Routine Description:
330
331 This code finds variable in storage blocks (Volatile or Non-Volatile)
332
333 Arguments:
334
335 VariableName Name of Variable to be found
336 VendorGuid Variable vendor GUID
337 Attributes OPTIONAL Attribute value of the variable found
338 DataSize Size of Data found. If size is less than the
339 data, this value contains the required size.
340 Data Data pointer
341 Global Pointer to VARIABLE_GLOBAL structure
342 Instance Instance of the Firmware Volume.
343
344 Returns:
345
346 EFI STATUS
347
348 --*/
349 {
350 VARIABLE_POINTER_TRACK Variable;
351 UINTN VarDataSize;
352 EFI_STATUS Status;
353
354 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
355 return EFI_INVALID_PARAMETER;
356 }
357 //
358 // Find existing variable
359 //
360 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
361
362 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
363 return Status;
364 }
365 //
366 // Get data size
367 //
368 VarDataSize = Variable.CurrPtr->DataSize;
369 if (*DataSize >= VarDataSize) {
370 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
371 if (Attributes) {
372 *Attributes = Variable.CurrPtr->Attributes;
373 }
374
375 *DataSize = VarDataSize;
376 return EFI_SUCCESS;
377 } else {
378 *DataSize = VarDataSize;
379 return EFI_BUFFER_TOO_SMALL;
380 }
381 }
382
383 EFI_STATUS
384 EFIAPI
385 GetNextVariableName (
386 IN OUT UINTN *VariableNameSize,
387 IN OUT CHAR16 *VariableName,
388 IN OUT EFI_GUID *VendorGuid,
389 IN VARIABLE_GLOBAL *Global,
390 IN UINT32 Instance
391 )
392 /*++
393
394 Routine Description:
395
396 This code Finds the Next available variable
397
398 Arguments:
399
400 VariableNameSize Size of the variable
401 VariableName Pointer to variable name
402 VendorGuid Variable Vendor Guid
403 Global VARIABLE_GLOBAL structure pointer.
404 Instance FV instance
405
406 Returns:
407
408 EFI STATUS
409
410 --*/
411 {
412 VARIABLE_POINTER_TRACK Variable;
413 UINTN VarNameSize;
414 EFI_STATUS Status;
415
416 if (VariableNameSize == NULL || VendorGuid == NULL) {
417 return EFI_INVALID_PARAMETER;
418 }
419
420 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
421
422 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
423 return Status;
424 }
425
426 while (TRUE) {
427 if (VariableName[0] != 0) {
428 //
429 // If variable name is not NULL, get next variable
430 //
431 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
432 }
433 //
434 // If both volatile and non-volatile variable store are parsed,
435 // return not found
436 //
437 if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {
438 Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));
439 if (Variable.Volatile) {
440 Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));
441 Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));
442 } else {
443 return EFI_NOT_FOUND;
444 }
445
446 Variable.CurrPtr = Variable.StartPtr;
447 if (Variable.CurrPtr->StartId != VARIABLE_DATA) {
448 continue;
449 }
450 }
451 //
452 // Variable is found
453 //
454 if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) {
455 if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
456 VarNameSize = Variable.CurrPtr->NameSize;
457 if (VarNameSize <= *VariableNameSize) {
458 CopyMem (
459 VariableName,
460 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
461 VarNameSize
462 );
463 CopyMem (
464 VendorGuid,
465 &Variable.CurrPtr->VendorGuid,
466 sizeof (EFI_GUID)
467 );
468 Status = EFI_SUCCESS;
469 } else {
470 Status = EFI_BUFFER_TOO_SMALL;
471 }
472
473 *VariableNameSize = VarNameSize;
474 return Status;
475 }
476 }
477 }
478
479 return EFI_NOT_FOUND;
480 }
481
482 EFI_STATUS
483 EFIAPI
484 SetVariable (
485 IN CHAR16 *VariableName,
486 IN EFI_GUID *VendorGuid,
487 IN UINT32 Attributes,
488 IN UINTN DataSize,
489 IN VOID *Data,
490 IN VARIABLE_GLOBAL *Global,
491 IN UINTN *VolatileOffset,
492 IN UINTN *NonVolatileOffset,
493 IN UINT32 Instance
494 )
495 /*++
496
497 Routine Description:
498
499 This code sets variable in storage blocks (Volatile or Non-Volatile)
500
501 Arguments:
502
503 VariableName Name of Variable to be found
504 VendorGuid Variable vendor GUID
505 Attributes Attribute value of the variable found
506 DataSize Size of Data found. If size is less than the
507 data, this value contains the required size.
508 Data Data pointer
509 Global Pointer to VARIABLE_GLOBAL structure
510 VolatileOffset The offset of last volatile variable
511 NonVolatileOffset The offset of last non-volatile variable
512 Instance Instance of the Firmware Volume.
513
514 Returns:
515
516 EFI STATUS
517
518 --*/
519 {
520 VARIABLE_POINTER_TRACK Variable;
521 EFI_STATUS Status;
522 VARIABLE_HEADER *NextVariable;
523 UINTN VarNameSize;
524 UINTN VarNameOffset;
525 UINTN VarDataOffset;
526 UINTN VarSize;
527
528 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
529 return EFI_INVALID_PARAMETER;
530 }
531
532 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
533
534 if (Status == EFI_INVALID_PARAMETER) {
535 return Status;
536 }
537 //
538 // The size of the VariableName, including the Unicode Null in bytes plus
539 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
540 //
541 else if (sizeof (VARIABLE_HEADER) + (ArrayLength (VariableName) + DataSize) > MAX_VARIABLE_SIZE) {
542 return EFI_INVALID_PARAMETER;
543 }
544 //
545 // Make sure if runtime bit is set, boot service bit is set also
546 //
547 else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS
548 ) {
549 return EFI_INVALID_PARAMETER;
550 }
551 //
552 // Runtime but Attribute is not Runtime
553 //
554 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
555 return EFI_INVALID_PARAMETER;
556 }
557 //
558 // Cannot set volatile variable in Runtime
559 //
560 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {
561 return EFI_INVALID_PARAMETER;
562 }
563 //
564 // Setting a data variable with no access, or zero DataSize attributes
565 // specified causes it to be deleted.
566 //
567 else if (DataSize == 0 || Attributes == 0) {
568 if (!EFI_ERROR (Status)) {
569 Variable.CurrPtr->State &= VAR_DELETED;
570 return EFI_SUCCESS;
571 }
572
573 return EFI_NOT_FOUND;
574 } else {
575 if (!EFI_ERROR (Status)) {
576 //
577 // If the variable is marked valid and the same data has been passed in
578 // then return to the caller immediately.
579 //
580 if (Variable.CurrPtr->DataSize == DataSize &&
581 !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)
582 ) {
583 return EFI_SUCCESS;
584 } else if (Variable.CurrPtr->State == VAR_ADDED) {
585 //
586 // Mark the old variable as in delete transition
587 //
588 Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION;
589 }
590 }
591 //
592 // Create a new variable and copy the data.
593 //
594 VarNameOffset = sizeof (VARIABLE_HEADER);
595 VarNameSize = ArrayLength (VariableName);
596 VarDataOffset = VarNameOffset + VarNameSize + GetPadSize (VarNameSize);
597 VarSize = VarDataOffset + DataSize + GetPadSize (DataSize);
598
599 if (Attributes & EFI_VARIABLE_NON_VOLATILE) {
600 if ((UINT32) (VarSize +*NonVolatileOffset) >
601 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size
602 ) {
603 return EFI_OUT_OF_RESOURCES;
604 }
605
606 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);
607 *NonVolatileOffset = *NonVolatileOffset + VarSize;
608 } else {
609 if (EfiAtRuntime ()) {
610 return EFI_INVALID_PARAMETER;
611 }
612
613 if ((UINT32) (VarSize +*VolatileOffset) >
614 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
615 ) {
616 return EFI_OUT_OF_RESOURCES;
617 }
618
619 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase);
620 *VolatileOffset = *VolatileOffset + VarSize;
621 }
622
623 NextVariable->StartId = VARIABLE_DATA;
624 NextVariable->Attributes = Attributes;
625 NextVariable->State = VAR_ADDED;
626 NextVariable->Reserved = 0;
627
628 //
629 // There will be pad bytes after Data, the NextVariable->NameSize and
630 // NextVariable->NameSize should not include pad size so that variable
631 // service can get actual size in GetVariable
632 //
633 NextVariable->NameSize = (UINT32)VarNameSize;
634 NextVariable->DataSize = (UINT32)DataSize;
635
636 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));
637 CopyMem (
638 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),
639 VariableName,
640 VarNameSize
641 );
642 CopyMem (
643 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
644 Data,
645 DataSize
646 );
647
648 //
649 // Mark the old variable as deleted
650 //
651 if (!EFI_ERROR (Status)) {
652 Variable.CurrPtr->State &= VAR_DELETED;
653 }
654 }
655
656 return EFI_SUCCESS;
657 }
658
659 EFI_STATUS
660 EFIAPI
661 InitializeVariableStore (
662 OUT EFI_PHYSICAL_ADDRESS *VariableBase,
663 OUT UINTN *LastVariableOffset
664 )
665 /*++
666
667 Routine Description:
668 This function initializes variable store
669
670 Arguments:
671
672 Returns:
673
674 --*/
675 {
676 VARIABLE_STORE_HEADER *VariableStore;
677
678 //
679 // Allocate memory for volatile variable store
680 //
681 VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (
682 VARIABLE_STORE_SIZE
683 );
684 if (NULL == VariableStore) {
685 return EFI_OUT_OF_RESOURCES;
686 }
687
688 SetMem (VariableStore, VARIABLE_STORE_SIZE, 0xff);
689
690 //
691 // Variable Specific Data
692 //
693 *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;
694 *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);
695
696 VariableStore->Signature = VARIABLE_STORE_SIGNATURE;
697 VariableStore->Size = VARIABLE_STORE_SIZE;
698 VariableStore->Format = VARIABLE_STORE_FORMATTED;
699 VariableStore->State = VARIABLE_STORE_HEALTHY;
700 VariableStore->Reserved = 0;
701 VariableStore->Reserved1 = 0;
702
703 return EFI_SUCCESS;
704 }
705
706 EFI_STATUS
707 EFIAPI
708 VariableCommonInitialize (
709 IN EFI_HANDLE ImageHandle,
710 IN EFI_SYSTEM_TABLE *SystemTable
711 )
712 /*++
713
714 Routine Description:
715 This function does common initialization for variable services
716
717 Arguments:
718
719 Returns:
720
721 --*/
722 {
723 EFI_STATUS Status;
724
725 //
726 // Allocate memory for mVariableModuleGlobal
727 //
728 mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool (
729 sizeof (ESAL_VARIABLE_GLOBAL)
730 );
731 if (NULL == mVariableModuleGlobal) {
732 return EFI_OUT_OF_RESOURCES;
733 }
734 //
735 // Intialize volatile variable store
736 //
737 Status = InitializeVariableStore (
738 &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase,
739 &mVariableModuleGlobal->VolatileLastVariableOffset
740 );
741
742 if (EFI_ERROR (Status)) {
743 return Status;
744 }
745 //
746 // Intialize non volatile variable store
747 //
748 Status = InitializeVariableStore (
749 &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,
750 &mVariableModuleGlobal->NonVolatileLastVariableOffset
751 );
752
753 return Status;
754 }