Changeset 58459 in vbox for trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe
- Timestamp:
- Oct 28, 2015 8:17:18 PM (9 years ago)
- Location:
- trunk/src/VBox/Devices/EFI/Firmware
- Files:
-
- 10 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/Reclaim.c
r48674 r58459 4 4 (Fault Tolerant Write) protocol. 5 5 6 Copyright (c) 2006 - 201 0, Intel Corporation. All rights reserved.<BR>6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 7 7 This program and the accompanying materials 8 8 are licensed and made available under the terms and conditions of the BSD License … … 48 48 UINT32 LbaIndex; 49 49 50 Fvb = NULL; 50 51 *Lba = (EFI_LBA) (-1); 51 52 *Offset = 0; … … 100 101 101 102 @param VariableBase Base address of variable to write 102 @param Buffer Point to the data buffer. 103 @param BufferSize The number of bytes of the data Buffer. 103 @param VariableBuffer Point to the variable data buffer. 104 104 105 105 @retval EFI_SUCCESS The function completed successfully. … … 111 111 FtwVariableSpace ( 112 112 IN EFI_PHYSICAL_ADDRESS VariableBase, 113 IN UINT8 *Buffer, 114 IN UINTN BufferSize 113 IN VARIABLE_STORE_HEADER *VariableBuffer 115 114 ) 116 115 { … … 119 118 EFI_LBA VarLba; 120 119 UINTN VarOffset; 121 UINT8 *FtwBuffer;122 120 UINTN FtwBufferSize; 123 121 EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; … … 144 142 return EFI_ABORTED; 145 143 } 146 // 147 // Prepare for the variable data. 148 // 144 149 145 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size; 150 FtwBuffer = AllocatePool (FtwBufferSize); 151 if (FtwBuffer == NULL) { 152 return EFI_OUT_OF_RESOURCES; 153 } 154 155 SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff); 156 CopyMem (FtwBuffer, Buffer, BufferSize); 146 ASSERT (FtwBufferSize == VariableBuffer->Size); 157 147 158 148 // … … 166 156 NULL, // PrivateData NULL 167 157 FvbHandle, // Fvb Handle 168 FtwBuffer// write buffer158 (VOID *) VariableBuffer // write buffer 169 159 ); 170 160 171 FreePool (FtwBuffer);172 161 return Status; 173 162 } -
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. -
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
r48674 r58459 4 4 internal structure and functions used by Variable modules. 5 5 6 Copyright (c) 2006 - 201 0, Intel Corporation. All rights reserved.<BR>6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 7 7 This program and the accompanying materials 8 8 are licensed and made available under the terms and conditions of the BSD License … … 23 23 #include <Protocol/FirmwareVolumeBlock.h> 24 24 #include <Protocol/Variable.h> 25 #include <Protocol/VariableLock.h> 25 26 #include <Library/PcdLib.h> 26 27 #include <Library/HobLib.h> … … 39 40 #include <Guid/VariableFormat.h> 40 41 #include <Guid/SystemNvDataGuid.h> 41 42 #define VARIABLE_RECLAIM_THRESHOLD (1024) 42 #include <Guid/FaultTolerantWrite.h> 43 #include <Guid/HardwareErrorVariable.h> 44 45 #define VARIABLE_ATTRIBUTE_BS_RT (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS) 46 #define VARIABLE_ATTRIBUTE_NV_BS_RT (VARIABLE_ATTRIBUTE_BS_RT | EFI_VARIABLE_NON_VOLATILE) 47 #define VARIABLE_ATTRIBUTE_NV_BS_RT_AT (VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) 48 49 typedef struct { 50 CHAR16 *Name; 51 UINT32 Attributes; 52 } GLOBAL_VARIABLE_ENTRY; 43 53 44 54 /// … … 56 66 typedef struct { 57 67 VARIABLE_HEADER *CurrPtr; 68 // 69 // If both ADDED and IN_DELETED_TRANSITION variable are present, 70 // InDeletedTransitionPtr will point to the IN_DELETED_TRANSITION one. 71 // Otherwise, CurrPtr will point to the ADDED or IN_DELETED_TRANSITION one, 72 // and InDeletedTransitionPtr will be NULL at the same time. 73 // 74 VARIABLE_HEADER *InDeletedTransitionPtr; 58 75 VARIABLE_HEADER *EndPtr; 59 76 VARIABLE_HEADER *StartPtr; … … 85 102 EFI_GUID *Guid; 86 103 CHAR16 *Name; 87 UINT32 Attributes; 88 UINTN DataSize; 89 VOID *Data; 90 } VARIABLE_CACHE_ENTRY; 104 UINTN VariableSize; 105 } VARIABLE_ENTRY_CONSISTENCY; 106 107 typedef struct { 108 EFI_GUID Guid; 109 CHAR16 *Name; 110 LIST_ENTRY Link; 111 } VARIABLE_ENTRY; 112 113 /** 114 Flush the HOB variable to flash. 115 116 @param[in] VariableName Name of variable has been updated or deleted. 117 @param[in] VendorGuid Guid of variable has been updated or deleted. 118 119 **/ 120 VOID 121 FlushHobVariableToFlash ( 122 IN CHAR16 *VariableName, 123 IN EFI_GUID *VendorGuid 124 ); 91 125 92 126 /** … … 98 132 99 133 @param VariableBase Base address of the variable to write. 100 @param Buffer Point to the data buffer. 101 @param BufferSize The number of bytes of the data Buffer. 134 @param VariableBuffer Point to the variable data buffer. 102 135 103 136 @retval EFI_SUCCESS The function completed successfully. … … 109 142 FtwVariableSpace ( 110 143 IN EFI_PHYSICAL_ADDRESS VariableBase, 111 IN UINT8 *Buffer, 112 IN UINTN BufferSize 144 IN VARIABLE_STORE_HEADER *VariableBuffer 113 145 ); 114 146 … … 128 160 @param[in] Attributes Attribues of the variable. 129 161 130 @param[in ] VariableThe variable information that is used to keep track of variable usage.162 @param[in, out] Variable The variable information that is used to keep track of variable usage. 131 163 132 164 @retval EFI_SUCCESS The update operation is success. … … 142 174 IN UINTN DataSize, 143 175 IN UINT32 Attributes OPTIONAL, 144 IN 176 IN OUT VARIABLE_POINTER_TRACK *Variable 145 177 ); 146 178 … … 423 455 associated with the attributes specified. 424 456 457 @return EFI_SUCCESS Query successfully. 458 459 **/ 460 EFI_STATUS 461 EFIAPI 462 VariableServiceQueryVariableInfoInternal ( 463 IN UINT32 Attributes, 464 OUT UINT64 *MaximumVariableStorageSize, 465 OUT UINT64 *RemainingVariableStorageSize, 466 OUT UINT64 *MaximumVariableSize 467 ); 468 469 /** 470 471 This code returns information about the EFI variables. 472 473 @param Attributes Attributes bitmask to specify the type of variables 474 on which to return information. 475 @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available 476 for the EFI variables associated with the attributes specified. 477 @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available 478 for EFI variables associated with the attributes specified. 479 @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables 480 associated with the attributes specified. 481 425 482 @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied. 426 483 @return EFI_SUCCESS Query successfully. … … 436 493 OUT UINT64 *MaximumVariableSize 437 494 ); 438 495 496 /** 497 Mark a variable that will become read-only after leaving the DXE phase of execution. 498 499 @param[in] This The VARIABLE_LOCK_PROTOCOL instance. 500 @param[in] VariableName A pointer to the variable name that will be made read-only subsequently. 501 @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently. 502 503 @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked 504 as pending to be read-only. 505 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL. 506 Or VariableName is an empty string. 507 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has 508 already been signaled. 509 @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request. 510 **/ 511 EFI_STATUS 512 EFIAPI 513 VariableLockRequestToLock ( 514 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This, 515 IN CHAR16 *VariableName, 516 IN EFI_GUID *VendorGuid 517 ); 518 439 519 extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; 440 520 -
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
r48674 r58459 4 4 and volatile storage space and install variable architecture protocol. 5 5 6 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> 6 Copyright (C) 2013, Red Hat, Inc. 7 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR> 7 8 This program and the accompanying materials 8 9 are licensed and made available under the terms and conditions of the BSD License … … 22 23 EFI_EVENT mVirtualAddressChangeEvent = NULL; 23 24 EFI_EVENT mFtwRegistration = NULL; 25 extern LIST_ENTRY mLockedVariableList; 26 extern BOOLEAN mEndOfDxe; 27 EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock }; 24 28 25 29 /** … … 219 223 ) 220 224 { 225 LIST_ENTRY *Link; 226 VARIABLE_ENTRY *Entry; 227 EFI_STATUS Status; 228 221 229 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize); 222 230 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress); … … 232 240 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase); 233 241 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase); 242 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase); 234 243 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal); 235 244 EfiConvertPointer (0x0, (VOID **) &mNvVariableCache); 245 246 // 247 // in the list of locked variables, convert the name pointers first 248 // 249 for ( Link = GetFirstNode (&mLockedVariableList) 250 ; !IsNull (&mLockedVariableList, Link) 251 ; Link = GetNextNode (&mLockedVariableList, Link) 252 ) { 253 Entry = BASE_CR (Link, VARIABLE_ENTRY, Link); 254 Status = EfiConvertPointer (0x0, (VOID **) &Entry->Name); 255 ASSERT_EFI_ERROR (Status); 256 } 257 // 258 // second, convert the list itself using UefiRuntimeLib 259 // 260 Status = EfiConvertList (0x0, &mLockedVariableList); 261 ASSERT_EFI_ERROR (Status); 236 262 } 237 263 … … 255 281 ) 256 282 { 283 // 284 // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled. 285 // 286 mEndOfDxe = TRUE; 257 287 ReclaimForOS (); 258 288 if (FeaturePcdGet (PcdVariableCollectStatistics)) { … … 261 291 } 262 292 293 /** 294 Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group. 295 296 This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group. 297 298 @param Event Event whose notification function is being invoked. 299 @param Context Pointer to the notification function's context. 300 301 **/ 302 VOID 303 EFIAPI 304 OnEndOfDxe ( 305 EFI_EVENT Event, 306 VOID *Context 307 ) 308 { 309 mEndOfDxe = TRUE; 310 if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) { 311 ReclaimForOS (); 312 } 313 } 263 314 264 315 /** … … 288 339 EFI_PHYSICAL_ADDRESS VariableStoreBase; 289 340 UINT64 VariableStoreLength; 341 UINTN FtwMaxBlockSize; 290 342 291 343 // … … 296 348 return ; 297 349 } 298 350 351 Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize); 352 if (!EFI_ERROR (Status)) { 353 ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize); 354 } 355 299 356 // 300 357 // Find the proper FVB protocol for variable. … … 313 370 // Mark the variable storage region of the FLASH as RUNTIME. 314 371 // 315 VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;372 VariableStoreBase = NvStorageVariableBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageVariableBase))->HeaderLength); 316 373 VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size; 317 374 BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK); … … 321 378 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor); 322 379 if (EFI_ERROR (Status)) { 323 DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));380 DEBUG ((DEBUG_WARN, "Variable driver failed to get flash memory attribute.\n")); 324 381 } else { 325 382 Status = gDS->SetMemorySpaceAttributes ( … … 375 432 { 376 433 EFI_STATUS Status; 377 EFI_EVENT ReadyToBootEvent; 434 EFI_EVENT ReadyToBootEvent; 435 EFI_EVENT EndOfDxeEvent; 378 436 379 437 Status = VariableCommonInitialize (); 438 ASSERT_EFI_ERROR (Status); 439 440 Status = gBS->InstallMultipleProtocolInterfaces ( 441 &mHandle, 442 &gEdkiiVariableLockProtocolGuid, 443 &mVariableLock, 444 NULL 445 ); 380 446 ASSERT_EFI_ERROR (Status); 381 447 … … 426 492 &ReadyToBootEvent 427 493 ); 494 ASSERT_EFI_ERROR (Status); 495 496 // 497 // Register the event handling function to set the End Of DXE flag. 498 // 499 Status = gBS->CreateEventEx ( 500 EVT_NOTIFY_SIGNAL, 501 TPL_NOTIFY, 502 OnEndOfDxe, 503 NULL, 504 &gEfiEndOfDxeEventGroupGuid, 505 &EndOfDxeEvent 506 ); 507 ASSERT_EFI_ERROR (Status); 428 508 429 509 return EFI_SUCCESS; -
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
r48674 r58459 1 1 ## @file 2 # Component description file for Variable module.2 # This module installs variable arch protocol and variable write arch protocol. 3 3 # 4 # This module installs three EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName. 5 # Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> 4 # It provides four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo. 5 # 6 # Caution: This module requires additional review when modified. 7 # This driver will have external input - variable data. 8 # This external input must be validated carefully to avoid security issues such as 9 # buffer overflow or integer overflow. 10 # 11 # Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 6 12 # 7 13 # This program and the accompanying materials … … 18 24 INF_VERSION = 0x00010005 19 25 BASE_NAME = VariableRuntimeDxe 26 MODULE_UNI_FILE = VariableRuntimeDxe.uni 20 27 FILE_GUID = CBD2E4D5-7068-4FF5-B462-9822B4AD8D60 21 28 MODULE_TYPE = DXE_RUNTIME_DRIVER … … 56 63 57 64 [Protocols] 58 gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES 59 gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES 60 gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES 61 gEfiFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES 65 gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES 66 ## CONSUMES 67 ## NOTIFY 68 gEfiFaultTolerantWriteProtocolGuid 69 gEfiVariableWriteArchProtocolGuid ## PRODUCES 70 gEfiVariableArchProtocolGuid ## PRODUCES 71 gEdkiiVariableLockProtocolGuid ## PRODUCES 62 72 63 73 [Guids] 64 gEfiVariableGuid ## PRODUCES ## Configuration Table Guid 65 gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid 66 gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event 67 gEfiSystemNvDataFvGuid ## CONSUMES 74 ## PRODUCES ## GUID # Signature of Variable store header 75 ## CONSUMES ## GUID # Signature of Variable store header 76 ## SOMETIMES_CONSUMES ## HOB 77 ## SOMETIMES_PRODUCES ## SystemTable 78 gEfiVariableGuid 79 ## SOMETIMES_CONSUMES ## Variable:L"PlatformLang" 80 ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" 81 ## SOMETIMES_CONSUMES ## Variable:L"Lang" 82 ## SOMETIMES_PRODUCES ## Variable:L"Lang" 83 ## SOMETIMES_CONSUMES ## Variable:L"HwErrRecSupport" 84 gEfiGlobalVariableGuid 85 gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event 86 gEfiSystemNvDataFvGuid ## CONSUMES ## GUID 87 gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES ## Variable:L"HwErrRec####" 88 gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event 89 ## SOMETIMES_CONSUMES ## HOB 90 gEdkiiFaultTolerantWriteGuid 68 91 69 92 [Pcd] 70 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize 71 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase 72 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 73 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize 74 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize 75 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize 76 gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize 77 93 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES 94 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES 95 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES 96 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES 97 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize ## CONSUMES 98 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize ## CONSUMES 99 gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize ## CONSUMES 100 gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe ## CONSUMES 101 78 102 [FeaturePcd] 79 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.) 103 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES # statistic the information of variable. 104 gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES 80 105 81 106 [Depex] 82 107 TRUE 83 108 84 # [Event] 85 # ## 86 # # Event will be signaled for VIRTUAL_ADDRESS_CHANGE event. 87 # # 88 # EVENT_TYPE_NOTIFY_SIGNAL ## PRODUCES 89 # 90 # 91 109 [UserExtensions.TianoCore."ExtraFiles"] 110 VariableRuntimeDxeExtra.uni -
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
r48674 r58459 5 5 to provide variable services. 6 6 7 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> 8 This program and the accompanying materials 9 are licensed and made available under the terms and conditions of the BSD License 10 which accompanies this distribution. The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php 7 Caution: This module requires additional review when modified. 8 This driver will have external input - variable data and communicate buffer in SMM mode. 9 This external input must be validated carefully to avoid security issue like 10 buffer overflow, integer overflow. 11 12 SmmVariableHandler() will receive untrusted input and do basic validation. 13 14 Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(), 15 VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(), 16 SmmVariableGetStatistics() should also do validation based on its own knowledge. 17 18 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR> 19 This program and the accompanying materials 20 are licensed and made available under the terms and conditions of the BSD License 21 which accompanies this distribution. The full text of the license may be found at 22 http://opensource.org/licenses/bsd-license.php 12 23 13 24 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, … … 18 29 #include <Protocol/SmmFirmwareVolumeBlock.h> 19 30 #include <Protocol/SmmFaultTolerantWrite.h> 31 #include <Protocol/SmmEndOfDxe.h> 32 20 33 #include <Library/SmmServicesTableLib.h> 34 #include <Library/SmmMemLib.h> 21 35 22 36 #include <Guid/VariableFormat.h> … … 29 43 BOOLEAN mAtRuntime = FALSE; 30 44 EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; 31 45 UINT8 *mVariableBufferPayload = NULL; 46 UINTN mVariableBufferPayloadSize; 47 extern BOOLEAN mEndOfDxe; 48 extern BOOLEAN mEnableLocking; 49 50 /** 51 52 This code sets variable in storage blocks (Volatile or Non-Volatile). 53 54 @param VariableName Name of Variable to be found. 55 @param VendorGuid Variable vendor GUID. 56 @param Attributes Attribute value of the variable found 57 @param DataSize Size of Data found. If size is less than the 58 data, this value contains the required size. 59 @param Data Data pointer. 60 61 @return EFI_INVALID_PARAMETER Invalid parameter. 62 @return EFI_SUCCESS Set successfully. 63 @return EFI_OUT_OF_RESOURCES Resource not enough to set variable. 64 @return EFI_NOT_FOUND Not found. 65 @return EFI_WRITE_PROTECTED Variable is read-only. 66 67 **/ 68 EFI_STATUS 69 EFIAPI 70 SmmVariableSetVariable ( 71 IN CHAR16 *VariableName, 72 IN EFI_GUID *VendorGuid, 73 IN UINT32 Attributes, 74 IN UINTN DataSize, 75 IN VOID *Data 76 ) 77 { 78 EFI_STATUS Status; 79 80 // 81 // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL. 82 // 83 mEnableLocking = FALSE; 84 Status = VariableServiceSetVariable ( 85 VariableName, 86 VendorGuid, 87 Attributes, 88 DataSize, 89 Data 90 ); 91 mEnableLocking = TRUE; 92 return Status; 93 } 94 32 95 EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = { 33 96 VariableServiceGetVariable, 34 97 VariableServiceGetNextVariableName, 35 VariableServiceSetVariable,98 SmmVariableSetVariable, 36 99 VariableServiceQueryVariableInfo 37 100 }; 38 39 101 40 102 /** … … 233 295 if (EFI_ERROR(Status)) { 234 296 *NumberHandles = 0; 297 FreePool (*Buffer); 298 *Buffer = NULL; 235 299 } 236 300 … … 242 306 Get the variable statistics information from the information buffer pointed by gVariableInfo. 243 307 244 @param[in, out] InfoEntry A pointer to the buffer of variable information entry. 245 On input, point to the variable information returned last time. if 246 InfoEntry->VendorGuid is zero, return the first information. 247 On output, point to the next variable information. 248 @param[in, out] InfoSize On input, the size of the variable information buffer. 249 On output, the returned variable information size. 308 Caution: This function may be invoked at SMM runtime. 309 InfoEntry and InfoSize are external input. Care must be taken to make sure not security issue at runtime. 310 311 @param[in, out] InfoEntry A pointer to the buffer of variable information entry. 312 On input, point to the variable information returned last time. if 313 InfoEntry->VendorGuid is zero, return the first information. 314 On output, point to the next variable information. 315 @param[in, out] InfoSize On input, the size of the variable information buffer. 316 On output, the returned variable information size. 250 317 251 318 @retval EFI_SUCCESS The variable information is found and returned successfully. … … 265 332 UINTN StatisticsInfoSize; 266 333 CHAR16 *InfoName; 267 334 EFI_GUID VendorGuid; 335 268 336 ASSERT (InfoEntry != NULL); 269 337 VariableInfo = gVariableInfo; … … 273 341 274 342 StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name); 275 if (*InfoSize < sizeof (VARIABLE_INFO_ENTRY)) {343 if (*InfoSize < StatisticsInfoSize) { 276 344 *InfoSize = StatisticsInfoSize; 277 345 return EFI_BUFFER_TOO_SMALL; … … 279 347 InfoName = (CHAR16 *)(InfoEntry + 1); 280 348 281 if (CompareGuid (&InfoEntry->VendorGuid, &mZeroGuid)) { 349 CopyGuid (&VendorGuid, &InfoEntry->VendorGuid); 350 351 if (CompareGuid (&VendorGuid, &mZeroGuid)) { 282 352 // 283 353 // Return the first variable info … … 293 363 // 294 364 while (VariableInfo != NULL) { 295 if (CompareGuid (&VariableInfo->VendorGuid, & InfoEntry->VendorGuid)) {365 if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) { 296 366 NameLength = StrSize (VariableInfo->Name); 297 367 if (NameLength == StrSize (InfoName)) { … … 335 405 This SMI handler provides services for the variable wrapper driver. 336 406 407 Caution: This function may receive untrusted input. 408 This variable data and communicate buffer are external input, so this function will do basic validation. 409 Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(), 410 VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(), 411 SmmVariableGetStatistics() should also do validation based on its own knowledge. 412 337 413 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). 338 414 @param[in] RegisterContext Points to an optional handler context which was specified when the … … 365 441 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo; 366 442 VARIABLE_INFO_ENTRY *VariableInfo; 443 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock; 367 444 UINTN InfoSize; 368 369 ASSERT (CommBuffer != NULL); 445 UINTN NameBufferSize; 446 UINTN CommBufferPayloadSize; 447 UINTN TempCommBufferSize; 448 449 // 450 // If input is invalid, stop processing this SMI 451 // 452 if (CommBuffer == NULL || CommBufferSize == NULL) { 453 return EFI_SUCCESS; 454 } 455 456 TempCommBufferSize = *CommBufferSize; 457 458 if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) { 459 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n")); 460 return EFI_SUCCESS; 461 } 462 CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE; 463 if (CommBufferPayloadSize > mVariableBufferPayloadSize) { 464 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n")); 465 return EFI_SUCCESS; 466 } 467 468 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { 469 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n")); 470 return EFI_SUCCESS; 471 } 370 472 371 473 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer; 372 474 switch (SmmVariableFunctionHeader->Function) { 373 475 case SMM_VARIABLE_FUNCTION_GET_VARIABLE: 374 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data; 476 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) { 477 DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n")); 478 return EFI_SUCCESS; 479 } 480 // 481 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload. 482 // 483 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize); 484 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload; 485 if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) || 486 ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) { 487 // 488 // Prevent InfoSize overflow happen 489 // 490 Status = EFI_ACCESS_DENIED; 491 goto EXIT; 492 } 493 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) 494 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize; 495 496 // 497 // SMRAM range check already covered before 498 // 499 if (InfoSize > CommBufferPayloadSize) { 500 DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n")); 501 Status = EFI_ACCESS_DENIED; 502 goto EXIT; 503 } 504 505 if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') { 506 // 507 // Make sure VariableName is A Null-terminated string. 508 // 509 Status = EFI_ACCESS_DENIED; 510 goto EXIT; 511 } 512 375 513 Status = VariableServiceGetVariable ( 376 514 SmmVariableHeader->Name, … … 380 518 (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize 381 519 ); 520 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize); 382 521 break; 383 522 384 523 case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME: 385 GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) SmmVariableFunctionHeader->Data; 524 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) { 525 DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n")); 526 return EFI_SUCCESS; 527 } 528 // 529 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload. 530 // 531 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize); 532 GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload; 533 if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) { 534 // 535 // Prevent InfoSize overflow happen 536 // 537 Status = EFI_ACCESS_DENIED; 538 goto EXIT; 539 } 540 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize; 541 542 // 543 // SMRAM range check already covered before 544 // 545 if (InfoSize > CommBufferPayloadSize) { 546 DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n")); 547 Status = EFI_ACCESS_DENIED; 548 goto EXIT; 549 } 550 551 NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name); 552 if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') { 553 // 554 // Make sure input VariableName is A Null-terminated string. 555 // 556 Status = EFI_ACCESS_DENIED; 557 goto EXIT; 558 } 559 386 560 Status = VariableServiceGetNextVariableName ( 387 561 &GetNextVariableName->NameSize, … … 389 563 &GetNextVariableName->Guid 390 564 ); 565 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize); 391 566 break; 392 567 393 568 case SMM_VARIABLE_FUNCTION_SET_VARIABLE: 394 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data; 569 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) { 570 DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n")); 571 return EFI_SUCCESS; 572 } 573 // 574 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload. 575 // 576 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize); 577 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload; 578 if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) || 579 ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) { 580 // 581 // Prevent InfoSize overflow happen 582 // 583 Status = EFI_ACCESS_DENIED; 584 goto EXIT; 585 } 586 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) 587 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize; 588 589 // 590 // SMRAM range check already covered before 591 // Data buffer should not contain SMM range 592 // 593 if (InfoSize > CommBufferPayloadSize) { 594 DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n")); 595 Status = EFI_ACCESS_DENIED; 596 goto EXIT; 597 } 598 599 if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') { 600 // 601 // Make sure VariableName is A Null-terminated string. 602 // 603 Status = EFI_ACCESS_DENIED; 604 goto EXIT; 605 } 606 395 607 Status = VariableServiceSetVariable ( 396 608 SmmVariableHeader->Name, … … 403 615 404 616 case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO: 617 if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) { 618 DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n")); 619 return EFI_SUCCESS; 620 } 405 621 QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data; 622 406 623 Status = VariableServiceQueryVariableInfo ( 407 624 QueryVariableInfo->Attributes, … … 413 630 414 631 case SMM_VARIABLE_FUNCTION_READY_TO_BOOT: 632 mEndOfDxe = TRUE; 633 if (AtRuntime()) { 634 Status = EFI_UNSUPPORTED; 635 break; 636 } 415 637 ReclaimForOS (); 416 638 Status = EFI_SUCCESS; … … 424 646 case SMM_VARIABLE_FUNCTION_GET_STATISTICS: 425 647 VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data; 426 InfoSize = *CommBufferSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data); 648 InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE; 649 650 // 651 // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here. 652 // It is covered by previous CommBuffer check 653 // 654 655 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) { 656 DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n")); 657 Status = EFI_ACCESS_DENIED; 658 goto EXIT; 659 } 660 427 661 Status = SmmVariableGetStatistics (VariableInfo, &InfoSize); 428 *CommBufferSize = InfoSize + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);662 *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE; 429 663 break; 430 664 665 case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE: 666 if (mEndOfDxe) { 667 Status = EFI_ACCESS_DENIED; 668 } else { 669 VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data; 670 Status = VariableLockRequestToLock ( 671 NULL, 672 VariableToLock->Name, 673 &VariableToLock->Guid 674 ); 675 } 676 break; 677 431 678 default: 432 ASSERT (FALSE);433 679 Status = EFI_UNSUPPORTED; 434 680 } 435 681 682 EXIT: 683 436 684 SmmVariableFunctionHeader->ReturnStatus = Status; 437 685 … … 439 687 } 440 688 689 /** 690 SMM END_OF_DXE protocol notification event handler. 691 692 @param Protocol Points to the protocol's unique identifier 693 @param Interface Points to the interface instance 694 @param Handle The handle on which the interface was installed 695 696 @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully 697 698 **/ 699 EFI_STATUS 700 EFIAPI 701 SmmEndOfDxeCallback ( 702 IN CONST EFI_GUID *Protocol, 703 IN VOID *Interface, 704 IN EFI_HANDLE Handle 705 ) 706 { 707 DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n")); 708 mEndOfDxe = TRUE; 709 if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) { 710 ReclaimForOS (); 711 } 712 return EFI_SUCCESS; 713 } 441 714 442 715 /** … … 466 739 EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; 467 740 EFI_PHYSICAL_ADDRESS NvStorageVariableBase; 741 UINTN FtwMaxBlockSize; 468 742 469 743 if (mVariableModuleGlobal->FvbInstance != NULL) { … … 477 751 if (EFI_ERROR (Status)) { 478 752 return Status; 753 } 754 755 Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize); 756 if (!EFI_ERROR (Status)) { 757 ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize); 479 758 } 480 759 … … 533 812 EFI_HANDLE VariableHandle; 534 813 VOID *SmmFtwRegistration; 535 814 VOID *SmmEndOfDxeRegistration; 815 536 816 // 537 817 // Variable initialize. … … 552 832 ASSERT_EFI_ERROR (Status); 553 833 834 mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) + 835 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER); 836 837 Status = gSmst->SmmAllocatePool ( 838 EfiRuntimeServicesData, 839 mVariableBufferPayloadSize, 840 (VOID **)&mVariableBufferPayload 841 ); 842 ASSERT_EFI_ERROR (Status); 843 554 844 /// 555 845 /// Register SMM variable SMI handler … … 571 861 572 862 // 863 // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function. 864 // 865 Status = gSmst->SmmRegisterProtocolNotify ( 866 &gEfiSmmEndOfDxeProtocolGuid, 867 SmmEndOfDxeCallback, 868 &SmmEndOfDxeRegistration 869 ); 870 ASSERT_EFI_ERROR (Status); 871 872 // 573 873 // Register FtwNotificationEvent () notify function. 574 874 // -
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
r48674 r58459 1 1 ## @file 2 # Component description file for SMM Variable module.3 #4 2 # This module installs SMM variable protocol into SMM protocol database, 5 3 # which can be used by SMM driver, and installs SMM variable protocol … … 9 7 # SMM Runtime DXE module would install variable arch protocol and variable 10 8 # write arch protocol based on SMM variable module. 11 # Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>12 9 # 13 # This program and the accompanying materials 14 # are licensed and made available under the terms and conditions of the BSD License 15 # which accompanies this distribution. The full text of the license may be found at 16 # http://opensource.org/licenses/bsd-license.php 17 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 18 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 10 # Caution: This module requires additional review when modified. 11 # This driver will have external input - variable data and communicate buffer in SMM mode. 12 # This external input must be validated carefully to avoid security issue like 13 # buffer overflow, integer overflow. 14 # 15 # Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR> 16 # This program and the accompanying materials 17 # are licensed and made available under the terms and conditions of the BSD License 18 # which accompanies this distribution. The full text of the license may be found at 19 # http://opensource.org/licenses/bsd-license.php 20 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 21 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19 22 # 20 23 # … … 24 27 INF_VERSION = 0x00010005 25 28 BASE_NAME = VariableSmm 29 MODULE_UNI_FILE = VariableSmm.uni 26 30 FILE_GUID = 23A089B3-EED5-4ac5-B2AB-43E3298C2343 27 31 MODULE_TYPE = DXE_SMM_DRIVER … … 58 62 DxeServicesTableLib 59 63 HobLib 64 PcdLib 65 SmmMemLib 60 66 61 67 [Protocols] 62 gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES 63 gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES 64 gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES 68 gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES 69 ## CONSUMES 70 ## NOTIFY 71 gEfiSmmFaultTolerantWriteProtocolGuid 72 ## PRODUCES 73 ## UNDEFINED # SmiHandlerRegister 74 gEfiSmmVariableProtocolGuid 75 gEfiSmmEndOfDxeProtocolGuid ## CONSUMES 65 76 66 77 [Guids] 67 gEfiVariableGuid ## PRODUCES ## Configuration Table Guid 68 gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid 69 gSmmVariableWriteGuid ## PRODUCES ## SMM Variable Write Guid 70 gEfiSystemNvDataFvGuid ## CONSUMES 78 ## PRODUCES ## GUID # Signature of Variable store header 79 ## CONSUMES ## GUID # Signature of Variable store header 80 ## SOMETIMES_CONSUMES ## HOB 81 gEfiVariableGuid 82 ## SOMETIMES_CONSUMES ## Variable:L"PlatformLang" 83 ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" 84 ## SOMETIMES_CONSUMES ## Variable:L"Lang" 85 ## SOMETIMES_PRODUCES ## Variable:L"Lang" 86 ## SOMETIMES_CONSUMES ## Variable:L"HwErrRecSupport" 87 gEfiGlobalVariableGuid 88 gSmmVariableWriteGuid ## PRODUCES ## UNDEFINED # Install protocol 89 gEfiSystemNvDataFvGuid ## CONSUMES ## GUID 90 gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES ## Variable:L"HwErrRec####" 91 ## SOMETIMES_CONSUMES ## HOB 92 gEdkiiFaultTolerantWriteGuid 71 93 72 94 [Pcd] 73 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize 74 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase 75 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 76 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize 77 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize 78 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize 79 gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize 80 95 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES 96 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES 97 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES 98 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES 99 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize ## CONSUMES 100 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize ## CONSUMES 101 gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize ## CONSUMES 102 gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe ## CONSUMES 103 81 104 [FeaturePcd] 82 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.) 105 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES # statistic the information of variable. 106 gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES 83 107 84 108 [Depex] 85 109 TRUE 86 110 87 111 [UserExtensions.TianoCore."ExtraFiles"] 112 VariableSmmExtra.uni -
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
r48674 r58459 5 5 based on SMM variable module. 6 6 7 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> 7 Caution: This module requires additional review when modified. 8 This driver will have external input - variable data. 9 This external input must be validated carefully to avoid security issue like 10 buffer overflow, integer overflow. 11 12 RuntimeServiceGetVariable() and RuntimeServiceSetVariable() are external API 13 to receive data buffer. The size should be checked carefully. 14 15 InitCommunicateBuffer() is really function to check the variable data size. 16 17 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR> 8 18 This program and the accompanying materials 9 19 are licensed and made available under the terms and conditions of the BSD License … … 20 30 #include <Protocol/SmmCommunication.h> 21 31 #include <Protocol/SmmVariable.h> 32 #include <Protocol/VariableLock.h> 22 33 23 34 #include <Library/UefiBootServicesTableLib.h> … … 43 54 UINT8 *mVariableBufferPhysical = NULL; 44 55 UINTN mVariableBufferSize; 45 56 UINTN mVariableBufferPayloadSize; 57 EFI_LOCK mVariableServicesLock; 58 EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock; 59 60 /** 61 Acquires lock only at boot time. Simply returns at runtime. 62 63 This is a temperary function that will be removed when 64 EfiAcquireLock() in UefiLib can handle the call in UEFI 65 Runtimer driver in RT phase. 66 It calls EfiAcquireLock() at boot time, and simply returns 67 at runtime. 68 69 @param Lock A pointer to the lock to acquire. 70 71 **/ 72 VOID 73 AcquireLockOnlyAtBootTime ( 74 IN EFI_LOCK *Lock 75 ) 76 { 77 if (!EfiAtRuntime ()) { 78 EfiAcquireLock (Lock); 79 } 80 } 81 82 /** 83 Releases lock only at boot time. Simply returns at runtime. 84 85 This is a temperary function which will be removed when 86 EfiReleaseLock() in UefiLib can handle the call in UEFI 87 Runtimer driver in RT phase. 88 It calls EfiReleaseLock() at boot time and simply returns 89 at runtime. 90 91 @param Lock A pointer to the lock to release. 92 93 **/ 94 VOID 95 ReleaseLockOnlyAtBootTime ( 96 IN EFI_LOCK *Lock 97 ) 98 { 99 if (!EfiAtRuntime ()) { 100 EfiReleaseLock (Lock); 101 } 102 } 46 103 47 104 /** … … 50 107 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + 51 108 DataSize. 109 110 Caution: This function may receive untrusted input. 111 The data size external input, so this function will validate it carefully to avoid buffer overflow. 52 112 53 113 @param[out] DataPtr Points to the data in the communicate buffer. … … 116 176 } 117 177 178 /** 179 Mark a variable that will become read-only after leaving the DXE phase of execution. 180 181 @param[in] This The VARIABLE_LOCK_PROTOCOL instance. 182 @param[in] VariableName A pointer to the variable name that will be made read-only subsequently. 183 @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently. 184 185 @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked 186 as pending to be read-only. 187 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL. 188 Or VariableName is an empty string. 189 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has 190 already been signaled. 191 @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request. 192 **/ 193 EFI_STATUS 194 EFIAPI 195 VariableLockRequestToLock ( 196 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This, 197 IN CHAR16 *VariableName, 198 IN EFI_GUID *VendorGuid 199 ) 200 { 201 EFI_STATUS Status; 202 UINTN VariableNameSize; 203 UINTN PayloadSize; 204 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock; 205 206 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { 207 return EFI_INVALID_PARAMETER; 208 } 209 210 VariableNameSize = StrSize (VariableName); 211 VariableToLock = NULL; 212 213 // 214 // If VariableName exceeds SMM payload limit. Return failure 215 // 216 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) { 217 return EFI_INVALID_PARAMETER; 218 } 219 220 AcquireLockOnlyAtBootTime(&mVariableServicesLock); 221 222 // 223 // Init the communicate buffer. The buffer data size is: 224 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. 225 // 226 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize; 227 Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE); 228 if (EFI_ERROR (Status)) { 229 goto Done; 230 } 231 ASSERT (VariableToLock != NULL); 232 233 CopyGuid (&VariableToLock->Guid, VendorGuid); 234 VariableToLock->NameSize = VariableNameSize; 235 CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize); 236 237 // 238 // Send data to SMM. 239 // 240 Status = SendCommunicateBuffer (PayloadSize); 241 242 Done: 243 ReleaseLockOnlyAtBootTime (&mVariableServicesLock); 244 return Status; 245 } 118 246 119 247 /** 120 248 This code finds variable in storage blocks (Volatile or Non-Volatile). 249 250 Caution: This function may receive untrusted input. 251 The data size is external input, so this function will validate it carefully to avoid buffer overflow. 121 252 122 253 @param[in] VariableName Name of Variable to be found. … … 146 277 UINTN PayloadSize; 147 278 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader; 279 UINTN TempDataSize; 280 UINTN VariableNameSize; 148 281 149 282 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) { … … 154 287 return EFI_INVALID_PARAMETER; 155 288 } 156 289 290 TempDataSize = *DataSize; 291 VariableNameSize = StrSize (VariableName); 292 SmmVariableHeader = NULL; 293 294 // 295 // If VariableName exceeds SMM payload limit. Return failure 296 // 297 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) { 298 return EFI_INVALID_PARAMETER; 299 } 300 301 AcquireLockOnlyAtBootTime(&mVariableServicesLock); 302 157 303 // 158 304 // Init the communicate buffer. The buffer data size is: 159 305 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. 160 306 // 161 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName); 307 if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) { 308 // 309 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size 310 // 311 TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize; 312 } 313 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize; 314 162 315 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE); 163 316 if (EFI_ERROR (Status)) { 164 return Status;317 goto Done; 165 318 } 166 319 ASSERT (SmmVariableHeader != NULL); 167 320 168 321 CopyGuid (&SmmVariableHeader->Guid, VendorGuid); 169 SmmVariableHeader->DataSize = *DataSize;170 SmmVariableHeader->NameSize = StrSize (VariableName);322 SmmVariableHeader->DataSize = TempDataSize; 323 SmmVariableHeader->NameSize = VariableNameSize; 171 324 if (Attributes == NULL) { 172 325 SmmVariableHeader->Attributes = 0; … … 184 337 // Get data from SMM. 185 338 // 186 *DataSize = SmmVariableHeader->DataSize; 339 if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) { 340 // 341 // SMM CommBuffer DataSize can be a trimed value 342 // Only update DataSize when needed 343 // 344 *DataSize = SmmVariableHeader->DataSize; 345 } 187 346 if (Attributes != NULL) { 188 347 *Attributes = SmmVariableHeader->Attributes; … … 190 349 191 350 if (EFI_ERROR (Status)) { 192 return Status;351 goto Done; 193 352 } 194 353 195 354 CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize); 196 355 356 Done: 357 ReleaseLockOnlyAtBootTime (&mVariableServicesLock); 197 358 return Status; 198 359 } … … 223 384 UINTN PayloadSize; 224 385 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName; 386 UINTN OutVariableNameSize; 387 UINTN InVariableNameSize; 225 388 226 389 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) { 227 390 return EFI_INVALID_PARAMETER; 228 391 } 229 392 393 OutVariableNameSize = *VariableNameSize; 394 InVariableNameSize = StrSize (VariableName); 395 SmmGetNextVariableName = NULL; 396 397 // 398 // If input string exceeds SMM payload limit. Return failure 399 // 400 if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) { 401 return EFI_INVALID_PARAMETER; 402 } 403 404 AcquireLockOnlyAtBootTime(&mVariableServicesLock); 405 230 406 // 231 407 // Init the communicate buffer. The buffer data size is: 232 408 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. 233 409 // 234 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize; 410 if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) { 411 // 412 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size 413 // 414 OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name); 415 } 416 // 417 // Payload should be Guid + NameSize + MAX of Input & Output buffer 418 // 419 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize); 420 421 235 422 Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME); 236 423 if (EFI_ERROR (Status)) { 237 return Status;424 goto Done; 238 425 } 239 426 ASSERT (SmmGetNextVariableName != NULL); 240 427 241 SmmGetNextVariableName->NameSize = *VariableNameSize; 428 // 429 // SMM comm buffer->NameSize is buffer size for return string 430 // 431 SmmGetNextVariableName->NameSize = OutVariableNameSize; 432 242 433 CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid); 243 CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize); 434 // 435 // Copy whole string 436 // 437 CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize); 438 if (OutVariableNameSize > InVariableNameSize) { 439 ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize); 440 } 244 441 245 442 // … … 251 448 // Get data from SMM. 252 449 // 253 *VariableNameSize = SmmGetNextVariableName->NameSize; 254 if (EFI_ERROR (Status)) { 255 return Status; 450 if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) { 451 // 452 // SMM CommBuffer NameSize can be a trimed value 453 // Only update VariableNameSize when needed 454 // 455 *VariableNameSize = SmmGetNextVariableName->NameSize; 456 } 457 if (EFI_ERROR (Status)) { 458 goto Done; 256 459 } 257 460 … … 259 462 CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize); 260 463 464 Done: 465 ReleaseLockOnlyAtBootTime (&mVariableServicesLock); 261 466 return Status; 262 467 } … … 264 469 /** 265 470 This code sets variable in storage blocks (Volatile or Non-Volatile). 471 472 Caution: This function may receive untrusted input. 473 The data size and data are external input, so this function will validate it carefully to avoid buffer overflow. 266 474 267 475 @param[in] VariableName Name of Variable to be found. … … 292 500 UINTN PayloadSize; 293 501 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader; 502 UINTN VariableNameSize; 294 503 295 504 // … … 303 512 return EFI_INVALID_PARAMETER; 304 513 } 305 514 515 VariableNameSize = StrSize (VariableName); 516 SmmVariableHeader = NULL; 517 518 // 519 // If VariableName or DataSize exceeds SMM payload limit. Return failure 520 // 521 if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) || 522 (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize)){ 523 return EFI_INVALID_PARAMETER; 524 } 525 526 AcquireLockOnlyAtBootTime(&mVariableServicesLock); 527 306 528 // 307 529 // Init the communicate buffer. The buffer data size is: 308 530 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. 309 531 // 310 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName)+ DataSize;532 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize; 311 533 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE); 312 534 if (EFI_ERROR (Status)) { 313 return Status;535 goto Done; 314 536 } 315 537 ASSERT (SmmVariableHeader != NULL); … … 317 539 CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid); 318 540 SmmVariableHeader->DataSize = DataSize; 319 SmmVariableHeader->NameSize = StrSize (VariableName);541 SmmVariableHeader->NameSize = VariableNameSize; 320 542 SmmVariableHeader->Attributes = Attributes; 321 543 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize); … … 326 548 // 327 549 Status = SendCommunicateBuffer (PayloadSize); 328 550 551 Done: 552 ReleaseLockOnlyAtBootTime (&mVariableServicesLock); 329 553 return Status; 330 554 } … … 361 585 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo; 362 586 587 SmmQueryVariableInfo = NULL; 588 363 589 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) { 364 590 return EFI_INVALID_PARAMETER; 365 591 } 366 592 593 AcquireLockOnlyAtBootTime(&mVariableServicesLock); 594 367 595 // 368 596 // Init the communicate buffer. The buffer data size is: … … 372 600 Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO); 373 601 if (EFI_ERROR (Status)) { 374 return Status;602 goto Done; 375 603 } 376 604 ASSERT (SmmQueryVariableInfo != NULL); … … 383 611 Status = SendCommunicateBuffer (PayloadSize); 384 612 if (EFI_ERROR (Status)) { 385 return Status;613 goto Done; 386 614 } 387 615 … … 392 620 *MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize; 393 621 *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize; 394 395 return EFI_SUCCESS; 622 623 Done: 624 ReleaseLockOnlyAtBootTime (&mVariableServicesLock); 625 return Status; 396 626 } 397 627 … … 502 732 503 733 // 504 // Allocate memory for variable store. 505 // 506 mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE; 507 mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)); 734 // Allocate memory for variable communicate buffer. 735 // 736 mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) + 737 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER); 738 mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize; 508 739 mVariableBuffer = AllocateRuntimePool (mVariableBufferSize); 509 740 ASSERT (mVariableBuffer != NULL); … … 586 817 ) 587 818 { 819 EFI_STATUS Status; 588 820 VOID *SmmVariableRegistration; 589 821 VOID *SmmVariableWriteRegistration; 590 822 EFI_EVENT OnReadyToBootEvent; 591 823 EFI_EVENT ExitBootServiceEvent; 592 824 825 EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY); 826 827 mVariableLock.RequestToLock = VariableLockRequestToLock; 828 Status = gBS->InstallMultipleProtocolInterfaces ( 829 &mHandle, 830 &gEdkiiVariableLockProtocolGuid, 831 &mVariableLock, 832 NULL 833 ); 834 ASSERT_EFI_ERROR (Status); 835 593 836 // 594 837 // Smm variable service is ready -
trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
r48674 r58459 1 1 ## @file 2 # Component description file for Variable SmmRuntimeDxe module.2 # This module is the Runtime DXE part correspond to SMM variable module. 3 3 # 4 # This module is the Runtime DXE part correspond to SMM variable module. It 5 # installs variable arch protocol and variable write arch protocol and works 6 # with SMM variable module together. 7 # Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> 4 # It installs variable arch protocol and variable write arch protocol to provide 5 # four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo 6 # and works with SMM variable module together. 7 # 8 # Caution: This module requires additional review when modified. 9 # This driver will have external input - variable data. 10 # This external input must be validated carefully to avoid security issues such as 11 # buffer overflow or integer overflow. 12 # 13 # Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR> 8 14 # 9 15 # This program and the accompanying materials … … 20 26 INF_VERSION = 0x00010005 21 27 BASE_NAME = VariableSmmRuntimeDxe 28 MODULE_UNI_FILE = VariableSmmRuntimeDxe.uni 22 29 FILE_GUID = 9F7DCADE-11EA-448a-A46F-76E003657DD1 23 30 MODULE_TYPE = DXE_RUNTIME_DRIVER … … 51 58 52 59 [Protocols] 53 gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES 54 gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES 55 gEfiSmmCommunicationProtocolGuid 60 gEfiVariableWriteArchProtocolGuid ## PRODUCES 61 gEfiVariableArchProtocolGuid ## PRODUCES 62 gEfiSmmCommunicationProtocolGuid ## CONSUMES 63 ## CONSUMES 64 ## NOTIFY 65 ## UNDEFINED # Used to do smm communication 56 66 gEfiSmmVariableProtocolGuid 67 gEdkiiVariableLockProtocolGuid ## PRODUCES 57 68 58 69 [Guids] 59 gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event 70 gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event 71 gEfiEventExitBootServicesGuid ## CONSUMES ## Event 72 ## CONSUMES ## GUID # Locate protocol 73 ## CONSUMES ## GUID # Protocol notify 60 74 gSmmVariableWriteGuid 61 75 62 76 [Pcd] 63 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize 64 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize 65 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase 77 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES 78 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize ## CONSUMES 66 79 67 80 [Depex] 68 81 gEfiSmmCommunicationProtocolGuid 82 83 [UserExtensions.TianoCore."ExtraFiles"] 84 VariableSmmRuntimeDxeExtra.uni
Note:
See TracChangeset
for help on using the changeset viewer.