TianoCore EDK2 master
Loading...
Searching...
No Matches
Variable.c
Go to the documentation of this file.
1
28#include "Variable.h"
29#include "VariableNonVolatile.h"
30#include "VariableParsing.h"
32
33VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
34
40
45
50
54BOOLEAN mEndOfDxe = FALSE;
55
60VAR_CHECK_REQUEST_SOURCE mRequestSource = VarCheckFromUntrusted;
61
62//
63// It will record the current boot error flag before EndOfDxe.
64//
65VAR_ERROR_FLAG mCurrentBootVarErrFlag = VAR_ERROR_FLAG_NO_ERROR;
66
67VARIABLE_ENTRY_PROPERTY mVariableEntryProperty[] = {
68 {
69 &gEdkiiVarErrorFlagGuid,
70 VAR_ERROR_FLAG_NAME,
71 {
72 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
73 VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
74 VARIABLE_ATTRIBUTE_NV_BS_RT,
75 sizeof (VAR_ERROR_FLAG),
76 sizeof (VAR_ERROR_FLAG)
77 }
78 },
79};
80
81AUTH_VAR_LIB_CONTEXT_IN mAuthContextIn = {
82 AUTH_VAR_LIB_CONTEXT_IN_STRUCT_VERSION,
83 //
84 // StructSize, TO BE FILLED
85 //
86 0,
87 //
88 // MaxAuthVariableSize, TO BE FILLED
89 //
90 0,
97};
98
99AUTH_VAR_LIB_CONTEXT_OUT mAuthContextOut;
100
124 IN VARIABLE_GLOBAL *Global,
125 IN BOOLEAN Volatile,
126 IN BOOLEAN SetByIndex,
128 IN UINTN DataPtrIndex,
129 IN UINT32 DataSize,
130 IN UINT8 *Buffer
131 )
132{
133 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
134 UINTN BlockIndex2;
135 UINTN LinearOffset;
136 UINTN CurrWriteSize;
137 UINTN CurrWritePtr;
138 UINT8 *CurrBuffer;
139 EFI_LBA LbaNumber;
140 UINTN Size;
141 VARIABLE_STORE_HEADER *VolatileBase;
142 EFI_PHYSICAL_ADDRESS FvVolHdr;
143 EFI_PHYSICAL_ADDRESS DataPtr;
144 EFI_STATUS Status;
145
146 FvVolHdr = 0;
147 DataPtr = DataPtrIndex;
148
149 //
150 // Check if the Data is Volatile.
151 //
152 if (!Volatile && !mVariableModuleGlobal->VariableGlobal.EmuNvMode) {
153 if (Fvb == NULL) {
154 return EFI_UNSUPPORTED;
155 }
156
157 Status = Fvb->GetPhysicalAddress (Fvb, &FvVolHdr);
158 ASSERT_EFI_ERROR (Status);
159
160 //
161 // Data Pointer should point to the actual Address where data is to be
162 // written.
163 //
164 if (SetByIndex) {
165 DataPtr += mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
166 }
167
168 if ((DataPtr + DataSize) > (FvVolHdr + mNvFvHeaderCache->FvLength)) {
169 return EFI_OUT_OF_RESOURCES;
170 }
171 } else {
172 //
173 // Data Pointer should point to the actual Address where data is to be
174 // written.
175 //
176 if (Volatile) {
177 VolatileBase = (VARIABLE_STORE_HEADER *)((UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
178 if (SetByIndex) {
179 DataPtr += mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
180 }
181
182 if ((DataPtr + DataSize) > ((UINTN)VolatileBase + VolatileBase->Size)) {
183 return EFI_OUT_OF_RESOURCES;
184 }
185 } else {
186 //
187 // Emulated non-volatile variable mode.
188 //
189 if (SetByIndex) {
190 DataPtr += (UINTN)mNvVariableCache;
191 }
192
193 if ((DataPtr + DataSize) > ((UINTN)mNvVariableCache + mNvVariableCache->Size)) {
194 return EFI_OUT_OF_RESOURCES;
195 }
196 }
197
198 //
199 // If Volatile/Emulated Non-volatile Variable just do a simple mem copy.
200 //
201 CopyMem ((UINT8 *)(UINTN)DataPtr, Buffer, DataSize);
202 return EFI_SUCCESS;
203 }
204
205 //
206 // If we are here we are dealing with Non-Volatile Variables.
207 //
208 LinearOffset = (UINTN)FvVolHdr;
209 CurrWritePtr = (UINTN)DataPtr;
210 CurrWriteSize = DataSize;
211 CurrBuffer = Buffer;
212 LbaNumber = 0;
213
214 if (CurrWritePtr < LinearOffset) {
215 return EFI_INVALID_PARAMETER;
216 }
217
218 for (PtrBlockMapEntry = mNvFvHeaderCache->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
219 for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
220 //
221 // Check to see if the Variable Writes are spanning through multiple
222 // blocks.
223 //
224 if ((CurrWritePtr >= LinearOffset) && (CurrWritePtr < LinearOffset + PtrBlockMapEntry->Length)) {
225 if ((CurrWritePtr + CurrWriteSize) <= (LinearOffset + PtrBlockMapEntry->Length)) {
226 Status = Fvb->Write (
227 Fvb,
228 LbaNumber,
229 (UINTN)(CurrWritePtr - LinearOffset),
230 &CurrWriteSize,
231 CurrBuffer
232 );
233 return Status;
234 } else {
235 Size = (UINT32)(LinearOffset + PtrBlockMapEntry->Length - CurrWritePtr);
236 Status = Fvb->Write (
237 Fvb,
238 LbaNumber,
239 (UINTN)(CurrWritePtr - LinearOffset),
240 &Size,
241 CurrBuffer
242 );
243 if (EFI_ERROR (Status)) {
244 return Status;
245 }
246
247 CurrWritePtr = LinearOffset + PtrBlockMapEntry->Length;
248 CurrBuffer = CurrBuffer + Size;
249 CurrWriteSize = CurrWriteSize - Size;
250 }
251 }
252
253 LinearOffset += PtrBlockMapEntry->Length;
254 LbaNumber++;
255 }
256 }
257
258 return EFI_SUCCESS;
259}
260
271VOID
273 IN VAR_ERROR_FLAG Flag,
274 IN CHAR16 *VariableName,
275 IN EFI_GUID *VendorGuid,
276 IN UINT32 Attributes,
277 IN UINTN VariableSize
278 )
279{
280 EFI_STATUS Status;
281 VARIABLE_POINTER_TRACK Variable;
282 VAR_ERROR_FLAG *VarErrFlag;
283 VAR_ERROR_FLAG TempFlag;
284
286 DEBUG ((DEBUG_ERROR, "RecordVarErrorFlag (0x%02x) %s:%g - 0x%08x - 0x%x\n", Flag, VariableName, VendorGuid, Attributes, VariableSize));
287 if (Flag == VAR_ERROR_FLAG_SYSTEM_ERROR) {
288 if (AtRuntime ()) {
289 DEBUG ((DEBUG_ERROR, "CommonRuntimeVariableSpace = 0x%x - CommonVariableTotalSize = 0x%x\n", mVariableModuleGlobal->CommonRuntimeVariableSpace, mVariableModuleGlobal->CommonVariableTotalSize));
290 } else {
291 DEBUG ((DEBUG_ERROR, "CommonVariableSpace = 0x%x - CommonVariableTotalSize = 0x%x\n", mVariableModuleGlobal->CommonVariableSpace, mVariableModuleGlobal->CommonVariableTotalSize));
292 }
293 } else {
294 DEBUG ((DEBUG_ERROR, "CommonMaxUserVariableSpace = 0x%x - CommonUserVariableTotalSize = 0x%x\n", mVariableModuleGlobal->CommonMaxUserVariableSpace, mVariableModuleGlobal->CommonUserVariableTotalSize));
295 }
296
298
299 if (!mEndOfDxe) {
300 //
301 // Before EndOfDxe, just record the current boot variable error flag to local variable,
302 // and leave the variable error flag in NV flash as the last boot variable error flag.
303 // After EndOfDxe in InitializeVarErrorFlag (), the variable error flag in NV flash
304 // will be initialized to this local current boot variable error flag.
305 //
306 mCurrentBootVarErrFlag &= Flag;
307 return;
308 }
309
310 //
311 // Record error flag (it should have be initialized).
312 //
313 Status = FindVariable (
314 VAR_ERROR_FLAG_NAME,
315 &gEdkiiVarErrorFlagGuid,
316 &Variable,
317 &mVariableModuleGlobal->VariableGlobal,
318 FALSE
319 );
320 if (!EFI_ERROR (Status)) {
321 VarErrFlag = (VAR_ERROR_FLAG *)GetVariableDataPtr (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
322 TempFlag = *VarErrFlag;
323 TempFlag &= Flag;
324 if (TempFlag == *VarErrFlag) {
325 return;
326 }
327
328 Status = UpdateVariableStore (
329 &mVariableModuleGlobal->VariableGlobal,
330 FALSE,
331 FALSE,
332 mVariableModuleGlobal->FvbInstance,
333 (UINTN)VarErrFlag - (UINTN)mNvVariableCache + (UINTN)mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
334 sizeof (TempFlag),
335 &TempFlag
336 );
337 if (!EFI_ERROR (Status)) {
338 //
339 // Update the data in NV cache.
340 //
341 *VarErrFlag = TempFlag;
343 &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache,
344 0,
346 );
347 ASSERT_EFI_ERROR (Status);
348 }
349 }
350}
351
361VOID
363 VOID
364 )
365{
366 EFI_STATUS Status;
367 VARIABLE_POINTER_TRACK Variable;
368 VAR_ERROR_FLAG Flag;
369 VAR_ERROR_FLAG VarErrFlag;
370
371 if (!mEndOfDxe) {
372 return;
373 }
374
375 Flag = mCurrentBootVarErrFlag;
376 DEBUG ((DEBUG_INFO, "Initialize variable error flag (%02x)\n", Flag));
377
378 Status = FindVariable (
379 VAR_ERROR_FLAG_NAME,
380 &gEdkiiVarErrorFlagGuid,
381 &Variable,
382 &mVariableModuleGlobal->VariableGlobal,
383 FALSE
384 );
385 if (!EFI_ERROR (Status)) {
386 VarErrFlag = *((VAR_ERROR_FLAG *)GetVariableDataPtr (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat));
387 if (VarErrFlag == Flag) {
388 return;
389 }
390 }
391
393 VAR_ERROR_FLAG_NAME,
394 &gEdkiiVarErrorFlagGuid,
395 &Flag,
396 sizeof (Flag),
397 VARIABLE_ATTRIBUTE_NV_BS_RT,
398 0,
399 0,
400 &Variable,
401 NULL
402 );
403}
404
414BOOLEAN
416 IN VARIABLE_HEADER *Variable
417 )
418{
420
421 //
422 // Only after End Of Dxe, the variables belong to system variable are fixed.
423 // If PcdMaxUserNvStorageVariableSize is 0, it means user variable share the same NV storage with system variable,
424 // then no need to check if the variable is user variable or not specially.
425 //
426 if (mEndOfDxe && (mVariableModuleGlobal->CommonMaxUserVariableSpace != mVariableModuleGlobal->CommonVariableSpace)) {
428 GetVariableNamePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat),
429 GetVendorGuidPtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat),
430 &Property
431 ) == EFI_NOT_FOUND)
432 {
433 return TRUE;
434 }
435 }
436
437 return FALSE;
438}
439
444VOID
446 VOID
447 )
448{
449 VARIABLE_HEADER *Variable;
450 VARIABLE_HEADER *NextVariable;
451 UINTN VariableSize;
453
454 //
455 // Only after End Of Dxe, the variables belong to system variable are fixed.
456 // If PcdMaxUserNvStorageVariableSize is 0, it means user variable share the same NV storage with system variable,
457 // then no need to calculate the common user variable total size specially.
458 //
459 if (mEndOfDxe && (mVariableModuleGlobal->CommonMaxUserVariableSpace != mVariableModuleGlobal->CommonVariableSpace)) {
462 NextVariable = GetNextVariablePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat);
463 VariableSize = (UINTN)NextVariable - (UINTN)Variable;
466 GetVariableNamePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat),
467 GetVendorGuidPtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat),
468 &Property
469 ) == EFI_NOT_FOUND)
470 {
471 //
472 // No property, it is user variable.
473 //
474 mVariableModuleGlobal->CommonUserVariableTotalSize += VariableSize;
475 }
476 }
477
478 Variable = NextVariable;
479 }
480 }
481}
482
487VOID
489 VOID
490 )
491{
492 if (!mEndOfDxe) {
493 return;
494 }
495
498}
499
519 IN EFI_PHYSICAL_ADDRESS VariableBase,
520 OUT UINTN *LastVariableOffset,
521 IN BOOLEAN IsVolatile,
522 IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
523 IN VARIABLE_HEADER *NewVariable,
524 IN UINTN NewVariableSize
525 )
526{
527 VARIABLE_HEADER *Variable;
528 VARIABLE_HEADER *AddedVariable;
529 VARIABLE_HEADER *NextVariable;
530 VARIABLE_HEADER *NextAddedVariable;
531 VARIABLE_STORE_HEADER *VariableStoreHeader;
532 UINT8 *ValidBuffer;
533 UINTN MaximumBufferSize;
534 UINTN VariableSize;
535 UINTN NameSize;
536 UINT8 *CurrPtr;
537 VOID *Point0;
538 VOID *Point1;
539 BOOLEAN FoundAdded;
540 EFI_STATUS Status;
541 EFI_STATUS DoneStatus;
542 UINTN CommonVariableTotalSize;
543 UINTN CommonUserVariableTotalSize;
544 UINTN HwErrVariableTotalSize;
545 VARIABLE_HEADER *UpdatingVariable;
546 VARIABLE_HEADER *UpdatingInDeletedTransition;
547 BOOLEAN AuthFormat;
548
549 AuthFormat = mVariableModuleGlobal->VariableGlobal.AuthFormat;
550 UpdatingVariable = NULL;
551 UpdatingInDeletedTransition = NULL;
552 if (UpdatingPtrTrack != NULL) {
553 UpdatingVariable = UpdatingPtrTrack->CurrPtr;
554 UpdatingInDeletedTransition = UpdatingPtrTrack->InDeletedTransitionPtr;
555 }
556
557 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)VariableBase);
558
559 CommonVariableTotalSize = 0;
560 CommonUserVariableTotalSize = 0;
561 HwErrVariableTotalSize = 0;
562
563 if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) {
564 //
565 // Start Pointers for the variable.
566 //
567 Variable = GetStartPointer (VariableStoreHeader);
568 MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);
569
570 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
571 NextVariable = GetNextVariablePtr (Variable, AuthFormat);
572 if (((Variable->State == VAR_ADDED) || (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) &&
573 (Variable != UpdatingVariable) &&
574 (Variable != UpdatingInDeletedTransition)
575 )
576 {
577 VariableSize = (UINTN)NextVariable - (UINTN)Variable;
578 MaximumBufferSize += VariableSize;
579 }
580
581 Variable = NextVariable;
582 }
583
584 if (NewVariable != NULL) {
585 //
586 // Add the new variable size.
587 //
588 MaximumBufferSize += NewVariableSize;
589 }
590
591 //
592 // Reserve the 1 Bytes with Oxff to identify the
593 // end of the variable buffer.
594 //
595 MaximumBufferSize += 1;
596 ValidBuffer = AllocatePool (MaximumBufferSize);
597 if (ValidBuffer == NULL) {
598 return EFI_OUT_OF_RESOURCES;
599 }
600 } else {
601 //
602 // For NV variable reclaim, don't allocate pool here and just use mNvVariableCache
603 // as the buffer to reduce SMRAM consumption for SMM variable driver.
604 //
605 MaximumBufferSize = mNvVariableCache->Size;
606 ValidBuffer = (UINT8 *)mNvVariableCache;
607 }
608
609 SetMem (ValidBuffer, MaximumBufferSize, 0xff);
610
611 //
612 // Copy variable store header.
613 //
614 CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
615 CurrPtr = (UINT8 *)GetStartPointer ((VARIABLE_STORE_HEADER *)ValidBuffer);
616
617 //
618 // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
619 //
620 Variable = GetStartPointer (VariableStoreHeader);
621 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
622 NextVariable = GetNextVariablePtr (Variable, AuthFormat);
623 if ((Variable != UpdatingVariable) && (Variable->State == VAR_ADDED)) {
624 VariableSize = (UINTN)NextVariable - (UINTN)Variable;
625 CopyMem (CurrPtr, (UINT8 *)Variable, VariableSize);
626 CurrPtr += VariableSize;
627 if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
628 HwErrVariableTotalSize += VariableSize;
629 } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
630 CommonVariableTotalSize += VariableSize;
631 if (IsUserVariable (Variable)) {
632 CommonUserVariableTotalSize += VariableSize;
633 }
634 }
635 }
636
637 Variable = NextVariable;
638 }
639
640 //
641 // Reinstall all in delete transition variables.
642 //
643 Variable = GetStartPointer (VariableStoreHeader);
644 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
645 NextVariable = GetNextVariablePtr (Variable, AuthFormat);
646 if ((Variable != UpdatingVariable) && (Variable != UpdatingInDeletedTransition) && (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) {
647 //
648 // Buffer has cached all ADDED variable.
649 // Per IN_DELETED variable, we have to guarantee that
650 // no ADDED one in previous buffer.
651 //
652
653 FoundAdded = FALSE;
654 AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)ValidBuffer);
655 while (IsValidVariableHeader (AddedVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)ValidBuffer))) {
656 NextAddedVariable = GetNextVariablePtr (AddedVariable, AuthFormat);
657 NameSize = NameSizeOfVariable (AddedVariable, AuthFormat);
658 if (CompareGuid (
659 GetVendorGuidPtr (AddedVariable, AuthFormat),
660 GetVendorGuidPtr (Variable, AuthFormat)
661 ) && (NameSize == NameSizeOfVariable (Variable, AuthFormat)))
662 {
663 Point0 = (VOID *)GetVariableNamePtr (AddedVariable, AuthFormat);
664 Point1 = (VOID *)GetVariableNamePtr (Variable, AuthFormat);
665 if (CompareMem (Point0, Point1, NameSize) == 0) {
666 FoundAdded = TRUE;
667 break;
668 }
669 }
670
671 AddedVariable = NextAddedVariable;
672 }
673
674 if (!FoundAdded) {
675 //
676 // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
677 //
678 VariableSize = (UINTN)NextVariable - (UINTN)Variable;
679 CopyMem (CurrPtr, (UINT8 *)Variable, VariableSize);
680 ((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;
681 CurrPtr += VariableSize;
682 if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
683 HwErrVariableTotalSize += VariableSize;
684 } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
685 CommonVariableTotalSize += VariableSize;
686 if (IsUserVariable (Variable)) {
687 CommonUserVariableTotalSize += VariableSize;
688 }
689 }
690 }
691 }
692
693 Variable = NextVariable;
694 }
695
696 //
697 // Install the new variable if it is not NULL.
698 //
699 if (NewVariable != NULL) {
700 if (((UINTN)CurrPtr - (UINTN)ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) {
701 //
702 // No enough space to store the new variable.
703 //
704 Status = EFI_OUT_OF_RESOURCES;
705 goto Done;
706 }
707
708 if (!IsVolatile) {
710 HwErrVariableTotalSize += NewVariableSize;
711 } else if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
712 CommonVariableTotalSize += NewVariableSize;
713 if (IsUserVariable (NewVariable)) {
714 CommonUserVariableTotalSize += NewVariableSize;
715 }
716 }
717
718 if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) ||
719 (CommonVariableTotalSize > mVariableModuleGlobal->CommonVariableSpace) ||
720 (CommonUserVariableTotalSize > mVariableModuleGlobal->CommonMaxUserVariableSpace))
721 {
722 //
723 // No enough space to store the new variable by NV or NV+HR attribute.
724 //
725 Status = EFI_OUT_OF_RESOURCES;
726 goto Done;
727 }
728 }
729
730 CopyMem (CurrPtr, (UINT8 *)NewVariable, NewVariableSize);
731 ((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;
732 if (UpdatingVariable != NULL) {
733 UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *)ValidBuffer)));
734 UpdatingPtrTrack->InDeletedTransitionPtr = NULL;
735 }
736
737 CurrPtr += NewVariableSize;
738 }
739
740 if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) {
741 //
742 // If volatile/emulated non-volatile variable store, just copy valid buffer.
743 //
744 SetMem ((UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size, 0xff);
745 CopyMem ((UINT8 *)(UINTN)VariableBase, ValidBuffer, (UINTN)CurrPtr - (UINTN)ValidBuffer);
746 *LastVariableOffset = (UINTN)CurrPtr - (UINTN)ValidBuffer;
747 if (!IsVolatile) {
748 //
749 // Emulated non-volatile variable mode.
750 //
751 mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;
752 mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;
753 mVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;
754 }
755
756 Status = EFI_SUCCESS;
757 } else {
758 //
759 // If non-volatile variable store, perform FTW here.
760 //
761 Status = FtwVariableSpace (
762 VariableBase,
763 (VARIABLE_STORE_HEADER *)ValidBuffer
764 );
765 if (!EFI_ERROR (Status)) {
766 *LastVariableOffset = (UINTN)CurrPtr - (UINTN)ValidBuffer;
767 mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;
768 mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;
769 mVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;
770 } else {
771 mVariableModuleGlobal->HwErrVariableTotalSize = 0;
772 mVariableModuleGlobal->CommonVariableTotalSize = 0;
773 mVariableModuleGlobal->CommonUserVariableTotalSize = 0;
774 Variable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);
775 while (IsValidVariableHeader (Variable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) {
776 NextVariable = GetNextVariablePtr (Variable, AuthFormat);
777 VariableSize = (UINTN)NextVariable - (UINTN)Variable;
779 mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
781 mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
782 if (IsUserVariable (Variable)) {
783 mVariableModuleGlobal->CommonUserVariableTotalSize += VariableSize;
784 }
785 }
786
787 Variable = NextVariable;
788 }
789
790 *LastVariableOffset = (UINTN)Variable - (UINTN)VariableBase;
791 }
792 }
793
794Done:
795 DoneStatus = EFI_SUCCESS;
796 if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) {
798 &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCache,
799 0,
800 VariableStoreHeader->Size
801 );
802 ASSERT_EFI_ERROR (DoneStatus);
803 FreePool (ValidBuffer);
804 } else {
805 //
806 // For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.
807 //
808 CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size);
810 &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache,
811 0,
812 VariableStoreHeader->Size
813 );
814 ASSERT_EFI_ERROR (DoneStatus);
815 }
816
817 if (!EFI_ERROR (Status) && EFI_ERROR (DoneStatus)) {
818 Status = DoneStatus;
819 }
820
821 return Status;
822}
823
852 IN CHAR16 *VariableName,
853 IN EFI_GUID *VendorGuid,
854 OUT VARIABLE_POINTER_TRACK *PtrTrack,
855 IN VARIABLE_GLOBAL *Global,
856 IN BOOLEAN IgnoreRtCheck
857 )
858{
859 EFI_STATUS Status;
860 VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
861 VARIABLE_STORE_TYPE Type;
862
863 if ((VariableName[0] != 0) && (VendorGuid == NULL)) {
864 return EFI_INVALID_PARAMETER;
865 }
866
867 //
868 // 0: Volatile, 1: HOB, 2: Non-Volatile.
869 // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
870 // make use of this mapping to implement search algorithm.
871 //
872 VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *)(UINTN)Global->VolatileVariableBase;
873 VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *)(UINTN)Global->HobVariableBase;
874 VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache;
875
876 //
877 // Find the variable by walk through HOB, volatile and non-volatile variable store.
878 //
879 for (Type = (VARIABLE_STORE_TYPE)0; Type < VariableStoreTypeMax; Type++) {
880 if (VariableStoreHeader[Type] == NULL) {
881 continue;
882 }
883
884 PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Type]);
885 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Type]);
886 PtrTrack->Volatile = (BOOLEAN)(Type == VariableStoreTypeVolatile);
887
888 Status = FindVariableEx (
889 VariableName,
890 VendorGuid,
891 IgnoreRtCheck,
892 PtrTrack,
893 mVariableModuleGlobal->VariableGlobal.AuthFormat
894 );
895 if (!EFI_ERROR (Status)) {
896 return Status;
897 }
898 }
899
900 return EFI_NOT_FOUND;
901}
902
929UINTN
931 IN CHAR8 *SupportedLang,
932 IN CHAR8 *Lang,
933 IN BOOLEAN Iso639Language
934 )
935{
936 UINTN Index;
937 UINTN CompareLength;
938 UINTN LanguageLength;
939
940 if (Iso639Language) {
941 CompareLength = ISO_639_2_ENTRY_SIZE;
942 for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {
943 if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {
944 //
945 // Successfully find the index of Lang string in SupportedLang string.
946 //
947 Index = Index / CompareLength;
948 return Index;
949 }
950 }
951
952 ASSERT (FALSE);
953 return 0;
954 } else {
955 //
956 // Compare RFC4646 language code
957 //
958 Index = 0;
959 for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++) {
960 }
961
962 for (Index = 0; *SupportedLang != '\0'; Index++, SupportedLang += CompareLength) {
963 //
964 // Skip ';' characters in SupportedLang
965 //
966 for ( ; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++) {
967 }
968
969 //
970 // Determine the length of the next language code in SupportedLang
971 //
972 for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++) {
973 }
974
975 if ((CompareLength == LanguageLength) &&
976 (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0))
977 {
978 //
979 // Successfully find the index of Lang string in SupportedLang string.
980 //
981 return Index;
982 }
983 }
984
985 ASSERT (FALSE);
986 return 0;
987 }
988}
989
1016CHAR8 *
1018 IN CHAR8 *SupportedLang,
1019 IN UINTN Index,
1020 IN BOOLEAN Iso639Language
1021 )
1022{
1023 UINTN SubIndex;
1024 UINTN CompareLength;
1025 CHAR8 *Supported;
1026
1027 SubIndex = 0;
1028 Supported = SupportedLang;
1029 if (Iso639Language) {
1030 //
1031 // According to the index of Lang string in SupportedLang string to get the language.
1032 // This code will be invoked in RUNTIME, therefore there is not a memory allocate/free operation.
1033 // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
1034 //
1035 CompareLength = ISO_639_2_ENTRY_SIZE;
1036 mVariableModuleGlobal->Lang[CompareLength] = '\0';
1037 return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);
1038 } else {
1039 while (TRUE) {
1040 //
1041 // Take semicolon as delimitation, sequentially traverse supported language codes.
1042 //
1043 for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {
1044 Supported++;
1045 }
1046
1047 if ((*Supported == '\0') && (SubIndex != Index)) {
1048 //
1049 // Have completed the traverse, but not find corrsponding string.
1050 // This case is not allowed to happen.
1051 //
1052 ASSERT (FALSE);
1053 return NULL;
1054 }
1055
1056 if (SubIndex == Index) {
1057 //
1058 // According to the index of Lang string in SupportedLang string to get the language.
1059 // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
1060 // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
1061 //
1062 mVariableModuleGlobal->PlatformLang[CompareLength] = '\0';
1063 return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);
1064 }
1065
1066 SubIndex++;
1067
1068 //
1069 // Skip ';' characters in Supported
1070 //
1071 for ( ; *Supported != '\0' && *Supported == ';'; Supported++) {
1072 }
1073 }
1074 }
1075}
1076
1116CHAR8 *
1117EFIAPI
1119 IN CONST CHAR8 *SupportedLanguages,
1120 IN UINTN Iso639Language,
1121 ...
1122 )
1123{
1124 VA_LIST Args;
1125 CHAR8 *Language;
1126 UINTN CompareLength;
1127 UINTN LanguageLength;
1128 CONST CHAR8 *Supported;
1129 CHAR8 *Buffer;
1130
1131 if (SupportedLanguages == NULL) {
1132 return NULL;
1133 }
1134
1135 VA_START (Args, Iso639Language);
1136 while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {
1137 //
1138 // Default to ISO 639-2 mode
1139 //
1140 CompareLength = 3;
1141 LanguageLength = MIN (3, AsciiStrLen (Language));
1142
1143 //
1144 // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language
1145 //
1146 if (Iso639Language == 0) {
1147 for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++) {
1148 }
1149 }
1150
1151 //
1152 // Trim back the length of Language used until it is empty
1153 //
1154 while (LanguageLength > 0) {
1155 //
1156 // Loop through all language codes in SupportedLanguages
1157 //
1158 for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
1159 //
1160 // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages
1161 //
1162 if (Iso639Language == 0) {
1163 //
1164 // Skip ';' characters in Supported
1165 //
1166 for ( ; *Supported != '\0' && *Supported == ';'; Supported++) {
1167 }
1168
1169 //
1170 // Determine the length of the next language code in Supported
1171 //
1172 for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++) {
1173 }
1174
1175 //
1176 // If Language is longer than the Supported, then skip to the next language
1177 //
1178 if (LanguageLength > CompareLength) {
1179 continue;
1180 }
1181 }
1182
1183 //
1184 // See if the first LanguageLength characters in Supported match Language
1185 //
1186 if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {
1187 VA_END (Args);
1188
1189 Buffer = (Iso639Language != 0) ? mVariableModuleGlobal->Lang : mVariableModuleGlobal->PlatformLang;
1190 Buffer[CompareLength] = '\0';
1191 return CopyMem (Buffer, Supported, CompareLength);
1192 }
1193 }
1194
1195 if (Iso639Language != 0) {
1196 //
1197 // If ISO 639 mode, then each language can only be tested once
1198 //
1199 LanguageLength = 0;
1200 } else {
1201 //
1202 // If RFC 4646 mode, then trim Language from the right to the next '-' character
1203 //
1204 for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--) {
1205 }
1206 }
1207 }
1208 }
1209
1210 VA_END (Args);
1211
1212 //
1213 // No matches were found
1214 //
1215 return NULL;
1216}
1217
1238BOOLEAN
1239EFIAPI
1241 IN UINT32 Attributes,
1242 IN VA_LIST Marker
1243 )
1244{
1245 EFI_STATUS Status;
1246 VA_LIST Args;
1247 VARIABLE_ENTRY_CONSISTENCY *VariableEntry;
1248 UINT64 MaximumVariableStorageSize;
1249 UINT64 RemainingVariableStorageSize;
1250 UINT64 MaximumVariableSize;
1251 UINTN TotalNeededSize;
1252 UINTN OriginalVarSize;
1253 VARIABLE_STORE_HEADER *VariableStoreHeader;
1254 VARIABLE_POINTER_TRACK VariablePtrTrack;
1255 VARIABLE_HEADER *NextVariable;
1256 UINTN VarNameSize;
1257 UINTN VarDataSize;
1258
1259 //
1260 // Non-Volatile related.
1261 //
1262 VariableStoreHeader = mNvVariableCache;
1263
1265 Attributes,
1266 &MaximumVariableStorageSize,
1267 &RemainingVariableStorageSize,
1268 &MaximumVariableSize
1269 );
1270 ASSERT_EFI_ERROR (Status);
1271
1272 TotalNeededSize = 0;
1273 VA_COPY (Args, Marker);
1274 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
1275 while (VariableEntry != NULL) {
1276 //
1277 // Calculate variable total size.
1278 //
1279 VarNameSize = StrSize (VariableEntry->Name);
1280 VarNameSize += GET_PAD_SIZE (VarNameSize);
1281 VarDataSize = VariableEntry->VariableSize;
1282 VarDataSize += GET_PAD_SIZE (VarDataSize);
1283 VariableEntry->VariableSize = HEADER_ALIGN (
1285 mVariableModuleGlobal->VariableGlobal.AuthFormat
1286 ) + VarNameSize + VarDataSize
1287 );
1288
1289 TotalNeededSize += VariableEntry->VariableSize;
1290 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
1291 }
1292
1293 VA_END (Args);
1294
1295 if (RemainingVariableStorageSize >= TotalNeededSize) {
1296 //
1297 // Already have enough space.
1298 //
1299 return TRUE;
1300 } else if (AtRuntime ()) {
1301 //
1302 // At runtime, no reclaim.
1303 // The original variable space of Variables can't be reused.
1304 //
1305 return FALSE;
1306 }
1307
1308 VA_COPY (Args, Marker);
1309 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
1310 while (VariableEntry != NULL) {
1311 //
1312 // Check if Variable[Index] has been present and get its size.
1313 //
1314 OriginalVarSize = 0;
1315 VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);
1316 VariablePtrTrack.EndPtr = GetEndPointer (VariableStoreHeader);
1317 Status = FindVariableEx (
1318 VariableEntry->Name,
1319 VariableEntry->Guid,
1320 FALSE,
1321 &VariablePtrTrack,
1322 mVariableModuleGlobal->VariableGlobal.AuthFormat
1323 );
1324 if (!EFI_ERROR (Status)) {
1325 //
1326 // Get size of Variable[Index].
1327 //
1328 NextVariable = GetNextVariablePtr (VariablePtrTrack.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
1329 OriginalVarSize = (UINTN)NextVariable - (UINTN)VariablePtrTrack.CurrPtr;
1330 //
1331 // Add the original size of Variable[Index] to remaining variable storage size.
1332 //
1333 RemainingVariableStorageSize += OriginalVarSize;
1334 }
1335
1336 if (VariableEntry->VariableSize > RemainingVariableStorageSize) {
1337 //
1338 // No enough space for Variable[Index].
1339 //
1340 VA_END (Args);
1341 return FALSE;
1342 }
1343
1344 //
1345 // Sub the (new) size of Variable[Index] from remaining variable storage size.
1346 //
1347 RemainingVariableStorageSize -= VariableEntry->VariableSize;
1348 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
1349 }
1350
1351 VA_END (Args);
1352
1353 return TRUE;
1354}
1355
1375BOOLEAN
1376EFIAPI
1378 IN UINT32 Attributes,
1379 ...
1380 )
1381{
1382 VA_LIST Marker;
1383 BOOLEAN Return;
1384
1385 VA_START (Marker, Attributes);
1386
1387 Return = CheckRemainingSpaceForConsistencyInternal (Attributes, Marker);
1388
1389 VA_END (Marker);
1390
1391 return Return;
1392}
1393
1416 IN CHAR16 *VariableName,
1417 IN VOID *Data,
1418 IN UINTN DataSize
1419 )
1420{
1421 EFI_STATUS Status;
1422 CHAR8 *BestPlatformLang;
1423 CHAR8 *BestLang;
1424 UINTN Index;
1425 UINT32 Attributes;
1426 VARIABLE_POINTER_TRACK Variable;
1427 BOOLEAN SetLanguageCodes;
1428 VARIABLE_ENTRY_CONSISTENCY VariableEntry[2];
1429
1430 //
1431 // Don't do updates for delete operation
1432 //
1433 if (DataSize == 0) {
1434 return EFI_SUCCESS;
1435 }
1436
1437 SetLanguageCodes = FALSE;
1438
1439 if (StrCmp (VariableName, EFI_PLATFORM_LANG_CODES_VARIABLE_NAME) == 0) {
1440 //
1441 // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
1442 //
1443 if (AtRuntime ()) {
1444 return EFI_WRITE_PROTECTED;
1445 }
1446
1447 SetLanguageCodes = TRUE;
1448
1449 //
1450 // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only
1451 // Therefore, in variable driver, only store the original value for other use.
1452 //
1453 if (mVariableModuleGlobal->PlatformLangCodes != NULL) {
1454 FreePool (mVariableModuleGlobal->PlatformLangCodes);
1455 }
1456
1457 mVariableModuleGlobal->PlatformLangCodes = AllocateRuntimeCopyPool (DataSize, Data);
1458 ASSERT (mVariableModuleGlobal->PlatformLangCodes != NULL);
1459
1460 //
1461 // PlatformLang holds a single language from PlatformLangCodes,
1462 // so the size of PlatformLangCodes is enough for the PlatformLang.
1463 //
1464 if (mVariableModuleGlobal->PlatformLang != NULL) {
1465 FreePool (mVariableModuleGlobal->PlatformLang);
1466 }
1467
1468 mVariableModuleGlobal->PlatformLang = AllocateRuntimePool (DataSize);
1469 ASSERT (mVariableModuleGlobal->PlatformLang != NULL);
1470 } else if (StrCmp (VariableName, EFI_LANG_CODES_VARIABLE_NAME) == 0) {
1471 //
1472 // LangCodes is a volatile variable, so it can not be updated at runtime.
1473 //
1474 if (AtRuntime ()) {
1475 return EFI_WRITE_PROTECTED;
1476 }
1477
1478 SetLanguageCodes = TRUE;
1479
1480 //
1481 // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only
1482 // Therefore, in variable driver, only store the original value for other use.
1483 //
1484 if (mVariableModuleGlobal->LangCodes != NULL) {
1485 FreePool (mVariableModuleGlobal->LangCodes);
1486 }
1487
1488 mVariableModuleGlobal->LangCodes = AllocateRuntimeCopyPool (DataSize, Data);
1489 ASSERT (mVariableModuleGlobal->LangCodes != NULL);
1490 }
1491
1492 if ( SetLanguageCodes
1493 && (mVariableModuleGlobal->PlatformLangCodes != NULL)
1494 && (mVariableModuleGlobal->LangCodes != NULL))
1495 {
1496 //
1497 // Update Lang if PlatformLang is already set
1498 // Update PlatformLang if Lang is already set
1499 //
1500 Status = FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
1501 if (!EFI_ERROR (Status)) {
1502 //
1503 // Update Lang
1504 //
1505 VariableName = EFI_PLATFORM_LANG_VARIABLE_NAME;
1506 Data = GetVariableDataPtr (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
1507 DataSize = DataSizeOfVariable (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
1508 } else {
1509 Status = FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
1510 if (!EFI_ERROR (Status)) {
1511 //
1512 // Update PlatformLang
1513 //
1514 VariableName = EFI_LANG_VARIABLE_NAME;
1515 Data = GetVariableDataPtr (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
1516 DataSize = DataSizeOfVariable (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
1517 } else {
1518 //
1519 // Neither PlatformLang nor Lang is set, directly return
1520 //
1521 return EFI_SUCCESS;
1522 }
1523 }
1524 }
1525
1526 Status = EFI_SUCCESS;
1527
1528 //
1529 // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.
1530 //
1531 Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
1532
1533 if (StrCmp (VariableName, EFI_PLATFORM_LANG_VARIABLE_NAME) == 0) {
1534 //
1535 // Update Lang when PlatformLangCodes/LangCodes were set.
1536 //
1537 if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {
1538 //
1539 // When setting PlatformLang, firstly get most matched language string from supported language codes.
1540 //
1541 BestPlatformLang = VariableGetBestLanguage (mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);
1542 if (BestPlatformLang != NULL) {
1543 //
1544 // Get the corresponding index in language codes.
1545 //
1546 Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);
1547
1548 //
1549 // Get the corresponding ISO639 language tag according to RFC4646 language tag.
1550 //
1551 BestLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, Index, TRUE);
1552
1553 //
1554 // Check the variable space for both Lang and PlatformLang variable.
1555 //
1556 VariableEntry[0].VariableSize = ISO_639_2_ENTRY_SIZE + 1;
1557 VariableEntry[0].Guid = &gEfiGlobalVariableGuid;
1558 VariableEntry[0].Name = EFI_LANG_VARIABLE_NAME;
1559
1560 VariableEntry[1].VariableSize = AsciiStrSize (BestPlatformLang);
1561 VariableEntry[1].Guid = &gEfiGlobalVariableGuid;
1562 VariableEntry[1].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;
1563 if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {
1564 //
1565 // No enough variable space to set both Lang and PlatformLang successfully.
1566 //
1567 Status = EFI_OUT_OF_RESOURCES;
1568 } else {
1569 //
1570 // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
1571 //
1572 FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
1573
1574 Status = UpdateVariable (
1576 &gEfiGlobalVariableGuid,
1577 BestLang,
1578 ISO_639_2_ENTRY_SIZE + 1,
1579 Attributes,
1580 0,
1581 0,
1582 &Variable,
1583 NULL
1584 );
1585 }
1586
1587 DEBUG ((DEBUG_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a Status: %r\n", BestPlatformLang, BestLang, Status));
1588 }
1589 }
1590 } else if (StrCmp (VariableName, EFI_LANG_VARIABLE_NAME) == 0) {
1591 //
1592 // Update PlatformLang when PlatformLangCodes/LangCodes were set.
1593 //
1594 if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {
1595 //
1596 // When setting Lang, firstly get most matched language string from supported language codes.
1597 //
1598 BestLang = VariableGetBestLanguage (mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);
1599 if (BestLang != NULL) {
1600 //
1601 // Get the corresponding index in language codes.
1602 //
1603 Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, BestLang, TRUE);
1604
1605 //
1606 // Get the corresponding RFC4646 language tag according to ISO639 language tag.
1607 //
1608 BestPlatformLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);
1609
1610 //
1611 // Check the variable space for both PlatformLang and Lang variable.
1612 //
1613 VariableEntry[0].VariableSize = AsciiStrSize (BestPlatformLang);
1614 VariableEntry[0].Guid = &gEfiGlobalVariableGuid;
1615 VariableEntry[0].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;
1616
1617 VariableEntry[1].VariableSize = ISO_639_2_ENTRY_SIZE + 1;
1618 VariableEntry[1].Guid = &gEfiGlobalVariableGuid;
1619 VariableEntry[1].Name = EFI_LANG_VARIABLE_NAME;
1620 if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {
1621 //
1622 // No enough variable space to set both PlatformLang and Lang successfully.
1623 //
1624 Status = EFI_OUT_OF_RESOURCES;
1625 } else {
1626 //
1627 // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
1628 //
1629 FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
1630
1631 Status = UpdateVariable (
1633 &gEfiGlobalVariableGuid,
1634 BestPlatformLang,
1635 AsciiStrSize (BestPlatformLang),
1636 Attributes,
1637 0,
1638 0,
1639 &Variable,
1640 NULL
1641 );
1642 }
1643
1644 DEBUG ((DEBUG_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status));
1645 }
1646 }
1647 }
1648
1649 if (SetLanguageCodes) {
1650 //
1651 // Continue to set PlatformLangCodes or LangCodes.
1652 //
1653 return EFI_SUCCESS;
1654 } else {
1655 return Status;
1656 }
1657}
1658
1679 IN CHAR16 *VariableName,
1680 IN EFI_GUID *VendorGuid,
1681 IN VOID *Data,
1682 IN UINTN DataSize,
1683 IN UINT32 Attributes OPTIONAL,
1684 IN UINT32 KeyIndex OPTIONAL,
1685 IN UINT64 MonotonicCount OPTIONAL,
1686 IN OUT VARIABLE_POINTER_TRACK *CacheVariable,
1687 IN EFI_TIME *TimeStamp OPTIONAL
1688 )
1689{
1690 EFI_STATUS Status;
1691 VARIABLE_HEADER *NextVariable;
1692 UINTN ScratchSize;
1693 UINTN MaxDataSize;
1694 UINTN VarNameOffset;
1695 UINTN VarDataOffset;
1696 UINTN VarNameSize;
1697 UINTN VarSize;
1698 BOOLEAN Volatile;
1700 UINT8 State;
1701 VARIABLE_POINTER_TRACK *Variable;
1702 VARIABLE_POINTER_TRACK NvVariable;
1703 VARIABLE_STORE_HEADER *VariableStoreHeader;
1704 VARIABLE_RUNTIME_CACHE *VolatileCacheInstance;
1705 UINT8 *BufferForMerge;
1706 UINTN MergedBufSize;
1707 BOOLEAN DataReady;
1708 UINTN DataOffset;
1709 BOOLEAN IsCommonVariable;
1710 BOOLEAN IsCommonUserVariable;
1711 AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
1712 BOOLEAN AuthFormat;
1713
1714 if ((mVariableModuleGlobal->FvbInstance == NULL) && !mVariableModuleGlobal->VariableGlobal.EmuNvMode) {
1715 //
1716 // The FVB protocol is not ready, so the EFI_VARIABLE_WRITE_ARCH_PROTOCOL is not installed.
1717 //
1718 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
1719 //
1720 // Trying to update NV variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL
1721 //
1722 DEBUG ((DEBUG_ERROR, "Update NV variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r\n", EFI_NOT_AVAILABLE_YET));
1723 return EFI_NOT_AVAILABLE_YET;
1724 } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {
1725 //
1726 // Trying to update volatile authenticated variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL
1727 // The authenticated variable perhaps is not initialized, just return here.
1728 //
1729 DEBUG ((DEBUG_ERROR, "Update AUTH variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r\n", EFI_NOT_AVAILABLE_YET));
1730 return EFI_NOT_AVAILABLE_YET;
1731 }
1732 }
1733
1734 AuthFormat = mVariableModuleGlobal->VariableGlobal.AuthFormat;
1735
1736 //
1737 // Check if CacheVariable points to the variable in variable HOB.
1738 // If yes, let CacheVariable points to the variable in NV variable cache.
1739 //
1740 if ((CacheVariable->CurrPtr != NULL) &&
1741 (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) &&
1742 (CacheVariable->StartPtr == GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase))
1743 )
1744 {
1745 CacheVariable->StartPtr = GetStartPointer (mNvVariableCache);
1746 CacheVariable->EndPtr = GetEndPointer (mNvVariableCache);
1747 CacheVariable->Volatile = FALSE;
1748 Status = FindVariableEx (VariableName, VendorGuid, FALSE, CacheVariable, AuthFormat);
1749 if ((CacheVariable->CurrPtr == NULL) || EFI_ERROR (Status)) {
1750 //
1751 // There is no matched variable in NV variable cache.
1752 //
1753 if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
1754 //
1755 // It is to delete variable,
1756 // go to delete this variable in variable HOB and
1757 // try to flush other variables from HOB to flash.
1758 //
1759 UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, FALSE, TRUE, FALSE, &gVariableInfo);
1760 FlushHobVariableToFlash (VariableName, VendorGuid);
1761 return EFI_SUCCESS;
1762 }
1763 }
1764 }
1765
1766 if ((CacheVariable->CurrPtr == NULL) || CacheVariable->Volatile) {
1767 Variable = CacheVariable;
1768 } else {
1769 //
1770 // Update/Delete existing NV variable.
1771 // CacheVariable points to the variable in the memory copy of Flash area
1772 // Now let Variable points to the same variable in Flash area.
1773 //
1774 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
1775 Variable = &NvVariable;
1776 Variable->StartPtr = GetStartPointer (VariableStoreHeader);
1777 Variable->EndPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->EndPtr - (UINTN)CacheVariable->StartPtr));
1778
1779 Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
1780 if (CacheVariable->InDeletedTransitionPtr != NULL) {
1781 Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));
1782 } else {
1783 Variable->InDeletedTransitionPtr = NULL;
1784 }
1785
1786 Variable->Volatile = FALSE;
1787 }
1788
1789 Fvb = mVariableModuleGlobal->FvbInstance;
1790
1791 //
1792 // Tricky part: Use scratch data area at the end of volatile variable store
1793 // as a temporary storage.
1794 //
1795 NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *)((UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));
1796 ScratchSize = mVariableModuleGlobal->ScratchBufferSize;
1797 SetMem (NextVariable, ScratchSize, 0xff);
1798 DataReady = FALSE;
1799
1800 if (Variable->CurrPtr != NULL) {
1801 //
1802 // Update/Delete existing variable.
1803 //
1804 if (AtRuntime ()) {
1805 //
1806 // If AtRuntime and the variable is Volatile and Runtime Access,
1807 // the volatile is ReadOnly, and SetVariable should be aborted and
1808 // return EFI_WRITE_PROTECTED.
1809 //
1810 if (Variable->Volatile) {
1811 Status = EFI_WRITE_PROTECTED;
1812 goto Done;
1813 }
1814
1815 //
1816 // Only variable that have NV attributes can be updated/deleted in Runtime.
1817 //
1818 if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
1819 Status = EFI_INVALID_PARAMETER;
1820 goto Done;
1821 }
1822
1823 //
1824 // Only variable that have RT attributes can be updated/deleted in Runtime.
1825 //
1826 if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {
1827 Status = EFI_INVALID_PARAMETER;
1828 goto Done;
1829 }
1830 }
1831
1832 //
1833 // Setting a data variable with no access, or zero DataSize attributes
1834 // causes it to be deleted.
1835 // When the EFI_VARIABLE_APPEND_WRITE attribute is set, DataSize of zero will
1836 // not delete the variable.
1837 //
1838 if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0)) {
1839 if (Variable->InDeletedTransitionPtr != NULL) {
1840 //
1841 // Both ADDED and IN_DELETED_TRANSITION variable are present,
1842 // set IN_DELETED_TRANSITION one to DELETED state first.
1843 //
1844 ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
1845 State = CacheVariable->InDeletedTransitionPtr->State;
1846 State &= VAR_DELETED;
1847 Status = UpdateVariableStore (
1848 &mVariableModuleGlobal->VariableGlobal,
1849 Variable->Volatile,
1850 FALSE,
1851 Fvb,
1852 (UINTN)&Variable->InDeletedTransitionPtr->State,
1853 sizeof (UINT8),
1854 &State
1855 );
1856 if (!EFI_ERROR (Status)) {
1857 if (!Variable->Volatile) {
1858 CacheVariable->InDeletedTransitionPtr->State = State;
1859 }
1860 } else {
1861 goto Done;
1862 }
1863 }
1864
1865 State = CacheVariable->CurrPtr->State;
1866 State &= VAR_DELETED;
1867
1868 Status = UpdateVariableStore (
1869 &mVariableModuleGlobal->VariableGlobal,
1870 Variable->Volatile,
1871 FALSE,
1872 Fvb,
1873 (UINTN)&Variable->CurrPtr->State,
1874 sizeof (UINT8),
1875 &State
1876 );
1877 if (!EFI_ERROR (Status)) {
1878 UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE, &gVariableInfo);
1879 if (!Variable->Volatile) {
1880 CacheVariable->CurrPtr->State = State;
1881 FlushHobVariableToFlash (VariableName, VendorGuid);
1882 }
1883 }
1884
1885 goto Done;
1886 }
1887
1888 //
1889 // If the variable is marked valid, and the same data has been passed in,
1890 // then return to the caller immediately.
1891 //
1892 if ((DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat) == DataSize) &&
1893 (CompareMem (Data, GetVariableDataPtr (CacheVariable->CurrPtr, AuthFormat), DataSize) == 0) &&
1894 ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&
1895 (TimeStamp == NULL))
1896 {
1897 //
1898 // Variable content unchanged and no need to update timestamp, just return.
1899 //
1900 UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
1901 Status = EFI_SUCCESS;
1902 goto Done;
1903 } else if ((CacheVariable->CurrPtr->State == VAR_ADDED) ||
1904 (CacheVariable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)))
1905 {
1906 //
1907 // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable.
1908 //
1909 if ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0) {
1910 //
1911 // NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name.
1912 // From DataOffset of NextVariable is to save the existing variable data.
1913 //
1914 DataOffset = GetVariableDataOffset (CacheVariable->CurrPtr, AuthFormat);
1915 BufferForMerge = (UINT8 *)((UINTN)NextVariable + DataOffset);
1916 CopyMem (
1917 BufferForMerge,
1918 (UINT8 *)((UINTN)CacheVariable->CurrPtr + DataOffset),
1919 DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat)
1920 );
1921
1922 //
1923 // Set Max Auth/Non-Volatile/Volatile Variable Data Size as default MaxDataSize.
1924 //
1925 if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {
1926 MaxDataSize = mVariableModuleGlobal->MaxAuthVariableSize - DataOffset;
1927 } else if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
1928 MaxDataSize = mVariableModuleGlobal->MaxVariableSize - DataOffset;
1929 } else {
1930 MaxDataSize = mVariableModuleGlobal->MaxVolatileVariableSize - DataOffset;
1931 }
1932
1933 //
1934 // Append the new data to the end of existing data.
1935 // Max Harware error record variable data size is different from common/auth variable.
1936 //
1938 MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - DataOffset;
1939 }
1940
1941 if (DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat) + DataSize > MaxDataSize) {
1942 //
1943 // Existing data size + new data size exceed maximum variable size limitation.
1944 //
1945 Status = EFI_INVALID_PARAMETER;
1946 goto Done;
1947 }
1948
1949 CopyMem (
1950 (UINT8 *)(
1951 (UINTN)BufferForMerge + DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat)
1952 ),
1953 Data,
1954 DataSize
1955 );
1956 MergedBufSize = DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat) +
1957 DataSize;
1958
1959 //
1960 // BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data.
1961 //
1962 Data = BufferForMerge;
1963 DataSize = MergedBufSize;
1964 DataReady = TRUE;
1965 }
1966
1967 //
1968 // Mark the old variable as in delete transition.
1969 //
1970 State = CacheVariable->CurrPtr->State;
1972
1973 Status = UpdateVariableStore (
1974 &mVariableModuleGlobal->VariableGlobal,
1975 Variable->Volatile,
1976 FALSE,
1977 Fvb,
1978 (UINTN)&Variable->CurrPtr->State,
1979 sizeof (UINT8),
1980 &State
1981 );
1982 if (EFI_ERROR (Status)) {
1983 goto Done;
1984 }
1985
1986 if (!Variable->Volatile) {
1987 CacheVariable->CurrPtr->State = State;
1988 }
1989 }
1990 } else {
1991 //
1992 // Not found existing variable. Create a new variable.
1993 //
1994
1995 if ((DataSize == 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0)) {
1996 Status = EFI_SUCCESS;
1997 goto Done;
1998 }
1999
2000 //
2001 // Make sure we are trying to create a new variable.
2002 // Setting a data variable with zero DataSize or no access attributes means to delete it.
2003 //
2004 if ((DataSize == 0) || ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0)) {
2005 Status = EFI_NOT_FOUND;
2006 goto Done;
2007 }
2008
2009 //
2010 // Only variable have NV|RT attribute can be created in Runtime.
2011 //
2012 if (AtRuntime () &&
2013 (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)))
2014 {
2015 Status = EFI_INVALID_PARAMETER;
2016 goto Done;
2017 }
2018 }
2019
2020 //
2021 // Function part - create a new variable and copy the data.
2022 // Both update a variable and create a variable will come here.
2023 //
2024 NextVariable->StartId = VARIABLE_DATA;
2025 //
2026 // NextVariable->State = VAR_ADDED;
2027 //
2028 NextVariable->Reserved = 0;
2029 if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
2030 AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)NextVariable;
2031 AuthVariable->PubKeyIndex = KeyIndex;
2032 AuthVariable->MonotonicCount = MonotonicCount;
2033 ZeroMem (&AuthVariable->TimeStamp, sizeof (EFI_TIME));
2034
2035 if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&
2036 (TimeStamp != NULL))
2037 {
2038 if ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) {
2039 CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));
2040 } else {
2041 //
2042 // In the case when the EFI_VARIABLE_APPEND_WRITE attribute is set, only
2043 // when the new TimeStamp value is later than the current timestamp associated
2044 // with the variable, we need associate the new timestamp with the updated value.
2045 //
2046 if (Variable->CurrPtr != NULL) {
2047 if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *)CacheVariable->CurrPtr)->TimeStamp), TimeStamp)) {
2048 CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));
2049 } else {
2050 CopyMem (&AuthVariable->TimeStamp, &(((AUTHENTICATED_VARIABLE_HEADER *)CacheVariable->CurrPtr)->TimeStamp), sizeof (EFI_TIME));
2051 }
2052 }
2053 }
2054 }
2055 }
2056
2057 //
2058 // The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the returned
2059 // Attributes bitmask parameter of a GetVariable() call.
2060 //
2061 NextVariable->Attributes = Attributes & (~EFI_VARIABLE_APPEND_WRITE);
2062
2063 VarNameOffset = GetVariableHeaderSize (AuthFormat);
2064 VarNameSize = StrSize (VariableName);
2065 CopyMem (
2066 (UINT8 *)((UINTN)NextVariable + VarNameOffset),
2067 VariableName,
2068 VarNameSize
2069 );
2070 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
2071
2072 //
2073 // If DataReady is TRUE, it means the variable data has been saved into
2074 // NextVariable during EFI_VARIABLE_APPEND_WRITE operation preparation.
2075 //
2076 if (!DataReady) {
2077 CopyMem (
2078 (UINT8 *)((UINTN)NextVariable + VarDataOffset),
2079 Data,
2080 DataSize
2081 );
2082 }
2083
2084 CopyMem (
2085 GetVendorGuidPtr (NextVariable, AuthFormat),
2086 VendorGuid,
2087 sizeof (EFI_GUID)
2088 );
2089 //
2090 // There will be pad bytes after Data, the NextVariable->NameSize and
2091 // NextVariable->DataSize should not include pad size so that variable
2092 // service can get actual size in GetVariable.
2093 //
2094 SetNameSizeOfVariable (NextVariable, VarNameSize, AuthFormat);
2095 SetDataSizeOfVariable (NextVariable, DataSize, AuthFormat);
2096
2097 //
2098 // The actual size of the variable that stores in storage should
2099 // include pad size.
2100 //
2101 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
2102 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
2103 //
2104 // Create a nonvolatile variable.
2105 //
2106 Volatile = FALSE;
2107
2108 IsCommonVariable = FALSE;
2109 IsCommonUserVariable = FALSE;
2110 if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) {
2111 IsCommonVariable = TRUE;
2112 IsCommonUserVariable = IsUserVariable (NextVariable);
2113 }
2114
2115 if ( ( ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
2116 && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
2117 || (IsCommonVariable && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonVariableSpace))
2118 || (IsCommonVariable && AtRuntime () && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonRuntimeVariableSpace))
2119 || (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace)))
2120 {
2121 if (AtRuntime ()) {
2122 if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace)) {
2123 RecordVarErrorFlag (VAR_ERROR_FLAG_USER_ERROR, VariableName, VendorGuid, Attributes, VarSize);
2124 }
2125
2126 if (IsCommonVariable && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonRuntimeVariableSpace)) {
2127 RecordVarErrorFlag (VAR_ERROR_FLAG_SYSTEM_ERROR, VariableName, VendorGuid, Attributes, VarSize);
2128 }
2129
2130 Status = EFI_OUT_OF_RESOURCES;
2131 goto Done;
2132 }
2133
2134 //
2135 // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
2136 //
2137 Status = Reclaim (
2138 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
2139 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
2140 FALSE,
2141 Variable,
2142 NextVariable,
2143 HEADER_ALIGN (VarSize)
2144 );
2145 if (!EFI_ERROR (Status)) {
2146 //
2147 // The new variable has been integrated successfully during reclaiming.
2148 //
2149 if (Variable->CurrPtr != NULL) {
2150 CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN)CacheVariable->StartPtr + ((UINTN)Variable->CurrPtr - (UINTN)Variable->StartPtr));
2151 CacheVariable->InDeletedTransitionPtr = NULL;
2152 }
2153
2154 UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
2155 FlushHobVariableToFlash (VariableName, VendorGuid);
2156 } else {
2157 if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace)) {
2158 RecordVarErrorFlag (VAR_ERROR_FLAG_USER_ERROR, VariableName, VendorGuid, Attributes, VarSize);
2159 }
2160
2161 if (IsCommonVariable && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonVariableSpace)) {
2162 RecordVarErrorFlag (VAR_ERROR_FLAG_SYSTEM_ERROR, VariableName, VendorGuid, Attributes, VarSize);
2163 }
2164 }
2165
2166 goto Done;
2167 }
2168
2169 if (!mVariableModuleGlobal->VariableGlobal.EmuNvMode) {
2170 //
2171 // Two steps
2172 // 1. Write variable header and data
2173 // 2. Set variable state to valid
2174 //
2175 //
2176 // Step 1:
2177 //
2178 Status = UpdateVariableStore (
2179 &mVariableModuleGlobal->VariableGlobal,
2180 FALSE,
2181 TRUE,
2182 Fvb,
2183 mVariableModuleGlobal->NonVolatileLastVariableOffset,
2184 (UINT32)VarSize,
2185 (UINT8 *)NextVariable
2186 );
2187
2188 if (EFI_ERROR (Status)) {
2189 goto Done;
2190 }
2191
2192 //
2193 // Step 2:
2194 //
2195 NextVariable->State = VAR_ADDED;
2196 Status = UpdateVariableStore (
2197 &mVariableModuleGlobal->VariableGlobal,
2198 FALSE,
2199 TRUE,
2200 Fvb,
2201 mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF (VARIABLE_HEADER, State),
2202 sizeof (UINT8),
2203 &NextVariable->State
2204 );
2205
2206 if (EFI_ERROR (Status)) {
2207 goto Done;
2208 }
2209
2210 //
2211 // Update the memory copy of Flash region.
2212 //
2213 CopyMem ((UINT8 *)mNvVariableCache + mVariableModuleGlobal->NonVolatileLastVariableOffset, (UINT8 *)NextVariable, VarSize);
2214 } else {
2215 //
2216 // Emulated non-volatile variable mode.
2217 //
2218 NextVariable->State = VAR_ADDED;
2219 Status = UpdateVariableStore (
2220 &mVariableModuleGlobal->VariableGlobal,
2221 FALSE,
2222 TRUE,
2223 Fvb,
2224 mVariableModuleGlobal->NonVolatileLastVariableOffset,
2225 (UINT32)VarSize,
2226 (UINT8 *)NextVariable
2227 );
2228
2229 if (EFI_ERROR (Status)) {
2230 goto Done;
2231 }
2232 }
2233
2234 mVariableModuleGlobal->NonVolatileLastVariableOffset += HEADER_ALIGN (VarSize);
2235
2236 if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
2237 mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VarSize);
2238 } else {
2239 mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VarSize);
2240 if (IsCommonUserVariable) {
2241 mVariableModuleGlobal->CommonUserVariableTotalSize += HEADER_ALIGN (VarSize);
2242 }
2243 }
2244 } else {
2245 //
2246 // Create a volatile variable.
2247 //
2248 Volatile = TRUE;
2249
2250 if ((UINT32)(VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >
2251 ((VARIABLE_STORE_HEADER *)((UINTN)(mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size)
2252 {
2253 //
2254 // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
2255 //
2256 Status = Reclaim (
2257 mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
2258 &mVariableModuleGlobal->VolatileLastVariableOffset,
2259 TRUE,
2260 Variable,
2261 NextVariable,
2262 HEADER_ALIGN (VarSize)
2263 );
2264 if (!EFI_ERROR (Status)) {
2265 //
2266 // The new variable has been integrated successfully during reclaiming.
2267 //
2268 if (Variable->CurrPtr != NULL) {
2269 CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN)CacheVariable->StartPtr + ((UINTN)Variable->CurrPtr - (UINTN)Variable->StartPtr));
2270 CacheVariable->InDeletedTransitionPtr = NULL;
2271 }
2272
2273 UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
2274 }
2275
2276 goto Done;
2277 }
2278
2279 NextVariable->State = VAR_ADDED;
2280 Status = UpdateVariableStore (
2281 &mVariableModuleGlobal->VariableGlobal,
2282 TRUE,
2283 TRUE,
2284 Fvb,
2285 mVariableModuleGlobal->VolatileLastVariableOffset,
2286 (UINT32)VarSize,
2287 (UINT8 *)NextVariable
2288 );
2289
2290 if (EFI_ERROR (Status)) {
2291 goto Done;
2292 }
2293
2294 mVariableModuleGlobal->VolatileLastVariableOffset += HEADER_ALIGN (VarSize);
2295 }
2296
2297 //
2298 // Mark the old variable as deleted.
2299 //
2300 if (!EFI_ERROR (Status) && (Variable->CurrPtr != NULL)) {
2301 if (Variable->InDeletedTransitionPtr != NULL) {
2302 //
2303 // Both ADDED and IN_DELETED_TRANSITION old variable are present,
2304 // set IN_DELETED_TRANSITION one to DELETED state first.
2305 //
2306 ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
2307 State = CacheVariable->InDeletedTransitionPtr->State;
2308 State &= VAR_DELETED;
2309 Status = UpdateVariableStore (
2310 &mVariableModuleGlobal->VariableGlobal,
2311 Variable->Volatile,
2312 FALSE,
2313 Fvb,
2314 (UINTN)&Variable->InDeletedTransitionPtr->State,
2315 sizeof (UINT8),
2316 &State
2317 );
2318 if (!EFI_ERROR (Status)) {
2319 if (!Variable->Volatile) {
2320 CacheVariable->InDeletedTransitionPtr->State = State;
2321 }
2322 } else {
2323 goto Done;
2324 }
2325 }
2326
2327 State = CacheVariable->CurrPtr->State;
2328 State &= VAR_DELETED;
2329
2330 Status = UpdateVariableStore (
2331 &mVariableModuleGlobal->VariableGlobal,
2332 Variable->Volatile,
2333 FALSE,
2334 Fvb,
2335 (UINTN)&Variable->CurrPtr->State,
2336 sizeof (UINT8),
2337 &State
2338 );
2339 if (!EFI_ERROR (Status) && !Variable->Volatile) {
2340 CacheVariable->CurrPtr->State = State;
2341 }
2342 }
2343
2344 if (!EFI_ERROR (Status)) {
2345 UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
2346 if (!Volatile) {
2347 FlushHobVariableToFlash (VariableName, VendorGuid);
2348 }
2349 }
2350
2351Done:
2352 if (!EFI_ERROR (Status)) {
2353 if (((Variable->CurrPtr != NULL) && !Variable->Volatile) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {
2354 VolatileCacheInstance = &(mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache);
2355 } else {
2356 VolatileCacheInstance = &(mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCache);
2357 }
2358
2359 if (VolatileCacheInstance->Store != NULL) {
2361 VolatileCacheInstance,
2362 0,
2363 VolatileCacheInstance->Store->Size
2364 );
2365 ASSERT_EFI_ERROR (Status);
2366 }
2367 } else if (Status == EFI_OUT_OF_RESOURCES) {
2368 DEBUG ((DEBUG_WARN, "UpdateVariable failed: Out of flash space\n"));
2369 }
2370
2371 return Status;
2372}
2373
2406EFIAPI
2408 IN CHAR16 *VariableName,
2409 IN EFI_GUID *VendorGuid,
2410 OUT UINT32 *Attributes OPTIONAL,
2411 IN OUT UINTN *DataSize,
2412 OUT VOID *Data OPTIONAL
2413 )
2414{
2415 EFI_STATUS Status;
2416 VARIABLE_POINTER_TRACK Variable;
2417 UINTN VarDataSize;
2418
2419 if ((VariableName == NULL) || (VendorGuid == NULL) || (DataSize == NULL)) {
2420 return EFI_INVALID_PARAMETER;
2421 }
2422
2423 if (VariableName[0] == 0) {
2424 return EFI_NOT_FOUND;
2425 }
2426
2427 AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
2428
2429 Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
2430 if (EFI_ERROR (Status) || (Variable.CurrPtr == NULL)) {
2431 goto Done;
2432 }
2433
2434 //
2435 // Get data size
2436 //
2437 VarDataSize = DataSizeOfVariable (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
2438 ASSERT (VarDataSize != 0);
2439
2440 if (*DataSize >= VarDataSize) {
2441 if (Data == NULL) {
2442 Status = EFI_INVALID_PARAMETER;
2443 goto Done;
2444 }
2445
2446 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat), VarDataSize);
2447
2448 *DataSize = VarDataSize;
2449 UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE, &gVariableInfo);
2450
2451 Status = EFI_SUCCESS;
2452 goto Done;
2453 } else {
2454 *DataSize = VarDataSize;
2455 Status = EFI_BUFFER_TOO_SMALL;
2456 goto Done;
2457 }
2458
2459Done:
2460 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {
2461 if ((Attributes != NULL) && (Variable.CurrPtr != NULL)) {
2462 *Attributes = Variable.CurrPtr->Attributes;
2463 }
2464 }
2465
2466 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
2467 return Status;
2468}
2469
2501EFIAPI
2503 IN OUT UINTN *VariableNameSize,
2504 IN OUT CHAR16 *VariableName,
2505 IN OUT EFI_GUID *VendorGuid
2506 )
2507{
2508 EFI_STATUS Status;
2509 UINTN MaxLen;
2510 UINTN VarNameSize;
2511 BOOLEAN AuthFormat;
2512 VARIABLE_HEADER *VariablePtr;
2513 VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
2514
2515 if ((VariableNameSize == NULL) || (VariableName == NULL) || (VendorGuid == NULL)) {
2516 return EFI_INVALID_PARAMETER;
2517 }
2518
2519 AuthFormat = mVariableModuleGlobal->VariableGlobal.AuthFormat;
2520
2521 //
2522 // Calculate the possible maximum length of name string, including the Null terminator.
2523 //
2524 MaxLen = *VariableNameSize / sizeof (CHAR16);
2525 if ((MaxLen == 0) || (StrnLenS (VariableName, MaxLen) == MaxLen)) {
2526 //
2527 // Null-terminator is not found in the first VariableNameSize bytes of the input VariableName buffer,
2528 // follow spec to return EFI_INVALID_PARAMETER.
2529 //
2530 return EFI_INVALID_PARAMETER;
2531 }
2532
2533 AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
2534
2535 //
2536 // 0: Volatile, 1: HOB, 2: Non-Volatile.
2537 // The index and attributes mapping must be kept in this order as FindVariable
2538 // makes use of this mapping to implement search algorithm.
2539 //
2540 VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
2541 VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase;
2542 VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache;
2543
2545 VariableName,
2546 VendorGuid,
2547 VariableStoreHeader,
2548 &VariablePtr,
2549 AuthFormat
2550 );
2551 if (!EFI_ERROR (Status)) {
2552 VarNameSize = NameSizeOfVariable (VariablePtr, AuthFormat);
2553 ASSERT (VarNameSize != 0);
2554 if (VarNameSize <= *VariableNameSize) {
2555 CopyMem (
2556 VariableName,
2557 GetVariableNamePtr (VariablePtr, AuthFormat),
2558 VarNameSize
2559 );
2560 CopyMem (
2561 VendorGuid,
2562 GetVendorGuidPtr (VariablePtr, AuthFormat),
2563 sizeof (EFI_GUID)
2564 );
2565 Status = EFI_SUCCESS;
2566 } else {
2567 Status = EFI_BUFFER_TOO_SMALL;
2568 }
2569
2570 *VariableNameSize = VarNameSize;
2571 }
2572
2573 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
2574 return Status;
2575}
2576
2611EFIAPI
2613 IN CHAR16 *VariableName,
2614 IN EFI_GUID *VendorGuid,
2615 IN UINT32 Attributes,
2616 IN UINTN DataSize,
2617 IN VOID *Data
2618 )
2619{
2620 VARIABLE_POINTER_TRACK Variable;
2621 EFI_STATUS Status;
2622 VARIABLE_HEADER *NextVariable;
2624 UINTN PayloadSize;
2625 BOOLEAN AuthFormat;
2626
2627 AuthFormat = mVariableModuleGlobal->VariableGlobal.AuthFormat;
2628
2629 //
2630 // Check input parameters.
2631 //
2632 if ((VariableName == NULL) || (VariableName[0] == 0) || (VendorGuid == NULL)) {
2633 return EFI_INVALID_PARAMETER;
2634 }
2635
2636 if ((DataSize != 0) && (Data == NULL)) {
2637 return EFI_INVALID_PARAMETER;
2638 }
2639
2640 //
2641 // Check for reserverd bit in variable attribute.
2642 // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is deprecated but we still allow
2643 // the delete operation of common authenticated variable at user physical presence.
2644 // So leave EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute check to AuthVariableLib
2645 //
2646 if ((Attributes & (~(EFI_VARIABLE_ATTRIBUTES_MASK | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS))) != 0) {
2647 return EFI_INVALID_PARAMETER;
2648 }
2649
2650 //
2651 // Check if the combination of attribute bits is valid.
2652 //
2653 if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
2654 //
2655 // Make sure if runtime bit is set, boot service bit is set also.
2656 //
2657 if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
2658 return EFI_UNSUPPORTED;
2659 } else {
2660 return EFI_INVALID_PARAMETER;
2661 }
2662 } else if ((Attributes & EFI_VARIABLE_ATTRIBUTES_MASK) == EFI_VARIABLE_NON_VOLATILE) {
2663 //
2664 // Only EFI_VARIABLE_NON_VOLATILE attribute is invalid
2665 //
2666 if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
2667 return EFI_UNSUPPORTED;
2668 } else {
2669 return EFI_INVALID_PARAMETER;
2670 }
2671 } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {
2672 if (!mVariableModuleGlobal->VariableGlobal.AuthSupport) {
2673 //
2674 // Not support authenticated variable write.
2675 //
2676 return EFI_INVALID_PARAMETER;
2677 }
2678 } else if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
2679 if (PcdGet32 (PcdHwErrStorageSize) == 0) {
2680 //
2681 // Not support harware error record variable variable.
2682 //
2683 return EFI_INVALID_PARAMETER;
2684 }
2685 }
2686
2687 //
2688 // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS and EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute
2689 // cannot be set both.
2690 //
2693 {
2694 return EFI_UNSUPPORTED;
2695 }
2696
2698 //
2699 // If DataSize == AUTHINFO_SIZE and then PayloadSize is 0.
2700 // Maybe it's the delete operation of common authenticated variable at user physical presence.
2701 //
2702 if (DataSize != AUTHINFO_SIZE) {
2703 return EFI_UNSUPPORTED;
2704 }
2705
2706 PayloadSize = DataSize - AUTHINFO_SIZE;
2708 //
2709 // Sanity check for EFI_VARIABLE_AUTHENTICATION_2 descriptor.
2710 //
2711 if ((DataSize < OFFSET_OF_AUTHINFO2_CERT_DATA) ||
2712 (((EFI_VARIABLE_AUTHENTICATION_2 *)Data)->AuthInfo.Hdr.dwLength > DataSize - (OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo))) ||
2713 (((EFI_VARIABLE_AUTHENTICATION_2 *)Data)->AuthInfo.Hdr.dwLength < OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)))
2714 {
2715 return EFI_SECURITY_VIOLATION;
2716 }
2717
2718 //
2719 // The VariableSpeculationBarrier() call here is to ensure the above sanity
2720 // check for the EFI_VARIABLE_AUTHENTICATION_2 descriptor has been completed
2721 // before the execution of subsequent codes.
2722 //
2724 PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
2725 } else {
2726 PayloadSize = DataSize;
2727 }
2728
2729 if ((UINTN)(~0) - PayloadSize < StrSize (VariableName)) {
2730 //
2731 // Prevent whole variable size overflow
2732 //
2733 return EFI_INVALID_PARAMETER;
2734 }
2735
2736 //
2737 // The size of the VariableName, including the Unicode Null in bytes plus
2738 // the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)
2739 // bytes for HwErrRec#### variable.
2740 //
2742 if (StrSize (VariableName) + PayloadSize >
2743 PcdGet32 (PcdMaxHardwareErrorVariableSize) - GetVariableHeaderSize (AuthFormat))
2744 {
2745 return EFI_INVALID_PARAMETER;
2746 }
2747 } else {
2748 //
2749 // The size of the VariableName, including the Unicode Null in bytes plus
2750 // the DataSize is limited to maximum size of Max(Auth|Volatile)VariableSize bytes.
2751 //
2752 if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {
2753 if (StrSize (VariableName) + PayloadSize >
2754 mVariableModuleGlobal->MaxAuthVariableSize -
2755 GetVariableHeaderSize (AuthFormat))
2756 {
2757 DEBUG ((
2758 DEBUG_ERROR,
2759 "%a: Failed to set variable '%s' with Guid %g\n",
2760 __func__,
2761 VariableName,
2762 VendorGuid
2763 ));
2764 DEBUG ((
2765 DEBUG_ERROR,
2766 "NameSize(0x%x) + PayloadSize(0x%x) > "
2767 "MaxAuthVariableSize(0x%x) - HeaderSize(0x%x)\n",
2768 StrSize (VariableName),
2769 PayloadSize,
2770 mVariableModuleGlobal->MaxAuthVariableSize,
2771 GetVariableHeaderSize (AuthFormat)
2772 ));
2773 return EFI_INVALID_PARAMETER;
2774 }
2775 } else if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
2776 if (StrSize (VariableName) + PayloadSize >
2777 mVariableModuleGlobal->MaxVariableSize - GetVariableHeaderSize (AuthFormat))
2778 {
2779 DEBUG ((
2780 DEBUG_ERROR,
2781 "%a: Failed to set variable '%s' with Guid %g\n",
2782 __func__,
2783 VariableName,
2784 VendorGuid
2785 ));
2786 DEBUG ((
2787 DEBUG_ERROR,
2788 "NameSize(0x%x) + PayloadSize(0x%x) > "
2789 "MaxVariableSize(0x%x) - HeaderSize(0x%x)\n",
2790 StrSize (VariableName),
2791 PayloadSize,
2792 mVariableModuleGlobal->MaxVariableSize,
2793 GetVariableHeaderSize (AuthFormat)
2794 ));
2795 return EFI_INVALID_PARAMETER;
2796 }
2797 } else {
2798 if (StrSize (VariableName) + PayloadSize >
2799 mVariableModuleGlobal->MaxVolatileVariableSize - GetVariableHeaderSize (AuthFormat))
2800 {
2801 DEBUG ((
2802 DEBUG_ERROR,
2803 "%a: Failed to set variable '%s' with Guid %g\n",
2804 __func__,
2805 VariableName,
2806 VendorGuid
2807 ));
2808 DEBUG ((
2809 DEBUG_ERROR,
2810 "NameSize(0x%x) + PayloadSize(0x%x) > "
2811 "MaxVolatileVariableSize(0x%x) - HeaderSize(0x%x)\n",
2812 StrSize (VariableName),
2813 PayloadSize,
2814 mVariableModuleGlobal->MaxVolatileVariableSize,
2815 GetVariableHeaderSize (AuthFormat)
2816 ));
2817 return EFI_INVALID_PARAMETER;
2818 }
2819 }
2820 }
2821
2822 //
2823 // Special Handling for MOR Lock variable.
2824 //
2825 Status = SetVariableCheckHandlerMor (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *)((UINTN)Data + DataSize - PayloadSize));
2826 if (Status == EFI_ALREADY_STARTED) {
2827 //
2828 // EFI_ALREADY_STARTED means the SetVariable() action is handled inside of SetVariableCheckHandlerMor().
2829 // Variable driver can just return SUCCESS.
2830 //
2831 return EFI_SUCCESS;
2832 }
2833
2834 if (EFI_ERROR (Status)) {
2835 return Status;
2836 }
2837
2838 Status = VarCheckLibSetVariableCheck (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *)((UINTN)Data + DataSize - PayloadSize), mRequestSource);
2839 if (EFI_ERROR (Status)) {
2840 return Status;
2841 }
2842
2843 AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
2844
2845 //
2846 // Consider reentrant in MCA/INIT/NMI. It needs be reupdated.
2847 //
2848 if (1 < InterlockedIncrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState)) {
2849 Point = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
2850 //
2851 // Parse non-volatile variable data and get last variable offset.
2852 //
2853 NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)Point);
2854 while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)Point))) {
2855 NextVariable = GetNextVariablePtr (NextVariable, AuthFormat);
2856 }
2857
2858 mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN)NextVariable - (UINTN)Point;
2859 }
2860
2861 //
2862 // Check whether the input variable is already existed.
2863 //
2864 Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE);
2865 if (!EFI_ERROR (Status)) {
2866 if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {
2867 Status = EFI_WRITE_PROTECTED;
2868 goto Done;
2869 }
2870
2871 if ((Attributes != 0) && ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Variable.CurrPtr->Attributes)) {
2872 //
2873 // If a preexisting variable is rewritten with different attributes, SetVariable() shall not
2874 // modify the variable and shall return EFI_INVALID_PARAMETER. Two exceptions to this rule:
2875 // 1. No access attributes specified
2876 // 2. The only attribute differing is EFI_VARIABLE_APPEND_WRITE
2877 //
2878 Status = EFI_INVALID_PARAMETER;
2879 DEBUG ((DEBUG_INFO, "[Variable]: Rewritten a preexisting variable(0x%08x) with different attributes(0x%08x) - %g:%s\n", Variable.CurrPtr->Attributes, Attributes, VendorGuid, VariableName));
2880 goto Done;
2881 }
2882 }
2883
2884 if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
2885 //
2886 // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
2887 //
2888 Status = AutoUpdateLangVariable (VariableName, Data, DataSize);
2889 if (EFI_ERROR (Status)) {
2890 //
2891 // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.
2892 //
2893 goto Done;
2894 }
2895 }
2896
2897 if (mVariableModuleGlobal->VariableGlobal.AuthSupport) {
2898 Status = AuthVariableLibProcessVariable (VariableName, VendorGuid, Data, DataSize, Attributes);
2899 } else {
2900 Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, &Variable, NULL);
2901 }
2902
2903Done:
2904 InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
2905 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
2906
2907 if (!AtRuntime ()) {
2908 if (!EFI_ERROR (Status)) {
2910 VariableName,
2911 VendorGuid
2912 );
2913 }
2914 }
2915
2916 return Status;
2917}
2918
2939EFIAPI
2941 IN UINT32 Attributes,
2942 OUT UINT64 *MaximumVariableStorageSize,
2943 OUT UINT64 *RemainingVariableStorageSize,
2944 OUT UINT64 *MaximumVariableSize
2945 )
2946{
2947 VARIABLE_HEADER *Variable;
2948 VARIABLE_HEADER *NextVariable;
2949 UINT64 VariableSize;
2950 VARIABLE_STORE_HEADER *VariableStoreHeader;
2951 UINT64 CommonVariableTotalSize;
2952 UINT64 HwErrVariableTotalSize;
2953 EFI_STATUS Status;
2954 VARIABLE_POINTER_TRACK VariablePtrTrack;
2955
2956 CommonVariableTotalSize = 0;
2957 HwErrVariableTotalSize = 0;
2958
2959 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
2960 //
2961 // Query is Volatile related.
2962 //
2963 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
2964 } else {
2965 //
2966 // Query is Non-Volatile related.
2967 //
2968 VariableStoreHeader = mNvVariableCache;
2969 }
2970
2971 //
2972 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
2973 // with the storage size (excluding the storage header size).
2974 //
2975 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
2976
2977 //
2978 // Harware error record variable needs larger size.
2979 //
2981 *MaximumVariableStorageSize = PcdGet32 (PcdHwErrStorageSize);
2982 *MaximumVariableSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) -
2983 GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);
2984 } else {
2985 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
2986 if (AtRuntime ()) {
2987 *MaximumVariableStorageSize = mVariableModuleGlobal->CommonRuntimeVariableSpace;
2988 } else {
2989 *MaximumVariableStorageSize = mVariableModuleGlobal->CommonVariableSpace;
2990 }
2991 }
2992
2993 //
2994 // Let *MaximumVariableSize be Max(Auth|Volatile)VariableSize with the exception of the variable header size.
2995 //
2996 if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {
2997 *MaximumVariableSize = mVariableModuleGlobal->MaxAuthVariableSize -
2998 GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);
2999 } else if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
3000 *MaximumVariableSize = mVariableModuleGlobal->MaxVariableSize -
3001 GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);
3002 } else {
3003 *MaximumVariableSize = mVariableModuleGlobal->MaxVolatileVariableSize -
3004 GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);
3005 }
3006 }
3007
3008 //
3009 // Point to the starting address of the variables.
3010 //
3011 Variable = GetStartPointer (VariableStoreHeader);
3012
3013 //
3014 // Now walk through the related variable store.
3015 //
3016 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
3017 NextVariable = GetNextVariablePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat);
3018 VariableSize = (UINT64)(UINTN)NextVariable - (UINT64)(UINTN)Variable;
3019
3020 if (AtRuntime ()) {
3021 //
3022 // We don't take the state of the variables in mind
3023 // when calculating RemainingVariableStorageSize,
3024 // since the space occupied by variables not marked with
3025 // VAR_ADDED is not allowed to be reclaimed in Runtime.
3026 //
3028 HwErrVariableTotalSize += VariableSize;
3029 } else {
3030 CommonVariableTotalSize += VariableSize;
3031 }
3032 } else {
3033 //
3034 // Only care about Variables with State VAR_ADDED, because
3035 // the space not marked as VAR_ADDED is reclaimable now.
3036 //
3037 if (Variable->State == VAR_ADDED) {
3039 HwErrVariableTotalSize += VariableSize;
3040 } else {
3041 CommonVariableTotalSize += VariableSize;
3042 }
3043 } else if (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
3044 //
3045 // If it is a IN_DELETED_TRANSITION variable,
3046 // and there is not also a same ADDED one at the same time,
3047 // this IN_DELETED_TRANSITION variable is valid.
3048 //
3049 VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);
3050 VariablePtrTrack.EndPtr = GetEndPointer (VariableStoreHeader);
3051 Status = FindVariableEx (
3052 GetVariableNamePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat),
3053 GetVendorGuidPtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat),
3054 FALSE,
3055 &VariablePtrTrack,
3056 mVariableModuleGlobal->VariableGlobal.AuthFormat
3057 );
3058 if (!EFI_ERROR (Status) && (VariablePtrTrack.CurrPtr->State != VAR_ADDED)) {
3060 HwErrVariableTotalSize += VariableSize;
3061 } else {
3062 CommonVariableTotalSize += VariableSize;
3063 }
3064 }
3065 }
3066 }
3067
3068 //
3069 // Go to the next one.
3070 //
3071 Variable = NextVariable;
3072 }
3073
3075 *RemainingVariableStorageSize = *MaximumVariableStorageSize - HwErrVariableTotalSize;
3076 } else {
3077 if (*MaximumVariableStorageSize < CommonVariableTotalSize) {
3078 *RemainingVariableStorageSize = 0;
3079 } else {
3080 *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;
3081 }
3082 }
3083
3084 if (*RemainingVariableStorageSize < GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat)) {
3085 *MaximumVariableSize = 0;
3086 } else if ((*RemainingVariableStorageSize - GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat)) <
3087 *MaximumVariableSize
3088 )
3089 {
3090 *MaximumVariableSize = *RemainingVariableStorageSize -
3091 GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);
3092 }
3093
3094 return EFI_SUCCESS;
3095}
3096
3119EFIAPI
3121 IN UINT32 Attributes,
3122 OUT UINT64 *MaximumVariableStorageSize,
3123 OUT UINT64 *RemainingVariableStorageSize,
3124 OUT UINT64 *MaximumVariableSize
3125 )
3126{
3127 EFI_STATUS Status;
3128
3129 if ((MaximumVariableStorageSize == NULL) || (RemainingVariableStorageSize == NULL) || (MaximumVariableSize == NULL) || (Attributes == 0)) {
3130 return EFI_INVALID_PARAMETER;
3131 }
3132
3133 if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
3134 //
3135 // Deprecated attribute, make this check as highest priority.
3136 //
3137 return EFI_UNSUPPORTED;
3138 }
3139
3140 if ((Attributes & EFI_VARIABLE_ATTRIBUTES_MASK) == 0) {
3141 //
3142 // Make sure the Attributes combination is supported by the platform.
3143 //
3144 return EFI_UNSUPPORTED;
3145 } else if ((Attributes & EFI_VARIABLE_ATTRIBUTES_MASK) == EFI_VARIABLE_NON_VOLATILE) {
3146 //
3147 // Only EFI_VARIABLE_NON_VOLATILE attribute is invalid
3148 //
3149 return EFI_INVALID_PARAMETER;
3150 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
3151 //
3152 // Make sure if runtime bit is set, boot service bit is set also.
3153 //
3154 return EFI_INVALID_PARAMETER;
3155 } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
3156 //
3157 // Make sure RT Attribute is set if we are in Runtime phase.
3158 //
3159 return EFI_INVALID_PARAMETER;
3161 //
3162 // Make sure Hw Attribute is set with NV.
3163 //
3164 return EFI_INVALID_PARAMETER;
3165 } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {
3166 if (!mVariableModuleGlobal->VariableGlobal.AuthSupport) {
3167 //
3168 // Not support authenticated variable write.
3169 //
3170 return EFI_UNSUPPORTED;
3171 }
3172 } else if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
3173 if (PcdGet32 (PcdHwErrStorageSize) == 0) {
3174 //
3175 // Not support harware error record variable variable.
3176 //
3177 return EFI_UNSUPPORTED;
3178 }
3179 }
3180
3181 AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
3182
3184 Attributes,
3185 MaximumVariableStorageSize,
3186 RemainingVariableStorageSize,
3187 MaximumVariableSize
3188 );
3189
3190 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
3191 return Status;
3192}
3193
3201VOID
3203 VOID
3204 )
3205{
3206 EFI_STATUS Status;
3207 UINTN RemainingCommonRuntimeVariableSpace;
3208 UINTN RemainingHwErrVariableSpace;
3209 STATIC BOOLEAN Reclaimed;
3210
3211 //
3212 // This function will be called only once at EndOfDxe or ReadyToBoot event.
3213 //
3214 if (Reclaimed) {
3215 return;
3216 }
3217
3218 Reclaimed = TRUE;
3219
3220 Status = EFI_SUCCESS;
3221
3222 if (mVariableModuleGlobal->CommonRuntimeVariableSpace < mVariableModuleGlobal->CommonVariableTotalSize) {
3223 RemainingCommonRuntimeVariableSpace = 0;
3224 } else {
3225 RemainingCommonRuntimeVariableSpace = mVariableModuleGlobal->CommonRuntimeVariableSpace - mVariableModuleGlobal->CommonVariableTotalSize;
3226 }
3227
3228 RemainingHwErrVariableSpace = PcdGet32 (PcdHwErrStorageSize) - mVariableModuleGlobal->HwErrVariableTotalSize;
3229
3230 //
3231 // Check if the free area is below a threshold.
3232 //
3233 if (((RemainingCommonRuntimeVariableSpace < mVariableModuleGlobal->MaxVariableSize) ||
3234 (RemainingCommonRuntimeVariableSpace < mVariableModuleGlobal->MaxAuthVariableSize)) ||
3235 ((PcdGet32 (PcdHwErrStorageSize) != 0) &&
3236 (RemainingHwErrVariableSpace < PcdGet32 (PcdMaxHardwareErrorVariableSize))))
3237 {
3238 Status = Reclaim (
3239 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
3240 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
3241 FALSE,
3242 NULL,
3243 NULL,
3244 0
3245 );
3246 ASSERT_EFI_ERROR (Status);
3247 }
3248}
3249
3256UINTN
3258 VOID
3259 )
3260{
3261 UINTN MaxVariableSize;
3262
3263 MaxVariableSize = GetNonVolatileMaxVariableSize ();
3264 //
3265 // The condition below fails implicitly if PcdMaxVolatileVariableSize equals
3266 // the default zero value.
3267 //
3268 if (MaxVariableSize < PcdGet32 (PcdMaxVolatileVariableSize)) {
3269 MaxVariableSize = PcdGet32 (PcdMaxVolatileVariableSize);
3270 }
3271
3272 return MaxVariableSize;
3273}
3274
3282VOID
3284 IN CHAR16 *VariableName,
3285 IN EFI_GUID *VendorGuid
3286 )
3287{
3288 EFI_STATUS Status;
3289 VARIABLE_STORE_HEADER *VariableStoreHeader;
3290 VARIABLE_HEADER *Variable;
3291 VOID *VariableData;
3292 VARIABLE_POINTER_TRACK VariablePtrTrack;
3293 BOOLEAN ErrorFlag;
3294 BOOLEAN AuthFormat;
3295
3296 ErrorFlag = FALSE;
3297 AuthFormat = mVariableModuleGlobal->VariableGlobal.AuthFormat;
3298
3299 //
3300 // Flush the HOB variable to flash.
3301 //
3302 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
3303 VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase;
3304 //
3305 // Set HobVariableBase to 0, it can avoid SetVariable to call back.
3306 //
3307 mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
3308 for ( Variable = GetStartPointer (VariableStoreHeader)
3309 ; IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))
3310 ; Variable = GetNextVariablePtr (Variable, AuthFormat)
3311 )
3312 {
3313 if (Variable->State != VAR_ADDED) {
3314 //
3315 // The HOB variable has been set to DELETED state in local.
3316 //
3317 continue;
3318 }
3319
3320 ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
3321 if ((VendorGuid == NULL) || (VariableName == NULL) ||
3322 !CompareGuid (VendorGuid, GetVendorGuidPtr (Variable, AuthFormat)) ||
3323 (StrCmp (VariableName, GetVariableNamePtr (Variable, AuthFormat)) != 0))
3324 {
3325 VariableData = GetVariableDataPtr (Variable, AuthFormat);
3326 FindVariable (
3327 GetVariableNamePtr (Variable, AuthFormat),
3328 GetVendorGuidPtr (Variable, AuthFormat),
3329 &VariablePtrTrack,
3330 &mVariableModuleGlobal->VariableGlobal,
3331 FALSE
3332 );
3333 Status = UpdateVariable (
3334 GetVariableNamePtr (Variable, AuthFormat),
3335 GetVendorGuidPtr (Variable, AuthFormat),
3336 VariableData,
3337 DataSizeOfVariable (Variable, AuthFormat),
3338 Variable->Attributes,
3339 0,
3340 0,
3341 &VariablePtrTrack,
3342 NULL
3343 );
3344 DEBUG ((
3345 DEBUG_INFO,
3346 "Variable driver flush the HOB variable to flash: %g %s %r\n",
3347 GetVendorGuidPtr (Variable, AuthFormat),
3348 GetVariableNamePtr (Variable, AuthFormat),
3349 Status
3350 ));
3351 } else {
3352 //
3353 // The updated or deleted variable is matched with this HOB variable.
3354 // Don't break here because we will try to set other HOB variables
3355 // since this variable could be set successfully.
3356 //
3357 Status = EFI_SUCCESS;
3358 }
3359
3360 if (!EFI_ERROR (Status)) {
3361 //
3362 // If set variable successful, or the updated or deleted variable is matched with the HOB variable,
3363 // set the HOB variable to DELETED state in local.
3364 //
3365 DEBUG ((
3366 DEBUG_INFO,
3367 "Variable driver set the HOB variable to DELETED state in local: %g %s\n",
3368 GetVendorGuidPtr (Variable, AuthFormat),
3369 GetVariableNamePtr (Variable, AuthFormat)
3370 ));
3371 Variable->State &= VAR_DELETED;
3372 } else {
3373 ErrorFlag = TRUE;
3374 }
3375 }
3376
3377 if (mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeHobCache.Store != NULL) {
3379 &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeHobCache,
3380 0,
3381 mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeHobCache.Store->Size
3382 );
3383 ASSERT_EFI_ERROR (Status);
3384 }
3385
3386 if (ErrorFlag) {
3387 //
3388 // We still have HOB variable(s) not flushed in flash.
3389 //
3390 mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStoreHeader;
3391 } else {
3392 //
3393 // All HOB variables have been flushed in flash.
3394 //
3395 DEBUG ((DEBUG_INFO, "Variable driver: all HOB variables have been flushed in flash.\n"));
3396 if (mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.HobFlushComplete != NULL) {
3397 *(mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.HobFlushComplete) = TRUE;
3398 }
3399
3400 if (!AtRuntime ()) {
3401 FreePool ((VOID *)VariableStoreHeader);
3402 }
3403 }
3404 }
3405}
3406
3416 VOID
3417 )
3418{
3419 EFI_STATUS Status;
3420 UINTN Index;
3421 UINT8 Data;
3422 VARIABLE_ENTRY_PROPERTY *VariableEntry;
3423
3424 AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
3425
3426 //
3427 // Check if the free area is really free.
3428 //
3429 for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < mNvVariableCache->Size; Index++) {
3430 Data = ((UINT8 *)mNvVariableCache)[Index];
3431 if (Data != 0xff) {
3432 //
3433 // There must be something wrong in variable store, do reclaim operation.
3434 //
3435 Status = Reclaim (
3436 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
3437 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
3438 FALSE,
3439 NULL,
3440 NULL,
3441 0
3442 );
3443 if (EFI_ERROR (Status)) {
3444 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
3445 return Status;
3446 }
3447
3448 break;
3449 }
3450 }
3451
3453
3454 Status = EFI_SUCCESS;
3455 ZeroMem (&mAuthContextOut, sizeof (mAuthContextOut));
3456 if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
3457 //
3458 // Authenticated variable initialize.
3459 //
3460 mAuthContextIn.StructSize = sizeof (AUTH_VAR_LIB_CONTEXT_IN);
3461 mAuthContextIn.MaxAuthVariableSize = mVariableModuleGlobal->MaxAuthVariableSize -
3462 GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);
3463 Status = AuthVariableLibInitialize (&mAuthContextIn, &mAuthContextOut);
3464 if (!EFI_ERROR (Status)) {
3465 DEBUG ((DEBUG_INFO, "Variable driver will work with auth variable support!\n"));
3466 mVariableModuleGlobal->VariableGlobal.AuthSupport = TRUE;
3467 if (mAuthContextOut.AuthVarEntry != NULL) {
3468 for (Index = 0; Index < mAuthContextOut.AuthVarEntryCount; Index++) {
3469 VariableEntry = &mAuthContextOut.AuthVarEntry[Index];
3471 VariableEntry->Name,
3472 VariableEntry->Guid,
3473 &VariableEntry->VariableProperty
3474 );
3475 ASSERT_EFI_ERROR (Status);
3476 }
3477 }
3478 } else if (Status == EFI_UNSUPPORTED) {
3479 DEBUG ((DEBUG_INFO, "NOTICE - AuthVariableLibInitialize() returns %r!\n", Status));
3480 DEBUG ((DEBUG_INFO, "Variable driver will continue to work without auth variable support!\n"));
3481 mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;
3482 Status = EFI_SUCCESS;
3483 }
3484 }
3485
3486 if (!EFI_ERROR (Status)) {
3487 for (Index = 0; Index < ARRAY_SIZE (mVariableEntryProperty); Index++) {
3488 VariableEntry = &mVariableEntryProperty[Index];
3489 Status = VarCheckLibVariablePropertySet (VariableEntry->Name, VariableEntry->Guid, &VariableEntry->VariableProperty);
3490 ASSERT_EFI_ERROR (Status);
3491 }
3492 }
3493
3494 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
3495
3496 //
3497 // Initialize MOR Lock variable.
3498 //
3499 MorLockInit ();
3500
3501 return Status;
3502}
3503
3511VOID *
3513 VARIABLE_STORE_HEADER *NormalVarStorage
3514 )
3515{
3516 VARIABLE_HEADER *StartPtr;
3517 UINT8 *NextPtr;
3518 VARIABLE_HEADER *EndPtr;
3519 UINTN AuthVarStroageSize;
3520 AUTHENTICATED_VARIABLE_HEADER *AuthStartPtr;
3521 VARIABLE_STORE_HEADER *AuthVarStorage;
3522
3523 AuthVarStroageSize = sizeof (VARIABLE_STORE_HEADER);
3524 //
3525 // Set AuthFormat as FALSE for normal variable storage
3526 //
3527 mVariableModuleGlobal->VariableGlobal.AuthFormat = FALSE;
3528
3529 //
3530 // Calculate Auth Variable Storage Size
3531 //
3532 StartPtr = GetStartPointer (NormalVarStorage);
3533 EndPtr = GetEndPointer (NormalVarStorage);
3534 while (StartPtr < EndPtr) {
3535 if (StartPtr->State == VAR_ADDED) {
3536 AuthVarStroageSize = HEADER_ALIGN (AuthVarStroageSize);
3537 AuthVarStroageSize += sizeof (AUTHENTICATED_VARIABLE_HEADER);
3538 AuthVarStroageSize += StartPtr->NameSize + GET_PAD_SIZE (StartPtr->NameSize);
3539 AuthVarStroageSize += StartPtr->DataSize + GET_PAD_SIZE (StartPtr->DataSize);
3540 }
3541
3542 StartPtr = GetNextVariablePtr (StartPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
3543 }
3544
3545 //
3546 // Allocate Runtime memory for Auth Variable Storage
3547 //
3548 AuthVarStorage = AllocateRuntimeZeroPool (AuthVarStroageSize);
3549 ASSERT (AuthVarStorage != NULL);
3550 if (AuthVarStorage == NULL) {
3551 return NULL;
3552 }
3553
3554 //
3555 // Copy Variable from Normal storage to Auth storage
3556 //
3557 StartPtr = GetStartPointer (NormalVarStorage);
3558 EndPtr = GetEndPointer (NormalVarStorage);
3559 AuthStartPtr = (AUTHENTICATED_VARIABLE_HEADER *)GetStartPointer (AuthVarStorage);
3560 while (StartPtr < EndPtr) {
3561 if (StartPtr->State == VAR_ADDED) {
3562 AuthStartPtr = (AUTHENTICATED_VARIABLE_HEADER *)HEADER_ALIGN (AuthStartPtr);
3563 //
3564 // Copy Variable Header
3565 //
3566 AuthStartPtr->StartId = StartPtr->StartId;
3567 AuthStartPtr->State = StartPtr->State;
3568 AuthStartPtr->Attributes = StartPtr->Attributes;
3569 AuthStartPtr->NameSize = StartPtr->NameSize;
3570 AuthStartPtr->DataSize = StartPtr->DataSize;
3571 CopyGuid (&AuthStartPtr->VendorGuid, &StartPtr->VendorGuid);
3572 //
3573 // Copy Variable Name
3574 //
3575 NextPtr = (UINT8 *)(AuthStartPtr + 1);
3576 CopyMem (
3577 NextPtr,
3578 GetVariableNamePtr (StartPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat),
3579 AuthStartPtr->NameSize
3580 );
3581 //
3582 // Copy Variable Data
3583 //
3584 NextPtr = NextPtr + AuthStartPtr->NameSize + GET_PAD_SIZE (AuthStartPtr->NameSize);
3585 CopyMem (NextPtr, GetVariableDataPtr (StartPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat), AuthStartPtr->DataSize);
3586 //
3587 // Go to next variable
3588 //
3589 AuthStartPtr = (AUTHENTICATED_VARIABLE_HEADER *)(NextPtr + AuthStartPtr->DataSize + GET_PAD_SIZE (AuthStartPtr->DataSize));
3590 }
3591
3592 StartPtr = GetNextVariablePtr (StartPtr, mVariableModuleGlobal->VariableGlobal.AuthFormat);
3593 }
3594
3595 //
3596 // Update Auth Storage Header
3597 //
3598 AuthVarStorage->Format = NormalVarStorage->Format;
3599 AuthVarStorage->State = NormalVarStorage->State;
3600 AuthVarStorage->Size = (UINT32)((UINTN)AuthStartPtr - (UINTN)AuthVarStorage);
3601 CopyGuid (&AuthVarStorage->Signature, &gEfiAuthenticatedVariableGuid);
3602 ASSERT (AuthVarStorage->Size <= AuthVarStroageSize);
3603
3604 //
3605 // Restore AuthFormat
3606 //
3607 mVariableModuleGlobal->VariableGlobal.AuthFormat = TRUE;
3608 return AuthVarStorage;
3609}
3610
3622 IN EFI_GUID *VariableGuid
3623 )
3624{
3625 VARIABLE_STORE_HEADER *VariableStoreHeader;
3626 UINT64 VariableStoreLength;
3627 EFI_HOB_GUID_TYPE *GuidHob;
3628 BOOLEAN NeedConvertNormalToAuth;
3629
3630 //
3631 // Make sure there is no more than one Variable HOB.
3632 //
3634 GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
3635 if (GuidHob != NULL) {
3636 if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {
3637 DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n"));
3638 ASSERT (FALSE);
3639 } else if (GetFirstGuidHob (&gEfiVariableGuid) != NULL) {
3640 DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable HOBs\n"));
3641 ASSERT (FALSE);
3642 }
3643 } else {
3644 GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
3645 if (GuidHob != NULL) {
3646 if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {
3647 DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"));
3648 ASSERT (FALSE);
3649 }
3650 }
3651 }
3652
3653 DEBUG_CODE_END ();
3654
3655 //
3656 // Combinations supported:
3657 // 1. Normal NV variable store +
3658 // Normal HOB variable store
3659 // 2. Auth NV variable store +
3660 // Auth HOB variable store
3661 // 3. Auth NV variable store +
3662 // Normal HOB variable store (code will convert it to Auth Format)
3663 //
3664 NeedConvertNormalToAuth = FALSE;
3665 GuidHob = GetFirstGuidHob (VariableGuid);
3666 if ((GuidHob == NULL) && (VariableGuid == &gEfiAuthenticatedVariableGuid)) {
3667 //
3668 // Try getting it from normal variable HOB
3669 //
3670 GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
3671 NeedConvertNormalToAuth = TRUE;
3672 }
3673
3674 if (GuidHob != NULL) {
3675 VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);
3676 VariableStoreLength = GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE);
3677 if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
3678 if (!NeedConvertNormalToAuth) {
3679 mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateRuntimeCopyPool ((UINTN)VariableStoreLength, (VOID *)VariableStoreHeader);
3680 } else {
3681 mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ConvertNormalVarStorageToAuthVarStorage ((VOID *)VariableStoreHeader);
3682 }
3683
3684 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {
3685 return EFI_OUT_OF_RESOURCES;
3686 }
3687 } else {
3688 DEBUG ((DEBUG_ERROR, "HOB Variable Store header is corrupted!\n"));
3689 }
3690 }
3691
3692 return EFI_SUCCESS;
3693}
3694
3704 VOID
3705 )
3706{
3707 EFI_STATUS Status;
3708 VARIABLE_STORE_HEADER *VolatileVariableStore;
3709 UINTN ScratchSize;
3710 EFI_GUID *VariableGuid;
3711
3712 //
3713 // Allocate runtime memory for variable driver global structure.
3714 //
3715 mVariableModuleGlobal = AllocateRuntimeZeroPool (sizeof (VARIABLE_MODULE_GLOBAL));
3716 if (mVariableModuleGlobal == NULL) {
3717 return EFI_OUT_OF_RESOURCES;
3718 }
3719
3720 InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);
3721
3722 //
3723 // Init non-volatile variable store.
3724 //
3725 Status = InitNonVolatileVariableStore ();
3726 if (EFI_ERROR (Status)) {
3727 FreePool (mVariableModuleGlobal);
3728 return Status;
3729 }
3730
3731 //
3732 // mVariableModuleGlobal->VariableGlobal.AuthFormat
3733 // has been initialized in InitNonVolatileVariableStore().
3734 //
3735 if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
3736 DEBUG ((DEBUG_INFO, "Variable driver will work with auth variable format!\n"));
3737 //
3738 // Set AuthSupport to FALSE first, VariableWriteServiceInitialize() will initialize it.
3739 //
3740 mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;
3741 VariableGuid = &gEfiAuthenticatedVariableGuid;
3742 } else {
3743 DEBUG ((DEBUG_INFO, "Variable driver will work without auth variable support!\n"));
3744 mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;
3745 VariableGuid = &gEfiVariableGuid;
3746 }
3747
3748 //
3749 // Get HOB variable store.
3750 //
3751 Status = GetHobVariableStore (VariableGuid);
3752 if (EFI_ERROR (Status)) {
3753 if (mNvFvHeaderCache != NULL) {
3755 }
3756
3757 FreePool (mVariableModuleGlobal);
3758 return Status;
3759 }
3760
3761 mVariableModuleGlobal->MaxVolatileVariableSize = ((PcdGet32 (PcdMaxVolatileVariableSize) != 0) ?
3762 PcdGet32 (PcdMaxVolatileVariableSize) :
3763 mVariableModuleGlobal->MaxVariableSize
3764 );
3765 //
3766 // Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.
3767 //
3768 ScratchSize = GetMaxVariableSize ();
3769 mVariableModuleGlobal->ScratchBufferSize = ScratchSize;
3770 VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);
3771 if (VolatileVariableStore == NULL) {
3772 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
3773 FreePool ((VOID *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase);
3774 }
3775
3776 if (mNvFvHeaderCache != NULL) {
3778 }
3779
3780 FreePool (mVariableModuleGlobal);
3781 return EFI_OUT_OF_RESOURCES;
3782 }
3783
3784 SetMem (VolatileVariableStore, PcdGet32 (PcdVariableStoreSize) + ScratchSize, 0xff);
3785
3786 //
3787 // Initialize Variable Specific Data.
3788 //
3789 mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VolatileVariableStore;
3790 mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN)GetStartPointer (VolatileVariableStore) - (UINTN)VolatileVariableStore;
3791
3792 CopyGuid (&VolatileVariableStore->Signature, VariableGuid);
3793 VolatileVariableStore->Size = PcdGet32 (PcdVariableStoreSize);
3794 VolatileVariableStore->Format = VARIABLE_STORE_FORMATTED;
3795 VolatileVariableStore->State = VARIABLE_STORE_HEALTHY;
3796 VolatileVariableStore->Reserved = 0;
3797 VolatileVariableStore->Reserved1 = 0;
3798
3799 return EFI_SUCCESS;
3800}
3801
3812 IN EFI_PHYSICAL_ADDRESS Address,
3813 OUT EFI_HANDLE *FvbHandle OPTIONAL,
3814 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvbProtocol OPTIONAL
3815 )
3816{
3817 EFI_STATUS Status;
3818 EFI_HANDLE *HandleBuffer;
3819 UINTN HandleCount;
3820 UINTN Index;
3821 EFI_PHYSICAL_ADDRESS FvbBaseAddress;
3823 EFI_FVB_ATTRIBUTES_2 Attributes;
3824 UINTN BlockSize;
3825 UINTN NumberOfBlocks;
3826
3827 HandleBuffer = NULL;
3828 //
3829 // Get all FVB handles.
3830 //
3831 Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
3832 if (EFI_ERROR (Status)) {
3833 return EFI_NOT_FOUND;
3834 }
3835
3836 //
3837 // Get the FVB to access variable store.
3838 //
3839 Fvb = NULL;
3840 for (Index = 0; Index < HandleCount; Index += 1, Status = EFI_NOT_FOUND, Fvb = NULL) {
3841 Status = GetFvbByHandle (HandleBuffer[Index], &Fvb);
3842 if (EFI_ERROR (Status)) {
3843 Status = EFI_NOT_FOUND;
3844 break;
3845 }
3846
3847 //
3848 // Ensure this FVB protocol supported Write operation.
3849 //
3850 Status = Fvb->GetAttributes (Fvb, &Attributes);
3851 if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
3852 continue;
3853 }
3854
3855 //
3856 // Compare the address and select the right one.
3857 //
3858 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
3859 if (EFI_ERROR (Status)) {
3860 continue;
3861 }
3862
3863 //
3864 // Assume one FVB has one type of BlockSize.
3865 //
3866 Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
3867 if (EFI_ERROR (Status)) {
3868 continue;
3869 }
3870
3871 if ((Address >= FvbBaseAddress) && (Address < (FvbBaseAddress + BlockSize * NumberOfBlocks))) {
3872 if (FvbHandle != NULL) {
3873 *FvbHandle = HandleBuffer[Index];
3874 }
3875
3876 if (FvbProtocol != NULL) {
3877 *FvbProtocol = Fvb;
3878 }
3879
3880 Status = EFI_SUCCESS;
3881 break;
3882 }
3883 }
3884
3885 FreePool (HandleBuffer);
3886
3887 if (Fvb == NULL) {
3888 Status = EFI_NOT_FOUND;
3889 }
3890
3891 return Status;
3892}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
VOID *EFIAPI GetNextGuidHob(IN CONST EFI_GUID *Guid, IN CONST VOID *HobStart)
Definition: HobLib.c:176
EFI_STATUS EFIAPI AuthVariableLibInitialize(IN AUTH_VAR_LIB_CONTEXT_IN *AuthVarLibContextIn, OUT AUTH_VAR_LIB_CONTEXT_OUT *AuthVarLibContextOut)
EFI_STATUS EFIAPI AuthVariableLibProcessVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN VOID *Data, IN UINTN DataSize, IN UINT32 Attributes)
#define AUTHINFO_SIZE
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
INTN EFIAPI AsciiStrnCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString, IN UINTN Length)
Definition: String.c:872
UINTN EFIAPI StrnLenS(IN CONST CHAR16 *String, IN UINTN MaxSize)
Definition: SafeString.c:119
UINTN EFIAPI AsciiStrSize(IN CONST CHAR8 *String)
Definition: String.c:681
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateRuntimePool(IN UINTN AllocationSize)
VOID *EFIAPI AllocateRuntimeCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
VOID *EFIAPI AllocateRuntimeZeroPool(IN UINTN AllocationSize)
#define EFI_LANG_VARIABLE_NAME
#define EFI_PLATFORM_LANG_CODES_VARIABLE_NAME
#define EFI_LANG_CODES_VARIABLE_NAME
#define EFI_PLATFORM_LANG_VARIABLE_NAME
VOID EFIAPI SecureBootHook(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
Definition: Measurement.c:236
EFI_STATUS GetFvbByHandle(IN EFI_HANDLE FvBlockHandle, OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock)
Definition: VariableDxe.c:180
EFI_LOCK * InitializeLock(IN OUT EFI_LOCK *Lock, IN EFI_TPL Priority)
Definition: VariableDxe.c:87
EFI_STATUS EFIAPI VariableExLibGetScratchBuffer(IN OUT UINTN *ScratchBufferSize, OUT VOID **ScratchBuffer)
BOOLEAN AtRuntime(VOID)
Definition: VariableDxe.c:63
VOID ReleaseLockOnlyAtBootTime(IN EFI_LOCK *Lock)
Definition: VariableDxe.c:130
BOOLEAN EFIAPI VariableExLibAtRuntime(VOID)
BOOLEAN EFIAPI VariableExLibCheckRemainingSpaceForConsistency(IN UINT32 Attributes,...)
VOID AcquireLockOnlyAtBootTime(IN EFI_LOCK *Lock)
Definition: VariableDxe.c:108
EFI_STATUS EFIAPI VariableExLibFindVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT AUTH_VARIABLE_INFO *AuthVariableInfo)
Definition: VariableExLib.c:32
EFI_STATUS EFIAPI VariableExLibUpdateVariable(IN AUTH_VARIABLE_INFO *AuthVariableInfo)
EFI_STATUS EFIAPI VariableExLibFindNextVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT AUTH_VARIABLE_INFO *AuthVariableInfo)
Definition: VariableExLib.c:92
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define MIN(a, b)
Definition: Base.h:1007
#define VA_ARG(Marker, TYPE)
Definition: Base.h:679
#define VA_START(Marker, Parameter)
Definition: Base.h:661
#define VA_COPY(Dest, Start)
Definition: Base.h:704
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
CHAR8 * VA_LIST
Definition: Base.h:643
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define VA_END(Marker)
Definition: Base.h:691
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
UINT32 EFI_FVB_ATTRIBUTES_2
#define EFI_NOT_AVAILABLE_YET
Definition: PiMultiPhase.h:54
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_STATUS MorLockInit(VOID)
Definition: TcgMorLockDxe.c:65
EFI_STATUS SetVariableCheckHandlerMor(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
Definition: TcgMorLockDxe.c:44
VOID VariableSpeculationBarrier(VOID)
EFI_STATUS FtwVariableSpace(IN EFI_PHYSICAL_ADDRESS VariableBase, IN VARIABLE_STORE_HEADER *VariableBuffer)
Definition: Reclaim.c:104
UINT32 EFIAPI InterlockedIncrement(IN volatile UINT32 *Value)
UINT32 EFIAPI InterlockedDecrement(IN volatile UINT32 *Value)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD
#define EFI_VARIABLE_NON_VOLATILE
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
EFI_STATUS GetFvbCountAndBuffer(OUT UINTN *NumberHandles, OUT EFI_HANDLE **Buffer)
UINTN NameSizeOfVariable(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:174
VARIABLE_HEADER * GetStartPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:86
VARIABLE_STORE_STATUS GetVariableStoreStatus(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:372
UINT8 * GetVariableDataPtr(IN VARIABLE_HEADER *Variable, IN VARIABLE_HEADER *VariableHeader, IN BOOLEAN AuthFlag)
Definition: Variable.c:300
VOID GetHobVariableStore(OUT VARIABLE_STORE_INFO *StoreInfo, OUT VARIABLE_STORE_HEADER **VariableStoreHeader)
Definition: Variable.c:540
CHAR16 * GetVariableNamePtr(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:256
EFI_STATUS FindVariable(IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VendorGuid, OUT VARIABLE_POINTER_TRACK *PtrTrack, OUT VARIABLE_STORE_INFO *StoreInfo)
Definition: Variable.c:992
VARIABLE_HEADER * GetEndPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:109
BOOLEAN IsValidVariableHeader(IN VARIABLE_HEADER *Variable)
Definition: Variable.c:129
UINTN DataSizeOfVariable(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:215
EFI_STATUS FindVariableEx(IN VARIABLE_STORE_INFO *StoreInfo, IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VendorGuid, OUT VARIABLE_POINTER_TRACK *PtrTrack)
Definition: Variable.c:844
UINTN GetVariableHeaderSize(IN BOOLEAN AuthFlag)
Definition: Variable.c:149
VARIABLE_HEADER * GetNextVariablePtr(IN VARIABLE_STORE_INFO *StoreInfo, IN VARIABLE_HEADER *Variable, IN VARIABLE_HEADER *VariableHeader)
Definition: Variable.c:329
EFI_GUID * GetVendorGuidPtr(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:274
EFI_FIRMWARE_VOLUME_HEADER * mNvFvHeaderCache
Definition: Variable.c:44
BOOLEAN mEndOfDxe
Definition: Variable.c:54
CHAR8 *EFIAPI VariableGetBestLanguage(IN CONST CHAR8 *SupportedLanguages, IN UINTN Iso639Language,...)
Definition: Variable.c:1118
VARIABLE_INFO_ENTRY * gVariableInfo
Definition: Variable.c:49
BOOLEAN IsUserVariable(IN VARIABLE_HEADER *Variable)
Definition: Variable.c:415
UINTN GetMaxVariableSize(VOID)
Definition: Variable.c:3257
EFI_STATUS EFIAPI VariableServiceGetVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data OPTIONAL)
Definition: Variable.c:2407
EFI_STATUS UpdateVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN VOID *Data, IN UINTN DataSize, IN UINT32 Attributes OPTIONAL, IN UINT32 KeyIndex OPTIONAL, IN UINT64 MonotonicCount OPTIONAL, IN OUT VARIABLE_POINTER_TRACK *CacheVariable, IN EFI_TIME *TimeStamp OPTIONAL)
Definition: Variable.c:1678
VOID CalculateCommonUserVariableTotalSize(VOID)
Definition: Variable.c:445
VOID InitializeVariableQuota(VOID)
Definition: Variable.c:488
UINTN GetIndexFromSupportedLangCodes(IN CHAR8 *SupportedLang, IN CHAR8 *Lang, IN BOOLEAN Iso639Language)
Definition: Variable.c:930
VOID InitializeVarErrorFlag(VOID)
Definition: Variable.c:362
EFI_STATUS Reclaim(IN EFI_PHYSICAL_ADDRESS VariableBase, OUT UINTN *LastVariableOffset, IN BOOLEAN IsVolatile, IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack, IN VARIABLE_HEADER *NewVariable, IN UINTN NewVariableSize)
Definition: Variable.c:518
CHAR8 * GetLangFromSupportedLangCodes(IN CHAR8 *SupportedLang, IN UINTN Index, IN BOOLEAN Iso639Language)
Definition: Variable.c:1017
VOID * ConvertNormalVarStorageToAuthVarStorage(VARIABLE_STORE_HEADER *NormalVarStorage)
Definition: Variable.c:3512
BOOLEAN EFIAPI CheckRemainingSpaceForConsistencyInternal(IN UINT32 Attributes, IN VA_LIST Marker)
Definition: Variable.c:1240
VARIABLE_STORE_HEADER * mNvVariableCache
Definition: Variable.c:39
EFI_STATUS VariableWriteServiceInitialize(VOID)
Definition: Variable.c:3415
VOID ReclaimForOS(VOID)
Definition: Variable.c:3202
EFI_STATUS VariableCommonInitialize(VOID)
Definition: Variable.c:3703
EFI_STATUS EFIAPI VariableServiceGetNextVariableName(IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid)
Definition: Variable.c:2502
VAR_CHECK_REQUEST_SOURCE mRequestSource
Definition: Variable.c:60
EFI_STATUS EFIAPI VariableServiceQueryVariableInfo(IN UINT32 Attributes, OUT UINT64 *MaximumVariableStorageSize, OUT UINT64 *RemainingVariableStorageSize, OUT UINT64 *MaximumVariableSize)
Definition: Variable.c:3120
EFI_STATUS UpdateVariableStore(IN VARIABLE_GLOBAL *Global, IN BOOLEAN Volatile, IN BOOLEAN SetByIndex, IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, IN UINTN DataPtrIndex, IN UINT32 DataSize, IN UINT8 *Buffer)
Definition: Variable.c:123
EFI_STATUS AutoUpdateLangVariable(IN CHAR16 *VariableName, IN VOID *Data, IN UINTN DataSize)
Definition: Variable.c:1415
EFI_STATUS GetFvbInfoByAddress(IN EFI_PHYSICAL_ADDRESS Address, OUT EFI_HANDLE *FvbHandle OPTIONAL, OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvbProtocol OPTIONAL)
Definition: Variable.c:3811
VOID FlushHobVariableToFlash(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
Definition: Variable.c:3283
EFI_STATUS EFIAPI VariableServiceQueryVariableInfoInternal(IN UINT32 Attributes, OUT UINT64 *MaximumVariableStorageSize, OUT UINT64 *RemainingVariableStorageSize, OUT UINT64 *MaximumVariableSize)
Definition: Variable.c:2940
BOOLEAN EFIAPI CheckRemainingSpaceForConsistency(IN UINT32 Attributes,...)
Definition: Variable.c:1377
EFI_STATUS EFIAPI VariableServiceSetVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
Definition: Variable.c:2612
VOID RecordVarErrorFlag(IN VAR_ERROR_FLAG Flag, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN VariableSize)
Definition: Variable.c:272
EFI_STATUS EFIAPI VarCheckLibVariablePropertySet(IN CHAR16 *Name, IN EFI_GUID *Guid, IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty)
Definition: VarCheckLib.c:483
EFI_STATUS EFIAPI VarCheckLibSetVariableCheck(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data, IN VAR_CHECK_REQUEST_SOURCE RequestSource)
Definition: VarCheckLib.c:607
EFI_STATUS EFIAPI VarCheckLibVariablePropertyGet(IN CHAR16 *Name, IN EFI_GUID *Guid, OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty)
Definition: VarCheckLib.c:558
#define VAR_DELETED
Variable is obsolete.
#define VAR_IN_DELETED_TRANSITION
Variable is in obsolete transition.
#define VARIABLE_DATA
#define VARIABLE_ATTRIBUTE_AT_AW
#define VARIABLE_STORE_FORMATTED
#define VAR_ADDED
Variable has been completely added.
EFI_STATUS InitNonVolatileVariableStore(VOID)
UINTN GetNonVolatileMaxVariableSize(VOID)
VOID SetDataSizeOfVariable(IN VARIABLE_HEADER *Variable, IN UINTN DataSize, IN BOOLEAN AuthFormat)
EFI_STATUS EFIAPI VariableServiceGetNextVariableInternal(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN VARIABLE_STORE_HEADER **VariableStoreList, OUT VARIABLE_HEADER **VariablePtr, IN BOOLEAN AuthFormat)
UINTN GetVariableDataOffset(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFormat)
VOID SetNameSizeOfVariable(IN VARIABLE_HEADER *Variable, IN UINTN NameSize, IN BOOLEAN AuthFormat)
VOID UpdateVariableInfo(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN BOOLEAN Volatile, IN BOOLEAN Read, IN BOOLEAN Write, IN BOOLEAN Delete, IN BOOLEAN Cache, IN OUT VARIABLE_INFO_ENTRY **VariableInfo)
BOOLEAN VariableCompareTimeStampInternal(IN EFI_TIME *FirstTime, IN EFI_TIME *SecondTime)
EFI_STATUS SynchronizeRuntimeVariableCache(IN VARIABLE_RUNTIME_CACHE *VariableRuntimeCache, IN UINTN Offset, IN UINTN Length)
EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]
EFI_HOB_GENERIC_HEADER Header
Definition: PiHob.h:343
Definition: Base.h:213