X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkModulePkg%2FUniversal%2FVariable%2FRuntimeDxe%2FVariable.c;h=f59d2a396981102b7fecde6faad535e41e028c2a;hp=0d91520d9722ce74286dbecf64f8b8acc2a29efd;hb=f53a07320e7021b5a80973cc7b265bd8ce5caf40;hpb=878ddf1fc3540a715f63594ed22b6929e881afb4 diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c index 0d91520d97..f59d2a3969 100644 --- a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c @@ -810,38 +810,45 @@ Returns: if (Status == EFI_INVALID_PARAMETER) { return Status; - } - // - // The size of the VariableName, including the Unicode Null in bytes plus - // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes. - // - else if (sizeof (VARIABLE_HEADER) + ArrayLength (VariableName) + DataSize > MAX_VARIABLE_SIZE) { + } else if (!EFI_ERROR (Status) && Variable.Volatile && EfiAtRuntime()) { + // + // If EfiAtRuntime and the variable is Volatile and Runtime Access, + // the volatile is ReadOnly, and SetVariable should be aborted and + // return EFI_WRITE_PROTECTED. + // + return EFI_WRITE_PROTECTED; + } else if (sizeof (VARIABLE_HEADER) + ArrayLength (VariableName) + DataSize > MAX_VARIABLE_SIZE) { + // + // The size of the VariableName, including the Unicode Null in bytes plus + // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes. + // return EFI_INVALID_PARAMETER; - } - // - // Make sure if runtime bit is set, boot service bit is set also - // - else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS - ) { + } else if (Attributes == EFI_VARIABLE_NON_VOLATILE) { + // + // Make sure not only EFI_VARIABLE_NON_VOLATILE is set + // return EFI_INVALID_PARAMETER; - } - // - // Runtime but Attribute is not Runtime - // - else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { + } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == + EFI_VARIABLE_RUNTIME_ACCESS) { + // + // Make sure if runtime bit is set, boot service bit is set also + // return EFI_INVALID_PARAMETER; - } - // - // Cannot set volatile variable in Runtime - // - else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) { + } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { + // + // Runtime but Attribute is not Runtime + // return EFI_INVALID_PARAMETER; - } - // - // Setting a data variable with no access, or zero DataSize attributes - // specified causes it to be deleted. - // - else if (DataSize == 0 || Attributes == 0) { + } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) { + // + // Cannot set volatile variable in Runtime + // + return EFI_INVALID_PARAMETER; + } else if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) { + // + // Setting a data variable with no access, or zero DataSize attributes + // specified causes it to be deleted. + // if (!EFI_ERROR (Status)) { State = Variable.CurrPtr->State; State &= VAR_DELETED; @@ -1090,6 +1097,135 @@ Returns: return EFI_SUCCESS; } +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) +EFI_STATUS +EFIAPI +QueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize, + IN VARIABLE_GLOBAL *Global, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code returns information about the EFI variables. + +Arguments: + + Attributes Attributes bitmask to specify the type of variables + on which to return information. + MaximumVariableStorageSize Pointer to the maximum size of the storage space available + for the EFI variables associated with the attributes specified. + RemainingVariableStorageSize Pointer to the remaining size of the storage space available + for the EFI variables associated with the attributes specified. + MaximumVariableSize Pointer to the maximum size of the individual EFI variables + associated with the attributes specified. + Global Pointer to VARIABLE_GLOBAL structure. + Instance Instance of the Firmware Volume. + +Returns: + + EFI STATUS + EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied. + EFI_SUCCESS - Query successfully. + EFI_UNSUPPORTED - The attribute is not supported on this platform. + +--*/ +{ + VARIABLE_HEADER *Variable; + VARIABLE_HEADER *NextVariable; + UINT64 VariableSize; + VARIABLE_STORE_HEADER *VariableStoreHeader; + + if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) { + // + // Make sure the Attributes combination is supported by the platform. + // + return EFI_UNSUPPORTED; + } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) { + // + // Make sure if runtime bit is set, boot service bit is set also. + // + return EFI_INVALID_PARAMETER; + } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { + // + // Make sure RT Attribute is set if we are in Runtime phase. + // + return EFI_INVALID_PARAMETER; + } + + if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) { + // + // Query is Volatile related. + // + VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase); + } else { + // + // Query is Non-Volatile related. + // + VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase); + } + + // + // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize + // with the storage size (excluding the storage header size). + // + *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER); + *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER); + + // + // Let *MaximumVariableSize be MAX_VARIABLE_SIZE. + // + *MaximumVariableSize = MAX_VARIABLE_SIZE; + + // + // Point to the starting address of the variables. + // + Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1); + + // + // Now walk through the related variable store. + // + while (IsValidVariableHeader (Variable) && (Variable < GetEndPointer (VariableStoreHeader))) { + NextVariable = GetNextVariablePtr (Variable); + VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable; + + if (EfiAtRuntime ()) { + // + // we don't take the state of the variables in mind + // when calculating RemainingVariableStorageSize, + // since the space occupied by variables not marked with + // VAR_ADDED is not allowed to be reclaimed in Runtime. + // + *RemainingVariableStorageSize -= VariableSize; + } else { + // + // Only care about Variables with State VAR_ADDED,because + // the space not marked as VAR_ADDED is reclaimable now. + // + if (Variable->State == VAR_ADDED) { + *RemainingVariableStorageSize -= VariableSize; + } + } + + // + // Go to the next one + // + Variable = NextVariable; + } + + return EFI_SUCCESS; +} +#endif + EFI_STATUS EFIAPI VariableCommonInitialize ( @@ -1125,14 +1261,14 @@ Returns: UINT32 Instance; EFI_PHYSICAL_ADDRESS FvVolHdr; - EFI_FLASH_MAP_ENTRY_DATA *FlashMapEntryData; + UINT64 TempVariableStoreHeader; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry; UINT64 BaseAddress; UINT64 Length; UINTN Index; UINT8 Data; - EFI_PEI_HOB_POINTERS GuidHob; Status = gBS->AllocatePool ( EfiRuntimeServicesData, @@ -1176,35 +1312,11 @@ Returns: // Get non volatile varaible store // - FlashMapEntryData = NULL; - - GuidHob.Raw = GetHobList (); - while (NULL != (GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw))) { - FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid); - - if (FlashMapEntryData->AreaType == EFI_FLASH_AREA_EFI_VARIABLES) { - break; - } - GuidHob.Raw = GET_NEXT_HOB (GuidHob); - } - - if (NULL == GuidHob.Raw || FlashMapEntryData == NULL) { - gBS->FreePool (mVariableModuleGlobal); - gBS->FreePool (VolatileVariableStore); - return EFI_NOT_FOUND; - } - - // - // Currently only one non-volatile variable store is supported - // - if (FlashMapEntryData->NumEntries != 1) { - gBS->FreePool (mVariableModuleGlobal); - gBS->FreePool (VolatileVariableStore); - return EFI_UNSUPPORTED; - } - - CopyMem (&VariableStoreEntry, &FlashMapEntryData->Entries[0], sizeof (VariableStoreEntry)); - + TempVariableStoreHeader = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase); + VariableStoreEntry.Base = TempVariableStoreHeader + \ + (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength); + VariableStoreEntry.Length = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \ + (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength); // // Mark the variable storage region of the FLASH as RUNTIME // @@ -1283,6 +1395,23 @@ Returns: mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) CurrPtr; + // + // Check if the free area is blow a threshold + // + if ((((VARIABLE_STORE_HEADER *)((UINTN) CurrPtr))->Size - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) { + Status = Reclaim ( + mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase, + &mVariableModuleGlobal->NonVolatileLastVariableOffset, + FALSE + ); + } + + if (EFI_ERROR (Status)) { + gBS->FreePool (mVariableModuleGlobal); + gBS->FreePool (VolatileVariableStore); + return Status; + } + // // Check if the free area is really free. //