Changeset 58459 in vbox for trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
- Timestamp:
- Oct 28, 2015 8:17:18 PM (9 years ago)
- Location:
- trunk/src/VBox/Devices/EFI/Firmware
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/Firmware
-
Property svn:mergeinfo
set to (toggle deleted branches)
/vendor/edk2/current 103735-103757
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
r48674 r58459 1 1 /** @file 2 2 3 The common variable operation routines shared by DXE_R INTIME variable3 The common variable operation routines shared by DXE_RUNTIME variable 4 4 module and DXE_SMM variable module. 5 5 6 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> 6 Caution: This module requires additional review when modified. 7 This driver will have external input - variable data. They may be input in SMM mode. 8 This external input must be validated carefully to avoid security issue like 9 buffer overflow, integer overflow. 10 11 VariableServiceGetNextVariableName () and VariableServiceQueryVariableInfo() are external API. 12 They need check input parameter. 13 14 VariableServiceGetVariable() and VariableServiceSetVariable() are external API 15 to receive datasize and data buffer. The size should be checked carefully. 16 17 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 7 18 This program and the accompanying materials 8 19 are licensed and made available under the terms and conditions of the BSD License … … 22 33 /// Define a memory cache that improves the search performance for a variable. 23 34 /// 24 VARIABLE_STORE_HEADER *mNvVariableCache = NULL;35 VARIABLE_STORE_HEADER *mNvVariableCache = NULL; 25 36 26 37 /// 27 38 /// The memory entry used for variable statistics data. 28 39 /// 29 VARIABLE_INFO_ENTRY *gVariableInfo = NULL; 30 40 VARIABLE_INFO_ENTRY *gVariableInfo = NULL; 41 42 /// 43 /// The list to store the variables which cannot be set after the EFI_END_OF_DXE_EVENT_GROUP_GUID 44 /// or EVT_GROUP_READY_TO_BOOT event. 45 /// 46 LIST_ENTRY mLockedVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mLockedVariableList); 47 48 /// 49 /// The flag to indicate whether the platform has left the DXE phase of execution. 50 /// 51 BOOLEAN mEndOfDxe = FALSE; 52 53 /// 54 /// The flag to indicate whether the variable storage locking is enabled. 55 /// 56 BOOLEAN mEnableLocking = TRUE; 57 58 // 59 // To prevent name collisions with possible future globally defined variables, 60 // other internal firmware data variables that are not defined here must be 61 // saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or 62 // any other GUID defined by the UEFI Specification. Implementations must 63 // only permit the creation of variables with a UEFI Specification-defined 64 // VendorGuid when these variables are documented in the UEFI Specification. 65 // 66 GLOBAL_VARIABLE_ENTRY mGlobalVariableList[] = { 67 {EFI_LANG_CODES_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 68 {EFI_LANG_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 69 {EFI_TIME_OUT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 70 {EFI_PLATFORM_LANG_CODES_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 71 {EFI_PLATFORM_LANG_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 72 {EFI_CON_IN_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 73 {EFI_CON_OUT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 74 {EFI_ERR_OUT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 75 {EFI_CON_IN_DEV_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 76 {EFI_CON_OUT_DEV_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 77 {EFI_ERR_OUT_DEV_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 78 {EFI_BOOT_ORDER_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 79 {EFI_BOOT_NEXT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 80 {EFI_BOOT_CURRENT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 81 {EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 82 {EFI_DRIVER_ORDER_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 83 {EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 84 {EFI_SETUP_MODE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 85 {EFI_KEY_EXCHANGE_KEY_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT_AT}, 86 {EFI_PLATFORM_KEY_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT_AT}, 87 {EFI_SIGNATURE_SUPPORT_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 88 {EFI_SECURE_BOOT_MODE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 89 {EFI_KEK_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 90 {EFI_PK_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 91 {EFI_DB_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 92 {EFI_DBX_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 93 {EFI_DBT_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 94 {EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 95 {EFI_OS_INDICATIONS_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT}, 96 {EFI_VENDOR_KEYS_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT}, 97 }; 98 GLOBAL_VARIABLE_ENTRY mGlobalVariableList2[] = { 99 {L"Boot####", VARIABLE_ATTRIBUTE_NV_BS_RT}, 100 {L"Driver####", VARIABLE_ATTRIBUTE_NV_BS_RT}, 101 {L"Key####", VARIABLE_ATTRIBUTE_NV_BS_RT}, 102 }; 31 103 32 104 /** … … 79 151 80 152 CopyGuid (&gVariableInfo->VendorGuid, VendorGuid); 81 gVariableInfo->Name = Allocate Pool (StrSize (VariableName));153 gVariableInfo->Name = AllocateZeroPool (StrSize (VariableName)); 82 154 ASSERT (gVariableInfo->Name != NULL); 83 Str Cpy (gVariableInfo->Name, VariableName);155 StrnCpy (gVariableInfo->Name, VariableName, StrLen (VariableName)); 84 156 gVariableInfo->Volatile = Volatile; 85 157 } … … 115 187 116 188 CopyGuid (&Entry->Next->VendorGuid, VendorGuid); 117 Entry->Next->Name = Allocate Pool (StrSize (VariableName));189 Entry->Next->Name = AllocateZeroPool (StrSize (VariableName)); 118 190 ASSERT (Entry->Next->Name != NULL); 119 Str Cpy (Entry->Next->Name, VariableName);191 StrnCpy (Entry->Next->Name, VariableName, StrLen (VariableName)); 120 192 Entry->Next->Volatile = Volatile; 121 193 } … … 130 202 This code checks if variable header is valid or not. 131 203 132 @param Variable Pointer to the Variable Header. 133 134 @retval TRUE Variable header is valid. 135 @retval FALSE Variable header is not valid. 204 @param Variable Pointer to the Variable Header. 205 @param VariableStoreEnd Pointer to the Variable Store End. 206 207 @retval TRUE Variable header is valid. 208 @retval FALSE Variable header is not valid. 136 209 137 210 **/ 138 211 BOOLEAN 139 212 IsValidVariableHeader ( 140 IN VARIABLE_HEADER *Variable 213 IN VARIABLE_HEADER *Variable, 214 IN VARIABLE_HEADER *VariableStoreEnd 141 215 ) 142 216 { 143 if (Variable == NULL || Variable->StartId != VARIABLE_DATA) { 217 if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) { 218 // 219 // Variable is NULL or has reached the end of variable store, 220 // or the StartId is not correct. 221 // 144 222 return FALSE; 145 223 } … … 439 517 UINTN Value; 440 518 441 if (!IsValidVariableHeader (Variable)) {442 return NULL;443 }444 445 519 Value = (UINTN) GetVariableDataPtr (Variable); 446 520 Value += DataSizeOfVariable (Variable); … … 505 579 @param IsVolatile The variable store is volatile or not; 506 580 if it is non-volatile, need FTW. 507 @param UpdatingVariable Pointer to updating variable. 581 @param UpdatingPtrTrack Pointer to updating variable pointer track structure. 582 @param NewVariable Pointer to new variable. 583 @param NewVariableSize New variable size. 508 584 509 585 @return EFI_OUT_OF_RESOURCES … … 517 593 OUT UINTN *LastVariableOffset, 518 594 IN BOOLEAN IsVolatile, 519 IN VARIABLE_HEADER *UpdatingVariable 595 IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack, 596 IN VARIABLE_HEADER *NewVariable, 597 IN UINTN NewVariableSize 520 598 ) 521 599 { … … 528 606 UINTN MaximumBufferSize; 529 607 UINTN VariableSize; 530 UINTN VariableNameSize;531 UINTN UpdatingVariableNameSize;532 608 UINTN NameSize; 533 609 UINT8 *CurrPtr; … … 536 612 BOOLEAN FoundAdded; 537 613 EFI_STATUS Status; 538 CHAR16 *VariableNamePtr; 539 CHAR16 *UpdatingVariableNamePtr; 614 UINTN CommonVariableTotalSize; 615 UINTN HwErrVariableTotalSize; 616 VARIABLE_HEADER *UpdatingVariable; 617 VARIABLE_HEADER *UpdatingInDeletedTransition; 618 619 UpdatingVariable = NULL; 620 UpdatingInDeletedTransition = NULL; 621 if (UpdatingPtrTrack != NULL) { 622 UpdatingVariable = UpdatingPtrTrack->CurrPtr; 623 UpdatingInDeletedTransition = UpdatingPtrTrack->InDeletedTransitionPtr; 624 } 540 625 541 626 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase); 542 // 543 // Recalculate the total size of Common/HwErr type variables in non-volatile area. 544 // 545 if (!IsVolatile) { 546 mVariableModuleGlobal->CommonVariableTotalSize = 0; 547 mVariableModuleGlobal->HwErrVariableTotalSize = 0; 548 } 549 550 // 551 // Start Pointers for the variable. 552 // 553 Variable = GetStartPointer (VariableStoreHeader); 554 MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER); 555 556 while (IsValidVariableHeader (Variable)) { 557 NextVariable = GetNextVariablePtr (Variable); 558 if (Variable->State == VAR_ADDED || 559 Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED) 560 ) { 561 VariableSize = (UINTN) NextVariable - (UINTN) Variable; 562 MaximumBufferSize += VariableSize; 563 } 564 565 Variable = NextVariable; 566 } 567 568 // 569 // Reserve the 1 Bytes with Oxff to identify the 570 // end of the variable buffer. 571 // 572 MaximumBufferSize += 1; 573 ValidBuffer = AllocatePool (MaximumBufferSize); 574 if (ValidBuffer == NULL) { 575 return EFI_OUT_OF_RESOURCES; 627 628 CommonVariableTotalSize = 0; 629 HwErrVariableTotalSize = 0; 630 631 if (IsVolatile) { 632 // 633 // Start Pointers for the variable. 634 // 635 Variable = GetStartPointer (VariableStoreHeader); 636 MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER); 637 638 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) { 639 NextVariable = GetNextVariablePtr (Variable); 640 if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) && 641 Variable != UpdatingVariable && 642 Variable != UpdatingInDeletedTransition 643 ) { 644 VariableSize = (UINTN) NextVariable - (UINTN) Variable; 645 MaximumBufferSize += VariableSize; 646 } 647 648 Variable = NextVariable; 649 } 650 651 if (NewVariable != NULL) { 652 // 653 // Add the new variable size. 654 // 655 MaximumBufferSize += NewVariableSize; 656 } 657 658 // 659 // Reserve the 1 Bytes with Oxff to identify the 660 // end of the variable buffer. 661 // 662 MaximumBufferSize += 1; 663 ValidBuffer = AllocatePool (MaximumBufferSize); 664 if (ValidBuffer == NULL) { 665 return EFI_OUT_OF_RESOURCES; 666 } 667 } else { 668 // 669 // For NV variable reclaim, don't allocate pool here and just use mNvVariableCache 670 // as the buffer to reduce SMRAM consumption for SMM variable driver. 671 // 672 MaximumBufferSize = mNvVariableCache->Size; 673 ValidBuffer = (UINT8 *) mNvVariableCache; 576 674 } 577 675 … … 588 686 // 589 687 Variable = GetStartPointer (VariableStoreHeader); 590 while (IsValidVariableHeader (Variable )) {688 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) { 591 689 NextVariable = GetNextVariablePtr (Variable); 592 if (Variable->State == VAR_ADDED) { 593 if (UpdatingVariable != NULL) { 594 if (UpdatingVariable == Variable) { 595 Variable = NextVariable; 596 continue; 597 } 598 599 VariableNameSize = NameSizeOfVariable(Variable); 600 UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable); 601 602 VariableNamePtr = GetVariableNamePtr (Variable); 603 UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable); 604 if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid) && 605 VariableNameSize == UpdatingVariableNameSize && 606 CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) { 607 Variable = NextVariable; 608 continue; 609 } 610 } 690 if (Variable != UpdatingVariable && Variable->State == VAR_ADDED) { 611 691 VariableSize = (UINTN) NextVariable - (UINTN) Variable; 612 692 CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize); 613 693 CurrPtr += VariableSize; 614 694 if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { 615 mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;695 HwErrVariableTotalSize += VariableSize; 616 696 } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { 617 mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;697 CommonVariableTotalSize += VariableSize; 618 698 } 619 699 } 620 700 Variable = NextVariable; 621 }622 623 //624 // Reinstall the variable being updated if it is not NULL.625 //626 if (UpdatingVariable != NULL) {627 VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;628 CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);629 CurrPtr += VariableSize;630 if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {631 mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;632 } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {633 mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;634 }635 701 } 636 702 … … 638 704 // Reinstall all in delete transition variables. 639 705 // 640 Variable 641 while (IsValidVariableHeader (Variable )) {706 Variable = GetStartPointer (VariableStoreHeader); 707 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) { 642 708 NextVariable = GetNextVariablePtr (Variable); 643 if (Variable != UpdatingVariable && Variable ->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {709 if (Variable != UpdatingVariable && Variable != UpdatingInDeletedTransition && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { 644 710 645 711 // … … 651 717 FoundAdded = FALSE; 652 718 AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer); 653 while (IsValidVariableHeader (AddedVariable )) {719 while (IsValidVariableHeader (AddedVariable, GetEndPointer ((VARIABLE_STORE_HEADER *) ValidBuffer))) { 654 720 NextAddedVariable = GetNextVariablePtr (AddedVariable); 655 721 NameSize = NameSizeOfVariable (AddedVariable); … … 659 725 Point0 = (VOID *) GetVariableNamePtr (AddedVariable); 660 726 Point1 = (VOID *) GetVariableNamePtr (Variable); 661 if (CompareMem (Point0, Point1, NameSize OfVariable (AddedVariable)) == 0) {727 if (CompareMem (Point0, Point1, NameSize) == 0) { 662 728 FoundAdded = TRUE; 663 729 break; … … 675 741 CurrPtr += VariableSize; 676 742 if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { 677 mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;743 HwErrVariableTotalSize += VariableSize; 678 744 } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { 679 mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;745 CommonVariableTotalSize += VariableSize; 680 746 } 681 747 } … … 685 751 } 686 752 753 // 754 // Install the new variable if it is not NULL. 755 // 756 if (NewVariable != NULL) { 757 if ((UINTN) (CurrPtr - ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) { 758 // 759 // No enough space to store the new variable. 760 // 761 Status = EFI_OUT_OF_RESOURCES; 762 goto Done; 763 } 764 if (!IsVolatile) { 765 if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 766 HwErrVariableTotalSize += NewVariableSize; 767 } else if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 768 CommonVariableTotalSize += NewVariableSize; 769 } 770 if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) || 771 (CommonVariableTotalSize > VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize))) { 772 // 773 // No enough space to store the new variable by NV or NV+HR attribute. 774 // 775 Status = EFI_OUT_OF_RESOURCES; 776 goto Done; 777 } 778 } 779 780 CopyMem (CurrPtr, (UINT8 *) NewVariable, NewVariableSize); 781 ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED; 782 if (UpdatingVariable != NULL) { 783 UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer))); 784 UpdatingPtrTrack->InDeletedTransitionPtr = NULL; 785 } 786 CurrPtr += NewVariableSize; 787 } 788 687 789 if (IsVolatile) { 688 790 // … … 690 792 // 691 793 SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff); 692 CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)); 794 CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer)); 795 *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer); 693 796 Status = EFI_SUCCESS; 694 797 } else { … … 698 801 Status = FtwVariableSpace ( 699 802 VariableBase, 700 ValidBuffer, 701 (UINTN) (CurrPtr - (UINT8 *) ValidBuffer) 803 (VARIABLE_STORE_HEADER *) ValidBuffer 702 804 ); 703 CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size); 704 } 705 if (!EFI_ERROR (Status)) { 706 *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer); 805 if (!EFI_ERROR (Status)) { 806 *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer); 807 mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize; 808 mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize; 809 } else { 810 NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase); 811 while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) { 812 VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER); 813 if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 814 mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize); 815 } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 816 mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize); 817 } 818 819 NextVariable = GetNextVariablePtr (NextVariable); 820 } 821 *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase; 822 } 823 } 824 825 Done: 826 if (IsVolatile) { 827 FreePool (ValidBuffer); 707 828 } else { 708 *LastVariableOffset = 0; 709 } 710 711 FreePool (ValidBuffer); 829 // 830 // For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back. 831 // 832 CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size); 833 } 712 834 713 835 return Status; … … 737 859 VOID *Point; 738 860 861 PtrTrack->InDeletedTransitionPtr = NULL; 862 739 863 // 740 864 // Find the variable by walk through HOB, volatile and non-volatile variable store. … … 743 867 744 868 for ( PtrTrack->CurrPtr = PtrTrack->StartPtr 745 ; (PtrTrack->CurrPtr < PtrTrack->EndPtr) && IsValidVariableHeader (PtrTrack->CurrPtr)869 ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr) 746 870 ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr) 747 871 ) { … … 754 878 InDeletedVariable = PtrTrack->CurrPtr; 755 879 } else { 880 PtrTrack->InDeletedTransitionPtr = InDeletedVariable; 756 881 return EFI_SUCCESS; 757 882 } … … 765 890 InDeletedVariable = PtrTrack->CurrPtr; 766 891 } else { 892 PtrTrack->InDeletedTransitionPtr = InDeletedVariable; 767 893 return EFI_SUCCESS; 768 894 } … … 1147 1273 1148 1274 /** 1275 This function is to check if the remaining variable space is enough to set 1276 all Variables from argument list successfully. The purpose of the check 1277 is to keep the consistency of the Variables to be in variable storage. 1278 1279 Note: Variables are assumed to be in same storage. 1280 The set sequence of Variables will be same with the sequence of VariableEntry from argument list, 1281 so follow the argument sequence to check the Variables. 1282 1283 @param[in] Attributes Variable attributes for Variable entries. 1284 @param ... The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *. 1285 A NULL terminates the list. The VariableSize of 1286 VARIABLE_ENTRY_CONSISTENCY is the variable data size as input. 1287 It will be changed to variable total size as output. 1288 1289 @retval TRUE Have enough variable space to set the Variables successfully. 1290 @retval FALSE No enough variable space to set the Variables successfully. 1291 1292 **/ 1293 BOOLEAN 1294 EFIAPI 1295 CheckRemainingSpaceForConsistency ( 1296 IN UINT32 Attributes, 1297 ... 1298 ) 1299 { 1300 EFI_STATUS Status; 1301 VA_LIST Args; 1302 VARIABLE_ENTRY_CONSISTENCY *VariableEntry; 1303 UINT64 MaximumVariableStorageSize; 1304 UINT64 RemainingVariableStorageSize; 1305 UINT64 MaximumVariableSize; 1306 UINTN TotalNeededSize; 1307 UINTN OriginalVarSize; 1308 VARIABLE_STORE_HEADER *VariableStoreHeader; 1309 VARIABLE_POINTER_TRACK VariablePtrTrack; 1310 VARIABLE_HEADER *NextVariable; 1311 UINTN VarNameSize; 1312 UINTN VarDataSize; 1313 1314 // 1315 // Non-Volatile related. 1316 // 1317 VariableStoreHeader = mNvVariableCache; 1318 1319 Status = VariableServiceQueryVariableInfoInternal ( 1320 Attributes, 1321 &MaximumVariableStorageSize, 1322 &RemainingVariableStorageSize, 1323 &MaximumVariableSize 1324 ); 1325 ASSERT_EFI_ERROR (Status); 1326 1327 TotalNeededSize = 0; 1328 VA_START (Args, Attributes); 1329 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *); 1330 while (VariableEntry != NULL) { 1331 // 1332 // Calculate variable total size. 1333 // 1334 VarNameSize = StrSize (VariableEntry->Name); 1335 VarNameSize += GET_PAD_SIZE (VarNameSize); 1336 VarDataSize = VariableEntry->VariableSize; 1337 VarDataSize += GET_PAD_SIZE (VarDataSize); 1338 VariableEntry->VariableSize = HEADER_ALIGN (sizeof (VARIABLE_HEADER) + VarNameSize + VarDataSize); 1339 1340 TotalNeededSize += VariableEntry->VariableSize; 1341 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *); 1342 } 1343 VA_END (Args); 1344 1345 if (RemainingVariableStorageSize >= TotalNeededSize) { 1346 // 1347 // Already have enough space. 1348 // 1349 return TRUE; 1350 } else if (AtRuntime ()) { 1351 // 1352 // At runtime, no reclaim. 1353 // The original variable space of Variables can't be reused. 1354 // 1355 return FALSE; 1356 } 1357 1358 VA_START (Args, Attributes); 1359 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *); 1360 while (VariableEntry != NULL) { 1361 // 1362 // Check if Variable[Index] has been present and get its size. 1363 // 1364 OriginalVarSize = 0; 1365 VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader); 1366 VariablePtrTrack.EndPtr = GetEndPointer (VariableStoreHeader); 1367 Status = FindVariableEx ( 1368 VariableEntry->Name, 1369 VariableEntry->Guid, 1370 FALSE, 1371 &VariablePtrTrack 1372 ); 1373 if (!EFI_ERROR (Status)) { 1374 // 1375 // Get size of Variable[Index]. 1376 // 1377 NextVariable = GetNextVariablePtr (VariablePtrTrack.CurrPtr); 1378 OriginalVarSize = (UINTN) NextVariable - (UINTN) VariablePtrTrack.CurrPtr; 1379 // 1380 // Add the original size of Variable[Index] to remaining variable storage size. 1381 // 1382 RemainingVariableStorageSize += OriginalVarSize; 1383 } 1384 if (VariableEntry->VariableSize > RemainingVariableStorageSize) { 1385 // 1386 // No enough space for Variable[Index]. 1387 // 1388 VA_END (Args); 1389 return FALSE; 1390 } 1391 // 1392 // Sub the (new) size of Variable[Index] from remaining variable storage size. 1393 // 1394 RemainingVariableStorageSize -= VariableEntry->VariableSize; 1395 VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *); 1396 } 1397 VA_END (Args); 1398 1399 return TRUE; 1400 } 1401 1402 /** 1149 1403 Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang. 1150 1404 … … 1160 1414 @param[in] DataSize Size of data. 0 means delete. 1161 1415 1162 **/ 1163 VOID 1416 @retval EFI_SUCCESS The update operation is successful or ignored. 1417 @retval EFI_WRITE_PROTECTED Update PlatformLangCodes/LangCodes at runtime. 1418 @retval EFI_OUT_OF_RESOURCES No enough variable space to do the update operation. 1419 @retval Others Other errors happened during the update operation. 1420 1421 **/ 1422 EFI_STATUS 1164 1423 AutoUpdateLangVariable ( 1165 1424 IN CHAR16 *VariableName, … … 1175 1434 VARIABLE_POINTER_TRACK Variable; 1176 1435 BOOLEAN SetLanguageCodes; 1436 VARIABLE_ENTRY_CONSISTENCY VariableEntry[2]; 1177 1437 1178 1438 // … … 1180 1440 // 1181 1441 if (DataSize == 0) { 1182 return ;1442 return EFI_SUCCESS; 1183 1443 } 1184 1444 1185 1445 SetLanguageCodes = FALSE; 1186 1446 1187 if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {1447 if (StrCmp (VariableName, EFI_PLATFORM_LANG_CODES_VARIABLE_NAME) == 0) { 1188 1448 // 1189 1449 // PlatformLangCodes is a volatile variable, so it can not be updated at runtime. 1190 1450 // 1191 1451 if (AtRuntime ()) { 1192 return ;1452 return EFI_WRITE_PROTECTED; 1193 1453 } 1194 1454 … … 1215 1475 ASSERT (mVariableModuleGlobal->PlatformLang != NULL); 1216 1476 1217 } else if (StrCmp (VariableName, L"LangCodes") == 0) {1477 } else if (StrCmp (VariableName, EFI_LANG_CODES_VARIABLE_NAME) == 0) { 1218 1478 // 1219 1479 // LangCodes is a volatile variable, so it can not be updated at runtime. 1220 1480 // 1221 1481 if (AtRuntime ()) { 1222 return ;1482 return EFI_WRITE_PROTECTED; 1223 1483 } 1224 1484 … … 1243 1503 // Update PlatformLang if Lang is already set 1244 1504 // 1245 Status = FindVariable ( L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);1505 Status = FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); 1246 1506 if (!EFI_ERROR (Status)) { 1247 1507 // 1248 1508 // Update Lang 1249 1509 // 1250 VariableName = L"PlatformLang";1510 VariableName = EFI_PLATFORM_LANG_VARIABLE_NAME; 1251 1511 Data = GetVariableDataPtr (Variable.CurrPtr); 1252 1512 DataSize = Variable.CurrPtr->DataSize; 1253 1513 } else { 1254 Status = FindVariable ( L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);1514 Status = FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); 1255 1515 if (!EFI_ERROR (Status)) { 1256 1516 // 1257 1517 // Update PlatformLang 1258 1518 // 1259 VariableName = L"Lang";1519 VariableName = EFI_LANG_VARIABLE_NAME; 1260 1520 Data = GetVariableDataPtr (Variable.CurrPtr); 1261 1521 DataSize = Variable.CurrPtr->DataSize; … … 1264 1524 // Neither PlatformLang nor Lang is set, directly return 1265 1525 // 1266 return; 1267 } 1268 } 1269 } 1270 1526 return EFI_SUCCESS; 1527 } 1528 } 1529 } 1530 1531 Status = EFI_SUCCESS; 1532 1271 1533 // 1272 1534 // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions. … … 1274 1536 Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; 1275 1537 1276 if (StrCmp (VariableName, L"PlatformLang") == 0) {1538 if (StrCmp (VariableName, EFI_PLATFORM_LANG_VARIABLE_NAME) == 0) { 1277 1539 // 1278 1540 // Update Lang when PlatformLangCodes/LangCodes were set. … … 1295 1557 1296 1558 // 1297 // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously. 1298 // 1299 FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal, FALSE); 1300 1301 Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, 1302 ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable); 1303 1304 DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang)); 1305 1306 ASSERT_EFI_ERROR(Status); 1307 } 1308 } 1309 1310 } else if (StrCmp (VariableName, L"Lang") == 0) { 1559 // Check the variable space for both Lang and PlatformLang variable. 1560 // 1561 VariableEntry[0].VariableSize = ISO_639_2_ENTRY_SIZE + 1; 1562 VariableEntry[0].Guid = &gEfiGlobalVariableGuid; 1563 VariableEntry[0].Name = EFI_LANG_VARIABLE_NAME; 1564 1565 VariableEntry[1].VariableSize = AsciiStrSize (BestPlatformLang); 1566 VariableEntry[1].Guid = &gEfiGlobalVariableGuid; 1567 VariableEntry[1].Name = EFI_PLATFORM_LANG_VARIABLE_NAME; 1568 if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) { 1569 // 1570 // No enough variable space to set both Lang and PlatformLang successfully. 1571 // 1572 Status = EFI_OUT_OF_RESOURCES; 1573 } else { 1574 // 1575 // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously. 1576 // 1577 FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); 1578 1579 Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang, 1580 ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable); 1581 } 1582 1583 DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a Status: %r\n", BestPlatformLang, BestLang, Status)); 1584 } 1585 } 1586 1587 } else if (StrCmp (VariableName, EFI_LANG_VARIABLE_NAME) == 0) { 1311 1588 // 1312 1589 // Update PlatformLang when PlatformLangCodes/LangCodes were set. … … 1329 1606 1330 1607 // 1331 // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously. 1332 // 1333 FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); 1334 1335 Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang, 1336 AsciiStrSize (BestPlatformLang), Attributes, &Variable); 1337 1338 DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang)); 1339 ASSERT_EFI_ERROR (Status); 1340 } 1341 } 1608 // Check the variable space for both PlatformLang and Lang variable. 1609 // 1610 VariableEntry[0].VariableSize = AsciiStrSize (BestPlatformLang); 1611 VariableEntry[0].Guid = &gEfiGlobalVariableGuid; 1612 VariableEntry[0].Name = EFI_PLATFORM_LANG_VARIABLE_NAME; 1613 1614 VariableEntry[1].VariableSize = ISO_639_2_ENTRY_SIZE + 1; 1615 VariableEntry[1].Guid = &gEfiGlobalVariableGuid; 1616 VariableEntry[1].Name = EFI_LANG_VARIABLE_NAME; 1617 if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) { 1618 // 1619 // No enough variable space to set both PlatformLang and Lang successfully. 1620 // 1621 Status = EFI_OUT_OF_RESOURCES; 1622 } else { 1623 // 1624 // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously. 1625 // 1626 FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); 1627 1628 Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang, 1629 AsciiStrSize (BestPlatformLang), Attributes, &Variable); 1630 } 1631 1632 DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status)); 1633 } 1634 } 1635 } 1636 1637 if (SetLanguageCodes) { 1638 // 1639 // Continue to set PlatformLangCodes or LangCodes. 1640 // 1641 return EFI_SUCCESS; 1642 } else { 1643 return Status; 1342 1644 } 1343 1645 } … … 1352 1654 @param[in] DataSize Size of data. 0 means delete. 1353 1655 @param[in] Attributes Attribues of the variable. 1354 @param[in ] CacheVariableThe variable information which is used to keep track of variable usage.1656 @param[in, out] CacheVariable The variable information which is used to keep track of variable usage. 1355 1657 1356 1658 @retval EFI_SUCCESS The update operation is success. … … 1365 1667 IN UINTN DataSize, 1366 1668 IN UINT32 Attributes OPTIONAL, 1367 IN 1669 IN OUT VARIABLE_POINTER_TRACK *CacheVariable 1368 1670 ) 1369 1671 { … … 1379 1681 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; 1380 1682 UINT8 State; 1381 BOOLEAN Reclaimed;1382 1683 VARIABLE_POINTER_TRACK *Variable; 1383 1684 VARIABLE_POINTER_TRACK NvVariable; … … 1406 1707 Variable->EndPtr = GetEndPointer (VariableStoreHeader); 1407 1708 Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr)); 1709 if (CacheVariable->InDeletedTransitionPtr != NULL) { 1710 Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr)); 1711 } else { 1712 Variable->InDeletedTransitionPtr = NULL; 1713 } 1408 1714 Variable->Volatile = FALSE; 1409 1715 } 1410 1716 1411 1717 Fvb = mVariableModuleGlobal->FvbInstance; 1412 Reclaimed = FALSE;1413 1718 1414 1719 if (Variable->CurrPtr != NULL) { … … 1440 1745 // 1441 1746 if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) { 1747 if (Variable->InDeletedTransitionPtr != NULL) { 1748 // 1749 // Both ADDED and IN_DELETED_TRANSITION variable are present, 1750 // set IN_DELETED_TRANSITION one to DELETED state first. 1751 // 1752 State = Variable->InDeletedTransitionPtr->State; 1753 State &= VAR_DELETED; 1754 Status = UpdateVariableStore ( 1755 &mVariableModuleGlobal->VariableGlobal, 1756 Variable->Volatile, 1757 FALSE, 1758 Fvb, 1759 (UINTN) &Variable->InDeletedTransitionPtr->State, 1760 sizeof (UINT8), 1761 &State 1762 ); 1763 if (!EFI_ERROR (Status)) { 1764 if (!Variable->Volatile) { 1765 ASSERT (CacheVariable->InDeletedTransitionPtr != NULL); 1766 CacheVariable->InDeletedTransitionPtr->State = State; 1767 } 1768 } else { 1769 goto Done; 1770 } 1771 } 1772 1442 1773 State = Variable->CurrPtr->State; 1443 1774 State &= VAR_DELETED; … … 1456 1787 if (!Variable->Volatile) { 1457 1788 CacheVariable->CurrPtr->State = State; 1789 FlushHobVariableToFlash (VariableName, VendorGuid); 1458 1790 } 1459 1791 } … … 1580 1912 } 1581 1913 // 1582 // Perform garbage collection & reclaim operation .1914 // Perform garbage collection & reclaim operation, and integrate the new variable at the same time. 1583 1915 // 1584 1916 Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, 1585 &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr); 1586 if (EFI_ERROR (Status)) { 1587 goto Done; 1588 } 1589 // 1590 // If still no enough space, return out of resources. 1591 // 1592 if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) 1593 && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize))) 1594 || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) 1595 && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) { 1596 Status = EFI_OUT_OF_RESOURCES; 1597 goto Done; 1598 } 1599 Reclaimed = TRUE; 1917 &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, NextVariable, HEADER_ALIGN (VarSize)); 1918 if (!EFI_ERROR (Status)) { 1919 // 1920 // The new variable has been integrated successfully during reclaiming. 1921 // 1922 if (Variable->CurrPtr != NULL) { 1923 CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr)); 1924 CacheVariable->InDeletedTransitionPtr = NULL; 1925 } 1926 UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE); 1927 FlushHobVariableToFlash (VariableName, VendorGuid); 1928 } 1929 goto Done; 1600 1930 } 1601 1931 // … … 1695 2025 ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) { 1696 2026 // 1697 // Perform garbage collection & reclaim operation .2027 // Perform garbage collection & reclaim operation, and integrate the new variable at the same time. 1698 2028 // 1699 2029 Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, 1700 &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr); 1701 if (EFI_ERROR (Status)) { 1702 goto Done; 1703 } 1704 // 1705 // If still no enough space, return out of resources. 1706 // 1707 if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) > 1708 ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size 1709 ) { 1710 Status = EFI_OUT_OF_RESOURCES; 1711 goto Done; 1712 } 1713 Reclaimed = TRUE; 2030 &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, NextVariable, HEADER_ALIGN (VarSize)); 2031 if (!EFI_ERROR (Status)) { 2032 // 2033 // The new variable has been integrated successfully during reclaiming. 2034 // 2035 if (Variable->CurrPtr != NULL) { 2036 CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr)); 2037 CacheVariable->InDeletedTransitionPtr = NULL; 2038 } 2039 UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE); 2040 } 2041 goto Done; 1714 2042 } 1715 2043 … … 1735 2063 // Mark the old variable as deleted. 1736 2064 // 1737 if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) { 2065 if (!EFI_ERROR (Status) && Variable->CurrPtr != NULL) { 2066 if (Variable->InDeletedTransitionPtr != NULL) { 2067 // 2068 // Both ADDED and IN_DELETED_TRANSITION old variable are present, 2069 // set IN_DELETED_TRANSITION one to DELETED state first. 2070 // 2071 State = Variable->InDeletedTransitionPtr->State; 2072 State &= VAR_DELETED; 2073 Status = UpdateVariableStore ( 2074 &mVariableModuleGlobal->VariableGlobal, 2075 Variable->Volatile, 2076 FALSE, 2077 Fvb, 2078 (UINTN) &Variable->InDeletedTransitionPtr->State, 2079 sizeof (UINT8), 2080 &State 2081 ); 2082 if (!EFI_ERROR (Status)) { 2083 if (!Variable->Volatile) { 2084 ASSERT (CacheVariable->InDeletedTransitionPtr != NULL); 2085 CacheVariable->InDeletedTransitionPtr->State = State; 2086 } 2087 } else { 2088 goto Done; 2089 } 2090 } 2091 1738 2092 State = Variable->CurrPtr->State; 1739 2093 State &= VAR_DELETED; … … 1755 2109 if (!EFI_ERROR (Status)) { 1756 2110 UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE); 2111 if (!Volatile) { 2112 FlushHobVariableToFlash (VariableName, VendorGuid); 2113 } 1757 2114 } 1758 2115 … … 1762 2119 1763 2120 /** 2121 Check if a Unicode character is a hexadecimal character. 2122 2123 This function checks if a Unicode character is a 2124 hexadecimal character. The valid hexadecimal character is 2125 L'0' to L'9', L'a' to L'f', or L'A' to L'F'. 2126 2127 2128 @param Char The character to check against. 2129 2130 @retval TRUE If the Char is a hexadecmial character. 2131 @retval FALSE If the Char is not a hexadecmial character. 2132 2133 **/ 2134 BOOLEAN 2135 EFIAPI 2136 IsHexaDecimalDigitCharacter ( 2137 IN CHAR16 Char 2138 ) 2139 { 2140 return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f')); 2141 } 2142 2143 /** 2144 2145 This code checks if variable is hardware error record variable or not. 2146 2147 According to UEFI spec, hardware error record variable should use the EFI_HARDWARE_ERROR_VARIABLE VendorGuid 2148 and have the L"HwErrRec####" name convention, #### is a printed hex value and no 0x or h is included in the hex value. 2149 2150 @param VariableName Pointer to variable name. 2151 @param VendorGuid Variable Vendor Guid. 2152 2153 @retval TRUE Variable is hardware error record variable. 2154 @retval FALSE Variable is not hardware error record variable. 2155 2156 **/ 2157 BOOLEAN 2158 EFIAPI 2159 IsHwErrRecVariable ( 2160 IN CHAR16 *VariableName, 2161 IN EFI_GUID *VendorGuid 2162 ) 2163 { 2164 if (!CompareGuid (VendorGuid, &gEfiHardwareErrorVariableGuid) || 2165 (StrLen (VariableName) != StrLen (L"HwErrRec####")) || 2166 (StrnCmp(VariableName, L"HwErrRec", StrLen (L"HwErrRec")) != 0) || 2167 !IsHexaDecimalDigitCharacter (VariableName[0x8]) || 2168 !IsHexaDecimalDigitCharacter (VariableName[0x9]) || 2169 !IsHexaDecimalDigitCharacter (VariableName[0xA]) || 2170 !IsHexaDecimalDigitCharacter (VariableName[0xB])) { 2171 return FALSE; 2172 } 2173 2174 return TRUE; 2175 } 2176 2177 /** 2178 This code checks if variable guid is global variable guid first. 2179 If yes, further check if variable name is in mGlobalVariableList or mGlobalVariableList2 and attributes matched. 2180 2181 @param[in] VariableName Pointer to variable name. 2182 @param[in] VendorGuid Variable Vendor Guid. 2183 @param[in] Attributes Attributes of the variable. 2184 2185 @retval EFI_SUCCESS Variable is not global variable, or Variable is global variable, variable name is in the lists and attributes matched. 2186 @retval EFI_INVALID_PARAMETER Variable is global variable, but variable name is not in the lists or attributes unmatched. 2187 2188 **/ 2189 EFI_STATUS 2190 EFIAPI 2191 CheckEfiGlobalVariable ( 2192 IN CHAR16 *VariableName, 2193 IN EFI_GUID *VendorGuid, 2194 IN UINT32 Attributes 2195 ) 2196 { 2197 UINTN Index; 2198 UINTN NameLength; 2199 2200 if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)){ 2201 // 2202 // Try list 1, exactly match. 2203 // 2204 for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) { 2205 if ((StrCmp (mGlobalVariableList[Index].Name, VariableName) == 0) && 2206 (Attributes == 0 || Attributes == mGlobalVariableList[Index].Attributes)) { 2207 return EFI_SUCCESS; 2208 } 2209 } 2210 2211 // 2212 // Try list 2. 2213 // 2214 NameLength = StrLen (VariableName) - 4; 2215 for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) { 2216 if ((StrLen (VariableName) == StrLen (mGlobalVariableList2[Index].Name)) && 2217 (StrnCmp (mGlobalVariableList2[Index].Name, VariableName, NameLength) == 0) && 2218 IsHexaDecimalDigitCharacter (VariableName[NameLength]) && 2219 IsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) && 2220 IsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) && 2221 IsHexaDecimalDigitCharacter (VariableName[NameLength + 3]) && 2222 (Attributes == 0 || Attributes == mGlobalVariableList2[Index].Attributes)) { 2223 return EFI_SUCCESS; 2224 } 2225 } 2226 2227 DEBUG ((EFI_D_INFO, "[Variable]: set global variable with invalid variable name or attributes - %g:%s:%x\n", VendorGuid, VariableName, Attributes)); 2228 return EFI_INVALID_PARAMETER; 2229 } 2230 2231 return EFI_SUCCESS; 2232 } 2233 2234 /** 2235 Mark a variable that will become read-only after leaving the DXE phase of execution. 2236 2237 @param[in] This The VARIABLE_LOCK_PROTOCOL instance. 2238 @param[in] VariableName A pointer to the variable name that will be made read-only subsequently. 2239 @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently. 2240 2241 @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked 2242 as pending to be read-only. 2243 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL. 2244 Or VariableName is an empty string. 2245 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has 2246 already been signaled. 2247 @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request. 2248 **/ 2249 EFI_STATUS 2250 EFIAPI 2251 VariableLockRequestToLock ( 2252 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This, 2253 IN CHAR16 *VariableName, 2254 IN EFI_GUID *VendorGuid 2255 ) 2256 { 2257 VARIABLE_ENTRY *Entry; 2258 2259 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { 2260 return EFI_INVALID_PARAMETER; 2261 } 2262 2263 if (mEndOfDxe) { 2264 return EFI_ACCESS_DENIED; 2265 } 2266 2267 Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (VariableName)); 2268 if (Entry == NULL) { 2269 return EFI_OUT_OF_RESOURCES; 2270 } 2271 2272 DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName)); 2273 2274 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); 2275 2276 Entry->Name = (CHAR16 *) (Entry + 1); 2277 StrnCpy (Entry->Name, VariableName, StrLen (VariableName)); 2278 CopyGuid (&Entry->Guid, VendorGuid); 2279 InsertTailList (&mLockedVariableList, &Entry->Link); 2280 2281 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); 2282 2283 return EFI_SUCCESS; 2284 } 2285 2286 /** 1764 2287 1765 2288 This code finds variable in storage blocks (Volatile or Non-Volatile). 2289 2290 Caution: This function may receive untrusted input. 2291 This function may be invoked in SMM mode, and datasize is external input. 2292 This function will do basic validation, before parse the data. 1766 2293 1767 2294 @param VariableName Name of Variable to be found. … … 1842 2369 This code Finds the Next available variable. 1843 2370 2371 Caution: This function may receive untrusted input. 2372 This function may be invoked in SMM mode. This function will do basic validation, before parse the data. 2373 1844 2374 @param VariableNameSize Size of the variable name. 1845 2375 @param VariableName Pointer to variable name. … … 1863 2393 VARIABLE_POINTER_TRACK Variable; 1864 2394 VARIABLE_POINTER_TRACK VariableInHob; 2395 VARIABLE_POINTER_TRACK VariablePtrTrack; 1865 2396 UINTN VarNameSize; 1866 2397 EFI_STATUS Status; … … 1898 2429 // Switch from Volatile to HOB, to Non-Volatile. 1899 2430 // 1900 while ((Variable.CurrPtr >= Variable.EndPtr) || 1901 (Variable.CurrPtr == NULL) || 1902 !IsValidVariableHeader (Variable.CurrPtr) 1903 ) { 2431 while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) { 1904 2432 // 1905 2433 // Find current storage index … … 1936 2464 // Variable is found 1937 2465 // 1938 if (Variable.CurrPtr->State == VAR_ADDED) { 1939 if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) { 2466 if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { 2467 if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) { 2468 if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { 2469 // 2470 // If it is a IN_DELETED_TRANSITION variable, 2471 // and there is also a same ADDED one at the same time, 2472 // don't return it. 2473 // 2474 VariablePtrTrack.StartPtr = Variable.StartPtr; 2475 VariablePtrTrack.EndPtr = Variable.EndPtr; 2476 Status = FindVariableEx ( 2477 GetVariableNamePtr (Variable.CurrPtr), 2478 &Variable.CurrPtr->VendorGuid, 2479 FALSE, 2480 &VariablePtrTrack 2481 ); 2482 if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) { 2483 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); 2484 continue; 2485 } 2486 } 1940 2487 1941 2488 // … … 1987 2534 This code sets variable in storage blocks (Volatile or Non-Volatile). 1988 2535 2536 Caution: This function may receive untrusted input. 2537 This function may be invoked in SMM mode, and datasize and data are external input. 2538 This function will do basic validation, before parse the data. 2539 1989 2540 @param VariableName Name of Variable to be found. 1990 2541 @param VendorGuid Variable vendor GUID. … … 2015 2566 VARIABLE_HEADER *NextVariable; 2016 2567 EFI_PHYSICAL_ADDRESS Point; 2568 LIST_ENTRY *Link; 2569 VARIABLE_ENTRY *Entry; 2017 2570 2018 2571 // … … 2028 2581 2029 2582 // 2030 // Not support authenticated variable write yet.2031 // 2032 if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {2583 // Not support authenticated or append variable write yet. 2584 // 2585 if ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE)) != 0) { 2033 2586 return EFI_INVALID_PARAMETER; 2034 2587 } … … 2038 2591 // 2039 2592 if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) { 2593 return EFI_INVALID_PARAMETER; 2594 } 2595 2596 if ((UINTN)(~0) - DataSize < StrSize(VariableName)){ 2597 // 2598 // Prevent whole variable size overflow 2599 // 2040 2600 return EFI_INVALID_PARAMETER; 2041 2601 } … … 2047 2607 // 2048 2608 if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 2049 if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) || 2050 (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) { 2609 if ( StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) { 2051 2610 return EFI_INVALID_PARAMETER; 2052 2611 } 2053 // 2054 // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX". 2055 // 2056 if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) { 2612 if (!IsHwErrRecVariable(VariableName, VendorGuid)) { 2057 2613 return EFI_INVALID_PARAMETER; 2058 2614 } … … 2062 2618 // the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes. 2063 2619 // 2064 if ((DataSize > PcdGet32 (PcdMaxVariableSize)) || 2065 (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) { 2620 if (StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) { 2066 2621 return EFI_INVALID_PARAMETER; 2067 2622 } 2068 } 2623 } 2624 2625 Status = CheckEfiGlobalVariable (VariableName, VendorGuid, Attributes); 2626 if (EFI_ERROR (Status)) { 2627 return Status; 2628 } 2069 2629 2070 2630 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); … … 2079 2639 // 2080 2640 NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point); 2081 while ((NextVariable < GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point)) 2082 && IsValidVariableHeader (NextVariable)) { 2641 while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point))) { 2083 2642 NextVariable = GetNextVariablePtr (NextVariable); 2084 2643 } 2085 2644 mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point; 2645 } 2646 2647 if (mEndOfDxe && mEnableLocking) { 2648 // 2649 // Treat the variables listed in the forbidden variable list as read-only after leaving DXE phase. 2650 // 2651 for ( Link = GetFirstNode (&mLockedVariableList) 2652 ; !IsNull (&mLockedVariableList, Link) 2653 ; Link = GetNextNode (&mLockedVariableList, Link) 2654 ) { 2655 Entry = BASE_CR (Link, VARIABLE_ENTRY, Link); 2656 if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, VariableName) == 0)) { 2657 Status = EFI_WRITE_PROTECTED; 2658 DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after leaving DXE phase - %g:%s\n", VendorGuid, VariableName)); 2659 goto Done; 2660 } 2661 } 2086 2662 } 2087 2663 … … 2092 2668 if (!EFI_ERROR (Status)) { 2093 2669 if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) { 2094 return EFI_WRITE_PROTECTED; 2095 } 2096 } 2097 2098 // 2099 // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang. 2100 // 2101 AutoUpdateLangVariable (VariableName, Data, DataSize); 2670 Status = EFI_WRITE_PROTECTED; 2671 goto Done; 2672 } 2673 if (Attributes != 0 && Attributes != Variable.CurrPtr->Attributes) { 2674 // 2675 // If a preexisting variable is rewritten with different attributes, SetVariable() shall not 2676 // modify the variable and shall return EFI_INVALID_PARAMETER. Two exceptions to this rule: 2677 // 1. No access attributes specified 2678 // 2. The only attribute differing is EFI_VARIABLE_APPEND_WRITE 2679 // 2680 Status = EFI_INVALID_PARAMETER; 2681 goto Done; 2682 } 2683 } 2684 2685 if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) { 2686 // 2687 // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang. 2688 // 2689 Status = AutoUpdateLangVariable (VariableName, Data, DataSize); 2690 if (EFI_ERROR (Status)) { 2691 // 2692 // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang. 2693 // 2694 goto Done; 2695 } 2696 } 2102 2697 2103 2698 Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable); 2104 2699 2700 Done: 2105 2701 InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState); 2106 2702 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); … … 2112 2708 2113 2709 This code returns information about the EFI variables. 2710 2711 Caution: This function may receive untrusted input. 2712 This function may be invoked in SMM mode. This function will do basic validation, before parse the data. 2114 2713 2115 2714 @param Attributes Attributes bitmask to specify the type of variables … … 2122 2721 associated with the attributes specified. 2123 2722 2124 @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.2125 2723 @return EFI_SUCCESS Query successfully. 2126 @return EFI_UNSUPPORTED The attribute is not supported on this platform.2127 2724 2128 2725 **/ 2129 2726 EFI_STATUS 2130 2727 EFIAPI 2131 VariableServiceQueryVariableInfo (2728 VariableServiceQueryVariableInfoInternal ( 2132 2729 IN UINT32 Attributes, 2133 2730 OUT UINT64 *MaximumVariableStorageSize, … … 2142 2739 UINT64 CommonVariableTotalSize; 2143 2740 UINT64 HwErrVariableTotalSize; 2741 EFI_STATUS Status; 2742 VARIABLE_POINTER_TRACK VariablePtrTrack; 2144 2743 2145 2744 CommonVariableTotalSize = 0; 2146 2745 HwErrVariableTotalSize = 0; 2147 2148 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {2149 return EFI_INVALID_PARAMETER;2150 }2151 2152 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {2153 //2154 // Make sure the Attributes combination is supported by the platform.2155 //2156 return EFI_UNSUPPORTED;2157 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {2158 //2159 // Make sure if runtime bit is set, boot service bit is set also.2160 //2161 return EFI_INVALID_PARAMETER;2162 } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {2163 //2164 // Make sure RT Attribute is set if we are in Runtime phase.2165 //2166 return EFI_INVALID_PARAMETER;2167 } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {2168 //2169 // Make sure Hw Attribute is set with NV.2170 //2171 return EFI_INVALID_PARAMETER;2172 } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {2173 //2174 // Not support authentiated variable write yet.2175 //2176 return EFI_UNSUPPORTED;2177 }2178 2179 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);2180 2746 2181 2747 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) { … … 2223 2789 // Now walk through the related variable store. 2224 2790 // 2225 while ( (Variable < GetEndPointer (VariableStoreHeader)) && IsValidVariableHeader (Variable)) {2791 while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) { 2226 2792 NextVariable = GetNextVariablePtr (Variable); 2227 2793 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable; … … 2250 2816 CommonVariableTotalSize += VariableSize; 2251 2817 } 2818 } else if (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { 2819 // 2820 // If it is a IN_DELETED_TRANSITION variable, 2821 // and there is not also a same ADDED one at the same time, 2822 // this IN_DELETED_TRANSITION variable is valid. 2823 // 2824 VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader); 2825 VariablePtrTrack.EndPtr = GetEndPointer (VariableStoreHeader); 2826 Status = FindVariableEx ( 2827 GetVariableNamePtr (Variable), 2828 &Variable->VendorGuid, 2829 FALSE, 2830 &VariablePtrTrack 2831 ); 2832 if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State != VAR_ADDED) { 2833 if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 2834 HwErrVariableTotalSize += VariableSize; 2835 } else { 2836 CommonVariableTotalSize += VariableSize; 2837 } 2838 } 2252 2839 } 2253 2840 } … … 2271 2858 } 2272 2859 2273 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);2274 2860 return EFI_SUCCESS; 2275 2861 } 2276 2862 2863 /** 2864 2865 This code returns information about the EFI variables. 2866 2867 Caution: This function may receive untrusted input. 2868 This function may be invoked in SMM mode. This function will do basic validation, before parse the data. 2869 2870 @param Attributes Attributes bitmask to specify the type of variables 2871 on which to return information. 2872 @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available 2873 for the EFI variables associated with the attributes specified. 2874 @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available 2875 for EFI variables associated with the attributes specified. 2876 @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables 2877 associated with the attributes specified. 2878 2879 @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied. 2880 @return EFI_SUCCESS Query successfully. 2881 @return EFI_UNSUPPORTED The attribute is not supported on this platform. 2882 2883 **/ 2884 EFI_STATUS 2885 EFIAPI 2886 VariableServiceQueryVariableInfo ( 2887 IN UINT32 Attributes, 2888 OUT UINT64 *MaximumVariableStorageSize, 2889 OUT UINT64 *RemainingVariableStorageSize, 2890 OUT UINT64 *MaximumVariableSize 2891 ) 2892 { 2893 EFI_STATUS Status; 2894 2895 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) { 2896 return EFI_INVALID_PARAMETER; 2897 } 2898 2899 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) { 2900 // 2901 // Make sure the Attributes combination is supported by the platform. 2902 // 2903 return EFI_UNSUPPORTED; 2904 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) { 2905 // 2906 // Make sure if runtime bit is set, boot service bit is set also. 2907 // 2908 return EFI_INVALID_PARAMETER; 2909 } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) { 2910 // 2911 // Make sure RT Attribute is set if we are in Runtime phase. 2912 // 2913 return EFI_INVALID_PARAMETER; 2914 } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 2915 // 2916 // Make sure Hw Attribute is set with NV. 2917 // 2918 return EFI_INVALID_PARAMETER; 2919 } else if ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE)) != 0) { 2920 // 2921 // Not support authenticated or append variable write yet. 2922 // 2923 return EFI_UNSUPPORTED; 2924 } 2925 2926 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); 2927 2928 Status = VariableServiceQueryVariableInfoInternal ( 2929 Attributes, 2930 MaximumVariableStorageSize, 2931 RemainingVariableStorageSize, 2932 MaximumVariableSize 2933 ); 2934 2935 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); 2936 return Status; 2937 } 2277 2938 2278 2939 /** 2279 2940 This function reclaims variable storage if free size is below the threshold. 2280 2941 2942 Caution: This function may be invoked at SMM mode. 2943 Care must be taken to make sure not security issue. 2944 2281 2945 **/ 2282 2946 VOID … … 2289 2953 UINTN RemainingCommonVariableSpace; 2290 2954 UINTN RemainingHwErrVariableSpace; 2955 STATIC BOOLEAN Reclaimed; 2956 2957 // 2958 // This function will be called only once at EndOfDxe or ReadyToBoot event. 2959 // 2960 if (Reclaimed) { 2961 return; 2962 } 2963 Reclaimed = TRUE; 2291 2964 2292 2965 Status = EFI_SUCCESS; … … 2307 2980 &mVariableModuleGlobal->NonVolatileLastVariableOffset, 2308 2981 FALSE, 2309 NULL 2982 NULL, 2983 NULL, 2984 0 2310 2985 ); 2311 2986 ASSERT_EFI_ERROR (Status); … … 2313 2988 } 2314 2989 2315 2316 2990 /** 2317 Initializes variable write service after FVB was ready. 2991 Init non-volatile variable store. 2992 2993 @retval EFI_SUCCESS Function successfully executed. 2994 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource. 2995 @retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted. 2996 2997 **/ 2998 EFI_STATUS 2999 InitNonVolatileVariableStore ( 3000 VOID 3001 ) 3002 { 3003 EFI_FIRMWARE_VOLUME_HEADER *FvHeader; 3004 VARIABLE_HEADER *NextVariable; 3005 EFI_PHYSICAL_ADDRESS VariableStoreBase; 3006 UINT64 VariableStoreLength; 3007 UINTN VariableSize; 3008 EFI_HOB_GUID_TYPE *GuidHob; 3009 EFI_PHYSICAL_ADDRESS NvStorageBase; 3010 UINT8 *NvStorageData; 3011 UINT32 NvStorageSize; 3012 FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; 3013 UINT32 BackUpOffset; 3014 UINT32 BackUpSize; 3015 3016 mVariableModuleGlobal->FvbInstance = NULL; 3017 3018 // 3019 // Note that in EdkII variable driver implementation, Hardware Error Record type variable 3020 // is stored with common variable in the same NV region. So the platform integrator should 3021 // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of 3022 // PcdFlashNvStorageVariableSize. 3023 // 3024 ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize)); 3025 3026 // 3027 // Allocate runtime memory used for a memory copy of the FLASH region. 3028 // Keep the memory and the FLASH in sync as updates occur. 3029 // 3030 NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize); 3031 NvStorageData = AllocateRuntimeZeroPool (NvStorageSize); 3032 if (NvStorageData == NULL) { 3033 return EFI_OUT_OF_RESOURCES; 3034 } 3035 3036 NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64); 3037 if (NvStorageBase == 0) { 3038 NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); 3039 } 3040 // 3041 // Copy NV storage data to the memory buffer. 3042 // 3043 CopyMem (NvStorageData, (UINT8 *) (UINTN) NvStorageBase, NvStorageSize); 3044 3045 // 3046 // Check the FTW last write data hob. 3047 // 3048 GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid); 3049 if (GuidHob != NULL) { 3050 FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob); 3051 if (FtwLastWriteData->TargetAddress == NvStorageBase) { 3052 DEBUG ((EFI_D_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress)); 3053 // 3054 // Copy the backed up NV storage data to the memory buffer from spare block. 3055 // 3056 CopyMem (NvStorageData, (UINT8 *) (UINTN) (FtwLastWriteData->SpareAddress), NvStorageSize); 3057 } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && 3058 (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) { 3059 // 3060 // Flash NV storage from the offset is backed up in spare block. 3061 // 3062 BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase); 3063 BackUpSize = NvStorageSize - BackUpOffset; 3064 DEBUG ((EFI_D_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress)); 3065 // 3066 // Copy the partial backed up NV storage data to the memory buffer from spare block. 3067 // 3068 CopyMem (NvStorageData + BackUpOffset, (UINT8 *) (UINTN) FtwLastWriteData->SpareAddress, BackUpSize); 3069 } 3070 } 3071 3072 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) NvStorageData; 3073 3074 // 3075 // Check if the Firmware Volume is not corrupted 3076 // 3077 if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) { 3078 FreePool (NvStorageData); 3079 DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n")); 3080 return EFI_VOLUME_CORRUPTED; 3081 } 3082 3083 VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength); 3084 VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength); 3085 3086 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase; 3087 mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase; 3088 if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) { 3089 FreePool (NvStorageData); 3090 DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n")); 3091 return EFI_VOLUME_CORRUPTED; 3092 } 3093 ASSERT(mNvVariableCache->Size == VariableStoreLength); 3094 3095 // 3096 // The max variable or hardware error variable size should be < variable store size. 3097 // 3098 ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength); 3099 3100 // 3101 // Parse non-volatile variable data and get last variable offset. 3102 // 3103 NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase); 3104 while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase))) { 3105 VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER); 3106 if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { 3107 mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize); 3108 } else { 3109 mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize); 3110 } 3111 3112 NextVariable = GetNextVariablePtr (NextVariable); 3113 } 3114 mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase; 3115 3116 return EFI_SUCCESS; 3117 } 3118 3119 /** 3120 Flush the HOB variable to flash. 3121 3122 @param[in] VariableName Name of variable has been updated or deleted. 3123 @param[in] VendorGuid Guid of variable has been updated or deleted. 3124 3125 **/ 3126 VOID 3127 FlushHobVariableToFlash ( 3128 IN CHAR16 *VariableName, 3129 IN EFI_GUID *VendorGuid 3130 ) 3131 { 3132 EFI_STATUS Status; 3133 VARIABLE_STORE_HEADER *VariableStoreHeader; 3134 VARIABLE_HEADER *Variable; 3135 VOID *VariableData; 3136 BOOLEAN ErrorFlag; 3137 3138 ErrorFlag = FALSE; 3139 3140 // 3141 // Flush the HOB variable to flash. 3142 // 3143 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) { 3144 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase; 3145 // 3146 // Set HobVariableBase to 0, it can avoid SetVariable to call back. 3147 // 3148 mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0; 3149 for ( Variable = GetStartPointer (VariableStoreHeader) 3150 ; IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader)) 3151 ; Variable = GetNextVariablePtr (Variable) 3152 ) { 3153 if (Variable->State != VAR_ADDED) { 3154 // 3155 // The HOB variable has been set to DELETED state in local. 3156 // 3157 continue; 3158 } 3159 ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0); 3160 if (VendorGuid == NULL || VariableName == NULL || 3161 !CompareGuid (VendorGuid, &Variable->VendorGuid) || 3162 StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) { 3163 VariableData = GetVariableDataPtr (Variable); 3164 Status = VariableServiceSetVariable ( 3165 GetVariableNamePtr (Variable), 3166 &Variable->VendorGuid, 3167 Variable->Attributes, 3168 Variable->DataSize, 3169 VariableData 3170 ); 3171 DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status)); 3172 } else { 3173 // 3174 // The updated or deleted variable is matched with the HOB variable. 3175 // Don't break here because we will try to set other HOB variables 3176 // since this variable could be set successfully. 3177 // 3178 Status = EFI_SUCCESS; 3179 } 3180 if (!EFI_ERROR (Status)) { 3181 // 3182 // If set variable successful, or the updated or deleted variable is matched with the HOB variable, 3183 // set the HOB variable to DELETED state in local. 3184 // 3185 DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable))); 3186 Variable->State &= VAR_DELETED; 3187 } else { 3188 ErrorFlag = TRUE; 3189 } 3190 } 3191 if (ErrorFlag) { 3192 // 3193 // We still have HOB variable(s) not flushed in flash. 3194 // 3195 mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader; 3196 } else { 3197 // 3198 // All HOB variables have been flushed in flash. 3199 // 3200 DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have been flushed in flash.\n")); 3201 if (!AtRuntime ()) { 3202 FreePool ((VOID *) VariableStoreHeader); 3203 } 3204 } 3205 } 3206 3207 } 3208 3209 /** 3210 Initializes variable write service after FTW was ready. 2318 3211 2319 3212 @retval EFI_SUCCESS Function successfully executed. … … 2331 3224 UINT8 Data; 2332 3225 EFI_PHYSICAL_ADDRESS VariableStoreBase; 2333 VARIABLE_HEADER *Variable; 2334 VOID *VariableData; 2335 2336 VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase; 3226 EFI_PHYSICAL_ADDRESS NvStorageBase; 3227 3228 NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64); 3229 if (NvStorageBase == 0) { 3230 NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); 3231 } 3232 VariableStoreBase = NvStorageBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageBase))->HeaderLength); 3233 3234 // 3235 // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready. 3236 // 3237 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase; 2337 3238 VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase; 2338 3239 … … 2350 3251 &mVariableModuleGlobal->NonVolatileLastVariableOffset, 2351 3252 FALSE, 2352 NULL 3253 NULL, 3254 NULL, 3255 0 2353 3256 ); 2354 3257 if (EFI_ERROR (Status)) { … … 2359 3262 } 2360 3263 2361 // 2362 // Flush the HOB variable to flash and invalidate HOB variable. 2363 // 2364 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) { 2365 // 2366 // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB 2367 // 2368 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase; 2369 mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0; 2370 2371 for ( Variable = GetStartPointer (VariableStoreHeader) 2372 ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable)) 2373 ; Variable = GetNextVariablePtr (Variable) 2374 ) { 2375 ASSERT (Variable->State == VAR_ADDED); 2376 ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0); 2377 VariableData = GetVariableDataPtr (Variable); 2378 Status = VariableServiceSetVariable ( 2379 GetVariableNamePtr (Variable), 2380 &Variable->VendorGuid, 2381 Variable->Attributes, 2382 Variable->DataSize, 2383 VariableData 2384 ); 2385 ASSERT_EFI_ERROR (Status); 2386 } 2387 } 3264 FlushHobVariableToFlash (NULL, NULL); 3265 2388 3266 return EFI_SUCCESS; 2389 3267 } … … 2405 3283 VARIABLE_STORE_HEADER *VolatileVariableStore; 2406 3284 VARIABLE_STORE_HEADER *VariableStoreHeader; 2407 VARIABLE_HEADER *NextVariable;2408 EFI_PHYSICAL_ADDRESS TempVariableStoreHeader;2409 EFI_PHYSICAL_ADDRESS VariableStoreBase;2410 3285 UINT64 VariableStoreLength; 2411 3286 UINTN ScratchSize; 2412 UINTN VariableSize;2413 3287 EFI_HOB_GUID_TYPE *GuidHob; 2414 3288 … … 2424 3298 2425 3299 // 2426 // Note that in EdkII variable driver implementation, Hardware Error Record type variable2427 // is stored with common variable in the same NV region. So the platform integrator should2428 // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of2429 // PcdFlashNvStorageVariableSize.2430 //2431 ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));2432 2433 //2434 3300 // Get HOB variable store. 2435 3301 // … … 2437 3303 if (GuidHob != NULL) { 2438 3304 VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob); 3305 VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE)); 2439 3306 if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) { 2440 mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader; 3307 mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader); 3308 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) { 3309 FreePool (mVariableModuleGlobal); 3310 return EFI_OUT_OF_RESOURCES; 3311 } 2441 3312 } else { 2442 3313 DEBUG ((EFI_D_ERROR, "HOB Variable Store header is corrupted!\n")); … … 2450 3321 VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize); 2451 3322 if (VolatileVariableStore == NULL) { 3323 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) { 3324 FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase); 3325 } 2452 3326 FreePool (mVariableModuleGlobal); 2453 3327 return EFI_OUT_OF_RESOURCES; … … 2461 3335 mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore; 2462 3336 mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore; 2463 mVariableModuleGlobal->FvbInstance = NULL;2464 3337 2465 3338 CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid); … … 2471 3344 2472 3345 // 2473 // Get non-volatile variable store. 2474 // 2475 2476 TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64); 2477 if (TempVariableStoreHeader == 0) { 2478 TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); 2479 } 2480 2481 // 2482 // Check if the Firmware Volume is not corrupted 2483 // 2484 if ((((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->Signature != EFI_FVH_SIGNATURE) || 2485 (!CompareGuid (&gEfiSystemNvDataFvGuid, &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->FileSystemGuid))) { 2486 Status = EFI_VOLUME_CORRUPTED; 2487 DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n")); 2488 goto Done; 2489 } 2490 2491 VariableStoreBase = TempVariableStoreHeader + \ 2492 (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength); 2493 VariableStoreLength = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \ 2494 (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength); 2495 2496 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase; 2497 VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase; 2498 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) { 2499 Status = EFI_VOLUME_CORRUPTED; 2500 DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n")); 2501 goto Done; 2502 } 2503 ASSERT(VariableStoreHeader->Size == VariableStoreLength); 2504 2505 // 2506 // Parse non-volatile variable data and get last variable offset. 2507 // 2508 NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase); 2509 while (IsValidVariableHeader (NextVariable)) { 2510 VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER); 2511 if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { 2512 mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize); 2513 } else { 2514 mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize); 2515 } 2516 2517 NextVariable = GetNextVariablePtr (NextVariable); 2518 } 2519 2520 mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase; 2521 2522 // 2523 // Allocate runtime memory used for a memory copy of the FLASH region. 2524 // Keep the memory and the FLASH in sync as updates occur 2525 // 2526 mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength); 2527 if (mNvVariableCache == NULL) { 2528 Status = EFI_OUT_OF_RESOURCES; 2529 goto Done; 2530 } 2531 CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength); 2532 Status = EFI_SUCCESS; 2533 2534 Done: 3346 // Init non-volatile variable store. 3347 // 3348 Status = InitNonVolatileVariableStore (); 2535 3349 if (EFI_ERROR (Status)) { 3350 if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) { 3351 FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase); 3352 } 2536 3353 FreePool (mVariableModuleGlobal); 2537 3354 FreePool (VolatileVariableStore); … … 2566 3383 EFI_FVB_ATTRIBUTES_2 Attributes; 2567 3384 3385 Fvb = NULL; 3386 HandleBuffer = NULL; 3387 2568 3388 // 2569 3389 // Get all FVB handles.
Note:
See TracChangeset
for help on using the changeset viewer.